From 027351f729b9e837200dae6e1520cda6577ab930 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Wed, 15 May 2002 02:29:24 +0000 Subject: This commit was manufactured by cvs2git to create branch 'unlabeled-1.1.1'. --- src/lib/libcrypto/aes/README | 3 + src/lib/libcrypto/aes/aes.h | 109 ++ src/lib/libcrypto/aes/aes_cbc.c | 89 + src/lib/libcrypto/aes/aes_cfb.c | 151 ++ src/lib/libcrypto/aes/aes_core.c | 1251 ++++++++++++++ src/lib/libcrypto/aes/aes_ctr.c | 117 ++ src/lib/libcrypto/aes/aes_ecb.c | 67 + src/lib/libcrypto/aes/aes_locl.h | 88 + src/lib/libcrypto/aes/aes_misc.c | 64 + src/lib/libcrypto/aes/aes_ofb.c | 136 ++ src/lib/libcrypto/asn1/a_enum.c | 326 ++++ src/lib/libcrypto/asn1/a_mbstr.c | 390 +++++ src/lib/libcrypto/asn1/a_strex.c | 533 ++++++ src/lib/libcrypto/asn1/a_strnid.c | 247 +++ src/lib/libcrypto/asn1/a_time.c | 123 ++ src/lib/libcrypto/asn1/a_utf8.c | 83 + src/lib/libcrypto/asn1/asn1t.h | 846 ++++++++++ src/lib/libcrypto/asn1/asn_moid.c | 95 ++ src/lib/libcrypto/asn1/asn_pack.c | 145 ++ src/lib/libcrypto/asn1/charmap.h | 15 + src/lib/libcrypto/asn1/charmap.pl | 80 + src/lib/libcrypto/asn1/f_enum.c | 207 +++ src/lib/libcrypto/asn1/nsseq.c | 118 ++ src/lib/libcrypto/asn1/p5_pbe.c | 156 ++ src/lib/libcrypto/asn1/p5_pbev2.c | 274 ++++ src/lib/libcrypto/asn1/p8_pkey.c | 129 ++ src/lib/libcrypto/asn1/t_bitst.c | 99 ++ src/lib/libcrypto/asn1/t_crl.c | 166 ++ src/lib/libcrypto/asn1/t_spki.c | 116 ++ src/lib/libcrypto/asn1/t_x509a.c | 102 ++ src/lib/libcrypto/asn1/tasn_dec.c | 958 +++++++++++ src/lib/libcrypto/asn1/tasn_enc.c | 497 ++++++ src/lib/libcrypto/asn1/tasn_fre.c | 226 +++ src/lib/libcrypto/asn1/tasn_new.c | 348 ++++ src/lib/libcrypto/asn1/tasn_prn.c | 198 +++ src/lib/libcrypto/asn1/tasn_typ.c | 133 ++ src/lib/libcrypto/asn1/tasn_utl.c | 253 +++ src/lib/libcrypto/asn1/x_bignum.c | 137 ++ src/lib/libcrypto/asn1/x_long.c | 169 ++ src/lib/libcrypto/asn1/x_x509a.c | 200 +++ src/lib/libcrypto/bf/bf_locl.h | 219 +++ src/lib/libcrypto/bio/bf_lbuf.c | 397 +++++ src/lib/libcrypto/bio/bss_bio.c | 588 +++++++ src/lib/libcrypto/bio/bss_log.c | 232 +++ src/lib/libcrypto/bn/asm/co-586.pl | 286 ++++ src/lib/libcrypto/bn/asm/ia64.S | 1498 +++++++++++++++++ src/lib/libcrypto/bn/asm/pa-risc2W.s | 1605 ++++++++++++++++++ src/lib/libcrypto/bn/asm/sparcv8.S | 1458 +++++++++++++++++ src/lib/libcrypto/bn/asm/sparcv8plus.S | 1535 +++++++++++++++++ src/lib/libcrypto/bn/asm/x86.pl | 28 + src/lib/libcrypto/bn/asm/x86/add.pl | 76 + src/lib/libcrypto/bn/asm/x86/comba.pl | 277 ++++ src/lib/libcrypto/bn/asm/x86/div.pl | 15 + src/lib/libcrypto/bn/asm/x86/mul.pl | 77 + src/lib/libcrypto/bn/asm/x86/mul_add.pl | 87 + src/lib/libcrypto/bn/asm/x86/sqr.pl | 60 + src/lib/libcrypto/bn/asm/x86/sub.pl | 76 + src/lib/libcrypto/bn/bn.h | 467 ++++++ src/lib/libcrypto/bn/bn_asm.c | 802 +++++++++ src/lib/libcrypto/bn/bn_ctx.c | 144 ++ src/lib/libcrypto/bn/bn_exp2.c | 195 +++ src/lib/libcrypto/bn/bn_kron.c | 182 +++ src/lib/libcrypto/bn/bn_sqrt.c | 387 +++++ src/lib/libcrypto/comp/c_rle.c | 61 + src/lib/libcrypto/comp/c_zlib.c | 133 ++ src/lib/libcrypto/comp/comp.h | 60 + src/lib/libcrypto/comp/comp_err.c | 91 ++ src/lib/libcrypto/comp/comp_lib.c | 78 + src/lib/libcrypto/conf/README | 78 + src/lib/libcrypto/conf/conf_api.c | 289 ++++ src/lib/libcrypto/conf/conf_api.h | 87 + src/lib/libcrypto/conf/conf_def.c | 703 ++++++++ src/lib/libcrypto/conf/conf_def.h | 145 ++ src/lib/libcrypto/conf/conf_lib.c | 352 ++++ src/lib/libcrypto/conf/conf_mall.c | 76 + src/lib/libcrypto/conf/conf_mod.c | 616 +++++++ src/lib/libcrypto/conf/conf_sap.c | 107 ++ src/lib/libcrypto/des/des.h | 249 +++ src/lib/libcrypto/des/des_locl.h | 408 +++++ src/lib/libcrypto/des/ede_cbcm_enc.c | 197 +++ src/lib/libcrypto/dh/dh_asn1.c | 87 + src/lib/libcrypto/doc/DH_generate_key.pod | 50 + src/lib/libcrypto/doc/DH_generate_parameters.pod | 72 + src/lib/libcrypto/doc/DH_get_ex_new_index.pod | 36 + src/lib/libcrypto/doc/DH_new.pod | 40 + src/lib/libcrypto/doc/DH_set_method.pod | 99 ++ src/lib/libcrypto/doc/DH_size.pod | 33 + src/lib/libcrypto/doc/DSA_SIG_new.pod | 39 + src/lib/libcrypto/doc/DSA_do_sign.pod | 47 + src/lib/libcrypto/doc/DSA_dup_DH.pod | 36 + src/lib/libcrypto/doc/DSA_generate_key.pod | 33 + src/lib/libcrypto/doc/DSA_generate_parameters.pod | 105 ++ src/lib/libcrypto/doc/DSA_get_ex_new_index.pod | 36 + src/lib/libcrypto/doc/DSA_new.pod | 41 + src/lib/libcrypto/doc/DSA_set_method.pod | 111 ++ src/lib/libcrypto/doc/DSA_sign.pod | 66 + src/lib/libcrypto/doc/DSA_size.pod | 33 + src/lib/libcrypto/doc/ERR_GET_LIB.pod | 51 + src/lib/libcrypto/doc/ERR_clear_error.pod | 29 + src/lib/libcrypto/doc/ERR_error_string.pod | 65 + src/lib/libcrypto/doc/ERR_get_error.pod | 62 + src/lib/libcrypto/doc/ERR_load_crypto_strings.pod | 46 + src/lib/libcrypto/doc/ERR_load_strings.pod | 54 + src/lib/libcrypto/doc/ERR_print_errors.pod | 51 + src/lib/libcrypto/doc/ERR_put_error.pod | 44 + src/lib/libcrypto/doc/ERR_remove_state.pod | 34 + src/lib/libcrypto/doc/EVP_BytesToKey.pod | 67 + src/lib/libcrypto/doc/EVP_DigestInit.pod | 197 +++ src/lib/libcrypto/doc/EVP_EncryptInit.pod | 224 +++ src/lib/libcrypto/doc/EVP_OpenInit.pod | 51 + src/lib/libcrypto/doc/EVP_SealInit.pod | 70 + src/lib/libcrypto/doc/EVP_SignInit.pod | 85 + src/lib/libcrypto/doc/EVP_VerifyInit.pod | 71 + src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod | 46 + .../libcrypto/doc/OpenSSL_add_all_algorithms.pod | 65 + src/lib/libcrypto/doc/RAND_add.pod | 68 + src/lib/libcrypto/doc/RAND_bytes.pod | 46 + src/lib/libcrypto/doc/RAND_cleanup.pod | 29 + src/lib/libcrypto/doc/RAND_load_file.pod | 53 + src/lib/libcrypto/doc/RAND_set_rand_method.pod | 57 + src/lib/libcrypto/doc/RSA_blinding_on.pod | 43 + src/lib/libcrypto/doc/RSA_check_key.pod | 39 + src/lib/libcrypto/doc/RSA_generate_key.pod | 68 + src/lib/libcrypto/doc/RSA_get_ex_new_index.pod | 122 ++ src/lib/libcrypto/doc/RSA_new.pod | 38 + .../libcrypto/doc/RSA_padding_add_PKCS1_type_1.pod | 124 ++ src/lib/libcrypto/doc/RSA_print.pod | 48 + src/lib/libcrypto/doc/RSA_private_encrypt.pod | 69 + src/lib/libcrypto/doc/RSA_public_encrypt.pod | 86 + src/lib/libcrypto/doc/RSA_set_method.pod | 153 ++ src/lib/libcrypto/doc/RSA_sign.pod | 62 + .../libcrypto/doc/RSA_sign_ASN1_OCTET_STRING.pod | 59 + src/lib/libcrypto/doc/RSA_size.pod | 33 + src/lib/libcrypto/doc/bn.pod | 148 ++ src/lib/libcrypto/doc/d2i_DHparams.pod | 30 + src/lib/libcrypto/doc/d2i_RSAPublicKey.pod | 39 + src/lib/libcrypto/doc/dh.pod | 68 + src/lib/libcrypto/doc/dsa.pod | 104 ++ src/lib/libcrypto/doc/evp.pod | 37 + src/lib/libcrypto/doc/lh_stats.pod | 60 + src/lib/libcrypto/doc/rsa.pod | 115 ++ src/lib/libcrypto/dsa/dsa_asn1.c | 96 ++ src/lib/libcrypto/dsa/dsa_ossl.c | 321 ++++ src/lib/libcrypto/dso/dso.h | 250 +++ src/lib/libcrypto/dso/dso_dlfcn.c | 276 ++++ src/lib/libcrypto/dso/dso_err.c | 128 ++ src/lib/libcrypto/dso/dso_lib.c | 306 ++++ src/lib/libcrypto/dso/dso_null.c | 86 + src/lib/libcrypto/dso/dso_openssl.c | 81 + src/lib/libcrypto/ec/ec.h | 245 +++ src/lib/libcrypto/ec/ec_cvt.c | 80 + src/lib/libcrypto/ec/ec_err.c | 151 ++ src/lib/libcrypto/ec/ec_lcl.h | 277 ++++ src/lib/libcrypto/ec/ec_lib.c | 646 ++++++++ src/lib/libcrypto/ec/ec_mult.c | 473 ++++++ src/lib/libcrypto/ec/ecp_mont.c | 304 ++++ src/lib/libcrypto/ec/ecp_nist.c | 134 ++ src/lib/libcrypto/ec/ecp_smpl.c | 1717 ++++++++++++++++++++ src/lib/libcrypto/engine/README | 278 ++++ src/lib/libcrypto/engine/eng_all.c | 118 ++ src/lib/libcrypto/engine/eng_cnf.c | 242 +++ src/lib/libcrypto/engine/eng_ctrl.c | 387 +++++ src/lib/libcrypto/engine/eng_dyn.c | 446 +++++ src/lib/libcrypto/engine/eng_err.c | 165 ++ src/lib/libcrypto/engine/eng_fat.c | 148 ++ src/lib/libcrypto/engine/eng_init.c | 158 ++ src/lib/libcrypto/engine/eng_int.h | 185 +++ src/lib/libcrypto/engine/eng_lib.c | 321 ++++ src/lib/libcrypto/engine/eng_list.c | 383 +++++ src/lib/libcrypto/engine/eng_openssl.c | 347 ++++ src/lib/libcrypto/engine/eng_pkey.c | 157 ++ src/lib/libcrypto/engine/eng_table.c | 361 ++++ src/lib/libcrypto/engine/engine.h | 398 +++++ src/lib/libcrypto/engine/tb_cipher.c | 145 ++ src/lib/libcrypto/engine/tb_dh.c | 120 ++ src/lib/libcrypto/engine/tb_digest.c | 145 ++ src/lib/libcrypto/engine/tb_dsa.c | 120 ++ src/lib/libcrypto/engine/tb_rand.c | 120 ++ src/lib/libcrypto/engine/tb_rsa.c | 120 ++ src/lib/libcrypto/err/openssl.ec | 71 + src/lib/libcrypto/evp/e_aes.c | 99 ++ src/lib/libcrypto/evp/e_bf.c | 80 + src/lib/libcrypto/evp/e_cast.c | 82 + src/lib/libcrypto/evp/e_des.c | 118 ++ src/lib/libcrypto/evp/e_des3.c | 165 ++ src/lib/libcrypto/evp/e_idea.c | 112 ++ src/lib/libcrypto/evp/e_rc2.c | 222 +++ src/lib/libcrypto/evp/evp_locl.h | 168 ++ src/lib/libcrypto/evp/evp_pbe.c | 134 ++ src/lib/libcrypto/evp/evp_pkey.c | 298 ++++ src/lib/libcrypto/evp/m_md4.c | 83 + src/lib/libcrypto/evp/p5_crpt.c | 146 ++ src/lib/libcrypto/evp/p5_crpt2.c | 247 +++ src/lib/libcrypto/idea/idea.h | 99 ++ src/lib/libcrypto/krb5/krb5_asn.c | 167 ++ src/lib/libcrypto/krb5/krb5_asn.h | 256 +++ src/lib/libcrypto/md32_common.h | 594 +++++++ src/lib/libcrypto/md4/md4.h | 114 ++ src/lib/libcrypto/md4/md4_dgst.c | 285 ++++ src/lib/libcrypto/md4/md4_locl.h | 154 ++ src/lib/libcrypto/md4/md4_one.c | 95 ++ src/lib/libcrypto/mem_dbg.c | 703 ++++++++ src/lib/libcrypto/o_time.c | 203 +++ src/lib/libcrypto/o_time.h | 66 + src/lib/libcrypto/objects/o_names.c | 243 +++ src/lib/libcrypto/objects/obj_mac.num | 392 +++++ src/lib/libcrypto/objects/objects.README | 44 + src/lib/libcrypto/objects/objects.pl | 224 +++ src/lib/libcrypto/ocsp/ocsp.h | 619 +++++++ src/lib/libcrypto/ocsp/ocsp_asn.c | 182 +++ src/lib/libcrypto/ocsp/ocsp_cl.c | 370 +++++ src/lib/libcrypto/ocsp/ocsp_err.c | 139 ++ src/lib/libcrypto/ocsp/ocsp_ext.c | 528 ++++++ src/lib/libcrypto/ocsp/ocsp_ht.c | 164 ++ src/lib/libcrypto/ocsp/ocsp_lib.c | 261 +++ src/lib/libcrypto/ocsp/ocsp_prn.c | 291 ++++ src/lib/libcrypto/ocsp/ocsp_srv.c | 264 +++ src/lib/libcrypto/ocsp/ocsp_vfy.c | 444 +++++ src/lib/libcrypto/opensslv.h | 21 + src/lib/libcrypto/ossl_typ.h | 120 ++ src/lib/libcrypto/pem/pem2.h | 60 + src/lib/libcrypto/pem/pem_oth.c | 85 + src/lib/libcrypto/pem/pem_pk8.c | 243 +++ src/lib/libcrypto/pem/pem_pkey.c | 139 ++ src/lib/libcrypto/pem/pem_x509.c | 69 + src/lib/libcrypto/pem/pem_xaux.c | 68 + src/lib/libcrypto/pkcs12/p12_add.c | 214 +++ src/lib/libcrypto/pkcs12/p12_asn.c | 125 ++ src/lib/libcrypto/pkcs12/p12_attr.c | 238 +++ src/lib/libcrypto/pkcs12/p12_crpt.c | 122 ++ src/lib/libcrypto/pkcs12/p12_crt.c | 159 ++ src/lib/libcrypto/pkcs12/p12_decr.c | 185 +++ src/lib/libcrypto/pkcs12/p12_init.c | 98 ++ src/lib/libcrypto/pkcs12/p12_key.c | 182 +++ src/lib/libcrypto/pkcs12/p12_kiss.c | 238 +++ src/lib/libcrypto/pkcs12/p12_mutl.c | 170 ++ src/lib/libcrypto/pkcs12/p12_npas.c | 212 +++ src/lib/libcrypto/pkcs12/p12_p8d.c | 68 + src/lib/libcrypto/pkcs12/p12_p8e.c | 97 ++ src/lib/libcrypto/pkcs12/p12_utl.c | 118 ++ src/lib/libcrypto/pkcs12/pk12err.c | 136 ++ src/lib/libcrypto/pkcs12/pkcs12.h | 337 ++++ src/lib/libcrypto/pkcs7/pk7_asn1.c | 213 +++ src/lib/libcrypto/pkcs7/pk7_attr.c | 85 + src/lib/libcrypto/pkcs7/pk7_mime.c | 673 ++++++++ src/lib/libcrypto/pkcs7/pk7_smime.c | 427 +++++ src/lib/libcrypto/rand/rand_err.c | 93 ++ src/lib/libcrypto/rand/rand_lib.c | 98 ++ src/lib/libcrypto/rc2/rc2.h | 99 ++ src/lib/libcrypto/rc4/rc4.h | 88 + src/lib/libcrypto/rc4/rc4_locl.h | 4 + src/lib/libcrypto/rsa/rsa_asn1.c | 121 ++ src/lib/libcrypto/rsa/rsa_chk.c | 184 +++ src/lib/libcrypto/rsa/rsa_oaep.c | 162 ++ src/lib/libcrypto/stack/safestack.h | 129 ++ src/lib/libcrypto/ui/ui.h | 387 +++++ src/lib/libcrypto/ui/ui_compat.h | 83 + src/lib/libcrypto/ui/ui_err.c | 111 ++ src/lib/libcrypto/ui/ui_lib.c | 899 ++++++++++ src/lib/libcrypto/ui/ui_locl.h | 148 ++ src/lib/libcrypto/ui/ui_openssl.c | 661 ++++++++ src/lib/libcrypto/ui/ui_util.c | 86 + src/lib/libcrypto/util/mkerr.pl | 503 ++++++ src/lib/libcrypto/util/mkstack.pl | 124 ++ src/lib/libcrypto/x509/x509_att.c | 326 ++++ src/lib/libcrypto/x509/x509_trs.c | 263 +++ src/lib/libcrypto/x509/x509cset.c | 169 ++ src/lib/libcrypto/x509/x509spki.c | 121 ++ src/lib/libcrypto/x509v3/ext_dat.h | 97 ++ src/lib/libcrypto/x509v3/v3_akey.c | 249 +++ src/lib/libcrypto/x509v3/v3_akeya.c | 72 + src/lib/libcrypto/x509v3/v3_alt.c | 402 +++++ src/lib/libcrypto/x509v3/v3_bcons.c | 164 ++ src/lib/libcrypto/x509v3/v3_bitst.c | 147 ++ src/lib/libcrypto/x509v3/v3_conf.c | 366 +++++ src/lib/libcrypto/x509v3/v3_cpols.c | 655 ++++++++ src/lib/libcrypto/x509v3/v3_crld.c | 283 ++++ src/lib/libcrypto/x509v3/v3_enum.c | 103 ++ src/lib/libcrypto/x509v3/v3_extku.c | 150 ++ src/lib/libcrypto/x509v3/v3_genn.c | 237 +++ src/lib/libcrypto/x509v3/v3_ia5.c | 116 ++ src/lib/libcrypto/x509v3/v3_info.c | 236 +++ src/lib/libcrypto/x509v3/v3_int.c | 79 + src/lib/libcrypto/x509v3/v3_lib.c | 177 ++ src/lib/libcrypto/x509v3/v3_ocsp.c | 272 ++++ src/lib/libcrypto/x509v3/v3_pku.c | 151 ++ src/lib/libcrypto/x509v3/v3_prn.c | 135 ++ src/lib/libcrypto/x509v3/v3_purp.c | 456 ++++++ src/lib/libcrypto/x509v3/v3_skey.c | 156 ++ src/lib/libcrypto/x509v3/v3_sxnet.c | 340 ++++ src/lib/libcrypto/x509v3/v3_utl.c | 418 +++++ src/lib/libcrypto/x509v3/v3err.c | 171 ++ src/lib/libssl/LICENSE | 127 ++ src/lib/libssl/doc/openssl.cnf | 214 +++ src/lib/libssl/doc/openssl.txt | 1174 +++++++++++++ src/lib/libssl/doc/standards.txt | 121 ++ src/lib/libssl/test/VMSca-response.1 | 1 + src/lib/libssl/test/VMSca-response.2 | 2 + src/lib/libssl/test/bctest | 111 ++ 299 files changed, 64443 insertions(+) create mode 100644 src/lib/libcrypto/aes/README create mode 100644 src/lib/libcrypto/aes/aes.h create mode 100644 src/lib/libcrypto/aes/aes_cbc.c create mode 100644 src/lib/libcrypto/aes/aes_cfb.c create mode 100644 src/lib/libcrypto/aes/aes_core.c create mode 100644 src/lib/libcrypto/aes/aes_ctr.c create mode 100644 src/lib/libcrypto/aes/aes_ecb.c create mode 100644 src/lib/libcrypto/aes/aes_locl.h create mode 100644 src/lib/libcrypto/aes/aes_misc.c create mode 100644 src/lib/libcrypto/aes/aes_ofb.c create mode 100644 src/lib/libcrypto/asn1/a_enum.c create mode 100644 src/lib/libcrypto/asn1/a_mbstr.c create mode 100644 src/lib/libcrypto/asn1/a_strex.c create mode 100644 src/lib/libcrypto/asn1/a_strnid.c create mode 100644 src/lib/libcrypto/asn1/a_time.c create mode 100644 src/lib/libcrypto/asn1/a_utf8.c create mode 100644 src/lib/libcrypto/asn1/asn1t.h create mode 100644 src/lib/libcrypto/asn1/asn_moid.c create mode 100644 src/lib/libcrypto/asn1/asn_pack.c create mode 100644 src/lib/libcrypto/asn1/charmap.h create mode 100644 src/lib/libcrypto/asn1/charmap.pl create mode 100644 src/lib/libcrypto/asn1/f_enum.c create mode 100644 src/lib/libcrypto/asn1/nsseq.c create mode 100644 src/lib/libcrypto/asn1/p5_pbe.c create mode 100644 src/lib/libcrypto/asn1/p5_pbev2.c create mode 100644 src/lib/libcrypto/asn1/p8_pkey.c create mode 100644 src/lib/libcrypto/asn1/t_bitst.c create mode 100644 src/lib/libcrypto/asn1/t_crl.c create mode 100644 src/lib/libcrypto/asn1/t_spki.c create mode 100644 src/lib/libcrypto/asn1/t_x509a.c create mode 100644 src/lib/libcrypto/asn1/tasn_dec.c create mode 100644 src/lib/libcrypto/asn1/tasn_enc.c create mode 100644 src/lib/libcrypto/asn1/tasn_fre.c create mode 100644 src/lib/libcrypto/asn1/tasn_new.c create mode 100644 src/lib/libcrypto/asn1/tasn_prn.c create mode 100644 src/lib/libcrypto/asn1/tasn_typ.c create mode 100644 src/lib/libcrypto/asn1/tasn_utl.c create mode 100644 src/lib/libcrypto/asn1/x_bignum.c create mode 100644 src/lib/libcrypto/asn1/x_long.c create mode 100644 src/lib/libcrypto/asn1/x_x509a.c create mode 100644 src/lib/libcrypto/bf/bf_locl.h create mode 100644 src/lib/libcrypto/bio/bf_lbuf.c create mode 100644 src/lib/libcrypto/bio/bss_bio.c create mode 100644 src/lib/libcrypto/bio/bss_log.c create mode 100644 src/lib/libcrypto/bn/asm/co-586.pl create mode 100644 src/lib/libcrypto/bn/asm/ia64.S create mode 100644 src/lib/libcrypto/bn/asm/pa-risc2W.s create mode 100644 src/lib/libcrypto/bn/asm/sparcv8.S create mode 100644 src/lib/libcrypto/bn/asm/sparcv8plus.S create mode 100644 src/lib/libcrypto/bn/asm/x86.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/add.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/comba.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/div.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/mul.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/mul_add.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/sqr.pl create mode 100644 src/lib/libcrypto/bn/asm/x86/sub.pl create mode 100644 src/lib/libcrypto/bn/bn.h create mode 100644 src/lib/libcrypto/bn/bn_asm.c create mode 100644 src/lib/libcrypto/bn/bn_ctx.c create mode 100644 src/lib/libcrypto/bn/bn_exp2.c create mode 100644 src/lib/libcrypto/bn/bn_kron.c create mode 100644 src/lib/libcrypto/bn/bn_sqrt.c create mode 100644 src/lib/libcrypto/comp/c_rle.c create mode 100644 src/lib/libcrypto/comp/c_zlib.c create mode 100644 src/lib/libcrypto/comp/comp.h create mode 100644 src/lib/libcrypto/comp/comp_err.c create mode 100644 src/lib/libcrypto/comp/comp_lib.c create mode 100644 src/lib/libcrypto/conf/README create mode 100644 src/lib/libcrypto/conf/conf_api.c create mode 100644 src/lib/libcrypto/conf/conf_api.h create mode 100644 src/lib/libcrypto/conf/conf_def.c create mode 100644 src/lib/libcrypto/conf/conf_def.h create mode 100644 src/lib/libcrypto/conf/conf_lib.c create mode 100644 src/lib/libcrypto/conf/conf_mall.c create mode 100644 src/lib/libcrypto/conf/conf_mod.c create mode 100644 src/lib/libcrypto/conf/conf_sap.c create mode 100644 src/lib/libcrypto/des/des.h create mode 100644 src/lib/libcrypto/des/des_locl.h create mode 100644 src/lib/libcrypto/des/ede_cbcm_enc.c create mode 100644 src/lib/libcrypto/dh/dh_asn1.c create mode 100644 src/lib/libcrypto/doc/DH_generate_key.pod create mode 100644 src/lib/libcrypto/doc/DH_generate_parameters.pod create mode 100644 src/lib/libcrypto/doc/DH_get_ex_new_index.pod create mode 100644 src/lib/libcrypto/doc/DH_new.pod create mode 100644 src/lib/libcrypto/doc/DH_set_method.pod create mode 100644 src/lib/libcrypto/doc/DH_size.pod create mode 100644 src/lib/libcrypto/doc/DSA_SIG_new.pod create mode 100644 src/lib/libcrypto/doc/DSA_do_sign.pod create mode 100644 src/lib/libcrypto/doc/DSA_dup_DH.pod create mode 100644 src/lib/libcrypto/doc/DSA_generate_key.pod create mode 100644 src/lib/libcrypto/doc/DSA_generate_parameters.pod create mode 100644 src/lib/libcrypto/doc/DSA_get_ex_new_index.pod create mode 100644 src/lib/libcrypto/doc/DSA_new.pod create mode 100644 src/lib/libcrypto/doc/DSA_set_method.pod create mode 100644 src/lib/libcrypto/doc/DSA_sign.pod create mode 100644 src/lib/libcrypto/doc/DSA_size.pod create mode 100644 src/lib/libcrypto/doc/ERR_GET_LIB.pod create mode 100644 src/lib/libcrypto/doc/ERR_clear_error.pod create mode 100644 src/lib/libcrypto/doc/ERR_error_string.pod create mode 100644 src/lib/libcrypto/doc/ERR_get_error.pod create mode 100644 src/lib/libcrypto/doc/ERR_load_crypto_strings.pod create mode 100644 src/lib/libcrypto/doc/ERR_load_strings.pod create mode 100644 src/lib/libcrypto/doc/ERR_print_errors.pod create mode 100644 src/lib/libcrypto/doc/ERR_put_error.pod create mode 100644 src/lib/libcrypto/doc/ERR_remove_state.pod create mode 100644 src/lib/libcrypto/doc/EVP_BytesToKey.pod create mode 100644 src/lib/libcrypto/doc/EVP_DigestInit.pod create mode 100644 src/lib/libcrypto/doc/EVP_EncryptInit.pod create mode 100644 src/lib/libcrypto/doc/EVP_OpenInit.pod create mode 100644 src/lib/libcrypto/doc/EVP_SealInit.pod create mode 100644 src/lib/libcrypto/doc/EVP_SignInit.pod create mode 100644 src/lib/libcrypto/doc/EVP_VerifyInit.pod create mode 100644 src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod create mode 100644 src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod create mode 100644 src/lib/libcrypto/doc/RAND_add.pod create mode 100644 src/lib/libcrypto/doc/RAND_bytes.pod create mode 100644 src/lib/libcrypto/doc/RAND_cleanup.pod create mode 100644 src/lib/libcrypto/doc/RAND_load_file.pod create mode 100644 src/lib/libcrypto/doc/RAND_set_rand_method.pod create mode 100644 src/lib/libcrypto/doc/RSA_blinding_on.pod create mode 100644 src/lib/libcrypto/doc/RSA_check_key.pod create mode 100644 src/lib/libcrypto/doc/RSA_generate_key.pod create mode 100644 src/lib/libcrypto/doc/RSA_get_ex_new_index.pod create mode 100644 src/lib/libcrypto/doc/RSA_new.pod create mode 100644 src/lib/libcrypto/doc/RSA_padding_add_PKCS1_type_1.pod create mode 100644 src/lib/libcrypto/doc/RSA_print.pod create mode 100644 src/lib/libcrypto/doc/RSA_private_encrypt.pod create mode 100644 src/lib/libcrypto/doc/RSA_public_encrypt.pod create mode 100644 src/lib/libcrypto/doc/RSA_set_method.pod create mode 100644 src/lib/libcrypto/doc/RSA_sign.pod create mode 100644 src/lib/libcrypto/doc/RSA_sign_ASN1_OCTET_STRING.pod create mode 100644 src/lib/libcrypto/doc/RSA_size.pod create mode 100644 src/lib/libcrypto/doc/bn.pod create mode 100644 src/lib/libcrypto/doc/d2i_DHparams.pod create mode 100644 src/lib/libcrypto/doc/d2i_RSAPublicKey.pod create mode 100644 src/lib/libcrypto/doc/dh.pod create mode 100644 src/lib/libcrypto/doc/dsa.pod create mode 100644 src/lib/libcrypto/doc/evp.pod create mode 100644 src/lib/libcrypto/doc/lh_stats.pod create mode 100644 src/lib/libcrypto/doc/rsa.pod create mode 100644 src/lib/libcrypto/dsa/dsa_asn1.c create mode 100644 src/lib/libcrypto/dsa/dsa_ossl.c create mode 100644 src/lib/libcrypto/dso/dso.h create mode 100644 src/lib/libcrypto/dso/dso_dlfcn.c create mode 100644 src/lib/libcrypto/dso/dso_err.c create mode 100644 src/lib/libcrypto/dso/dso_lib.c create mode 100644 src/lib/libcrypto/dso/dso_null.c create mode 100644 src/lib/libcrypto/dso/dso_openssl.c create mode 100644 src/lib/libcrypto/ec/ec.h create mode 100644 src/lib/libcrypto/ec/ec_cvt.c create mode 100644 src/lib/libcrypto/ec/ec_err.c create mode 100644 src/lib/libcrypto/ec/ec_lcl.h create mode 100644 src/lib/libcrypto/ec/ec_lib.c create mode 100644 src/lib/libcrypto/ec/ec_mult.c create mode 100644 src/lib/libcrypto/ec/ecp_mont.c create mode 100644 src/lib/libcrypto/ec/ecp_nist.c create mode 100644 src/lib/libcrypto/ec/ecp_smpl.c create mode 100644 src/lib/libcrypto/engine/README create mode 100644 src/lib/libcrypto/engine/eng_all.c create mode 100644 src/lib/libcrypto/engine/eng_cnf.c create mode 100644 src/lib/libcrypto/engine/eng_ctrl.c create mode 100644 src/lib/libcrypto/engine/eng_dyn.c create mode 100644 src/lib/libcrypto/engine/eng_err.c create mode 100644 src/lib/libcrypto/engine/eng_fat.c create mode 100644 src/lib/libcrypto/engine/eng_init.c create mode 100644 src/lib/libcrypto/engine/eng_int.h create mode 100644 src/lib/libcrypto/engine/eng_lib.c create mode 100644 src/lib/libcrypto/engine/eng_list.c create mode 100644 src/lib/libcrypto/engine/eng_openssl.c create mode 100644 src/lib/libcrypto/engine/eng_pkey.c create mode 100644 src/lib/libcrypto/engine/eng_table.c create mode 100644 src/lib/libcrypto/engine/engine.h create mode 100644 src/lib/libcrypto/engine/tb_cipher.c create mode 100644 src/lib/libcrypto/engine/tb_dh.c create mode 100644 src/lib/libcrypto/engine/tb_digest.c create mode 100644 src/lib/libcrypto/engine/tb_dsa.c create mode 100644 src/lib/libcrypto/engine/tb_rand.c create mode 100644 src/lib/libcrypto/engine/tb_rsa.c create mode 100644 src/lib/libcrypto/err/openssl.ec create mode 100644 src/lib/libcrypto/evp/e_aes.c create mode 100644 src/lib/libcrypto/evp/e_bf.c create mode 100644 src/lib/libcrypto/evp/e_cast.c create mode 100644 src/lib/libcrypto/evp/e_des.c create mode 100644 src/lib/libcrypto/evp/e_des3.c create mode 100644 src/lib/libcrypto/evp/e_idea.c create mode 100644 src/lib/libcrypto/evp/e_rc2.c create mode 100644 src/lib/libcrypto/evp/evp_locl.h create mode 100644 src/lib/libcrypto/evp/evp_pbe.c create mode 100644 src/lib/libcrypto/evp/evp_pkey.c create mode 100644 src/lib/libcrypto/evp/m_md4.c create mode 100644 src/lib/libcrypto/evp/p5_crpt.c create mode 100644 src/lib/libcrypto/evp/p5_crpt2.c create mode 100644 src/lib/libcrypto/idea/idea.h create mode 100644 src/lib/libcrypto/krb5/krb5_asn.c create mode 100644 src/lib/libcrypto/krb5/krb5_asn.h create mode 100644 src/lib/libcrypto/md32_common.h create mode 100644 src/lib/libcrypto/md4/md4.h create mode 100644 src/lib/libcrypto/md4/md4_dgst.c create mode 100644 src/lib/libcrypto/md4/md4_locl.h create mode 100644 src/lib/libcrypto/md4/md4_one.c create mode 100644 src/lib/libcrypto/mem_dbg.c create mode 100644 src/lib/libcrypto/o_time.c create mode 100644 src/lib/libcrypto/o_time.h create mode 100644 src/lib/libcrypto/objects/o_names.c create mode 100644 src/lib/libcrypto/objects/obj_mac.num create mode 100644 src/lib/libcrypto/objects/objects.README create mode 100644 src/lib/libcrypto/objects/objects.pl create mode 100644 src/lib/libcrypto/ocsp/ocsp.h create mode 100644 src/lib/libcrypto/ocsp/ocsp_asn.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_cl.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_err.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_ext.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_ht.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_lib.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_prn.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_srv.c create mode 100644 src/lib/libcrypto/ocsp/ocsp_vfy.c create mode 100644 src/lib/libcrypto/opensslv.h create mode 100644 src/lib/libcrypto/ossl_typ.h create mode 100644 src/lib/libcrypto/pem/pem2.h create mode 100644 src/lib/libcrypto/pem/pem_oth.c create mode 100644 src/lib/libcrypto/pem/pem_pk8.c create mode 100644 src/lib/libcrypto/pem/pem_pkey.c create mode 100644 src/lib/libcrypto/pem/pem_x509.c create mode 100644 src/lib/libcrypto/pem/pem_xaux.c create mode 100644 src/lib/libcrypto/pkcs12/p12_add.c create mode 100644 src/lib/libcrypto/pkcs12/p12_asn.c create mode 100644 src/lib/libcrypto/pkcs12/p12_attr.c create mode 100644 src/lib/libcrypto/pkcs12/p12_crpt.c create mode 100644 src/lib/libcrypto/pkcs12/p12_crt.c create mode 100644 src/lib/libcrypto/pkcs12/p12_decr.c create mode 100644 src/lib/libcrypto/pkcs12/p12_init.c create mode 100644 src/lib/libcrypto/pkcs12/p12_key.c create mode 100644 src/lib/libcrypto/pkcs12/p12_kiss.c create mode 100644 src/lib/libcrypto/pkcs12/p12_mutl.c create mode 100644 src/lib/libcrypto/pkcs12/p12_npas.c create mode 100644 src/lib/libcrypto/pkcs12/p12_p8d.c create mode 100644 src/lib/libcrypto/pkcs12/p12_p8e.c create mode 100644 src/lib/libcrypto/pkcs12/p12_utl.c create mode 100644 src/lib/libcrypto/pkcs12/pk12err.c create mode 100644 src/lib/libcrypto/pkcs12/pkcs12.h create mode 100644 src/lib/libcrypto/pkcs7/pk7_asn1.c create mode 100644 src/lib/libcrypto/pkcs7/pk7_attr.c create mode 100644 src/lib/libcrypto/pkcs7/pk7_mime.c create mode 100644 src/lib/libcrypto/pkcs7/pk7_smime.c create mode 100644 src/lib/libcrypto/rand/rand_err.c create mode 100644 src/lib/libcrypto/rand/rand_lib.c create mode 100644 src/lib/libcrypto/rc2/rc2.h create mode 100644 src/lib/libcrypto/rc4/rc4.h create mode 100644 src/lib/libcrypto/rc4/rc4_locl.h create mode 100644 src/lib/libcrypto/rsa/rsa_asn1.c create mode 100644 src/lib/libcrypto/rsa/rsa_chk.c create mode 100644 src/lib/libcrypto/rsa/rsa_oaep.c create mode 100644 src/lib/libcrypto/stack/safestack.h create mode 100644 src/lib/libcrypto/ui/ui.h create mode 100644 src/lib/libcrypto/ui/ui_compat.h create mode 100644 src/lib/libcrypto/ui/ui_err.c create mode 100644 src/lib/libcrypto/ui/ui_lib.c create mode 100644 src/lib/libcrypto/ui/ui_locl.h create mode 100644 src/lib/libcrypto/ui/ui_openssl.c create mode 100644 src/lib/libcrypto/ui/ui_util.c create mode 100644 src/lib/libcrypto/util/mkerr.pl create mode 100644 src/lib/libcrypto/util/mkstack.pl create mode 100644 src/lib/libcrypto/x509/x509_att.c create mode 100644 src/lib/libcrypto/x509/x509_trs.c create mode 100644 src/lib/libcrypto/x509/x509cset.c create mode 100644 src/lib/libcrypto/x509/x509spki.c create mode 100644 src/lib/libcrypto/x509v3/ext_dat.h create mode 100644 src/lib/libcrypto/x509v3/v3_akey.c create mode 100644 src/lib/libcrypto/x509v3/v3_akeya.c create mode 100644 src/lib/libcrypto/x509v3/v3_alt.c create mode 100644 src/lib/libcrypto/x509v3/v3_bcons.c create mode 100644 src/lib/libcrypto/x509v3/v3_bitst.c create mode 100644 src/lib/libcrypto/x509v3/v3_conf.c create mode 100644 src/lib/libcrypto/x509v3/v3_cpols.c create mode 100644 src/lib/libcrypto/x509v3/v3_crld.c create mode 100644 src/lib/libcrypto/x509v3/v3_enum.c create mode 100644 src/lib/libcrypto/x509v3/v3_extku.c create mode 100644 src/lib/libcrypto/x509v3/v3_genn.c create mode 100644 src/lib/libcrypto/x509v3/v3_ia5.c create mode 100644 src/lib/libcrypto/x509v3/v3_info.c create mode 100644 src/lib/libcrypto/x509v3/v3_int.c create mode 100644 src/lib/libcrypto/x509v3/v3_lib.c create mode 100644 src/lib/libcrypto/x509v3/v3_ocsp.c create mode 100644 src/lib/libcrypto/x509v3/v3_pku.c create mode 100644 src/lib/libcrypto/x509v3/v3_prn.c create mode 100644 src/lib/libcrypto/x509v3/v3_purp.c create mode 100644 src/lib/libcrypto/x509v3/v3_skey.c create mode 100644 src/lib/libcrypto/x509v3/v3_sxnet.c create mode 100644 src/lib/libcrypto/x509v3/v3_utl.c create mode 100644 src/lib/libcrypto/x509v3/v3err.c create mode 100644 src/lib/libssl/LICENSE create mode 100644 src/lib/libssl/doc/openssl.cnf create mode 100644 src/lib/libssl/doc/openssl.txt create mode 100644 src/lib/libssl/doc/standards.txt create mode 100644 src/lib/libssl/test/VMSca-response.1 create mode 100644 src/lib/libssl/test/VMSca-response.2 create mode 100644 src/lib/libssl/test/bctest diff --git a/src/lib/libcrypto/aes/README b/src/lib/libcrypto/aes/README new file mode 100644 index 0000000000..0f9620a80e --- /dev/null +++ b/src/lib/libcrypto/aes/README @@ -0,0 +1,3 @@ +This is an OpenSSL-compatible version of AES (also called Rijndael). +aes_core.c is basically the same as rijndael-alg-fst.c but with an +API that looks like the rest of the OpenSSL symmetric cipher suite. diff --git a/src/lib/libcrypto/aes/aes.h b/src/lib/libcrypto/aes/aes.h new file mode 100644 index 0000000000..e8da921ec5 --- /dev/null +++ b/src/lib/libcrypto/aes/aes.h @@ -0,0 +1,109 @@ +/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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. + * ==================================================================== + * + */ + +#ifndef HEADER_AES_H +#define HEADER_AES_H + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +static const int AES_DECRYPT = 0; +static const int AES_ENCRYPT = 1; +/* Because array size can't be a const in C, the following two are macros. + Both sizes are in bytes. */ +#define AES_MAXNR 14 +#define AES_BLOCK_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { + unsigned long rd_key[4 *(AES_MAXNR + 1)]; + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +const char *AES_options(void); + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, int *num); +void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *counter, unsigned int *num); + + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_AES_H */ diff --git a/src/lib/libcrypto/aes/aes_cbc.c b/src/lib/libcrypto/aes/aes_cbc.c new file mode 100644 index 0000000000..3dfd7aba2a --- /dev/null +++ b/src/lib/libcrypto/aes/aes_cbc.c @@ -0,0 +1,89 @@ +/* crypto/aes/aes_cbc.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "aes_locl.h" + +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, const int enc) { + + int n; + unsigned long len = length; + unsigned char tmp[16]; + + assert(in && out && key && ivec); + assert(length % AES_BLOCK_SIZE == 0); + assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); + + if (AES_ENCRYPT == enc) + while (len > 0) { + for(n=0; n < 16; ++n) + tmp[n] = in[n] ^ ivec[n]; + AES_encrypt(tmp, out, key); + memcpy(ivec, out, 16); + len -= 16; + in += 16; + out += 16; + } + else + while (len > 0) { + memcpy(tmp, in, 16); + AES_decrypt(in, out, key); + for(n=0; n < 16; ++n) + out[n] ^= ivec[n]; + memcpy(ivec, tmp, 16); + len -= 16; + in += 16; + out += 16; + } +} diff --git a/src/lib/libcrypto/aes/aes_cfb.c b/src/lib/libcrypto/aes/aes_cfb.c new file mode 100644 index 0000000000..9b2917298a --- /dev/null +++ b/src/lib/libcrypto/aes/aes_cfb.c @@ -0,0 +1,151 @@ +/* crypto/aes/aes_cfb.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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. + * ==================================================================== + * + */ +/* 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 "aes_locl.h" + +/* The input and output encrypted as though 128bit cfb mode is being + * used. The extra state information to record how much of the + * 128bit block we have used is contained in *num; + */ + +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) { + + unsigned int n; + unsigned long l = length; + unsigned char c; + + assert(in && out && key && ivec && num); + + n = *num; + + if (enc) { + while (l--) { + if (n == 0) { + AES_encrypt(ivec, ivec, key); + } + ivec[n] = *(out++) = *(in++) ^ ivec[n]; + n = (n+1) % AES_BLOCK_SIZE; + } + } else { + while (l--) { + if (n == 0) { + AES_decrypt(ivec, ivec, key); + } + c = *(in); + *(out++) = *(in++) ^ ivec[n]; + ivec[n] = c; + n = (n+1) % AES_BLOCK_SIZE; + } + } + + *num=n; +} + diff --git a/src/lib/libcrypto/aes/aes_core.c b/src/lib/libcrypto/aes/aes_core.c new file mode 100644 index 0000000000..937988dd8c --- /dev/null +++ b/src/lib/libcrypto/aes/aes_core.c @@ -0,0 +1,1251 @@ +/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */ +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ + +/* Note: rewritten a little bit to provide error control and an OpenSSL- + compatible API */ + +#include +#include +#include +#include "aes_locl.h" + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits==128) + key->rounds = 10; + else if (bits==192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = AES_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return 0; +} + +/* + * Encrypt a single block + * in and out can overlap + */ +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +/* + * Decrypt a single block + * in and out can overlap + */ +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + diff --git a/src/lib/libcrypto/aes/aes_ctr.c b/src/lib/libcrypto/aes/aes_ctr.c new file mode 100644 index 0000000000..8e800481de --- /dev/null +++ b/src/lib/libcrypto/aes/aes_ctr.c @@ -0,0 +1,117 @@ +/* crypto/aes/aes_ctr.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "aes_locl.h" + +/* NOTE: CTR mode is big-endian. The rest of the AES code + * is endian-neutral. */ + +/* increment counter (128-bit int) by 2^64 */ +static void AES_ctr128_inc(unsigned char *counter) { + unsigned long c; + + /* Grab 3rd dword of counter and increment */ +#ifdef L_ENDIAN + c = GETU32(counter + 8); + c++; + PUTU32(counter + 8, c); +#else + c = GETU32(counter + 4); + c++; + PUTU32(counter + 4, c); +#endif + + /* if no overflow, we're done */ + if (c) + return; + + /* Grab top dword of counter and increment */ +#ifdef L_ENDIAN + c = GETU32(counter + 12); + c++; + PUTU32(counter + 12, c); +#else + c = GETU32(counter + 0); + c++; + PUTU32(counter + 0, c); +#endif + +} + +/* The input encrypted as though 128bit counter mode is being + * used. The extra state information to record how much of the + * 128bit block we have used is contained in *num; + */ +void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *counter, unsigned int *num) { + + unsigned int n; + unsigned long l=length; + unsigned char tmp[AES_BLOCK_SIZE]; + + assert(in && out && key && counter && num); + + n = *num; + + while (l--) { + if (n == 0) { + AES_ctr128_inc(counter); + AES_encrypt(counter, tmp, key); + } + *(out++) = *(in++) ^ tmp[n]; + n = (n+1) % AES_BLOCK_SIZE; + } + + *num=n; +} diff --git a/src/lib/libcrypto/aes/aes_ecb.c b/src/lib/libcrypto/aes/aes_ecb.c new file mode 100644 index 0000000000..1cb2e07d3d --- /dev/null +++ b/src/lib/libcrypto/aes/aes_ecb.c @@ -0,0 +1,67 @@ +/* crypto/aes/aes_ecb.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "aes_locl.h" + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc) { + + assert(in && out && key); + assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); + + if (AES_ENCRYPT == enc) + AES_encrypt(in, out, key); + else + AES_decrypt(in, out, key); +} + diff --git a/src/lib/libcrypto/aes/aes_locl.h b/src/lib/libcrypto/aes/aes_locl.h new file mode 100644 index 0000000000..541d1d6e84 --- /dev/null +++ b/src/lib/libcrypto/aes/aes_locl.h @@ -0,0 +1,88 @@ +/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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. + * ==================================================================== + * + */ + +#ifndef HEADER_AES_LOCL_H +#define HEADER_AES_LOCL_H + +#include + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +#include +#include + +#if defined(__STDC__) || defined(OPENSSL_SYS_VMS) || defined(M_XENIX) || defined(OPENSSL_SYS_MSDOS) +#include +#endif + +#ifdef _MSC_VER +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +typedef unsigned long u32; +typedef unsigned short u16; +typedef unsigned char u8; + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +/* This controls loop-unrolling in aes_core.c */ +#undef FULL_UNROLL + +#endif /* !HEADER_AES_LOCL_H */ diff --git a/src/lib/libcrypto/aes/aes_misc.c b/src/lib/libcrypto/aes/aes_misc.c new file mode 100644 index 0000000000..090def25d5 --- /dev/null +++ b/src/lib/libcrypto/aes/aes_misc.c @@ -0,0 +1,64 @@ +/* crypto/aes/aes_misc.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "aes_locl.h" + +const char *AES_version="AES" OPENSSL_VERSION_PTEXT; + +const char *AES_options(void) { +#ifdef FULL_UNROLL + return "aes(full)"; +#else + return "aes(partial)"; +#endif +} diff --git a/src/lib/libcrypto/aes/aes_ofb.c b/src/lib/libcrypto/aes/aes_ofb.c new file mode 100644 index 0000000000..e33bdaea28 --- /dev/null +++ b/src/lib/libcrypto/aes/aes_ofb.c @@ -0,0 +1,136 @@ +/* crypto/aes/aes_ofb.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== + * Copyright (c) 1998-2002 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. + * ==================================================================== + * + */ +/* 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 "aes_locl.h" + +/* The input and output encrypted as though 128bit ofb mode is being + * used. The extra state information to record how much of the + * 128bit block we have used is contained in *num; + */ +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, int *num) { + + unsigned int n; + unsigned long l=length; + + assert(in && out && key && ivec && num); + + n = *num; + + while (l--) { + if (n == 0) { + AES_encrypt(ivec, ivec, key); + } + *(out++) = *(in++) ^ ivec[n]; + n = (n+1) % AES_BLOCK_SIZE; + } + + *num=n; +} diff --git a/src/lib/libcrypto/asn1/a_enum.c b/src/lib/libcrypto/asn1/a_enum.c new file mode 100644 index 0000000000..9239ecc439 --- /dev/null +++ b/src/lib/libcrypto/asn1/a_enum.c @@ -0,0 +1,326 @@ +/* crypto/asn1/a_enum.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 + +/* + * Code for ENUMERATED type: identical to INTEGER apart from a different tag. + * for comments on encoding see a_int.c + */ + +int i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **pp) + { + int pad=0,ret,r,i,t; + unsigned char *p,*n,pb=0; + + if ((a == NULL) || (a->data == NULL)) return(0); + t=a->type; + if (a->length == 0) + ret=1; + else + { + ret=a->length; + i=a->data[0]; + if ((t == V_ASN1_ENUMERATED) && (i > 127)) { + pad=1; + pb=0; + } else if(t == V_ASN1_NEG_ENUMERATED) { + if(i>128) { + pad=1; + pb=0xFF; + } else if(i == 128) { + for(i = 1; i < a->length; i++) if(a->data[i]) { + pad=1; + pb=0xFF; + break; + } + } + } + ret+=pad; + } + r=ASN1_object_size(0,ret,V_ASN1_ENUMERATED); + if (pp == NULL) return(r); + p= *pp; + + ASN1_put_object(&p,0,ret,V_ASN1_ENUMERATED,V_ASN1_UNIVERSAL); + if (pad) *(p++)=pb; + if (a->length == 0) + *(p++)=0; + else if (t == V_ASN1_ENUMERATED) + { + memcpy(p,a->data,(unsigned int)a->length); + p+=a->length; + } + else { + /* Begin at the end of the encoding */ + n=a->data + a->length - 1; + p += a->length - 1; + i = a->length; + /* Copy zeros to destination as long as source is zero */ + while(!*n) { + *(p--) = 0; + n--; + i--; + } + /* Complement and increment next octet */ + *(p--) = ((*(n--)) ^ 0xff) + 1; + i--; + /* Complement any octets left */ + for(;i > 0; i--) *(p--) = *(n--) ^ 0xff; + p += a->length; + } + + *pp=p; + return(r); + } + +ASN1_ENUMERATED *d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, unsigned char **pp, + long length) + { + ASN1_ENUMERATED *ret=NULL; + unsigned char *p,*to,*s; + long len; + int inf,tag,xclass; + int i; + + if ((a == NULL) || ((*a) == NULL)) + { + if ((ret=ASN1_ENUMERATED_new()) == NULL) return(NULL); + ret->type=V_ASN1_ENUMERATED; + } + else + ret=(*a); + + p= *pp; + inf=ASN1_get_object(&p,&len,&tag,&xclass,length); + if (inf & 0x80) + { + i=ASN1_R_BAD_OBJECT_HEADER; + goto err; + } + + if (tag != V_ASN1_ENUMERATED) + { + i=ASN1_R_EXPECTING_AN_ENUMERATED; + goto err; + } + + /* We must Malloc stuff, even for 0 bytes otherwise it + * signifies a missing NULL parameter. */ + s=(unsigned char *)Malloc((int)len+1); + if (s == NULL) + { + i=ERR_R_MALLOC_FAILURE; + goto err; + } + to=s; + if (*p & 0x80) /* a negative number */ + { + ret->type=V_ASN1_NEG_ENUMERATED; + if ((*p == 0xff) && (len != 1)) { + p++; + len--; + } + i = len; + p += i - 1; + to += i - 1; + while((!*p) && i) { + *(to--) = 0; + i--; + p--; + } + if(!i) { + *s = 1; + s[len] = 0; + p += len; + len++; + } else { + *(to--) = (*(p--) ^ 0xff) + 1; + i--; + for(;i > 0; i--) *(to--) = *(p--) ^ 0xff; + p += len; + } + } else { + ret->type=V_ASN1_ENUMERATED; + if ((*p == 0) && (len != 1)) + { + p++; + len--; + } + memcpy(s,p,(int)len); + p+=len; + } + + if (ret->data != NULL) Free((char *)ret->data); + ret->data=s; + ret->length=(int)len; + if (a != NULL) (*a)=ret; + *pp=p; + return(ret); +err: + ASN1err(ASN1_F_D2I_ASN1_ENUMERATED,i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + ASN1_ENUMERATED_free(ret); + return(NULL); + } + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) + { + int i,j,k; + unsigned char buf[sizeof(long)+1]; + long d; + + a->type=V_ASN1_ENUMERATED; + if (a->length < (sizeof(long)+1)) + { + if (a->data != NULL) + Free((char *)a->data); + if ((a->data=(unsigned char *)Malloc(sizeof(long)+1)) != NULL) + memset((char *)a->data,0,sizeof(long)+1); + } + if (a->data == NULL) + { + ASN1err(ASN1_F_ASN1_ENUMERATED_SET,ERR_R_MALLOC_FAILURE); + return(0); + } + d=v; + if (d < 0) + { + d= -d; + a->type=V_ASN1_NEG_ENUMERATED; + } + + for (i=0; i>=8; + } + j=0; + for (k=i-1; k >=0; k--) + a->data[j++]=buf[k]; + a->length=j; + return(1); + } + +long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a) + { + int neg=0,i; + long r=0; + + if (a == NULL) return(0L); + i=a->type; + if (i == V_ASN1_NEG_ENUMERATED) + neg=1; + else if (i != V_ASN1_ENUMERATED) + return(0); + + if (a->length > sizeof(long)) + { + /* hmm... a bit ugly */ + return(0xffffffffL); + } + if (a->data == NULL) + return(0); + + for (i=0; ilength; i++) + { + r<<=8; + r|=(unsigned char)a->data[i]; + } + if (neg) r= -r; + return(r); + } + +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai) + { + ASN1_ENUMERATED *ret; + int len,j; + + if (ai == NULL) + ret=ASN1_ENUMERATED_new(); + else + ret=ai; + if (ret == NULL) + { + ASN1err(ASN1_F_BN_TO_ASN1_ENUMERATED,ERR_R_NESTED_ASN1_ERROR); + goto err; + } + if(bn->neg) ret->type = V_ASN1_NEG_ENUMERATED; + else ret->type=V_ASN1_ENUMERATED; + j=BN_num_bits(bn); + len=((j == 0)?0:((j/8)+1)); + ret->data=(unsigned char *)Malloc(len+4); + ret->length=BN_bn2bin(bn,ret->data); + return(ret); +err: + if (ret != ai) ASN1_ENUMERATED_free(ret); + return(NULL); + } + +BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn) + { + BIGNUM *ret; + + if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL) + ASN1err(ASN1_F_ASN1_ENUMERATED_TO_BN,ASN1_R_BN_LIB); + if(ai->type == V_ASN1_NEG_ENUMERATED) bn->neg = 1; + return(ret); + } diff --git a/src/lib/libcrypto/asn1/a_mbstr.c b/src/lib/libcrypto/asn1/a_mbstr.c new file mode 100644 index 0000000000..7a710d5459 --- /dev/null +++ b/src/lib/libcrypto/asn1/a_mbstr.c @@ -0,0 +1,390 @@ +/* a_mbstr.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 +#include "cryptlib.h" +#include + +static int traverse_string(const unsigned char *p, int len, int inform, + int (*rfunc)(unsigned long value, void *in), void *arg); +static int in_utf8(unsigned long value, void *arg); +static int out_utf8(unsigned long value, void *arg); +static int type_str(unsigned long value, void *arg); +static int cpy_asc(unsigned long value, void *arg); +static int cpy_bmp(unsigned long value, void *arg); +static int cpy_univ(unsigned long value, void *arg); +static int cpy_utf8(unsigned long value, void *arg); +static int is_printable(unsigned long value); + +/* These functions take a string in UTF8, ASCII or multibyte form and + * a mask of permissible ASN1 string types. It then works out the minimal + * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) + * and creates a string of the correct type with the supplied data. + * Yes this is horrible: it has to be :-( + * The 'ncopy' form checks minimum and maximum size limits too. + */ + +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask) +{ + return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); +} + +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize) +{ + int str_type; + int ret; + int outform, outlen; + ASN1_STRING *dest; + unsigned char *p; + int nchar; + char strbuf[32]; + int (*cpyfunc)(unsigned long,void *) = NULL; + if(len == -1) len = strlen((const char *)in); + if(!mask) mask = DIRSTRING_TYPE; + + /* First do a string check and work out the number of characters */ + switch(inform) { + + case MBSTRING_BMP: + if(len & 1) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, + ASN1_R_INVALID_BMPSTRING_LENGTH); + return -1; + } + nchar = len >> 1; + break; + + case MBSTRING_UNIV: + if(len & 3) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, + ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); + return -1; + } + nchar = len >> 2; + break; + + case MBSTRING_UTF8: + nchar = 0; + /* This counts the characters and does utf8 syntax checking */ + ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); + if(ret < 0) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, + ASN1_R_INVALID_UTF8STRING); + return -1; + } + break; + + case MBSTRING_ASC: + nchar = len; + break; + + default: + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_UNKNOWN_FORMAT); + return -1; + } + + if((minsize > 0) && (nchar < minsize)) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_STRING_TOO_SHORT); + sprintf(strbuf, "%ld", minsize); + ERR_add_error_data(2, "minsize=", strbuf); + return -1; + } + + if((maxsize > 0) && (nchar > maxsize)) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_STRING_TOO_LONG); + sprintf(strbuf, "%ld", maxsize); + ERR_add_error_data(2, "maxsize=", strbuf); + return -1; + } + + /* Now work out minimal type (if any) */ + if(traverse_string(in, len, inform, type_str, &mask) < 0) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_ILLEGAL_CHARACTERS); + return -1; + } + + + /* Now work out output format and string type */ + outform = MBSTRING_ASC; + if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING; + else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING; + else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING; + else if(mask & B_ASN1_BMPSTRING) { + str_type = V_ASN1_BMPSTRING; + outform = MBSTRING_BMP; + } else if(mask & B_ASN1_UNIVERSALSTRING) { + str_type = V_ASN1_UNIVERSALSTRING; + outform = MBSTRING_UNIV; + } else { + str_type = V_ASN1_UTF8STRING; + outform = MBSTRING_UTF8; + } + if(!out) return str_type; + if(*out) { + dest = *out; + if(dest->data) { + dest->length = 0; + Free(dest->data); + dest->data = NULL; + } + dest->type = str_type; + } else { + dest = ASN1_STRING_type_new(str_type); + if(!dest) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY, + ERR_R_MALLOC_FAILURE); + return -1; + } + *out = dest; + } + /* If both the same type just copy across */ + if(inform == outform) { + if(!ASN1_STRING_set(dest, in, len)) { + ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE); + return -1; + } + return str_type; + } + + /* Work out how much space the destination will need */ + switch(outform) { + case MBSTRING_ASC: + outlen = nchar; + cpyfunc = cpy_asc; + break; + + case MBSTRING_BMP: + outlen = nchar << 1; + cpyfunc = cpy_bmp; + break; + + case MBSTRING_UNIV: + outlen = nchar << 2; + cpyfunc = cpy_univ; + break; + + case MBSTRING_UTF8: + outlen = 0; + traverse_string(in, len, inform, out_utf8, &outlen); + cpyfunc = cpy_utf8; + break; + } + if(!(p = Malloc(outlen + 1))) { + ASN1_STRING_free(dest); + ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE); + return -1; + } + dest->length = outlen; + dest->data = p; + p[outlen] = 0; + traverse_string(in, len, inform, cpyfunc, &p); + return str_type; +} + +/* This function traverses a string and passes the value of each character + * to an optional function along with a void * argument. + */ + +static int traverse_string(const unsigned char *p, int len, int inform, + int (*rfunc)(unsigned long value, void *in), void *arg) +{ + unsigned long value; + int ret; + while(len) { + if(inform == MBSTRING_ASC) { + value = *p++; + len--; + } else if(inform == MBSTRING_BMP) { + value = *p++ << 8; + value |= *p++; + len -= 2; + } else if(inform == MBSTRING_UNIV) { + value = *p++ << 24; + value |= *p++ << 16; + value |= *p++ << 8; + value |= *p++; + len -= 4; + } else { + ret = UTF8_getc(p, len, &value); + if(ret < 0) return -1; + len -= ret; + p += ret; + } + if(rfunc) { + ret = rfunc(value, arg); + if(ret <= 0) return ret; + } + } + return 1; +} + +/* Various utility functions for traverse_string */ + +/* Just count number of characters */ + +static int in_utf8(unsigned long value, void *arg) +{ + int *nchar; + nchar = arg; + (*nchar)++; + return 1; +} + +/* Determine size of output as a UTF8 String */ + +static int out_utf8(unsigned long value, void *arg) +{ + long *outlen; + outlen = arg; + *outlen += UTF8_putc(NULL, -1, value); + return 1; +} + +/* Determine the "type" of a string: check each character against a + * supplied "mask". + */ + +static int type_str(unsigned long value, void *arg) +{ + unsigned long types; + types = *((unsigned long *)arg); + if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value)) + types &= ~B_ASN1_PRINTABLESTRING; + if((types & B_ASN1_IA5STRING) && (value > 127)) + types &= ~B_ASN1_IA5STRING; + if((types & B_ASN1_T61STRING) && (value > 0xff)) + types &= ~B_ASN1_T61STRING; + if((types & B_ASN1_BMPSTRING) && (value > 0xffff)) + types &= ~B_ASN1_BMPSTRING; + if(!types) return -1; + *((unsigned long *)arg) = types; + return 1; +} + +/* Copy one byte per character ASCII like strings */ + +static int cpy_asc(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q = (unsigned char) value; + (*p)++; + return 1; +} + +/* Copy two byte per character BMPStrings */ + +static int cpy_bmp(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q++ = (unsigned char) ((value >> 8) & 0xff); + *q = (unsigned char) (value & 0xff); + *p += 2; + return 1; +} + +/* Copy four byte per character UniversalStrings */ + +static int cpy_univ(unsigned long value, void *arg) +{ + unsigned char **p, *q; + p = arg; + q = *p; + *q++ = (unsigned char) ((value >> 24) & 0xff); + *q++ = (unsigned char) ((value >> 16) & 0xff); + *q++ = (unsigned char) ((value >> 8) & 0xff); + *q = (unsigned char) (value & 0xff); + *p += 4; + return 1; +} + +/* Copy to a UTF8String */ + +static int cpy_utf8(unsigned long value, void *arg) +{ + unsigned char **p; + int ret; + p = arg; + /* We already know there is enough room so pass 0xff as the length */ + ret = UTF8_putc(*p, 0xff, value); + *p += ret; + return 1; +} + +/* Return 1 if the character is permitted in a PrintableString */ +static int is_printable(unsigned long value) +{ + int ch; + if(value > 0x7f) return 0; + ch = (int) value; + /* Note: we can't use 'isalnum' because certain accented + * characters may count as alphanumeric in some environments. + */ + if((ch >= 'a') && (ch <= 'z')) return 1; + if((ch >= 'A') && (ch <= 'Z')) return 1; + if((ch >= '0') && (ch <= '9')) return 1; + if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1; + return 0; +} diff --git a/src/lib/libcrypto/asn1/a_strex.c b/src/lib/libcrypto/asn1/a_strex.c new file mode 100644 index 0000000000..569b811998 --- /dev/null +++ b/src/lib/libcrypto/asn1/a_strex.c @@ -0,0 +1,533 @@ +/* a_strex.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include + +#include "charmap.h" + +/* ASN1_STRING_print_ex() and X509_NAME_print_ex(). + * Enhanced string and name printing routines handling + * multibyte characters, RFC2253 and a host of other + * options. + */ + + +#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253) + + +/* Three IO functions for sending data to memory, a BIO and + * and a FILE pointer. + */ + +int send_mem_chars(void *arg, const void *buf, int len) +{ + unsigned char **out = arg; + if(!out) return 1; + memcpy(*out, buf, len); + *out += len; + return 1; +} + +int send_bio_chars(void *arg, const void *buf, int len) +{ + if(!arg) return 1; + if(BIO_write(arg, buf, len) != len) return 0; + return 1; +} + +int send_fp_chars(void *arg, const void *buf, int len) +{ + if(!arg) return 1; + if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0; + return 1; +} + +typedef int char_io(void *arg, const void *buf, int len); + +/* This function handles display of + * strings, one character at a time. + * It is passed an unsigned long for each + * character because it could come from 2 or even + * 4 byte forms. + */ + +static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg) +{ + unsigned char chflgs, chtmp; + char tmphex[11]; + if(c > 0xffff) { + BIO_snprintf(tmphex, 11, "\\W%08lX", c); + if(!io_ch(arg, tmphex, 10)) return -1; + return 10; + } + if(c > 0xff) { + BIO_snprintf(tmphex, 11, "\\U%04lX", c); + if(!io_ch(arg, tmphex, 6)) return -1; + return 6; + } + chtmp = (unsigned char)c; + if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB; + else chflgs = char_type[chtmp] & flags; + if(chflgs & CHARTYPE_BS_ESC) { + /* If we don't escape with quotes, signal we need quotes */ + if(chflgs & ASN1_STRFLGS_ESC_QUOTE) { + if(do_quotes) *do_quotes = 1; + if(!io_ch(arg, &chtmp, 1)) return -1; + return 1; + } + if(!io_ch(arg, "\\", 1)) return -1; + if(!io_ch(arg, &chtmp, 1)) return -1; + return 2; + } + if(chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) { + BIO_snprintf(tmphex, 11, "\\%02X", chtmp); + if(!io_ch(arg, tmphex, 3)) return -1; + return 3; + } + if(!io_ch(arg, &chtmp, 1)) return -1; + return 1; +} + +#define BUF_TYPE_WIDTH_MASK 0x7 +#define BUF_TYPE_CONVUTF8 0x8 + +/* This function sends each character in a buffer to + * do_esc_char(). It interprets the content formats + * and converts to or from UTF8 as appropriate. + */ + +static int do_buf(unsigned char *buf, int buflen, + int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg) +{ + int i, outlen, len; + unsigned char orflags, *p, *q; + unsigned long c; + p = buf; + q = buf + buflen; + outlen = 0; + while(p != q) { + if(p == buf) orflags = CHARTYPE_FIRST_ESC_2253; + else orflags = 0; + switch(type & BUF_TYPE_WIDTH_MASK) { + case 4: + c = ((unsigned long)*p++) << 24; + c |= ((unsigned long)*p++) << 16; + c |= ((unsigned long)*p++) << 8; + c |= *p++; + break; + + case 2: + c = ((unsigned long)*p++) << 8; + c |= *p++; + break; + + case 1: + c = *p++; + break; + + case 0: + i = UTF8_getc(p, buflen, &c); + if(i < 0) return -1; /* Invalid UTF8String */ + p += i; + break; + } + if (p == q) orflags = CHARTYPE_LAST_ESC_2253; + if(type & BUF_TYPE_CONVUTF8) { + unsigned char utfbuf[6]; + int utflen; + utflen = UTF8_putc(utfbuf, 6, c); + for(i = 0; i < utflen; i++) { + /* We don't need to worry about setting orflags correctly + * because if utflen==1 its value will be correct anyway + * otherwise each character will be > 0x7f and so the + * character will never be escaped on first and last. + */ + len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg); + if(len < 0) return -1; + outlen += len; + } + } else { + len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg); + if(len < 0) return -1; + outlen += len; + } + } + return outlen; +} + +/* This function hex dumps a buffer of characters */ + +static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen) +{ + const static char hexdig[] = "0123456789ABCDEF"; + unsigned char *p, *q; + char hextmp[2]; + if(arg) { + p = buf; + q = buf + buflen; + while(p != q) { + hextmp[0] = hexdig[*p >> 4]; + hextmp[1] = hexdig[*p & 0xf]; + if(!io_ch(arg, hextmp, 2)) return -1; + p++; + } + } + return buflen << 1; +} + +/* "dump" a string. This is done when the type is unknown, + * or the flags request it. We can either dump the content + * octets or the entire DER encoding. This uses the RFC2253 + * #01234 format. + */ + +int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str) +{ + /* Placing the ASN1_STRING in a temp ASN1_TYPE allows + * the DER encoding to readily obtained + */ + ASN1_TYPE t; + unsigned char *der_buf, *p; + int outlen, der_len; + + if(!io_ch(arg, "#", 1)) return -1; + /* If we don't dump DER encoding just dump content octets */ + if(!(lflags & ASN1_STRFLGS_DUMP_DER)) { + outlen = do_hex_dump(io_ch, arg, str->data, str->length); + if(outlen < 0) return -1; + return outlen + 1; + } + t.type = str->type; + t.value.ptr = (char *)str; + der_len = i2d_ASN1_TYPE(&t, NULL); + der_buf = OPENSSL_malloc(der_len); + if(!der_buf) return -1; + p = der_buf; + i2d_ASN1_TYPE(&t, &p); + outlen = do_hex_dump(io_ch, arg, der_buf, der_len); + OPENSSL_free(der_buf); + if(outlen < 0) return -1; + return outlen + 1; +} + +/* Lookup table to convert tags to character widths, + * 0 = UTF8 encoded, -1 is used for non string types + * otherwise it is the number of bytes per character + */ + +const static char tag2nbyte[] = { + -1, -1, -1, -1, -1, /* 0-4 */ + -1, -1, -1, -1, -1, /* 5-9 */ + -1, -1, 0, -1, /* 10-13 */ + -1, -1, -1, -1, /* 15-17 */ + -1, 1, 1, /* 18-20 */ + -1, 1, -1,-1, /* 21-24 */ + -1, 1, -1, /* 25-27 */ + 4, -1, 2 /* 28-30 */ +}; + +#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB) + +/* This is the main function, print out an + * ASN1_STRING taking note of various escape + * and display options. Returns number of + * characters written or -1 if an error + * occurred. + */ + +static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STRING *str) +{ + int outlen, len; + int type; + char quotes; + unsigned char flags; + quotes = 0; + /* Keep a copy of escape flags */ + flags = (unsigned char)(lflags & ESC_FLAGS); + + type = str->type; + + outlen = 0; + + + if(lflags & ASN1_STRFLGS_SHOW_TYPE) { + const char *tagname; + tagname = ASN1_tag2str(type); + outlen += strlen(tagname); + if(!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) return -1; + outlen++; + } + + /* Decide what to do with type, either dump content or display it */ + + /* Dump everything */ + if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1; + /* Ignore the string type */ + else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1; + else { + /* Else determine width based on type */ + if((type > 0) && (type < 31)) type = tag2nbyte[type]; + else type = -1; + if((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1; + } + + if(type == -1) { + len = do_dump(lflags, io_ch, arg, str); + if(len < 0) return -1; + outlen += len; + return outlen; + } + + if(lflags & ASN1_STRFLGS_UTF8_CONVERT) { + /* Note: if string is UTF8 and we want + * to convert to UTF8 then we just interpret + * it as 1 byte per character to avoid converting + * twice. + */ + if(!type) type = 1; + else type |= BUF_TYPE_CONVUTF8; + } + + len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL); + if(outlen < 0) return -1; + outlen += len; + if(quotes) outlen += 2; + if(!arg) return outlen; + if(quotes && !io_ch(arg, "\"", 1)) return -1; + do_buf(str->data, str->length, type, flags, NULL, io_ch, arg); + if(quotes && !io_ch(arg, "\"", 1)) return -1; + return outlen; +} + +/* Used for line indenting: print 'indent' spaces */ + +static int do_indent(char_io *io_ch, void *arg, int indent) +{ + int i; + for(i = 0; i < indent; i++) + if(!io_ch(arg, " ", 1)) return 0; + return 1; +} + + +static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, + int indent, unsigned long flags) +{ + int i, prev = -1, orflags, cnt; + int fn_opt, fn_nid; + ASN1_OBJECT *fn; + ASN1_STRING *val; + X509_NAME_ENTRY *ent; + char objtmp[80]; + const char *objbuf; + int outlen, len; + char *sep_dn, *sep_mv, *sep_eq; + int sep_dn_len, sep_mv_len, sep_eq_len; + if(indent < 0) indent = 0; + outlen = indent; + if(!do_indent(io_ch, arg, indent)) return -1; + switch (flags & XN_FLAG_SEP_MASK) + { + case XN_FLAG_SEP_MULTILINE: + sep_dn = "\n"; + sep_dn_len = 1; + sep_mv = " + "; + sep_mv_len = 3; + break; + + case XN_FLAG_SEP_COMMA_PLUS: + sep_dn = ","; + sep_dn_len = 1; + sep_mv = "+"; + sep_mv_len = 1; + indent = 0; + break; + + case XN_FLAG_SEP_CPLUS_SPC: + sep_dn = ", "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + case XN_FLAG_SEP_SPLUS_SPC: + sep_dn = "; "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + default: + return -1; + } + + if(flags & XN_FLAG_SPC_EQ) { + sep_eq = " = "; + sep_eq_len = 3; + } else { + sep_eq = "="; + sep_eq_len = 1; + } + + fn_opt = flags & XN_FLAG_FN_MASK; + + cnt = X509_NAME_entry_count(n); + for(i = 0; i < cnt; i++) { + if(flags & XN_FLAG_DN_REV) + ent = X509_NAME_get_entry(n, cnt - i - 1); + else ent = X509_NAME_get_entry(n, i); + if(prev != -1) { + if(prev == ent->set) { + if(!io_ch(arg, sep_mv, sep_mv_len)) return -1; + outlen += sep_mv_len; + } else { + if(!io_ch(arg, sep_dn, sep_dn_len)) return -1; + outlen += sep_dn_len; + if(!do_indent(io_ch, arg, indent)) return -1; + outlen += indent; + } + } + prev = ent->set; + fn = X509_NAME_ENTRY_get_object(ent); + val = X509_NAME_ENTRY_get_data(ent); + fn_nid = OBJ_obj2nid(fn); + if(fn_opt != XN_FLAG_FN_NONE) { + int objlen; + if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) { + OBJ_obj2txt(objtmp, 80, fn, 1); + objbuf = objtmp; + } else { + if(fn_opt == XN_FLAG_FN_SN) + objbuf = OBJ_nid2sn(fn_nid); + else if(fn_opt == XN_FLAG_FN_LN) + objbuf = OBJ_nid2ln(fn_nid); + else objbuf = ""; + } + objlen = strlen(objbuf); + if(!io_ch(arg, objbuf, objlen)) return -1; + if(!io_ch(arg, sep_eq, sep_eq_len)) return -1; + outlen += objlen + sep_eq_len; + } + /* If the field name is unknown then fix up the DER dump + * flag. We might want to limit this further so it will + * DER dump on anything other than a few 'standard' fields. + */ + if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) + orflags = ASN1_STRFLGS_DUMP_ALL; + else orflags = 0; + + len = do_print_ex(io_ch, arg, flags | orflags, val); + if(len < 0) return -1; + outlen += len; + } + return outlen; +} + +/* Wrappers round the main functions */ + +int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags) +{ + return do_name_ex(send_bio_chars, out, nm, indent, flags); +} + + +int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags) +{ + return do_name_ex(send_fp_chars, fp, nm, indent, flags); +} + +int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags) +{ + return do_print_ex(send_bio_chars, out, flags, str); +} + + +int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags) +{ + return do_print_ex(send_fp_chars, fp, flags, str); +} + +/* Utility function: convert any string type to UTF8, returns number of bytes + * in output string or a negative error code + */ + +int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) +{ + ASN1_STRING stmp, *str = &stmp; + int mbflag, type, ret; + if(!*out || !in) return -1; + type = in->type; + if((type < 0) || (type > 30)) return -1; + mbflag = tag2nbyte[type]; + if(mbflag == -1) return -1; + mbflag |= MBSTRING_FLAG; + stmp.data = NULL; + ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING); + if(ret < 0) return ret; + if(out) *out = stmp.data; + return stmp.length; +} diff --git a/src/lib/libcrypto/asn1/a_strnid.c b/src/lib/libcrypto/asn1/a_strnid.c new file mode 100644 index 0000000000..ab8417ffab --- /dev/null +++ b/src/lib/libcrypto/asn1/a_strnid.c @@ -0,0 +1,247 @@ +/* a_strnid.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 +#include "cryptlib.h" +#include +#include + + +static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; +static void st_free(ASN1_STRING_TABLE *tbl); +static int sk_table_cmp(ASN1_STRING_TABLE **a, ASN1_STRING_TABLE **b); +static int table_cmp(ASN1_STRING_TABLE *a, ASN1_STRING_TABLE *b); + + +/* This is the global mask for the mbstring functions: this is use to + * mask out certain types (such as BMPString and UTF8String) because + * certain software (e.g. Netscape) has problems with them. + */ + +static unsigned long global_mask = 0xFFFFFFFFL; + +void ASN1_STRING_set_default_mask(unsigned long mask) +{ + global_mask = mask; +} + +unsigned long ASN1_STRING_get_default_mask(void) +{ + return global_mask; +} + +/* This function sets the default to various "flavours" of configuration. + * based on an ASCII string. Currently this is: + * MASK:XXXX : a numerical mask value. + * nobmp : Don't use BMPStrings (just Printable, T61). + * pkix : PKIX recommendation in RFC2459. + * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). + * default: the default value, Printable, T61, BMP. + */ + +int ASN1_STRING_set_default_mask_asc(char *p) +{ + unsigned long mask; + char *end; + if(!strncmp(p, "MASK:", 5)) { + if(!p[5]) return 0; + mask = strtoul(p + 5, &end, 0); + if(*end) return 0; + } else if(!strcmp(p, "nombstr")) + mask = ~(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING); + else if(!strcmp(p, "pkix")) + mask = ~B_ASN1_T61STRING; + else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING; + else if(!strcmp(p, "default")) + mask = 0xFFFFFFFFL; + else return 0; + ASN1_STRING_set_default_mask(mask); + return 1; +} + +/* The following function generates an ASN1_STRING based on limits in a table. + * Frequently the types and length of an ASN1_STRING are restricted by a + * corresponding OID. For example certificates and certificate requests. + */ + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, + int inlen, int inform, int nid) +{ + ASN1_STRING_TABLE *tbl; + ASN1_STRING *str = NULL; + unsigned long mask; + int ret; + if(!out) out = &str; + tbl = ASN1_STRING_TABLE_get(nid); + if(tbl) { + mask = tbl->mask; + if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask; + ret = ASN1_mbstring_ncopy(out, in, inlen, inform, tbl->mask, + tbl->minsize, tbl->maxsize); + } else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask); + if(ret <= 0) return NULL; + return *out; +} + +/* Now the tables and helper functions for the 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 + +/* This table must be kept in NID order */ + +static ASN1_STRING_TABLE tbl_standard[] = { +{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, +{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, +{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, +{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, +{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, +{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0}, +{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK}, +{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, +{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, +{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, +{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, +{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, +{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, +{NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, +{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK} +}; + +static int sk_table_cmp(ASN1_STRING_TABLE **a, ASN1_STRING_TABLE **b) +{ + return (*a)->nid - (*b)->nid; +} + +static int table_cmp(ASN1_STRING_TABLE *a, ASN1_STRING_TABLE *b) +{ + return a->nid - b->nid; +} + +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) +{ + int idx; + ASN1_STRING_TABLE *ttmp; + ASN1_STRING_TABLE fnd; + fnd.nid = nid; + ttmp = (ASN1_STRING_TABLE *) OBJ_bsearch((char *)&fnd, + (char *)tbl_standard, + sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), + sizeof(ASN1_STRING_TABLE), (int(*)())table_cmp); + if(ttmp) return ttmp; + if(!stable) return NULL; + idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); + if(idx < 0) return NULL; + return sk_ASN1_STRING_TABLE_value(stable, idx); +} + +int ASN1_STRING_TABLE_add(int nid, + long minsize, long maxsize, unsigned long mask, + unsigned long flags) +{ + ASN1_STRING_TABLE *tmp; + char new_nid = 0; + flags &= ~STABLE_FLAGS_MALLOC; + if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); + if(!stable) { + ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); + return 0; + } + if(!(tmp = ASN1_STRING_TABLE_get(nid))) { + tmp = Malloc(sizeof(ASN1_STRING_TABLE)); + if(!tmp) { + ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, + ERR_R_MALLOC_FAILURE); + return 0; + } + tmp->flags = flags | STABLE_FLAGS_MALLOC; + tmp->nid = nid; + new_nid = 1; + } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; + if(minsize != -1) tmp->minsize = minsize; + if(maxsize != -1) tmp->maxsize = maxsize; + tmp->mask = mask; + if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp); + return 1; +} + +void ASN1_STRING_TABLE_cleanup(void) +{ + STACK_OF(ASN1_STRING_TABLE) *tmp; + tmp = stable; + if(!tmp) return; + stable = NULL; + sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); +} + +static void st_free(ASN1_STRING_TABLE *tbl) +{ + if(tbl->flags & STABLE_FLAGS_MALLOC) Free(tbl); +} + +IMPLEMENT_STACK_OF(ASN1_STRING_TABLE) diff --git a/src/lib/libcrypto/asn1/a_time.c b/src/lib/libcrypto/asn1/a_time.c new file mode 100644 index 0000000000..c1690a5694 --- /dev/null +++ b/src/lib/libcrypto/asn1/a_time.c @@ -0,0 +1,123 @@ +/* crypto/asn1/a_time.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 + * 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). + * + */ + + +/* This is an implementation of the ASN1 Time structure which is: + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + * written by Steve Henson. + */ + +#include +#include +#include "cryptlib.h" +#include + +int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) + { +#ifdef CHARSET_EBCDIC + /* KLUDGE! We convert to ascii before writing DER */ + char tmp[24]; + ASN1_STRING tmpstr; + + if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) { + int len; + + tmpstr = *(ASN1_STRING *)a; + len = tmpstr.length; + ebcdic2ascii(tmp, tmpstr.data, (len >= sizeof tmp) ? sizeof tmp : len); + tmpstr.data = tmp; + a = (ASN1_GENERALIZEDTIME *) &tmpstr; + } +#endif + if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME) + return(i2d_ASN1_bytes((ASN1_STRING *)a,pp, + a->type ,V_ASN1_UNIVERSAL)); + ASN1err(ASN1_F_I2D_ASN1_TIME,ASN1_R_EXPECTING_A_TIME); + return -1; + } + + +ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **a, unsigned char **pp, long length) + { + unsigned char tag; + tag = **pp & ~V_ASN1_CONSTRUCTED; + if(tag == (V_ASN1_UTCTIME|V_ASN1_UNIVERSAL)) + return d2i_ASN1_UTCTIME(a, pp, length); + if(tag == (V_ASN1_GENERALIZEDTIME|V_ASN1_UNIVERSAL)) + return d2i_ASN1_GENERALIZEDTIME(a, pp, length); + ASN1err(ASN1_F_D2I_ASN1_TIME,ASN1_R_EXPECTING_A_TIME); + return(NULL); + } + + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) + { + struct tm *ts; +#if defined(THREADS) && !defined(WIN32) + struct tm data; +#endif + +#if defined(THREADS) && !defined(WIN32) + gmtime_r(&t,&data); + ts=&data; /* should return &data, but doesn't on some systems, so we don't even look at the return value */ +#else + ts=gmtime(&t); +#endif + if((ts->tm_year >= 50) && (ts->tm_year < 150)) + return ASN1_UTCTIME_set(s, t); + return ASN1_GENERALIZEDTIME_set(s,t); + } diff --git a/src/lib/libcrypto/asn1/a_utf8.c b/src/lib/libcrypto/asn1/a_utf8.c new file mode 100644 index 0000000000..4a8a92e9e4 --- /dev/null +++ b/src/lib/libcrypto/asn1/a_utf8.c @@ -0,0 +1,83 @@ +/* crypto/asn1/a_utf8.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 + +int i2d_ASN1_UTF8STRING(ASN1_UTF8STRING *a, unsigned char **pp) + { + return(i2d_ASN1_bytes((ASN1_STRING *)a,pp, + V_ASN1_UTF8STRING,V_ASN1_UNIVERSAL)); + } + +ASN1_UTF8STRING *d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **a, unsigned char **pp, + long length) + { + ASN1_UTF8STRING *ret=NULL; + + ret=(ASN1_UTF8STRING *)d2i_ASN1_bytes((ASN1_STRING **)a, + pp,length,V_ASN1_UTF8STRING,V_ASN1_UNIVERSAL); + if (ret == NULL) + { + ASN1err(ASN1_F_D2I_ASN1_UTF8STRING,ERR_R_NESTED_ASN1_ERROR); + return(NULL); + } + return(ret); + } + diff --git a/src/lib/libcrypto/asn1/asn1t.h b/src/lib/libcrypto/asn1/asn1t.h new file mode 100644 index 0000000000..ed372f8554 --- /dev/null +++ b/src/lib/libcrypto/asn1/asn1t.h @@ -0,0 +1,846 @@ +/* asn1t.h */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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). + * + */ +#ifndef HEADER_ASN1T_H +#define HEADER_ASN1T_H + +#include +#include +#include + +#ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + + +/* Macros for start and end of ASN1_ITEM definition */ + +#define ASN1_ITEM_start(itname) \ + OPENSSL_GLOBAL const ASN1_ITEM itname##_it = { + +#define ASN1_ITEM_end(itname) \ + }; + +#else + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr())) + + +/* Macros for start and end of ASN1_ITEM definition */ + +#define ASN1_ITEM_start(itname) \ + const ASN1_ITEM * itname##_it(void) \ + { \ + static const ASN1_ITEM local_it = { \ + +#define ASN1_ITEM_end(itname) \ + }; \ + return &local_it; \ + } + +#endif + + +/* Macros to aid ASN1 template writing */ + +#define ASN1_ITEM_TEMPLATE(tname) \ + const static ASN1_TEMPLATE tname##_item_tt + +#define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + + +/* This is a ASN1 type which just embeds a template */ + +/* This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +#define ASN1_SEQUENCE(tname) \ + const static ASN1_TEMPLATE tname##_seq_tt[] + +#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +#define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_SEQUENCE_cb(tname, cb) \ + const static ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_BROKEN_SEQUENCE(tname) \ + const static ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_ref(tname, cb, lck) \ + const static ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_enc(tname, enc, cb) \ + const static ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname) + +#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + + +/* This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +#define ASN1_CHOICE(tname) \ + const static ASN1_TEMPLATE tname##_ch_tt[] + +#define ASN1_CHOICE_cb(tname, cb) \ + const static ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +#define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* used when the structure is combined with the parent */ + +#define ASN1_EX_COMBINE(flags, tag, type) { \ + (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +#define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) + +#define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION +#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +#else +#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb } +#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb } +#endif +/* Plain simple type */ +#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) + +/* OPTIONAL simple type */ +#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) + +/* IMPLICIT tagged OPTIONAL simple type */ +#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* Same as above but EXPLICIT */ + +#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* SEQUENCE OF type */ +#define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +#define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +#define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +#define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* Macros for the ASN1_ADB structure */ + +#define ASN1_ADB(name) \ + const static ASN1_ADB_TABLE name##_adbtbl[] + +#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + const static ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + +#else + +#define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + const static ASN1_ITEM *name##_adb(void) \ + { \ + const static ASN1_ADB internal_adb = \ + {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + }; \ + return (const ASN1_ITEM *) &internal_adb; \ + } \ + void dummy_function(void) + +#endif + +#define ADB_ENTRY(val, template) {val, template} + +#define ASN1_ADB_TEMPLATE(name) \ + const static ASN1_TEMPLATE name##_tt + +/* This is the ASN1 template structure that defines + * a wrapper round the actual type. It determines the + * actual position of the field in the value structure, + * various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { +unsigned long flags; /* Various flags */ +long tag; /* tag, not used if no tagging */ +unsigned long offset; /* Offset of this field in structure */ +#ifndef NO_ASN1_FIELD_NAMES +char *field_name; /* Field name */ +#endif +ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +#define ASN1_TEMPLATE_item(t) (t->item_ptr) +#define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +#define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +#define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* Special case: this refers to a SET OF that + * will be sorted into DER order when encoded *and* + * the corresponding STACK will be modified to match + * the new order. + */ +#define ASN1_TFLG_SET_ORDER (0x3 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +#define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* These flags mean the tag should be taken from the + * tag field. If EXPLICIT then the underlying type + * is used for the inner tag. + */ + +/* IMPLICIT tagging */ +#define ASN1_TFLG_IMPTAG (0x1 << 3) + + +/* EXPLICIT tagging, inner tag from underlying type */ +#define ASN1_TFLG_EXPTAG (0x2 << 3) + +#define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT + +/* context specific EXPLICIT */ +#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT + +/* If tagging is in force these determine the + * type of tag to use. Otherwise the tag is + * determined by the underlying type. These + * values reflect the actual octet format. + */ + +/* Universal tag */ +#define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +#define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +#define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +#define ASN1_TFLG_PRIVATE (0x3<<6) + +#define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* These are for ANY DEFINED BY type. In this case + * the 'item' field points to an ASN1_ADB structure + * which contains a table of values to decode the + * relevant type + */ + +#define ASN1_TFLG_ADB_MASK (0x3<<8) + +#define ASN1_TFLG_ADB_OID (0x1<<8) + +#define ASN1_TFLG_ADB_INT (0x1<<9) + +/* This flag means a parent structure is passed + * instead of the field: this is useful is a + * SEQUENCE is being combined with a CHOICE for + * example. Since this means the structure and + * item name will differ we need to use the + * ASN1_CHOICE_END_name() macro for example. + */ + +#define ASN1_TFLG_COMBINE (0x1<<10) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { +char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ +long utype; /* underlying type */ +const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ +long tcount; /* Number of templates if SEQUENCE or CHOICE */ +const void *funcs; /* functions that handle this type */ +long size; /* Structure size (usually)*/ +#ifndef NO_ASN1_FIELD_NAMES +const char *sname; /* Structure name */ +#endif +}; + +/* These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * For COMPAT types the funcs field gives a + * set of functions that handle this type, this + * supports the old d2i, i2d convention. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + */ + +#define ASN1_ITYPE_PRIMITIVE 0x0 + +#define ASN1_ITYPE_SEQUENCE 0x1 + +#define ASN1_ITYPE_CHOICE 0x2 + +#define ASN1_ITYPE_COMPAT 0x3 + +#define ASN1_ITYPE_EXTERN 0x4 + +#define ASN1_ITYPE_MSTRING 0x5 + +/* Cache for ASN1 tag and length, so we + * don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st{ + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 function pointers */ + +typedef ASN1_VALUE * ASN1_new_func(void); +typedef void ASN1_free_func(ASN1_VALUE *a); +typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, unsigned char ** in, long length); +typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in); + +typedef int ASN1_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); + +typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); + +typedef struct ASN1_COMPAT_FUNCS_st { + ASN1_new_func *asn1_new; + ASN1_free_func *asn1_free; + ASN1_d2i_func *asn1_d2i; + ASN1_i2d_func *asn1_i2d; +} ASN1_COMPAT_FUNCS; + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_free_func *asn1_ex_clear; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; +} ASN1_EXTERN_FUNCS; + +typedef struct ASN1_PRIMITIVE_FUNCS_st { + void *app_data; + unsigned long flags; + ASN1_ex_new_func *prim_new; + ASN1_ex_free_func *prim_free; + ASN1_ex_free_func *prim_clear; + ASN1_primitive_c2i *prim_c2i; + ASN1_primitive_i2c *prim_i2c; +} ASN1_PRIMITIVE_FUNCS; + +/* This is the ASN1_AUX structure: it handles various + * miscellaneous requirements. For example the use of + * reference counts and an informational callback. + * + * The "informational callback" is called at various + * points during the ASN1 encoding and decoding. It can + * be used to provide minor customisation of the structures + * used. This is most useful where the supplied routines + * *almost* do the right thing but need some extra help + * at a few points. If the callback returns zero then + * it is assumed a fatal error has occurred and the + * main operation should be abandoned. + * + * If major changes in the default behaviour are required + * then an external type is more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it); + +typedef struct ASN1_AUX_st { + void *app_data; + int flags; + int ref_offset; /* Offset of reference value */ + int ref_lock; /* Lock type to use */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +#define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +#define ASN1_AFLG_ENCODING 2 +/* The Sequence length is invalid */ +#define ASN1_AFLG_BROKEN 4 + +/* operation values for asn1_cb */ + +#define ASN1_OP_NEW_PRE 0 +#define ASN1_OP_NEW_POST 1 +#define ASN1_OP_FREE_PRE 2 +#define ASN1_OP_FREE_POST 3 +#define ASN1_OP_D2I_PRE 4 +#define ASN1_OP_D2I_POST 5 +#define ASN1_OP_I2D_PRE 6 +#define ASN1_OP_I2D_POST 7 + +/* Macro to implement a primitive type */ +#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +#define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement an ASN1_ITEM in terms of old style funcs */ + +#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE) + +#define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \ + static const ASN1_COMPAT_FUNCS sname##_ff = { \ + (ASN1_new_func *)sname##_new, \ + (ASN1_free_func *)sname##_free, \ + (ASN1_d2i_func *)d2i_##sname, \ + (ASN1_i2d_func *)i2d_##sname, \ + }; \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_COMPAT, \ + tag, \ + NULL, \ + 0, \ + &sname##_ff, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +/* This includes evil casts to remove const: they will go away when full + * ASN1 constification is done. + */ +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, (unsigned char **)in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname * stname##_dup(stname *x) \ + { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +/* external definitions for primitive types */ + +DECLARE_ASN1_ITEM(ASN1_BOOLEAN) +DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_ANY) +DECLARE_ASN1_ITEM(ASN1_SEQUENCE) +DECLARE_ASN1_ITEM(CBIGNUM) +DECLARE_ASN1_ITEM(BIGNUM) +DECLARE_ASN1_ITEM(LONG) +DECLARE_ASN1_ITEM(ZLONG) + +DECLARE_STACK_OF(ASN1_VALUE) + +/* Functions used internally by the ASN1 code */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it); + +void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +int ASN1_template_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_TEMPLATE *tt); +int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt); +void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +int asn1_ex_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); + +ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr); + +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_save(ASN1_VALUE **pval, unsigned char *in, int inlen, const ASN1_ITEM *it); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/libcrypto/asn1/asn_moid.c b/src/lib/libcrypto/asn1/asn_moid.c new file mode 100644 index 0000000000..be20db4bad --- /dev/null +++ b/src/lib/libcrypto/asn1/asn_moid.c @@ -0,0 +1,95 @@ +/* asn_moid.c */ +/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include "cryptlib.h" +#include +#include +#include + +/* Simple ASN1 OID module: add all objects in a given section */ + +static int oid_module_init(CONF_IMODULE *md, const CONF *cnf) + { + int i; + const char *oid_section; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *oval; + oid_section = CONF_imodule_get_value(md); + if(!(sktmp = NCONF_get_section(cnf, oid_section))) + { + ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); + return 0; + } + for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) + { + oval = sk_CONF_VALUE_value(sktmp, i); + if(OBJ_create(oval->value, oval->name, oval->name) == NID_undef) + { + ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT); + return 0; + } + } + return 1; +} + +void ASN1_add_oid_module(void) + { + CONF_module_add("oid_section", oid_module_init, 0); + } diff --git a/src/lib/libcrypto/asn1/asn_pack.c b/src/lib/libcrypto/asn1/asn_pack.c new file mode 100644 index 0000000000..662a2626a1 --- /dev/null +++ b/src/lib/libcrypto/asn1/asn_pack.c @@ -0,0 +1,145 @@ +/* asn_pack.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 + +/* ASN1 packing and unpacking functions */ + +/* Turn an ASN1 encoded SEQUENCE OF into a STACK of structures */ + +STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(), + void (*free_func)()) +{ + STACK *sk; + unsigned char *pbuf; + pbuf = buf; + if (!(sk = d2i_ASN1_SET(NULL, &pbuf, len, d2i, free_func, + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL))) + ASN1err(ASN1_F_ASN1_SEQ_UNPACK,ASN1_R_DECODE_ERROR); + return sk; +} + +/* Turn a STACK structures into an ASN1 encoded SEQUENCE OF structure in a + * Malloc'ed buffer + */ + +unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, + int *len) +{ + int safelen; + unsigned char *safe, *p; + if (!(safelen = i2d_ASN1_SET(safes, NULL, i2d, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE))) { + ASN1err(ASN1_F_ASN1_SEQ_PACK,ASN1_R_ENCODE_ERROR); + return NULL; + } + if (!(safe = Malloc (safelen))) { + ASN1err(ASN1_F_ASN1_SEQ_PACK,ERR_R_MALLOC_FAILURE); + return NULL; + } + p = safe; + i2d_ASN1_SET(safes, &p, i2d, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, + IS_SEQUENCE); + if (len) *len = safelen; + if (buf) *buf = safe; + return safe; +} + +/* Extract an ASN1 object from an ASN1_STRING */ + +void *ASN1_unpack_string (ASN1_STRING *oct, char *(*d2i)()) +{ + unsigned char *p; + char *ret; + + p = oct->data; + if(!(ret = d2i(NULL, &p, oct->length))) + ASN1err(ASN1_F_ASN1_UNPACK_STRING,ASN1_R_DECODE_ERROR); + return ret; +} + +/* Pack an ASN1 object into an ASN1_STRING */ + +ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct) +{ + unsigned char *p; + ASN1_STRING *octmp; + + if (!oct || !*oct) { + if (!(octmp = ASN1_STRING_new ())) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + if (oct) *oct = octmp; + } else octmp = *oct; + + if (!(octmp->length = i2d(obj, NULL))) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ASN1_R_ENCODE_ERROR); + return NULL; + } + if (!(p = Malloc (octmp->length))) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + octmp->data = p; + i2d (obj, &p); + return octmp; +} + diff --git a/src/lib/libcrypto/asn1/charmap.h b/src/lib/libcrypto/asn1/charmap.h new file mode 100644 index 0000000000..bd020a9562 --- /dev/null +++ b/src/lib/libcrypto/asn1/charmap.h @@ -0,0 +1,15 @@ +/* Auto generated with chartype.pl script. + * Mask of various character properties + */ + +static unsigned char char_type[] = { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +120, 0, 1,40, 0, 0, 0,16,16,16, 0,25,25,16,16,16, +16,16,16,16,16,16,16,16,16,16,16, 9, 9,16, 9,16, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,16, 0, 1, 0, 0, 0, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,16, 0, 0, 0, 0, 2 +}; + diff --git a/src/lib/libcrypto/asn1/charmap.pl b/src/lib/libcrypto/asn1/charmap.pl new file mode 100644 index 0000000000..2875c59867 --- /dev/null +++ b/src/lib/libcrypto/asn1/charmap.pl @@ -0,0 +1,80 @@ +#!/usr/local/bin/perl -w + +use strict; + +my ($i, @arr); + +# Set up an array with the type of ASCII characters +# Each set bit represents a character property. + +# RFC2253 character properties +my $RFC2253_ESC = 1; # Character escaped with \ +my $ESC_CTRL = 2; # Escaped control character +# These are used with RFC1779 quoting using " +my $NOESC_QUOTE = 8; # Not escaped if quoted +my $PSTRING_CHAR = 0x10; # Valid PrintableString character +my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character +my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character + +for($i = 0; $i < 128; $i++) { + # Set the RFC2253 escape characters (control) + $arr[$i] = 0; + if(($i < 32) || ($i > 126)) { + $arr[$i] |= $ESC_CTRL; + } + + # Some PrintableString characters + if( ( ( $i >= ord("a")) && ( $i <= ord("z")) ) + || ( ( $i >= ord("A")) && ( $i <= ord("Z")) ) + || ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) { + $arr[$i] |= $PSTRING_CHAR; + } +} + +# Now setup the rest + +# Remaining RFC2253 escaped characters + +$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC; +$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC; + +$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("\"")] |= $RFC2253_ESC; +$arr[ord("\\")] |= $RFC2253_ESC; +$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC; + +# Remaining PrintableString characters + +$arr[ord(" ")] |= $PSTRING_CHAR; +$arr[ord("'")] |= $PSTRING_CHAR; +$arr[ord("(")] |= $PSTRING_CHAR; +$arr[ord(")")] |= $PSTRING_CHAR; +$arr[ord("+")] |= $PSTRING_CHAR; +$arr[ord(",")] |= $PSTRING_CHAR; +$arr[ord("-")] |= $PSTRING_CHAR; +$arr[ord(".")] |= $PSTRING_CHAR; +$arr[ord("/")] |= $PSTRING_CHAR; +$arr[ord(":")] |= $PSTRING_CHAR; +$arr[ord("=")] |= $PSTRING_CHAR; +$arr[ord("?")] |= $PSTRING_CHAR; + +# Now generate the C code + +print < +#include "cryptlib.h" +#include +#include + +/* Based on a_int.c: equivalent ENUMERATED functions */ + +int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a) + { + int i,n=0; + static const char *h="0123456789ABCDEF"; + char buf[2]; + + if (a == NULL) return(0); + + if (a->length == 0) + { + if (BIO_write(bp,"00",2) != 2) goto err; + n=2; + } + else + { + for (i=0; ilength; i++) + { + if ((i != 0) && (i%35 == 0)) + { + if (BIO_write(bp,"\\\n",2) != 2) goto err; + n+=2; + } + buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f]; + buf[1]=h[((unsigned char)a->data[i] )&0x0f]; + if (BIO_write(bp,buf,2) != 2) goto err; + n+=2; + } + } + return(n); +err: + return(-1); + } + +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) + { + int ret=0; + int i,j,k,m,n,again,bufsize; + unsigned char *s=NULL,*sp; + unsigned char *bufp; + int num=0,slen=0,first=1; + + bs->type=V_ASN1_ENUMERATED; + + bufsize=BIO_gets(bp,buf,size); + for (;;) + { + if (bufsize < 1) goto err_sl; + i=bufsize; + if (buf[i-1] == '\n') buf[--i]='\0'; + if (i == 0) goto err_sl; + if (buf[i-1] == '\r') buf[--i]='\0'; + if (i == 0) goto err_sl; + again=(buf[i-1] == '\\'); + + for (j=0; j= '0') && (buf[j] <= '9')) || + ((buf[j] >= 'a') && (buf[j] <= 'f')) || + ((buf[j] >= 'A') && (buf[j] <= 'F')))) + { + i=j; + break; + } + } + buf[i]='\0'; + /* We have now cleared all the crap off the end of the + * line */ + if (i < 2) goto err_sl; + + bufp=(unsigned char *)buf; + if (first) + { + first=0; + if ((bufp[0] == '0') && (buf[1] == '0')) + { + bufp+=2; + i-=2; + } + } + k=0; + i-=again; + if (i%2 != 0) + { + ASN1err(ASN1_F_A2I_ASN1_ENUMERATED,ASN1_R_ODD_NUMBER_OF_CHARS); + goto err; + } + i/=2; + if (num+i > slen) + { + if (s == NULL) + sp=(unsigned char *)Malloc( + (unsigned int)num+i*2); + else + sp=(unsigned char *)Realloc(s, + (unsigned int)num+i*2); + if (sp == NULL) + { + ASN1err(ASN1_F_A2I_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE); + if (s != NULL) Free((char *)s); + goto err; + } + s=sp; + slen=num+i*2; + } + for (j=0; j= '0') && (m <= '9')) + m-='0'; + else if ((m >= 'a') && (m <= 'f')) + m=m-'a'+10; + else if ((m >= 'A') && (m <= 'F')) + m=m-'A'+10; + else + { + ASN1err(ASN1_F_A2I_ASN1_ENUMERATED,ASN1_R_NON_HEX_CHARACTERS); + goto err; + } + s[num+j]<<=4; + s[num+j]|=m; + } + } + num+=i; + if (again) + bufsize=BIO_gets(bp,buf,size); + else + break; + } + bs->length=num; + bs->data=s; + ret=1; +err: + if (0) + { +err_sl: + ASN1err(ASN1_F_A2I_ASN1_ENUMERATED,ASN1_R_SHORT_LINE); + } + return(ret); + } + diff --git a/src/lib/libcrypto/asn1/nsseq.c b/src/lib/libcrypto/asn1/nsseq.c new file mode 100644 index 0000000000..417d024b81 --- /dev/null +++ b/src/lib/libcrypto/asn1/nsseq.c @@ -0,0 +1,118 @@ +/* nsseq.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 +#include +#include +#include +#include + +/* Netscape certificate sequence structure */ + +int i2d_NETSCAPE_CERT_SEQUENCE(NETSCAPE_CERT_SEQUENCE *a, unsigned char **pp) +{ + int v = 0; + M_ASN1_I2D_vars(a); + M_ASN1_I2D_len (a->type, i2d_ASN1_OBJECT); + M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(X509,a->certs,i2d_X509,0, + V_ASN1_SEQUENCE,v); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->type, i2d_ASN1_OBJECT); + M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(X509,a->certs,i2d_X509,0, + V_ASN1_SEQUENCE,v); + + M_ASN1_I2D_finish(); +} + +NETSCAPE_CERT_SEQUENCE *NETSCAPE_CERT_SEQUENCE_new(void) +{ + NETSCAPE_CERT_SEQUENCE *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, NETSCAPE_CERT_SEQUENCE); + /* Note hardcoded object type */ + ret->type = OBJ_nid2obj(NID_netscape_cert_sequence); + ret->certs = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_NETSCAPE_CERT_SEQUENCE_NEW); +} + +NETSCAPE_CERT_SEQUENCE *d2i_NETSCAPE_CERT_SEQUENCE(NETSCAPE_CERT_SEQUENCE **a, + unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,NETSCAPE_CERT_SEQUENCE *, + NETSCAPE_CERT_SEQUENCE_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->type, d2i_ASN1_OBJECT); + M_ASN1_D2I_get_EXP_set_opt_type(X509,ret->certs,d2i_X509,X509_free,0, + V_ASN1_SEQUENCE); + M_ASN1_D2I_Finish(a, NETSCAPE_CERT_SEQUENCE_free, + ASN1_F_D2I_NETSCAPE_CERT_SEQUENCE); +} + +void NETSCAPE_CERT_SEQUENCE_free (NETSCAPE_CERT_SEQUENCE *a) +{ + if (a == NULL) return; + ASN1_OBJECT_free(a->type); + if(a->certs) + sk_X509_pop_free(a->certs, X509_free); + Free (a); +} diff --git a/src/lib/libcrypto/asn1/p5_pbe.c b/src/lib/libcrypto/asn1/p5_pbe.c new file mode 100644 index 0000000000..b831836e7b --- /dev/null +++ b/src/lib/libcrypto/asn1/p5_pbe.c @@ -0,0 +1,156 @@ +/* p5_pbe.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 + +/* PKCS#5 password based encryption structure */ + +int i2d_PBEPARAM(PBEPARAM *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + M_ASN1_I2D_len (a->salt, i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_len (a->iter, i2d_ASN1_INTEGER); + + M_ASN1_I2D_seq_total (); + + M_ASN1_I2D_put (a->salt, i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_put (a->iter, i2d_ASN1_INTEGER); + M_ASN1_I2D_finish(); +} + +PBEPARAM *PBEPARAM_new(void) +{ + PBEPARAM *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, PBEPARAM); + M_ASN1_New(ret->iter,ASN1_INTEGER_new); + M_ASN1_New(ret->salt,ASN1_OCTET_STRING_new); + return (ret); + M_ASN1_New_Error(ASN1_F_PBEPARAM_NEW); +} + +PBEPARAM *d2i_PBEPARAM(PBEPARAM **a, unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,PBEPARAM *,PBEPARAM_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->salt, d2i_ASN1_OCTET_STRING); + M_ASN1_D2I_get (ret->iter, d2i_ASN1_INTEGER); + M_ASN1_D2I_Finish(a, PBEPARAM_free, ASN1_F_D2I_PBEPARAM); +} + +void PBEPARAM_free (PBEPARAM *a) +{ + if(a==NULL) return; + ASN1_OCTET_STRING_free(a->salt); + ASN1_INTEGER_free (a->iter); + Free ((char *)a); +} + +/* Return an algorithm identifier for a PKCS#5 PBE algorithm */ + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, + int saltlen) +{ + PBEPARAM *pbe; + ASN1_OBJECT *al; + X509_ALGOR *algor; + ASN1_TYPE *astype; + + if (!(pbe = PBEPARAM_new ())) { + ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); + return NULL; + } + if(iter <= 0) iter = PKCS5_DEFAULT_ITER; + ASN1_INTEGER_set (pbe->iter, iter); + if (!saltlen) saltlen = PKCS5_SALT_LEN; + if (!(pbe->salt->data = Malloc (saltlen))) { + ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); + return NULL; + } + pbe->salt->length = saltlen; + if (salt) memcpy (pbe->salt->data, salt, saltlen); + else RAND_bytes (pbe->salt->data, saltlen); + + if (!(astype = ASN1_TYPE_new())) { + ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); + return NULL; + } + + astype->type = V_ASN1_SEQUENCE; + if(!ASN1_pack_string(pbe, i2d_PBEPARAM, &astype->value.sequence)) { + ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); + return NULL; + } + PBEPARAM_free (pbe); + + al = OBJ_nid2obj(alg); /* never need to free al */ + if (!(algor = X509_ALGOR_new())) { + ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); + return NULL; + } + ASN1_OBJECT_free(algor->algorithm); + algor->algorithm = al; + algor->parameter = astype; + + return (algor); +} diff --git a/src/lib/libcrypto/asn1/p5_pbev2.c b/src/lib/libcrypto/asn1/p5_pbev2.c new file mode 100644 index 0000000000..09f4bf6112 --- /dev/null +++ b/src/lib/libcrypto/asn1/p5_pbev2.c @@ -0,0 +1,274 @@ +/* p5_pbev2.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 + +/* PKCS#5 v2.0 password based encryption structures */ + +int i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + M_ASN1_I2D_len (a->keyfunc, i2d_X509_ALGOR); + M_ASN1_I2D_len (a->encryption, i2d_X509_ALGOR); + + M_ASN1_I2D_seq_total (); + + M_ASN1_I2D_put (a->keyfunc, i2d_X509_ALGOR); + M_ASN1_I2D_put (a->encryption, i2d_X509_ALGOR); + + M_ASN1_I2D_finish(); +} + +PBE2PARAM *PBE2PARAM_new(void) +{ + PBE2PARAM *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, PBE2PARAM); + M_ASN1_New(ret->keyfunc,X509_ALGOR_new); + M_ASN1_New(ret->encryption,X509_ALGOR_new); + return (ret); + M_ASN1_New_Error(ASN1_F_PBE2PARAM_NEW); +} + +PBE2PARAM *d2i_PBE2PARAM(PBE2PARAM **a, unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,PBE2PARAM *,PBE2PARAM_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->keyfunc, d2i_X509_ALGOR); + M_ASN1_D2I_get (ret->encryption, d2i_X509_ALGOR); + M_ASN1_D2I_Finish(a, PBE2PARAM_free, ASN1_F_D2I_PBE2PARAM); +} + +void PBE2PARAM_free (PBE2PARAM *a) +{ + if(a==NULL) return; + X509_ALGOR_free(a->keyfunc); + X509_ALGOR_free(a->encryption); + Free ((char *)a); +} + +int i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + M_ASN1_I2D_len (a->salt, i2d_ASN1_TYPE); + M_ASN1_I2D_len (a->iter, i2d_ASN1_INTEGER); + M_ASN1_I2D_len (a->keylength, i2d_ASN1_INTEGER); + M_ASN1_I2D_len (a->prf, i2d_X509_ALGOR); + + M_ASN1_I2D_seq_total (); + + M_ASN1_I2D_put (a->salt, i2d_ASN1_TYPE); + M_ASN1_I2D_put (a->iter, i2d_ASN1_INTEGER); + M_ASN1_I2D_put (a->keylength, i2d_ASN1_INTEGER); + M_ASN1_I2D_put (a->prf, i2d_X509_ALGOR); + + M_ASN1_I2D_finish(); +} + +PBKDF2PARAM *PBKDF2PARAM_new(void) +{ + PBKDF2PARAM *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, PBKDF2PARAM); + M_ASN1_New(ret->salt, ASN1_TYPE_new); + M_ASN1_New(ret->iter, ASN1_INTEGER_new); + ret->keylength = NULL; + ret->prf = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_PBKDF2PARAM_NEW); +} + +PBKDF2PARAM *d2i_PBKDF2PARAM(PBKDF2PARAM **a, unsigned char **pp, + long length) +{ + M_ASN1_D2I_vars(a,PBKDF2PARAM *,PBKDF2PARAM_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->salt, d2i_ASN1_TYPE); + M_ASN1_D2I_get (ret->iter, d2i_ASN1_INTEGER); + M_ASN1_D2I_get_opt (ret->keylength, d2i_ASN1_INTEGER, V_ASN1_INTEGER); + M_ASN1_D2I_get_opt (ret->prf, d2i_X509_ALGOR, V_ASN1_SEQUENCE); + M_ASN1_D2I_Finish(a, PBKDF2PARAM_free, ASN1_F_D2I_PBKDF2PARAM); +} + +void PBKDF2PARAM_free (PBKDF2PARAM *a) +{ + if(a==NULL) return; + ASN1_TYPE_free(a->salt); + ASN1_INTEGER_free(a->iter); + ASN1_INTEGER_free(a->keylength); + X509_ALGOR_free(a->prf); + Free ((char *)a); +} + +/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: + * yes I know this is horrible! + */ + +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen) +{ + X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; + int alg_nid; + EVP_CIPHER_CTX ctx; + unsigned char iv[EVP_MAX_IV_LENGTH]; + PBKDF2PARAM *kdf = NULL; + PBE2PARAM *pbe2 = NULL; + ASN1_OCTET_STRING *osalt = NULL; + + if(!(pbe2 = PBE2PARAM_new())) goto merr; + + /* Setup the AlgorithmIdentifier for the encryption scheme */ + scheme = pbe2->encryption; + + alg_nid = EVP_CIPHER_type(cipher); + + scheme->algorithm = OBJ_nid2obj(alg_nid); + if(!(scheme->parameter = ASN1_TYPE_new())) goto merr; + + /* Create random IV */ + RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)); + + /* Dummy cipherinit to just setup the IV */ + EVP_CipherInit(&ctx, cipher, NULL, iv, 0); + if(EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { + ASN1err(ASN1_F_PKCS5_PBE2_SET, + ASN1_R_ERROR_SETTING_CIPHER_PARAMS); + goto err; + } + EVP_CIPHER_CTX_cleanup(&ctx); + + if(!(kdf = PBKDF2PARAM_new())) goto merr; + if(!(osalt = ASN1_OCTET_STRING_new())) goto merr; + + if (!saltlen) saltlen = PKCS5_SALT_LEN; + if (!(osalt->data = Malloc (saltlen))) goto merr; + osalt->length = saltlen; + if (salt) memcpy (osalt->data, salt, saltlen); + else RAND_bytes (osalt->data, saltlen); + + if(iter <= 0) iter = PKCS5_DEFAULT_ITER; + if(!ASN1_INTEGER_set(kdf->iter, iter)) goto merr; + + /* Now include salt in kdf structure */ + kdf->salt->value.octet_string = osalt; + kdf->salt->type = V_ASN1_OCTET_STRING; + osalt = NULL; + + /* If its RC2 then we'd better setup the key length */ + + if(alg_nid == NID_rc2_cbc) { + if(!(kdf->keylength = ASN1_INTEGER_new())) goto merr; + if(!ASN1_INTEGER_set (kdf->keylength, + EVP_CIPHER_key_length(cipher))) goto merr; + } + + /* prf can stay NULL because we are using hmacWithSHA1 */ + + /* Now setup the PBE2PARAM keyfunc structure */ + + pbe2->keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); + + /* Encode PBKDF2PARAM into parameter of pbe2 */ + + if(!(pbe2->keyfunc->parameter = ASN1_TYPE_new())) goto merr; + + if(!ASN1_pack_string(kdf, i2d_PBKDF2PARAM, + &pbe2->keyfunc->parameter->value.sequence)) goto merr; + pbe2->keyfunc->parameter->type = V_ASN1_SEQUENCE; + + PBKDF2PARAM_free(kdf); + kdf = NULL; + + /* Now set up top level AlgorithmIdentifier */ + + if(!(ret = X509_ALGOR_new())) goto merr; + if(!(ret->parameter = ASN1_TYPE_new())) goto merr; + + ret->algorithm = OBJ_nid2obj(NID_pbes2); + + /* Encode PBE2PARAM into parameter */ + + if(!ASN1_pack_string(pbe2, i2d_PBE2PARAM, + &ret->parameter->value.sequence)) goto merr; + ret->parameter->type = V_ASN1_SEQUENCE; + + PBE2PARAM_free(pbe2); + pbe2 = NULL; + + return ret; + + merr: + ASN1err(ASN1_F_PKCS5_PBE2_SET,ERR_R_MALLOC_FAILURE); + + err: + PBE2PARAM_free(pbe2); + /* Note 'scheme' is freed as part of pbe2 */ + ASN1_OCTET_STRING_free(osalt); + PBKDF2PARAM_free(kdf); + X509_ALGOR_free(kalg); + X509_ALGOR_free(ret); + + return NULL; + +} diff --git a/src/lib/libcrypto/asn1/p8_pkey.c b/src/lib/libcrypto/asn1/p8_pkey.c new file mode 100644 index 0000000000..aa9a4f6c96 --- /dev/null +++ b/src/lib/libcrypto/asn1/p8_pkey.c @@ -0,0 +1,129 @@ +/* p8_pkey.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 + +int i2d_PKCS8_PRIV_KEY_INFO (PKCS8_PRIV_KEY_INFO *a, unsigned char **pp) +{ + + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->version, i2d_ASN1_INTEGER); + M_ASN1_I2D_len (a->pkeyalg, i2d_X509_ALGOR); + M_ASN1_I2D_len (a->pkey, i2d_ASN1_TYPE); + M_ASN1_I2D_len_IMP_SET_opt_type (X509_ATTRIBUTE, a->attributes, + i2d_X509_ATTRIBUTE, 0); + + M_ASN1_I2D_seq_total (); + + M_ASN1_I2D_put (a->version, i2d_ASN1_INTEGER); + M_ASN1_I2D_put (a->pkeyalg, i2d_X509_ALGOR); + M_ASN1_I2D_put (a->pkey, i2d_ASN1_TYPE); + M_ASN1_I2D_put_IMP_SET_opt_type (X509_ATTRIBUTE, a->attributes, + i2d_X509_ATTRIBUTE, 0); + + M_ASN1_I2D_finish(); +} + +PKCS8_PRIV_KEY_INFO *PKCS8_PRIV_KEY_INFO_new(void) +{ + PKCS8_PRIV_KEY_INFO *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, PKCS8_PRIV_KEY_INFO); + M_ASN1_New (ret->version, ASN1_INTEGER_new); + M_ASN1_New (ret->pkeyalg, X509_ALGOR_new); + M_ASN1_New (ret->pkey, ASN1_TYPE_new); + ret->attributes = NULL; + ret->broken = PKCS8_OK; + return (ret); + M_ASN1_New_Error(ASN1_F_PKCS8_PRIV_KEY_INFO_NEW); +} + +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a, + unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,PKCS8_PRIV_KEY_INFO *,PKCS8_PRIV_KEY_INFO_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->version, d2i_ASN1_INTEGER); + M_ASN1_D2I_get (ret->pkeyalg, d2i_X509_ALGOR); + M_ASN1_D2I_get (ret->pkey, d2i_ASN1_TYPE); + M_ASN1_D2I_get_IMP_set_opt_type(X509_ATTRIBUTE, ret->attributes, + d2i_X509_ATTRIBUTE, + X509_ATTRIBUTE_free, 0); + if (ASN1_TYPE_get(ret->pkey) == V_ASN1_SEQUENCE) + ret->broken = PKCS8_NO_OCTET; + M_ASN1_D2I_Finish(a, PKCS8_PRIV_KEY_INFO_free, ASN1_F_D2I_PKCS8_PRIV_KEY_INFO); +} + +void PKCS8_PRIV_KEY_INFO_free (PKCS8_PRIV_KEY_INFO *a) +{ + if (a == NULL) return; + ASN1_INTEGER_free (a->version); + X509_ALGOR_free(a->pkeyalg); + /* Clear sensitive data */ + if (a->pkey->value.octet_string) + memset (a->pkey->value.octet_string->data, + 0, a->pkey->value.octet_string->length); + ASN1_TYPE_free (a->pkey); + sk_X509_ATTRIBUTE_pop_free (a->attributes, X509_ATTRIBUTE_free); + Free (a); +} diff --git a/src/lib/libcrypto/asn1/t_bitst.c b/src/lib/libcrypto/asn1/t_bitst.c new file mode 100644 index 0000000000..8ee789f082 --- /dev/null +++ b/src/lib/libcrypto/asn1/t_bitst.c @@ -0,0 +1,99 @@ +/* t_bitst.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 + +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent) +{ + BIT_STRING_BITNAME *bnam; + char first = 1; + BIO_printf(out, "%*s", indent, ""); + for(bnam = tbl; bnam->lname; bnam++) { + if(ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { + if(!first) BIO_puts(out, ", "); + BIO_puts(out, bnam->lname); + first = 0; + } + } + BIO_puts(out, "\n"); + return 1; +} + +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value, + BIT_STRING_BITNAME *tbl) +{ + int bitnum; + bitnum = ASN1_BIT_STRING_num_asc(name, tbl); + if(bitnum < 0) return 0; + if(bs) ASN1_BIT_STRING_set_bit(bs, bitnum, value); + return 1; +} + +int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl) +{ + BIT_STRING_BITNAME *bnam; + for(bnam = tbl; bnam->lname; bnam++) { + if(!strcmp(bnam->sname, name) || + !strcmp(bnam->lname, name) ) return bnam->bitnum; + } + return -1; +} diff --git a/src/lib/libcrypto/asn1/t_crl.c b/src/lib/libcrypto/asn1/t_crl.c new file mode 100644 index 0000000000..c2e447ce6f --- /dev/null +++ b/src/lib/libcrypto/asn1/t_crl.c @@ -0,0 +1,166 @@ +/* t_crl.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 +#include +#include + +static void ext_print(BIO *out, X509_EXTENSION *ex); +#ifndef NO_FP_API +int X509_CRL_print_fp(FILE *fp, X509_CRL *x) + { + BIO *b; + int ret; + + if ((b=BIO_new(BIO_s_file())) == NULL) + { + X509err(X509_F_X509_PRINT_FP,ERR_R_BUF_LIB); + return(0); + } + BIO_set_fp(b,fp,BIO_NOCLOSE); + ret=X509_CRL_print(b, x); + BIO_free(b); + return(ret); + } +#endif + +int X509_CRL_print(BIO *out, X509_CRL *x) +{ + char buf[256]; + unsigned char *s; + STACK_OF(X509_REVOKED) *rev; + X509_REVOKED *r; + long l; + int i, j, n; + + BIO_printf(out, "Certificate Revocation List (CRL):\n"); + l = X509_CRL_get_version(x); + BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l); + i = OBJ_obj2nid(x->sig_alg->algorithm); + BIO_printf(out, "%8sSignature Algorithm: %s\n", "", + (i == NID_undef) ? "NONE" : OBJ_nid2ln(i)); + X509_NAME_oneline(X509_CRL_get_issuer(x),buf,256); + BIO_printf(out,"%8sIssuer: %s\n","",buf); + BIO_printf(out,"%8sLast Update: ",""); + ASN1_TIME_print(out,X509_CRL_get_lastUpdate(x)); + BIO_printf(out,"\n%8sNext Update: ",""); + if (X509_CRL_get_nextUpdate(x)) + ASN1_TIME_print(out,X509_CRL_get_nextUpdate(x)); + else BIO_printf(out,"NONE"); + BIO_printf(out,"\n"); + + n=X509_CRL_get_ext_count(x); + if (n > 0) { + BIO_printf(out,"%8sCRL extensions:\n",""); + for (i=0; iserialNumber); + BIO_printf(out,"\n Revocation Date: ",""); + ASN1_TIME_print(out,r->revocationDate); + BIO_printf(out,"\n"); + for(j = 0; j < X509_REVOKED_get_ext_count(r); j++) + ext_print(out, X509_REVOKED_get_ext(r, j)); + } + + i=OBJ_obj2nid(x->sig_alg->algorithm); + BIO_printf(out," Signature Algorithm: %s", + (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)); + + s = x->signature->data; + n = x->signature->length; + for (i=0; ivalue); + } + BIO_write(out,"\n",1); +} diff --git a/src/lib/libcrypto/asn1/t_spki.c b/src/lib/libcrypto/asn1/t_spki.c new file mode 100644 index 0000000000..d708434fca --- /dev/null +++ b/src/lib/libcrypto/asn1/t_spki.c @@ -0,0 +1,116 @@ +/* t_spki.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 + +/* Print out an SPKI */ + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) +{ + EVP_PKEY *pkey; + ASN1_IA5STRING *chal; + int i, n; + char *s; + BIO_printf(out, "Netscape SPKI:\n"); + i=OBJ_obj2nid(spki->spkac->pubkey->algor->algorithm); + BIO_printf(out," Public Key Algorithm: %s\n", + (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)); + pkey = X509_PUBKEY_get(spki->spkac->pubkey); + if(!pkey) BIO_printf(out, " Unable to load public key\n"); + else { +#ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + BIO_printf(out," RSA Public Key: (%d bit)\n", + BN_num_bits(pkey->pkey.rsa->n)); + RSA_print(out,pkey->pkey.rsa,2); + } + else +#endif +#ifndef NO_DSA + if (pkey->type == EVP_PKEY_DSA) + { + BIO_printf(out," DSA Public Key:\n"); + DSA_print(out,pkey->pkey.dsa,2); + } + else +#endif + BIO_printf(out," Unknown Public Key:\n"); + EVP_PKEY_free(pkey); + } + chal = spki->spkac->challenge; + if(chal->length) + BIO_printf(out, " Challenge String: %s\n", chal->data); + i=OBJ_obj2nid(spki->sig_algor->algorithm); + BIO_printf(out," Signature Algorithm: %s", + (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)); + + n=spki->signature->length; + s=(char *)spki->signature->data; + for (i=0; i +#include "cryptlib.h" +#include +#include +#include + +/* X509_CERT_AUX and string set routines + */ + +int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) +{ + char oidstr[80], first; + int i; + if(!aux) return 1; + if(aux->trust) { + first = 1; + BIO_printf(out, "%*sTrusted Uses:\n%*s", + indent, "", indent + 2, ""); + for(i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) { + if(!first) BIO_puts(out, ", "); + else first = 0; + OBJ_obj2txt(oidstr, 80, + sk_ASN1_OBJECT_value(aux->trust, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); + if(aux->reject) { + first = 1; + BIO_printf(out, "%*sRejected Uses:\n%*s", + indent, "", indent + 2, ""); + for(i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) { + if(!first) BIO_puts(out, ", "); + else first = 0; + OBJ_obj2txt(oidstr, 80, + sk_ASN1_OBJECT_value(aux->reject, i), 0); + BIO_puts(out, oidstr); + } + BIO_puts(out, "\n"); + } else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); + if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "", + aux->alias->data); + return 1; +} diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c new file mode 100644 index 0000000000..0fc1f421e2 --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_dec.c @@ -0,0 +1,958 @@ +/* tasn_dec.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include +#include +#include + +static int asn1_check_eoc(unsigned char **in, long len); +static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass); +static int collect_data(BUF_MEM *buf, unsigned char **p, long plen); +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst, + unsigned char **in, long len, int exptag, int expclass, char opt, ASN1_TLC *ctx); +static int asn1_template_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); +static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx); + +/* Table to convert tags to bit values, used for MSTRING type */ +static unsigned long tag2bit[32]={ +0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ +B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */ +B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */ +B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */ +0, 0, B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */ +B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */ +B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */ +B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */ +B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */ + }; + +unsigned long ASN1_tag2bit(int tag) +{ + if((tag < 0) || (tag > 30)) return 0; + return tag2bit[tag]; +} + +/* Macro to initialize and invalidate the cache */ + +#define asn1_tlc_clear(c) if(c) (c)->valid = 0 + +/* Decode an ASN1 item, this currently behaves just + * like a standard 'd2i' function. 'in' points to + * a buffer to read the data from, in future we will + * have more advanced versions that can input data + * a piece at a time and this will simply be a special + * case. + */ + +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_ITEM *it) +{ + ASN1_TLC c; + ASN1_VALUE *ptmpval = NULL; + if(!pval) pval = &ptmpval; + asn1_tlc_clear(&c); + if(ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) + return *pval; + return NULL; +} + +int ASN1_template_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_TEMPLATE *tt) +{ + ASN1_TLC c; + asn1_tlc_clear(&c); + return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); +} + + +/* Decode an item, taking care of IMPLICIT tagging, if any. + * If 'opt' set and tag mismatch return -1 to handle OPTIONAL + */ + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + const ASN1_TEMPLATE *tt, *errtt = NULL; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + unsigned char *p, *q, imphack = 0, oclass; + char seq_eoc, seq_nolen, cst, isopt; + long tmplen; + int i; + int otag; + int ret = 0; + ASN1_VALUE *pchval, **pchptr, *ptmpval; + if(!pval) return 0; + if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; + else asn1_cb = 0; + + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) { + /* tagging or OPTIONAL is currently illegal on an item template + * because the flags can't get passed down. In practice this isn't + * a problem: we include the relevant flags from the item template + * in the template itself. + */ + if ((tag != -1) || opt) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); + goto err; + } + return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx); + } + return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt, ctx); + break; + + case ASN1_ITYPE_MSTRING: + p = *in; + /* Just read in tag and class */ + ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, &p, len, -1, 0, 1, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + /* Must be UNIVERSAL class */ + if(oclass != V_ASN1_UNIVERSAL) { + /* If OPTIONAL, assume this is OK */ + if(opt) return -1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); + goto err; + } + /* Check tag matches bit map */ + if(!(ASN1_tag2bit(otag) & it->utype)) { + /* If OPTIONAL, assume this is OK */ + if(opt) return -1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_WRONG_TAG); + goto err; + } + return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); + + case ASN1_ITYPE_EXTERN: + /* Use new style d2i */ + ef = it->funcs; + return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); + + case ASN1_ITYPE_COMPAT: + /* we must resort to old style evil hackery */ + cf = it->funcs; + + /* If OPTIONAL see if it is there */ + if(opt) { + int exptag; + p = *in; + if(tag == -1) exptag = it->utype; + else exptag = tag; + /* Don't care about anything other than presence of expected tag */ + ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, &p, len, exptag, aclass, 1, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + if(ret == -1) return -1; + } + /* This is the old style evil hack IMPLICIT handling: + * since the underlying code is expecting a tag and + * class other than the one present we change the + * buffer temporarily then change it back afterwards. + * This doesn't and never did work for tags > 30. + * + * Yes this is *horrible* but it is only needed for + * old style d2i which will hopefully not be around + * for much longer. + * FIXME: should copy the buffer then modify it so + * the input buffer can be const: we should *always* + * copy because the old style d2i might modify the + * buffer. + */ + + if(tag != -1) { + p = *in; + imphack = *p; + *p = (unsigned char)((*p & V_ASN1_CONSTRUCTED) | it->utype); + } + + ptmpval = cf->asn1_d2i(pval, in, len); + + if(tag != -1) *p = imphack; + + if(ptmpval) return 1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + + + case ASN1_ITYPE_CHOICE: + if(asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) + goto auxerr; + + /* Allocate structure */ + if(!*pval) { + if(!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + } + /* CHOICE type, try each possibility in turn */ + pchval = NULL; + p = *in; + for(i = 0, tt=it->templates; i < it->tcount; i++, tt++) { + pchptr = asn1_get_field_ptr(pval, tt); + /* We mark field as OPTIONAL so its absence + * can be recognised. + */ + ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); + /* If field not present, try the next one */ + if(ret == -1) continue; + /* If positive return, read OK, break loop */ + if(ret > 0) break; + /* Otherwise must be an ASN1 parsing error */ + errtt = tt; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + /* Did we fall off the end without reading anything? */ + if(i == it->tcount) { + /* If OPTIONAL, this is OK */ + if(opt) { + /* Free and zero it */ + ASN1_item_ex_free(pval, it); + return -1; + } + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); + goto err; + } + asn1_set_choice_selector(pval, i, it); + *in = p; + if(asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it)) + goto auxerr; + return 1; + + case ASN1_ITYPE_SEQUENCE: + p = *in; + tmplen = len; + + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if(tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* Get SEQUENCE length and update len, p */ + ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, &p, len, tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if(ret == -1) return -1; + if(aux && (aux->flags & ASN1_AFLG_BROKEN)) { + len = tmplen - (p - *in); + seq_nolen = 1; + } else seq_nolen = seq_eoc; /* If indefinite we don't do a length check */ + if(!cst) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); + goto err; + } + + if(!*pval) { + if(!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + } + if(asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) + goto auxerr; + + /* Get each field entry */ + for(i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if(!seqtt) goto err; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* Have we ran out of data? */ + if(!len) break; + q = p; + if(asn1_check_eoc(&p, len)) { + if(!seq_eoc) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + seq_eoc = 0; + q = p; + break; + } + /* This determines the OPTIONAL flag value. The field cannot + * be omitted if it is the last of a SEQUENCE and there is + * still data to be read. This isn't strictly necessary but + * it increases efficiency in some cases. + */ + if(i == (it->tcount - 1)) isopt = 0; + else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); + /* attempt to read in field, allowing each to be OPTIONAL */ + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); + if(!ret) { + errtt = seqtt; + goto err; + } else if(ret == -1) { + /* OPTIONAL component absent. Free and zero the field + */ + ASN1_template_free(pseqval, seqtt); + continue; + } + /* Update length */ + len -= p - q; + } + /* Check for EOC if expecting one */ + if(seq_eoc && !asn1_check_eoc(&p, len)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); + goto err; + } + /* Check all data read */ + if(!seq_nolen && len) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); + goto err; + } + + /* If we get here we've got no more data in the SEQUENCE, + * however we may not have read all fields so check all + * remaining are OPTIONAL and clear any that are. + */ + for(; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + seqtt = asn1_do_adb(pval, tt, 1); + if(!seqtt) goto err; + if(seqtt->flags & ASN1_TFLG_OPTIONAL) { + ASN1_VALUE **pseqval; + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } else { + errtt = seqtt; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_FIELD_MISSING); + goto err; + } + } + /* Save encoding */ + if(!asn1_enc_save(pval, *in, p - *in, it)) goto auxerr; + *in = p; + if(asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it)) + goto auxerr; + return 1; + + default: + return 0; + } + auxerr: + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR); + err: + ASN1_item_ex_free(pval, it); + if(errtt) ERR_add_error_data(4, "Field=", errtt->field_name, ", Type=", it->sname); + else ERR_add_error_data(2, "Type=", it->sname); + return 0; +} + +/* Templates are handled with two separate functions. One handles any EXPLICIT tag and the other handles the + * rest. + */ + +static int asn1_template_ex_d2i(ASN1_VALUE **val, unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) +{ + int flags, aclass; + int ret; + long len; + unsigned char *p, *q; + char exp_eoc; + if(!val) return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + + /* Check if EXPLICIT tag expected */ + if(flags & ASN1_TFLG_EXPTAG) { + char cst; + /* Need to work out amount of data available to the inner content and where it + * starts: so read in EXPLICIT header to get the info. + */ + ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, &p, inlen, tt->tag, aclass, opt, ctx); + q = p; + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if(ret == -1) return -1; + if(!cst) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + return 0; + } + /* We've found the field so it can't be OPTIONAL now */ + ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + /* We read the field in OK so update length */ + len -= p - q; + if(exp_eoc) { + /* If NDEF we must have an EOC here */ + if(!asn1_check_eoc(&p, len)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_MISSING_EOC); + goto err; + } + } else { + /* Otherwise we must hit the EXPLICIT tag end or its an error */ + if(len) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_EXPLICIT_LENGTH_MISMATCH); + goto err; + } + } + } else + return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); + + *in = p; + return 1; + + err: + ASN1_template_free(val, tt); + *val = NULL; + return 0; +} + +static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) +{ + int flags, aclass; + int ret; + unsigned char *p, *q; + if(!val) return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + q = p; + + if(flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + int sktag, skaclass; + char sk_eoc; + /* First work out expected inner tag value */ + if(flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if(flags & ASN1_TFLG_SET_OF) sktag = V_ASN1_SET; + else sktag = V_ASN1_SEQUENCE; + } + /* Get the tag */ + ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, &p, len, sktag, skaclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if(ret == -1) return -1; + if(!*val) *val = (ASN1_VALUE *)sk_new_null(); + else { + /* We've got a valid STACK: free up any items present */ + STACK *sktmp = (STACK *)*val; + ASN1_VALUE *vtmp; + while(sk_num(sktmp) > 0) { + vtmp = (ASN1_VALUE *)sk_pop(sktmp); + ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); + } + } + + if(!*val) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_MALLOC_FAILURE); + goto err; + } + /* Read as many items as we can */ + while(len > 0) { + ASN1_VALUE *skfield; + q = p; + /* See if EOC found */ + if(asn1_check_eoc(&p, len)) { + if(!sk_eoc) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + sk_eoc = 0; + break; + } + skfield = NULL; + if(!ASN1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + len -= p - q; + if(!sk_push((STACK *)*val, (char *)skfield)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if(sk_eoc) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_MISSING_EOC); + goto err; + } + } else if(flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if(ret == -1) return -1; + } else { + /* Nothing special */ + ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), -1, 0, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if(ret == -1) return -1; + } + + *in = p; + return 1; + + err: + ASN1_template_free(val, tt); + *val = NULL; + return 0; +} + +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inlen, + const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + int ret = 0, utype; + long plen; + char cst, inf, free_cont = 0; + unsigned char *p; + BUF_MEM buf; + unsigned char *cont = NULL; + long len; + if(!pval) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); + return 0; /* Should never happen */ + } + + if(it->itype == ASN1_ITYPE_MSTRING) { + utype = tag; + tag = -1; + } else utype = it->utype; + + if(utype == V_ASN1_ANY) { + /* If type is ANY need to figure out type from tag */ + unsigned char oclass; + if(tag >= 0) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); + return 0; + } + if(opt) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_OPTIONAL_ANY); + return 0; + } + p = *in; + ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, &p, inlen, -1, 0, 0, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + if(oclass != V_ASN1_UNIVERSAL) utype = V_ASN1_OTHER; + } + if(tag == -1) { + tag = utype; + aclass = V_ASN1_UNIVERSAL; + } + p = *in; + /* Check header */ + ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, &p, inlen, tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if(ret == -1) return -1; + /* SEQUENCE, SET and "OTHER" are left in encoded form */ + if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { + /* Clear context cache for type OTHER because the auto clear when + * we have a exact match wont work + */ + if(utype == V_ASN1_OTHER) { + asn1_tlc_clear(ctx); + /* SEQUENCE and SET must be constructed */ + } else if(!cst) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_CONSTRUCTED); + return 0; + } + + cont = *in; + /* If indefinite length constructed find the real end */ + if(inf) { + if(!asn1_collect(NULL, &p, plen, inf, -1, -1)) goto err; + len = p - cont; + } else { + len = p - cont + plen; + p += plen; + buf.data = NULL; + } + } else if(cst) { + buf.length = 0; + buf.max = 0; + buf.data = NULL; + /* Should really check the internal tags are correct but + * some things may get this wrong. The relevant specs + * say that constructed string types should be OCTET STRINGs + * internally irrespective of the type. So instead just check + * for UNIVERSAL class and ignore the tag. + */ + if(!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL)) goto err; + len = buf.length; + /* Append a final null to string */ + if(!BUF_MEM_grow(&buf, len + 1)) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + return 0; + } + buf.data[len] = 0; + cont = (unsigned char *)buf.data; + free_cont = 1; + } else { + cont = p; + len = plen; + p += plen; + } + + /* We now have content length and type: translate into a structure */ + if(!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) goto err; + + *in = p; + ret = 1; + err: + if(free_cont && buf.data) OPENSSL_free(buf.data); + return ret; +} + +/* Translate ASN1 content octets into a structure */ + +int asn1_ex_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it) +{ + ASN1_STRING *stmp; + ASN1_TYPE *typ = NULL; + int ret = 0; + const ASN1_PRIMITIVE_FUNCS *pf; + ASN1_INTEGER **tint; + pf = it->funcs; + if(pf && pf->prim_c2i) return pf->prim_c2i(pval, cont, len, utype, free_cont, it); + /* If ANY type clear type and set pointer to internal value */ + if(it->utype == V_ASN1_ANY) { + if(!*pval) { + typ = ASN1_TYPE_new(); + *pval = (ASN1_VALUE *)typ; + } else typ = (ASN1_TYPE *)*pval; + if(utype != typ->type) ASN1_TYPE_set(typ, utype, NULL); + pval = (ASN1_VALUE **)&typ->value.ptr; + } + switch(utype) { + case V_ASN1_OBJECT: + if(!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) goto err; + break; + + case V_ASN1_NULL: + if(len) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_NULL_IS_WRONG_LENGTH); + goto err; + } + *pval = (ASN1_VALUE *)1; + break; + + case V_ASN1_BOOLEAN: + if(len != 1) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + goto err; + } else { + ASN1_BOOLEAN *tbool; + tbool = (ASN1_BOOLEAN *)pval; + *tbool = *cont; + } + break; + + case V_ASN1_BIT_STRING: + if(!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) goto err; + break; + + case V_ASN1_INTEGER: + case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_NEG_ENUMERATED: + tint = (ASN1_INTEGER **)pval; + if(!c2i_ASN1_INTEGER(tint, &cont, len)) goto err; + /* Fixup type to match the expected form */ + (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_OTHER: + case V_ASN1_SET: + case V_ASN1_SEQUENCE: + default: + /* All based on ASN1_STRING and handled the same */ + if(!*pval) { + stmp = ASN1_STRING_type_new(utype); + if(!stmp) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + goto err; + } + *pval = (ASN1_VALUE *)stmp; + } else { + stmp = (ASN1_STRING *)*pval; + stmp->type = utype; + } + /* If we've already allocated a buffer use it */ + if(*free_cont) { + if(stmp->data) OPENSSL_free(stmp->data); + stmp->data = cont; + stmp->length = len; + *free_cont = 0; + } else { + if(!ASN1_STRING_set(stmp, cont, len)) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; + } + } + break; + } + /* If ASN1_ANY and NULL type fix up value */ + if(typ && utype==V_ASN1_NULL) typ->value.ptr = NULL; + + ret = 1; + err: + if(!ret) ASN1_TYPE_free(typ); + return ret; +} + +/* This function collects the asn1 data from a constructred string + * type into a buffer. The values of 'in' and 'len' should refer + * to the contents of the constructed type and 'inf' should be set + * if it is indefinite length. If 'buf' is NULL then we just want + * to find the end of the current structure: useful for indefinite + * length constructed stuff. + */ + +static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass) +{ + unsigned char *p, *q; + long plen; + char cst, ininf; + p = *in; + inf &= 1; + /* If no buffer and not indefinite length constructed just pass over the encoded data */ + if(!buf && !inf) { + *in += len; + return 1; + } + while(len > 0) { + q = p; + /* Check for EOC */ + if(asn1_check_eoc(&p, len)) { + /* EOC is illegal outside indefinite length constructed form */ + if(!inf) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); + return 0; + } + inf = 0; + break; + } + if(!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, len, tag, aclass, 0, NULL)) { + ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + /* If indefinite length constructed update max length */ + if(cst) { + if(!asn1_collect(buf, &p, plen, ininf, tag, aclass)) return 0; + } else { + if(!collect_data(buf, &p, plen)) return 0; + } + len -= p - q; + } + if(inf) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); + return 0; + } + *in = p; + return 1; +} + +static int collect_data(BUF_MEM *buf, unsigned char **p, long plen) +{ + int len; + if(buf) { + len = buf->length; + if(!BUF_MEM_grow(buf, len + plen)) { + ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(buf->data + len, *p, plen); + } + *p += plen; + return 1; +} + +/* Check for ASN1 EOC and swallow it if found */ + +static int asn1_check_eoc(unsigned char **in, long len) +{ + unsigned char *p; + if(len < 2) return 0; + p = *in; + if(!p[0] && !p[1]) { + *in += 2; + return 1; + } + return 0; +} + +/* Check an ASN1 tag and length: a bit like ASN1_get_object + * but it sets the length for indefinite length constructed + * form, we don't know the exact length but we can set an + * upper bound to the amount of data available minus the + * header length just read. + */ + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst, + unsigned char **in, long len, int exptag, int expclass, char opt, ASN1_TLC *ctx) +{ + int i; + int ptag, pclass; + long plen; + unsigned char *p, *q; + p = *in; + q = p; + + if(ctx && ctx->valid) { + i = ctx->ret; + plen = ctx->plen; + pclass = ctx->pclass; + ptag = ctx->ptag; + p += ctx->hdrlen; + } else { + i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); + if(ctx) { + ctx->ret = i; + ctx->plen = plen; + ctx->pclass = pclass; + ctx->ptag = ptag; + ctx->hdrlen = p - q; + ctx->valid = 1; + /* If definite length, length + header can't exceed total + * amount of data available. + */ + if(!(i & 1) && ((plen + ctx->hdrlen) > len)) { + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); + asn1_tlc_clear(ctx); + return 0; + } + } + } + + if(i & 0x80) { + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); + asn1_tlc_clear(ctx); + return 0; + } + if(exptag >= 0) { + if((exptag != ptag) || (expclass != pclass)) { + /* If type is OPTIONAL, not an error, but indicate missing + * type. + */ + if(opt) return -1; + asn1_tlc_clear(ctx); + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); + return 0; + } + /* We have a tag and class match, so assume we are going to do something with it */ + asn1_tlc_clear(ctx); + } + + if(i & 1) plen = len - (p - q); + + if(inf) *inf = i & 1; + + if(cst) *cst = i & V_ASN1_CONSTRUCTED; + + if(olen) *olen = plen; + if(oclass) *oclass = pclass; + if(otag) *otag = ptag; + + *in = p; + return 1; +} diff --git a/src/lib/libcrypto/asn1/tasn_enc.c b/src/lib/libcrypto/asn1/tasn_enc.c new file mode 100644 index 0000000000..f6c8ddef0a --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_enc.c @@ -0,0 +1,497 @@ +/* tasn_enc.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *seq, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int isset); + +/* Encode an ASN1 item, this is compatible with the + * standard 'i2d' function. 'out' points to + * a buffer to output the data to, in future we will + * have more advanced versions that can output data + * a piece at a time and this will simply be a special + * case. + * + * The new i2d has one additional feature. If the output + * buffer is NULL (i.e. *out == NULL) then a buffer is + * allocated and populated with the encoding. + */ + + +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) +{ + if(out && !*out) { + unsigned char *p, *buf; + int len; + len = ASN1_item_ex_i2d(&val, NULL, it, -1, 0); + if(len <= 0) return len; + buf = OPENSSL_malloc(len); + if(!buf) return -1; + p = buf; + ASN1_item_ex_i2d(&val, &p, it, -1, 0); + *out = buf; + return len; + } + + return ASN1_item_ex_i2d(&val, out, it, -1, 0); +} + +/* Encode an item, taking care of IMPLICIT tagging (if any). + * This function performs the normal item handling: it can be + * used in external types. + */ + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) +{ + const ASN1_TEMPLATE *tt = NULL; + unsigned char *p = NULL; + int i, seqcontlen, seqlen; + ASN1_STRING *strtmp; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + if((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) return 0; + if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; + else asn1_cb = 0; + + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) + return ASN1_template_i2d(pval, out, it->templates); + return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); + break; + + case ASN1_ITYPE_MSTRING: + strtmp = (ASN1_STRING *)*pval; + return asn1_i2d_ex_primitive(pval, out, it, -1, 0); + + case ASN1_ITYPE_CHOICE: + if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) + return 0; + i = asn1_get_choice_selector(pval, it); + if((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + const ASN1_TEMPLATE *chtt; + chtt = it->templates + i; + pchval = asn1_get_field_ptr(pval, chtt); + return ASN1_template_i2d(pchval, out, chtt); + } + /* Fixme: error condition if selector out of range */ + if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) + return 0; + break; + + case ASN1_ITYPE_EXTERN: + /* If new style i2d it does all the work */ + ef = it->funcs; + return ef->asn1_ex_i2d(pval, out, it, tag, aclass); + + case ASN1_ITYPE_COMPAT: + /* old style hackery... */ + cf = it->funcs; + if(out) p = *out; + i = cf->asn1_i2d(*pval, out); + /* Fixup for IMPLICIT tag: note this messes up for tags > 30, + * but so did the old code. Tags > 30 are very rare anyway. + */ + if(out && (tag != -1)) + *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); + return i; + + case ASN1_ITYPE_SEQUENCE: + i = asn1_enc_restore(&seqcontlen, out, pval, it); + /* An error occurred */ + if(i < 0) return 0; + /* We have a valid cached encoding... */ + if(i > 0) return seqcontlen; + /* Otherwise carry on */ + seqcontlen = 0; + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if(tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it)) + return 0; + /* First work out sequence content length */ + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if(!seqtt) return 0; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* FIXME: check for errors in enhanced version */ + /* FIXME: special handling of indefinite length encoding */ + seqcontlen += ASN1_template_i2d(pseqval, NULL, seqtt); + } + seqlen = ASN1_object_size(1, seqcontlen, tag); + if(!out) return seqlen; + /* Output SEQUENCE header */ + ASN1_put_object(out, 1, seqcontlen, tag, aclass); + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 1); + if(!seqtt) return 0; + pseqval = asn1_get_field_ptr(pval, seqtt); + /* FIXME: check for errors in enhanced version */ + ASN1_template_i2d(pseqval, out, seqtt); + } + if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it)) + return 0; + return seqlen; + + default: + return 0; + } + return 0; +} + +int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt) +{ + int i, ret, flags, aclass; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + if(flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + int isset, sktag, skaclass; + int skcontlen, sklen; + ASN1_VALUE *skitem; + if(!*pval) return 0; + if(flags & ASN1_TFLG_SET_OF) { + isset = 1; + /* 2 means we reorder */ + if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2; + } else isset = 0; + /* First work out inner tag value */ + if(flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if(isset) sktag = V_ASN1_SET; + else sktag = V_ASN1_SEQUENCE; + } + /* Now work out length of items */ + skcontlen = 0; + for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + skitem = sk_ASN1_VALUE_value(sk, i); + skcontlen += ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); + } + sklen = ASN1_object_size(1, skcontlen, sktag); + /* If EXPLICIT need length of surrounding tag */ + if(flags & ASN1_TFLG_EXPTAG) + ret = ASN1_object_size(1, sklen, tt->tag); + else ret = sklen; + + if(!out) return ret; + + /* Now encode this lot... */ + /* EXPLICIT tag */ + if(flags & ASN1_TFLG_EXPTAG) + ASN1_put_object(out, 1, sklen, tt->tag, aclass); + /* SET or SEQUENCE and IMPLICIT tag */ + ASN1_put_object(out, 1, skcontlen, sktag, skaclass); + /* And finally the stuff itself */ + asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset); + + return ret; + } + + if(flags & ASN1_TFLG_EXPTAG) { + /* EXPLICIT tagging */ + /* Find length of tagged item */ + i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); + if(!i) return 0; + /* Find length of EXPLICIT tag */ + ret = ASN1_object_size(1, i, tt->tag); + if(out) { + /* Output tag and item */ + ASN1_put_object(out, 1, i, tt->tag, aclass); + ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0); + } + return ret; + } + if(flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), tt->tag, aclass); + } + /* Nothing special: treat as normal */ + return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0); +} + +/* Temporary structure used to hold DER encoding of items for SET OF */ + +typedef struct { + unsigned char *data; + int length; + ASN1_VALUE *field; +} DER_ENC; + +static int der_cmp(const void *a, const void *b) +{ + const DER_ENC *d1 = a, *d2 = b; + int cmplen, i; + cmplen = (d1->length < d2->length) ? d1->length : d2->length; + i = memcmp(d1->data, d2->data, cmplen); + if(i) return i; + return d1->length - d2->length; +} + +/* Output the content octets of SET OF or SEQUENCE OF */ + +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort) +{ + int i; + ASN1_VALUE *skitem; + unsigned char *tmpdat = NULL, *p = NULL; + DER_ENC *derlst = NULL, *tder; + if(do_sort) { + /* Don't need to sort less than 2 items */ + if(sk_ASN1_VALUE_num(sk) < 2) do_sort = 0; + else { + derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*derlst)); + tmpdat = OPENSSL_malloc(skcontlen); + if(!derlst || !tmpdat) return 0; + } + } + /* If not sorting just output each item */ + if(!do_sort) { + for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + skitem = sk_ASN1_VALUE_value(sk, i); + ASN1_item_i2d(skitem, out, item); + } + return 1; + } + p = tmpdat; + /* Doing sort: build up a list of each member's DER encoding */ + for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + skitem = sk_ASN1_VALUE_value(sk, i); + tder->data = p; + tder->length = ASN1_item_i2d(skitem, &p, item); + tder->field = skitem; + } + /* Now sort them */ + qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); + /* Output sorted DER encoding */ + p = *out; + for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { + memcpy(p, tder->data, tder->length); + p += tder->length; + } + *out = p; + /* If do_sort is 2 then reorder the STACK */ + if(do_sort == 2) { + for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) + sk_ASN1_VALUE_set(sk, i, tder->field); + } + OPENSSL_free(derlst); + OPENSSL_free(tmpdat); + return 1; +} + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) +{ + int len; + int utype; + int usetag; + + utype = it->utype; + + /* Get length of content octets and maybe find + * out the underlying type. + */ + + len = asn1_ex_i2c(pval, NULL, &utype, it); + + /* If SEQUENCE, SET or OTHER then header is + * included in pseudo content octets so don't + * include tag+length. We need to check here + * because the call to asn1_ex_i2c() could change + * utype. + */ + if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || + (utype == V_ASN1_OTHER)) + usetag = 0; + else usetag = 1; + + /* -1 means omit type */ + + if(len == -1) return 0; + + /* If not implicitly tagged get tag from underlying type */ + if(tag == -1) tag = utype; + + /* Output tag+length followed by content octets */ + if(out) { + if(usetag) ASN1_put_object(out, 0, len, tag, aclass); + asn1_ex_i2c(pval, *out, &utype, it); + *out += len; + } + + if(usetag) return ASN1_object_size(0, len, tag); + return len; +} + +/* Produce content octets from a structure */ + +int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it) +{ + ASN1_BOOLEAN *tbool = NULL; + ASN1_STRING *strtmp; + ASN1_OBJECT *otmp; + int utype; + unsigned char *cont, c; + int len; + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if(pf && pf->prim_i2c) return pf->prim_i2c(pval, cout, putype, it); + + /* Should type be omitted? */ + if((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { + if(!*pval) return -1; + } + + if(it->itype == ASN1_ITYPE_MSTRING) { + /* If MSTRING type set the underlying type */ + strtmp = (ASN1_STRING *)*pval; + utype = strtmp->type; + *putype = utype; + } else if(it->utype == V_ASN1_ANY) { + /* If ANY set type and pointer to value */ + ASN1_TYPE *typ; + typ = (ASN1_TYPE *)*pval; + utype = typ->type; + *putype = utype; + pval = (ASN1_VALUE **)&typ->value.ptr; + } else utype = *putype; + + switch(utype) { + case V_ASN1_OBJECT: + otmp = (ASN1_OBJECT *)*pval; + cont = otmp->data; + len = otmp->length; + break; + + case V_ASN1_NULL: + cont = NULL; + len = 0; + break; + + case V_ASN1_BOOLEAN: + tbool = (ASN1_BOOLEAN *)pval; + if(*tbool == -1) return -1; + /* Default handling if value == size field then omit */ + if(*tbool && (it->size > 0)) return -1; + if(!*tbool && !it->size) return -1; + c = (unsigned char)*tbool; + cont = &c; + len = 1; + break; + + case V_ASN1_BIT_STRING: + return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); + break; + + case V_ASN1_INTEGER: + case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_NEG_ENUMERATED: + /* These are all have the same content format + * as ASN1_INTEGER + */ + return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + default: + /* All based on ASN1_STRING and handled the same */ + strtmp = (ASN1_STRING *)*pval; + cont = strtmp->data; + len = strtmp->length; + + break; + + } + if(cout && len) memcpy(cout, cont, len); + return len; +} diff --git a/src/lib/libcrypto/asn1/tasn_fre.c b/src/lib/libcrypto/asn1/tasn_fre.c new file mode 100644 index 0000000000..c7610776f2 --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_fre.c @@ -0,0 +1,226 @@ +/* tasn_fre.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include + +static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); + +/* Free up an ASN1 structure */ + +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) +{ + asn1_item_combine_free(&val, it, 0); +} + +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + asn1_item_combine_free(pval, it, 0); +} + +static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) +{ + const ASN1_TEMPLATE *tt = NULL, *seqtt; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + int i; + if(!pval) return; + if((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) return; + if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; + else asn1_cb = 0; + + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) ASN1_template_free(pval, it->templates); + else ASN1_primitive_free(pval, it); + break; + + case ASN1_ITYPE_MSTRING: + ASN1_primitive_free(pval, it); + break; + + case ASN1_ITYPE_CHOICE: + if(asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it); + if(i == 2) return; + } + i = asn1_get_choice_selector(pval, it); + if(asn1_cb) asn1_cb(ASN1_OP_FREE_PRE, pval, it); + if((i >= 0) && (i < it->tcount)) { + ASN1_VALUE **pchval; + tt = it->templates + i; + pchval = asn1_get_field_ptr(pval, tt); + ASN1_template_free(pchval, tt); + } + if(asn1_cb) asn1_cb(ASN1_OP_FREE_POST, pval, it); + if(!combine) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; + + case ASN1_ITYPE_COMPAT: + cf = it->funcs; + if(cf && cf->asn1_free) cf->asn1_free(*pval); + break; + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if(ef && ef->asn1_ex_free) ef->asn1_ex_free(pval, it); + break; + + case ASN1_ITYPE_SEQUENCE: + if(asn1_do_lock(pval, -1, it) > 0) return; + if(asn1_cb) { + i = asn1_cb(ASN1_OP_FREE_PRE, pval, it); + if(i == 2) return; + } + asn1_enc_free(pval, it); + /* If we free up as normal we will invalidate any + * ANY DEFINED BY field and we wont be able to + * determine the type of the field it defines. So + * free up in reverse order. + */ + tt = it->templates + it->tcount - 1; + for(i = 0; i < it->tcount; tt--, i++) { + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(pval, tt, 0); + if(!seqtt) continue; + pseqval = asn1_get_field_ptr(pval, seqtt); + ASN1_template_free(pseqval, seqtt); + } + if(asn1_cb) asn1_cb(ASN1_OP_FREE_POST, pval, it); + if(!combine) { + OPENSSL_free(*pval); + *pval = NULL; + } + break; + } +} + +void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + int i; + if(tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; + for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) { + ASN1_VALUE *vtmp; + vtmp = sk_ASN1_VALUE_value(sk, i); + asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0); + } + sk_ASN1_VALUE_free(sk); + *pval = NULL; + } else asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item), + tt->flags & ASN1_TFLG_COMBINE); +} + +void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int utype; + if(it) { + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if(pf && pf->prim_free) { + pf->prim_free(pval, it); + return; + } + } + /* Special case: if 'it' is NULL free contents of ASN1_TYPE */ + if(!it) { + ASN1_TYPE *typ = (ASN1_TYPE *)*pval; + utype = typ->type; + pval = (ASN1_VALUE **)&typ->value.ptr; + if(!*pval) return; + } else if(it->itype == ASN1_ITYPE_MSTRING) { + utype = -1; + if(!*pval) return; + } else { + utype = it->utype; + if((utype != V_ASN1_BOOLEAN) && !*pval) return; + } + + switch(utype) { + case V_ASN1_OBJECT: + ASN1_OBJECT_free((ASN1_OBJECT *)*pval); + break; + + case V_ASN1_BOOLEAN: + *(ASN1_BOOLEAN *)pval = it->size; + return; + + case V_ASN1_NULL: + break; + + case V_ASN1_ANY: + ASN1_primitive_free(pval, NULL); + OPENSSL_free(*pval); + break; + + default: + ASN1_STRING_free((ASN1_STRING *)*pval); + *pval = NULL; + break; + } + *pval = NULL; +} diff --git a/src/lib/libcrypto/asn1/tasn_new.c b/src/lib/libcrypto/asn1/tasn_new.c new file mode 100644 index 0000000000..e33861f864 --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_new.c @@ -0,0 +1,348 @@ +/* tasn_new.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include +#include + +static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); + +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) +{ + ASN1_VALUE *ret = NULL; + if(ASN1_item_ex_new(&ret, it) > 0) return ret; + return NULL; +} + +/* Allocate an ASN1 structure */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + return asn1_item_ex_combine_new(pval, it, 0); +} + +static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine) +{ + const ASN1_TEMPLATE *tt = NULL; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_AUX *aux = it->funcs; + ASN1_aux_cb *asn1_cb; + ASN1_VALUE **pseqval; + int i; + if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb; + else asn1_cb = 0; + + if(!combine) *pval = NULL; + +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_push_info(it->sname); +#endif + + switch(it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if(ef && ef->asn1_ex_new) { + if(!ef->asn1_ex_new(pval, it)) + goto memerr; + } + break; + + case ASN1_ITYPE_COMPAT: + cf = it->funcs; + if(cf && cf->asn1_new) { + *pval = cf->asn1_new(); + if(!*pval) goto memerr; + } + break; + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) { + if(!ASN1_template_new(pval, it->templates)) + goto memerr; + } else { + if(!ASN1_primitive_new(pval, it)) + goto memerr; + } + break; + + case ASN1_ITYPE_MSTRING: + if(!ASN1_primitive_new(pval, it)) + goto memerr; + break; + + case ASN1_ITYPE_CHOICE: + if(asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it); + if(!i) goto auxerr; + if(i==2) { +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_pop_info(); +#endif + return 1; + } + } + if(!combine) { + *pval = OPENSSL_malloc(it->size); + if(!*pval) goto memerr; + memset(*pval, 0, it->size); + } + asn1_set_choice_selector(pval, -1, it); + if(asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it)) + goto auxerr; + break; + + case ASN1_ITYPE_SEQUENCE: + if(asn1_cb) { + i = asn1_cb(ASN1_OP_NEW_PRE, pval, it); + if(!i) goto auxerr; + if(i==2) { +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_pop_info(); +#endif + return 1; + } + } + if(!combine) { + *pval = OPENSSL_malloc(it->size); + if(!*pval) goto memerr; + memset(*pval, 0, it->size); + asn1_do_lock(pval, 0, it); + asn1_enc_init(pval, it); + } + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + pseqval = asn1_get_field_ptr(pval, tt); + if(!ASN1_template_new(pseqval, tt)) goto memerr; + } + if(asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it)) + goto auxerr; + break; + } +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_pop_info(); +#endif + return 1; + + memerr: + ASN1err(ASN1_F_ASN1_ITEM_NEW, ERR_R_MALLOC_FAILURE); +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_pop_info(); +#endif + return 0; + + auxerr: + ASN1err(ASN1_F_ASN1_ITEM_NEW, ASN1_R_AUX_ERROR); + ASN1_item_ex_free(pval, it); +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_pop_info(); +#endif + return 0; + +} + +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + const ASN1_EXTERN_FUNCS *ef; + + switch(it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if(ef && ef->asn1_ex_clear) + ef->asn1_ex_clear(pval, it); + else *pval = NULL; + break; + + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) + asn1_template_clear(pval, it->templates); + else + asn1_primitive_clear(pval, it); + break; + + case ASN1_ITYPE_MSTRING: + asn1_primitive_clear(pval, it); + break; + + case ASN1_ITYPE_COMPAT: + case ASN1_ITYPE_CHOICE: + case ASN1_ITYPE_SEQUENCE: + *pval = NULL; + break; + } +} + + +int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); + int ret; + if(tt->flags & ASN1_TFLG_OPTIONAL) { + asn1_template_clear(pval, tt); + return 1; + } + /* If ANY DEFINED BY nothing to do */ + + if(tt->flags & ASN1_TFLG_ADB_MASK) { + *pval = NULL; + return 1; + } +#ifdef CRYPTO_MDEBUG + if(tt->field_name) CRYPTO_push_info(tt->field_name); +#endif + /* If SET OF or SEQUENCE OF, its a STACK */ + if(tt->flags & ASN1_TFLG_SK_MASK) { + STACK_OF(ASN1_VALUE) *skval; + skval = sk_ASN1_VALUE_new_null(); + if(!skval) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); + ret = 0; + goto done; + } + *pval = (ASN1_VALUE *)skval; + ret = 1; + goto done; + } + /* Otherwise pass it back to the item routine */ + ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE); + done: +#ifdef CRYPTO_MDEBUG + if(it->sname) CRYPTO_pop_info(); +#endif + return ret; +} + +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + /* If ADB or STACK just NULL the field */ + if(tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK)) + *pval = NULL; + else + asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); +} + + +/* NB: could probably combine most of the real XXX_new() behaviour and junk all the old + * functions. + */ + +int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_TYPE *typ; + int utype; + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if(pf && pf->prim_new) return pf->prim_new(pval, it); + if(!it || (it->itype == ASN1_ITYPE_MSTRING)) utype = -1; + else utype = it->utype; + switch(utype) { + case V_ASN1_OBJECT: + *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); + return 1; + + case V_ASN1_BOOLEAN: + *(ASN1_BOOLEAN *)pval = it->size; + return 1; + + case V_ASN1_NULL: + *pval = (ASN1_VALUE *)1; + return 1; + + case V_ASN1_ANY: + typ = OPENSSL_malloc(sizeof(ASN1_TYPE)); + if(!typ) return 0; + typ->value.ptr = NULL; + typ->type = -1; + *pval = (ASN1_VALUE *)typ; + break; + + default: + *pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype); + break; + } + if(*pval) return 1; + return 0; +} + +void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int utype; + const ASN1_PRIMITIVE_FUNCS *pf; + pf = it->funcs; + if(pf) { + if(pf->prim_clear) + pf->prim_clear(pval, it); + else + *pval = NULL; + return; + } + if(!it || (it->itype == ASN1_ITYPE_MSTRING)) utype = -1; + else utype = it->utype; + if(utype == V_ASN1_BOOLEAN) + *(ASN1_BOOLEAN *)pval = it->size; + else *pval = NULL; +} diff --git a/src/lib/libcrypto/asn1/tasn_prn.c b/src/lib/libcrypto/asn1/tasn_prn.c new file mode 100644 index 0000000000..fab67ae5ac --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_prn.c @@ -0,0 +1,198 @@ +/* tasn_prn.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include +#include + +/* Print routines. Print out a whole structure from a template. + */ + +static int asn1_item_print_nm(BIO *out, void *fld, int indent, const ASN1_ITEM *it, const char *name); + +int ASN1_item_print(BIO *out, void *fld, int indent, const ASN1_ITEM *it) +{ + return asn1_item_print_nm(out, fld, indent, it, it->sname); +} + +static int asn1_item_print_nm(BIO *out, void *fld, int indent, const ASN1_ITEM *it, const char *name) +{ + ASN1_STRING *str; + const ASN1_TEMPLATE *tt; + void *tmpfld; + int i; + if(!fld) { + BIO_printf(out, "%*s%s ABSENT\n", indent, "", name); + return 1; + } + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) + return ASN1_template_print(out, fld, indent, it->templates); + return asn1_primitive_print(out, fld, it->utype, indent, name); + break; + + case ASN1_ITYPE_MSTRING: + str = fld; + return asn1_primitive_print(out, fld, str->type, indent, name); + + case ASN1_ITYPE_EXTERN: + BIO_printf(out, "%*s%s:EXTERNAL TYPE %s %s\n", indent, "", name, it->sname, fld ? "" : "ABSENT"); + return 1; + case ASN1_ITYPE_COMPAT: + BIO_printf(out, "%*s%s:COMPATIBLE TYPE %s %s\n", indent, "", name, it->sname, fld ? "" : "ABSENT"); + return 1; + + + case ASN1_ITYPE_CHOICE: + /* CHOICE type, get selector */ + i = asn1_get_choice_selector(fld, it); + /* This should never happen... */ + if((i < 0) || (i >= it->tcount)) { + BIO_printf(out, "%s selector [%d] out of range\n", it->sname, i); + return 1; + } + tt = it->templates + i; + tmpfld = asn1_get_field(fld, tt); + return ASN1_template_print(out, tmpfld, indent, tt); + + case ASN1_ITYPE_SEQUENCE: + BIO_printf(out, "%*s%s {\n", indent, "", name); + /* Get each field entry */ + for(i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + tmpfld = asn1_get_field(fld, tt); + ASN1_template_print(out, tmpfld, indent + 2, tt); + } + BIO_printf(out, "%*s}\n", indent, ""); + return 1; + + default: + return 0; + } +} + +int ASN1_template_print(BIO *out, void *fld, int indent, const ASN1_TEMPLATE *tt) +{ + int i, flags; +#if 0 + if(!fld) return 0; +#endif + flags = tt->flags; + if(flags & ASN1_TFLG_SK_MASK) { + char *tname; + void *skitem; + /* SET OF, SEQUENCE OF */ + if(flags & ASN1_TFLG_SET_OF) tname = "SET"; + else tname = "SEQUENCE"; + if(fld) { + BIO_printf(out, "%*s%s OF %s {\n", indent, "", tname, tt->field_name); + for(i = 0; i < sk_num(fld); i++) { + skitem = sk_value(fld, i); + asn1_item_print_nm(out, skitem, indent + 2, tt->item, ""); + } + BIO_printf(out, "%*s}\n", indent, ""); + } else + BIO_printf(out, "%*s%s OF %s ABSENT\n", indent, "", tname, tt->field_name); + return 1; + } + return asn1_item_print_nm(out, fld, indent, tt->item, tt->field_name); +} + +static int asn1_primitive_print(BIO *out, void *fld, long utype, int indent, const char *name) +{ + ASN1_STRING *str = fld; + if(fld) { + if(utype == V_ASN1_BOOLEAN) { + int *bool = fld; +if(*bool == -1) printf("BOOL MISSING\n"); + BIO_printf(out, "%*s%s:%s", indent, "", "BOOLEAN", *bool ? "TRUE" : "FALSE"); + } else if((utype == V_ASN1_INTEGER) + || (utype == V_ASN1_ENUMERATED)) { + char *s, *nm; + s = i2s_ASN1_INTEGER(NULL, fld); + if(utype == V_ASN1_INTEGER) nm = "INTEGER"; + else nm = "ENUMERATED"; + BIO_printf(out, "%*s%s:%s", indent, "", nm, s); + OPENSSL_free(s); + } else if(utype == V_ASN1_NULL) { + BIO_printf(out, "%*s%s", indent, "", "NULL"); + } else if(utype == V_ASN1_UTCTIME) { + BIO_printf(out, "%*s%s:%s:", indent, "", name, "UTCTIME"); + ASN1_UTCTIME_print(out, str); + } else if(utype == V_ASN1_GENERALIZEDTIME) { + BIO_printf(out, "%*s%s:%s:", indent, "", name, "GENERALIZEDTIME"); + ASN1_GENERALIZEDTIME_print(out, str); + } else if(utype == V_ASN1_OBJECT) { + char objbuf[80], *ln; + ln = OBJ_nid2ln(OBJ_obj2nid(fld)); + if(!ln) ln = ""; + OBJ_obj2txt(objbuf, 80, fld, 1); + BIO_printf(out, "%*s%s:%s (%s)", indent, "", "OBJECT", ln, objbuf); + } else { + BIO_printf(out, "%*s%s:", indent, "", name); + ASN1_STRING_print_ex(out, str, ASN1_STRFLGS_DUMP_UNKNOWN|ASN1_STRFLGS_SHOW_TYPE); + } + BIO_printf(out, "\n"); + } else BIO_printf(out, "%*s%s [ABSENT]\n", indent, "", name); + return 1; +} diff --git a/src/lib/libcrypto/asn1/tasn_typ.c b/src/lib/libcrypto/asn1/tasn_typ.c new file mode 100644 index 0000000000..804d2eeba2 --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_typ.c @@ -0,0 +1,133 @@ +/* tasn_typ.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include + +/* Declarations for string types */ + + +IMPLEMENT_ASN1_TYPE(ASN1_INTEGER) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER) + +IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED) + +IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_BIT_STRING) + +IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_OCTET_STRING) + +IMPLEMENT_ASN1_TYPE(ASN1_NULL) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL) + +IMPLEMENT_ASN1_TYPE(ASN1_OBJECT) + +IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTF8STRING) + +IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_T61STRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING) + +IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING) + +IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME) + +IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) + +IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_BMPSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_ANY) + +/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */ +IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE) + +IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +/* Multistring types */ + +IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) + +IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) + +/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */ +IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1) +IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1) +IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0) diff --git a/src/lib/libcrypto/asn1/tasn_utl.c b/src/lib/libcrypto/asn1/tasn_utl.c new file mode 100644 index 0000000000..8996ce8c13 --- /dev/null +++ b/src/lib/libcrypto/asn1/tasn_utl.c @@ -0,0 +1,253 @@ +/* tasn_utl.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include +#include + +/* Utility functions for manipulating fields and offsets */ + +/* Add 'offset' to 'addr' */ +#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset) + +/* Given an ASN1_ITEM CHOICE type return + * the selector value + */ + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + int *sel = offset2ptr(*pval, it->utype); + return *sel; +} + +/* Given an ASN1_ITEM CHOICE type set + * the selector value, return old value. + */ + +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it) +{ + int *sel, ret; + sel = offset2ptr(*pval, it->utype); + ret = *sel; + *sel = value; + return ret; +} + +/* Do reference counting. The value 'op' decides what to do. + * if it is +1 then the count is incremented. If op is 0 count is + * set to 1. If op is -1 count is decremented and the return value + * is the current refrence count or 0 if no reference count exists. + */ + +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) +{ + const ASN1_AUX *aux; + int *lck, ret; + if(it->itype != ASN1_ITYPE_SEQUENCE) return 0; + aux = it->funcs; + if(!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) return 0; + lck = offset2ptr(*pval, aux->ref_offset); + if(op == 0) { + *lck = 1; + return 1; + } + ret = CRYPTO_add(lck, op, aux->ref_lock); +#ifdef REF_PRINT + fprintf(stderr, "%s: Reference Count: %d\n", it->sname, *lck); +#endif +#ifdef REF_CHECK + if(ret < 0) + fprintf(stderr, "%s, bad reference count\n", it->sname); +#endif + return ret; +} + +static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + const ASN1_AUX *aux; + if(!pval || !*pval) return NULL; + aux = it->funcs; + if(!aux || !(aux->flags & ASN1_AFLG_ENCODING)) return NULL; + return offset2ptr(*pval, aux->enc_offset); +} + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if(enc) { + enc->enc = NULL; + enc->len = 0; + enc->modified = 1; + } +} + +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if(enc) { + if(enc->enc) OPENSSL_free(enc->enc); + enc->enc = NULL; + enc->len = 0; + enc->modified = 1; + } +} + +int asn1_enc_save(ASN1_VALUE **pval, unsigned char *in, int inlen, const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if(!enc) return 1; + + if(enc->enc) OPENSSL_free(enc->enc); + enc->enc = OPENSSL_malloc(inlen); + if(!enc->enc) return 0; + memcpy(enc->enc, in, inlen); + enc->len = inlen; + enc->modified = 0; + + return 1; +} + +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + ASN1_ENCODING *enc; + enc = asn1_get_enc_ptr(pval, it); + if(!enc || enc->modified) return 0; + if(out) { + memcpy(*out, enc->enc, enc->len); + *out += enc->len; + } + if(len) *len = enc->len; + return 1; +} + +/* Given an ASN1_TEMPLATE get a pointer to a field */ +ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + ASN1_VALUE **pvaltmp; + if(tt->flags & ASN1_TFLG_COMBINE) return pval; + pvaltmp = offset2ptr(*pval, tt->offset); + /* NOTE for BOOLEAN types the field is just a plain + * int so we can't return int **, so settle for + * (int *). + */ + return pvaltmp; +} + +/* Handle ANY DEFINED BY template, find the selector, look up + * the relevant ASN1_TEMPLATE in the table and return it. + */ + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr) +{ + const ASN1_ADB *adb; + const ASN1_ADB_TABLE *atbl; + long selector; + ASN1_VALUE **sfld; + int i; + if(!(tt->flags & ASN1_TFLG_ADB_MASK)) return tt; + + /* Else ANY DEFINED BY ... get the table */ + adb = ASN1_ADB_ptr(tt->item); + + /* Get the selector field */ + sfld = offset2ptr(*pval, adb->offset); + + /* Check if NULL */ + if(!sfld) { + if(!adb->null_tt) goto err; + return adb->null_tt; + } + + /* Convert type to a long: + * NB: don't check for NID_undef here because it + * might be a legitimate value in the table + */ + if(tt->flags & ASN1_TFLG_ADB_OID) + selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); + else + selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); + + /* Try to find matching entry in table + * Maybe should check application types first to + * allow application override? Might also be useful + * to have a flag which indicates table is sorted and + * we can do a binary search. For now stick to a + * linear search. + */ + + for(atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) + if(atbl->value == selector) return &atbl->tt; + + /* FIXME: need to search application table too */ + + /* No match, return default type */ + if(!adb->default_tt) goto err; + return adb->default_tt; + + err: + /* FIXME: should log the value or OID of unsupported type */ + if(nullerr) ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); + return NULL; +} diff --git a/src/lib/libcrypto/asn1/x_bignum.c b/src/lib/libcrypto/asn1/x_bignum.c new file mode 100644 index 0000000000..848c7a0877 --- /dev/null +++ b/src/lib/libcrypto/asn1/x_bignum.c @@ -0,0 +1,137 @@ +/* x_bignum.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 + +/* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER as a + * BIGNUM directly. Currently it ignores the sign which isn't a problem since all + * BIGNUMs used are non negative and anything that looks negative is normally due + * to an encoding error. + */ + +#define BN_SENSITIVE 1 + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +static int bn_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); + +static ASN1_PRIMITIVE_FUNCS bignum_pf = { + NULL, 0, + bn_new, + bn_free, + 0, + bn_c2i, + bn_i2c +}; + +ASN1_ITEM_start(BIGNUM) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM" +ASN1_ITEM_end(BIGNUM) + +ASN1_ITEM_start(CBIGNUM) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM" +ASN1_ITEM_end(CBIGNUM) + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *pval = (ASN1_VALUE *)BN_new(); + if(*pval) return 1; + else return 0; +} + +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if(!*pval) return; + if(it->size & BN_SENSITIVE) BN_clear_free((BIGNUM *)*pval); + else BN_free((BIGNUM *)*pval); + *pval = NULL; +} + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it) +{ + BIGNUM *bn; + int pad; + if(!*pval) return -1; + bn = (BIGNUM *)*pval; + /* If MSB set in an octet we need a padding byte */ + if(BN_num_bits(bn) & 0x7) pad = 0; + else pad = 1; + if(cont) { + if(pad) *cont++ = 0; + BN_bn2bin(bn, cont); + } + return pad + BN_num_bytes(bn); +} + +static int bn_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it) +{ + BIGNUM *bn; + if(!*pval) bn_new(pval, it); + bn = (BIGNUM *)*pval; + if(!BN_bin2bn(cont, len, bn)) { + bn_free(pval, it); + return 0; + } + return 1; +} + + diff --git a/src/lib/libcrypto/asn1/x_long.c b/src/lib/libcrypto/asn1/x_long.c new file mode 100644 index 0000000000..c5f25956cb --- /dev/null +++ b/src/lib/libcrypto/asn1/x_long.c @@ -0,0 +1,169 @@ +/* x_long.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 + +/* Custom primitive type for long handling. This converts between an ASN1_INTEGER + * and a long directly. + */ + + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +static int long_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); + +static ASN1_PRIMITIVE_FUNCS long_pf = { + NULL, 0, + long_new, + long_free, + long_free, /* Clear should set to initial value */ + long_c2i, + long_i2c +}; + +ASN1_ITEM_start(LONG) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG" +ASN1_ITEM_end(LONG) + +ASN1_ITEM_start(ZLONG) + ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG" +ASN1_ITEM_end(ZLONG) + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *(long *)pval = it->size; + return 1; +} + +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + *(long *)pval = it->size; +} + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it) +{ + long ltmp; + unsigned long utmp; + int clen, pad, i; + /* this exists to bypass broken gcc optimization */ + char *cp = (char *)pval; + + /* use memcpy, because we may not be long aligned */ + memcpy(<mp, cp, sizeof(long)); + + if(ltmp == it->size) return -1; + /* Convert the long to positive: we subtract one if negative so + * we can cleanly handle the padding if only the MSB of the leading + * octet is set. + */ + if(ltmp < 0) utmp = -ltmp - 1; + else utmp = ltmp; + clen = BN_num_bits_word(utmp); + /* If MSB of leading octet set we need to pad */ + if(!(clen & 0x7)) pad = 1; + else pad = 0; + + /* Convert number of bits to number of octets */ + clen = (clen + 7) >> 3; + + if(cont) { + if(pad) *cont++ = (ltmp < 0) ? 0xff : 0; + for(i = clen - 1; i >= 0; i--) { + cont[i] = (unsigned char)(utmp & 0xff); + if(ltmp < 0) cont[i] ^= 0xff; + utmp >>= 8; + } + } + return clen + pad; +} + +static int long_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it) +{ + int neg, i; + long ltmp; + unsigned long utmp = 0; + char *cp = (char *)pval; + if(len > sizeof(long)) { + ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + /* Is it negative? */ + if(len && (cont[0] & 0x80)) neg = 1; + else neg = 0; + utmp = 0; + for(i = 0; i < len; i++) { + utmp <<= 8; + if(neg) utmp |= cont[i] ^ 0xff; + else utmp |= cont[i]; + } + ltmp = (long)utmp; + if(neg) { + ltmp++; + ltmp = -ltmp; + } + if(ltmp == it->size) { + ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); + return 0; + } + memcpy(cp, <mp, sizeof(long)); + return 1; +} diff --git a/src/lib/libcrypto/asn1/x_x509a.c b/src/lib/libcrypto/asn1/x_x509a.c new file mode 100644 index 0000000000..b9987ea968 --- /dev/null +++ b/src/lib/libcrypto/asn1/x_x509a.c @@ -0,0 +1,200 @@ +/* a_x509a.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 + +/* X509_CERT_AUX routines. These are used to encode additional + * user modifiable data about a certificate. This data is + * appended to the X509 encoding when the *_X509_AUX routines + * are used. This means that the "traditional" X509 routines + * will simply ignore the extra data. + */ + +static X509_CERT_AUX *aux_get(X509 *x); + +X509_CERT_AUX *d2i_X509_CERT_AUX(X509_CERT_AUX **a, unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a, X509_CERT_AUX *, X509_CERT_AUX_new); + + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + + M_ASN1_D2I_get_seq_opt_type(ASN1_OBJECT, ret->trust, + d2i_ASN1_OBJECT, ASN1_OBJECT_free); + M_ASN1_D2I_get_IMP_set_opt_type(ASN1_OBJECT, ret->reject, + d2i_ASN1_OBJECT, ASN1_OBJECT_free, 0); + M_ASN1_D2I_get_opt(ret->alias, d2i_ASN1_UTF8STRING, V_ASN1_UTF8STRING); + M_ASN1_D2I_get_opt(ret->keyid, d2i_ASN1_OCTET_STRING, V_ASN1_OCTET_STRING); + M_ASN1_D2I_get_IMP_set_opt_type(X509_ALGOR, ret->other, + d2i_X509_ALGOR, X509_ALGOR_free, 1); + + M_ASN1_D2I_Finish(a, X509_CERT_AUX_free, ASN1_F_D2I_X509_CERT_AUX); +} + +X509_CERT_AUX *X509_CERT_AUX_new() +{ + X509_CERT_AUX *ret = NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, X509_CERT_AUX); + ret->trust = NULL; + ret->reject = NULL; + ret->alias = NULL; + ret->keyid = NULL; + ret->other = NULL; + return(ret); + M_ASN1_New_Error(ASN1_F_X509_CERT_AUX_NEW); +} + +void X509_CERT_AUX_free(X509_CERT_AUX *a) +{ + if(a == NULL) return; + sk_ASN1_OBJECT_pop_free(a->trust, ASN1_OBJECT_free); + sk_ASN1_OBJECT_pop_free(a->reject, ASN1_OBJECT_free); + ASN1_UTF8STRING_free(a->alias); + ASN1_OCTET_STRING_free(a->keyid); + sk_X509_ALGOR_pop_free(a->other, X509_ALGOR_free); + Free(a); +} + +int i2d_X509_CERT_AUX(X509_CERT_AUX *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len_SEQUENCE_opt_type(ASN1_OBJECT, a->trust, i2d_ASN1_OBJECT); + M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(ASN1_OBJECT, a->reject, i2d_ASN1_OBJECT, 0); + + M_ASN1_I2D_len(a->alias, i2d_ASN1_UTF8STRING); + M_ASN1_I2D_len(a->keyid, i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(X509_ALGOR, a->other, i2d_X509_ALGOR, 1); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put_SEQUENCE_opt_type(ASN1_OBJECT, a->trust, i2d_ASN1_OBJECT); + M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(ASN1_OBJECT, a->reject, i2d_ASN1_OBJECT, 0); + + M_ASN1_I2D_put(a->alias, i2d_ASN1_UTF8STRING); + M_ASN1_I2D_put(a->keyid, i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(X509_ALGOR, a->other, i2d_X509_ALGOR, 1); + + M_ASN1_I2D_finish(); +} + +static X509_CERT_AUX *aux_get(X509 *x) +{ + if(!x) return NULL; + if(!x->aux && !(x->aux = X509_CERT_AUX_new())) return NULL; + return x->aux; +} + +int X509_alias_set1(X509 *x, unsigned char *name, int len) +{ + X509_CERT_AUX *aux; + if(!(aux = aux_get(x))) return 0; + if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0; + return ASN1_STRING_set(aux->alias, name, len); +} + +unsigned char *X509_alias_get0(X509 *x, int *len) +{ + if(!x->aux || !x->aux->alias) return NULL; + if(len) *len = x->aux->alias->length; + return x->aux->alias->data; +} + +int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj) +{ + X509_CERT_AUX *aux; + ASN1_OBJECT *objtmp; + if(!(objtmp = OBJ_dup(obj))) return 0; + if(!(aux = aux_get(x))) return 0; + if(!aux->trust + && !(aux->trust = sk_ASN1_OBJECT_new_null())) return 0; + return sk_ASN1_OBJECT_push(aux->trust, objtmp); +} + +int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj) +{ + X509_CERT_AUX *aux; + ASN1_OBJECT *objtmp; + if(!(objtmp = OBJ_dup(obj))) return 0; + if(!(aux = aux_get(x))) return 0; + if(!aux->reject + && !(aux->reject = sk_ASN1_OBJECT_new_null())) return 0; + return sk_ASN1_OBJECT_push(aux->reject, objtmp); +} + +void X509_trust_clear(X509 *x) +{ + if(x->aux && x->aux->trust) { + sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free); + x->aux->trust = NULL; + } +} + +void X509_reject_clear(X509 *x) +{ + if(x->aux && x->aux->reject) { + sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free); + x->aux->reject = NULL; + } +} + diff --git a/src/lib/libcrypto/bf/bf_locl.h b/src/lib/libcrypto/bf/bf_locl.h new file mode 100644 index 0000000000..05756b5d3b --- /dev/null +++ b/src/lib/libcrypto/bf/bf_locl.h @@ -0,0 +1,219 @@ +/* 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 +#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)) + +/* This is actually a big endian algorithm, the most significate 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/src/lib/libcrypto/bio/bf_lbuf.c b/src/lib/libcrypto/bio/bf_lbuf.c new file mode 100644 index 0000000000..7bcf8ed941 --- /dev/null +++ b/src/lib/libcrypto/bio/bf_lbuf.c @@ -0,0 +1,397 @@ +/* crypto/bio/bf_buff.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 + +static int linebuffer_write(BIO *h, const char *buf,int num); +static int linebuffer_read(BIO *h, char *buf, int size); +static int linebuffer_puts(BIO *h, const char *str); +static int linebuffer_gets(BIO *h, char *str, int size); +static long linebuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int linebuffer_new(BIO *h); +static int linebuffer_free(BIO *data); +static long linebuffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); + +/* A 10k maximum should be enough for most purposes */ +#define DEFAULT_LINEBUFFER_SIZE 1024*10 + +/* #define DEBUG */ + +static BIO_METHOD methods_linebuffer= + { + BIO_TYPE_LINEBUFFER, + "linebuffer", + linebuffer_write, + linebuffer_read, + linebuffer_puts, + linebuffer_gets, + linebuffer_ctrl, + linebuffer_new, + linebuffer_free, + linebuffer_callback_ctrl, + }; + +BIO_METHOD *BIO_f_linebuffer(void) + { + return(&methods_linebuffer); + } + +typedef struct bio_linebuffer_ctx_struct + { + char *obuf; /* the output char array */ + int obuf_size; /* how big is the output buffer */ + int obuf_len; /* how many bytes are in it */ + } BIO_LINEBUFFER_CTX; + +static int linebuffer_new(BIO *bi) + { + BIO_LINEBUFFER_CTX *ctx; + + ctx=(BIO_LINEBUFFER_CTX *)OPENSSL_malloc(sizeof(BIO_LINEBUFFER_CTX)); + if (ctx == NULL) return(0); + ctx->obuf=(char *)OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE); + if (ctx->obuf == NULL) { OPENSSL_free(ctx); return(0); } + ctx->obuf_size=DEFAULT_LINEBUFFER_SIZE; + ctx->obuf_len=0; + + bi->init=1; + bi->ptr=(char *)ctx; + bi->flags=0; + return(1); + } + +static int linebuffer_free(BIO *a) + { + BIO_LINEBUFFER_CTX *b; + + if (a == NULL) return(0); + b=(BIO_LINEBUFFER_CTX *)a->ptr; + if (b->obuf != NULL) OPENSSL_free(b->obuf); + OPENSSL_free(a->ptr); + a->ptr=NULL; + a->init=0; + a->flags=0; + return(1); + } + +static int linebuffer_read(BIO *b, char *out, int outl) + { + int ret=0; + + if (out == NULL) return(0); + if (b->next_bio == NULL) return(0); + ret=BIO_read(b->next_bio,out,outl); + BIO_clear_retry_flags(b); + BIO_copy_next_retry(b); + return(ret); + } + +static int linebuffer_write(BIO *b, const char *in, int inl) + { + int i,num=0,foundnl; + BIO_LINEBUFFER_CTX *ctx; + + if ((in == NULL) || (inl <= 0)) return(0); + ctx=(BIO_LINEBUFFER_CTX *)b->ptr; + if ((ctx == NULL) || (b->next_bio == NULL)) return(0); + + BIO_clear_retry_flags(b); + + do + { + const char *p; + + for(p = in; p < in + inl && *p != '\n'; p++) + ; + if (*p == '\n') + { + p++; + foundnl = 1; + } + else + foundnl = 0; + + /* If a NL was found and we already have text in the save + buffer, concatenate them and write */ + while ((foundnl || p - in > ctx->obuf_size - ctx->obuf_len) + && ctx->obuf_len > 0) + { + int orig_olen = ctx->obuf_len; + + i = ctx->obuf_size - ctx->obuf_len; + if (p - in > 0) + { + if (i >= p - in) + { + memcpy(&(ctx->obuf[ctx->obuf_len]), + in,p - in); + ctx->obuf_len += p - in; + inl -= p - in; + num += p - in; + in = p; + } + else + { + memcpy(&(ctx->obuf[ctx->obuf_len]), + in,i); + ctx->obuf_len += i; + inl -= i; + in += i; + num += i; + } + } + +#ifdef DEBUG +BIO_write(b->next_bio, "<*<", 3); +#endif + i=BIO_write(b->next_bio, + ctx->obuf, ctx->obuf_len); + if (i <= 0) + { + ctx->obuf_len = orig_olen; + BIO_copy_next_retry(b); + +#ifdef DEBUG +BIO_write(b->next_bio, ">*>", 3); +#endif + if (i < 0) return((num > 0)?num:i); + if (i == 0) return(num); + } +#ifdef DEBUG +BIO_write(b->next_bio, ">*>", 3); +#endif + if (i < ctx->obuf_len) + memmove(ctx->obuf, ctx->obuf + i, + ctx->obuf_len - i); + ctx->obuf_len-=i; + } + + /* Now that the save buffer is emptied, let's write the input + buffer if a NL was found and there is anything to write. */ + if ((foundnl || p - in > ctx->obuf_size) && p - in > 0) + { +#ifdef DEBUG +BIO_write(b->next_bio, "<*<", 3); +#endif + i=BIO_write(b->next_bio,in,p - in); + if (i <= 0) + { + BIO_copy_next_retry(b); +#ifdef DEBUG +BIO_write(b->next_bio, ">*>", 3); +#endif + if (i < 0) return((num > 0)?num:i); + if (i == 0) return(num); + } +#ifdef DEBUG +BIO_write(b->next_bio, ">*>", 3); +#endif + num+=i; + in+=i; + inl-=i; + } + } + while(foundnl && inl > 0); + /* We've written as much as we can. The rest of the input buffer, if + any, is text that doesn't and with a NL and therefore needs to be + saved for the next trip. */ + if (inl > 0) + { + memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); + ctx->obuf_len += inl; + num += inl; + } + return num; + } + +static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) + { + BIO *dbio; + BIO_LINEBUFFER_CTX *ctx; + long ret=1; + char *p; + int r; + int obs; + + ctx=(BIO_LINEBUFFER_CTX *)b->ptr; + + switch (cmd) + { + case BIO_CTRL_RESET: + ctx->obuf_len=0; + if (b->next_bio == NULL) return(0); + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + break; + case BIO_CTRL_INFO: + ret=(long)ctx->obuf_len; + break; + case BIO_CTRL_WPENDING: + ret=(long)ctx->obuf_len; + if (ret == 0) + { + if (b->next_bio == NULL) return(0); + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + } + break; + case BIO_C_SET_BUFF_SIZE: + obs=(int)num; + p=ctx->obuf; + if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) + { + p=(char *)OPENSSL_malloc((int)num); + if (p == NULL) + goto malloc_error; + } + if (ctx->obuf != p) + { + if (ctx->obuf_len > obs) + { + ctx->obuf_len = obs; + } + memcpy(p, ctx->obuf, ctx->obuf_len); + OPENSSL_free(ctx->obuf); + ctx->obuf=p; + ctx->obuf_size=obs; + } + break; + case BIO_C_DO_STATE_MACHINE: + if (b->next_bio == NULL) return(0); + BIO_clear_retry_flags(b); + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + BIO_copy_next_retry(b); + break; + + case BIO_CTRL_FLUSH: + if (b->next_bio == NULL) return(0); + if (ctx->obuf_len <= 0) + { + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + break; + } + + for (;;) + { + BIO_clear_retry_flags(b); + if (ctx->obuf_len > 0) + { + r=BIO_write(b->next_bio, + ctx->obuf, ctx->obuf_len); +#if 0 +fprintf(stderr,"FLUSH %3d -> %3d\n",ctx->obuf_len,r); +#endif + BIO_copy_next_retry(b); + if (r <= 0) return((long)r); + if (r < ctx->obuf_len) + memmove(ctx->obuf, ctx->obuf + r, + ctx->obuf_len - r); + ctx->obuf_len-=r; + } + else + { + ctx->obuf_len=0; + ret=1; + break; + } + } + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + break; + case BIO_CTRL_DUP: + dbio=(BIO *)ptr; + if ( !BIO_set_write_buffer_size(dbio,ctx->obuf_size)) + ret=0; + break; + default: + if (b->next_bio == NULL) return(0); + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + break; + } + return(ret); +malloc_error: + BIOerr(BIO_F_LINEBUFFER_CTRL,ERR_R_MALLOC_FAILURE); + return(0); + } + +static long linebuffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + +static int linebuffer_gets(BIO *b, char *buf, int size) + { + if (b->next_bio == NULL) return(0); + return(BIO_gets(b->next_bio,buf,size)); + } + +static int linebuffer_puts(BIO *b, const char *str) + { + return(linebuffer_write(b,str,strlen(str))); + } + diff --git a/src/lib/libcrypto/bio/bss_bio.c b/src/lib/libcrypto/bio/bss_bio.c new file mode 100644 index 0000000000..562e9d8de2 --- /dev/null +++ b/src/lib/libcrypto/bio/bss_bio.c @@ -0,0 +1,588 @@ +/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ + +/* Special method for a BIO where the other endpoint is also a BIO + * of this kind, handled by the same thread (i.e. the "peer" is actually + * ourselves, wearing a different hat). + * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces + * for which no specific BIO method is available. + * See ssl/ssltest.c for some hints on how this can be used. */ + +#ifndef BIO_PAIR_DEBUG +# undef NDEBUG /* avoid conflicting definitions */ +# define NDEBUG +#endif + +#include +#include +#include + +#include +#include +#include + +static int bio_new(BIO *bio); +static int bio_free(BIO *bio); +static int bio_read(BIO *bio, char *buf, int size); +static int bio_write(BIO *bio, char *buf, int num); +static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); +static int bio_puts(BIO *bio, char *str); + +static int bio_make_pair(BIO *bio1, BIO *bio2); +static void bio_destroy_pair(BIO *bio); + +static BIO_METHOD methods_biop = +{ + BIO_TYPE_BIO, + "BIO pair", + bio_write, + bio_read, + bio_puts, + NULL /* no bio_gets */, + bio_ctrl, + bio_new, + bio_free +}; + +BIO_METHOD *BIO_s_bio(void) + { + return &methods_biop; + } + +struct bio_bio_st +{ + BIO *peer; /* NULL if buf == NULL. + * If peer != NULL, then peer->ptr is also a bio_bio_st, + * and its "peer" member points back to us. + * peer != NULL iff init != 0 in the BIO. */ + + /* This is for what we write (i.e. reading uses peer's struct): */ + int closed; /* valid iff peer != NULL */ + size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ + size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ + size_t size; + char *buf; /* "size" elements (if != NULL) */ + + size_t request; /* valid iff peer != NULL; 0 if len != 0, + * otherwise set by peer to number of bytes + * it (unsuccesfully) tried to read, + * never more than buffer space (size-len) warrants. */ +}; + +static int bio_new(BIO *bio) + { + struct bio_bio_st *b; + + b = Malloc(sizeof *b); + if (b == NULL) + return 0; + + b->peer = NULL; + b->size = 17*1024; /* enough for one TLS record (just a default) */ + b->buf = NULL; + + bio->ptr = b; + return 1; + } + + +static int bio_free(BIO *bio) + { + struct bio_bio_st *b; + + if (bio == NULL) + return 0; + b = bio->ptr; + + assert(b != NULL); + + if (b->peer) + bio_destroy_pair(bio); + + if (b->buf != NULL) + { + Free(b->buf); + } + + Free(b); + + return 1; + } + + + +static int bio_read(BIO *bio, char *buf, int size_) + { + size_t size = size_; + size_t rest; + struct bio_bio_st *b, *peer_b; + + BIO_clear_retry_flags(bio); + + if (!bio->init) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + peer_b = b->peer->ptr; + assert(peer_b != NULL); + assert(peer_b->buf != NULL); + + peer_b->request = 0; /* will be set in "retry_read" situation */ + + if (buf == NULL || size == 0) + return 0; + + if (peer_b->len == 0) + { + if (peer_b->closed) + return 0; /* writer has closed, and no data is left */ + else + { + BIO_set_retry_read(bio); /* buffer is empty */ + if (size <= peer_b->size) + peer_b->request = size; + else + /* don't ask for more than the peer can + * deliver in one write */ + peer_b->request = peer_b->size; + return -1; + } + } + + /* we can read */ + if (peer_b->len < size) + size = peer_b->len; + + /* now read "size" bytes */ + + rest = size; + + assert(rest > 0); + do /* one or two iterations */ + { + size_t chunk; + + assert(rest <= peer_b->len); + if (peer_b->offset + rest <= peer_b->size) + chunk = rest; + else + /* wrap around ring buffer */ + chunk = peer_b->size - peer_b->offset; + assert(peer_b->offset + chunk <= peer_b->size); + + memcpy(buf, peer_b->buf + peer_b->offset, chunk); + + peer_b->len -= chunk; + if (peer_b->len) + { + peer_b->offset += chunk; + assert(peer_b->offset <= peer_b->size); + if (peer_b->offset == peer_b->size) + peer_b->offset = 0; + buf += chunk; + } + else + { + /* buffer now empty, no need to advance "buf" */ + assert(chunk == rest); + peer_b->offset = 0; + } + rest -= chunk; + } + while (rest); + + return size; + } + +static int bio_write(BIO *bio, char *buf, int num_) + { + size_t num = num_; + size_t rest; + struct bio_bio_st *b; + + BIO_clear_retry_flags(bio); + + if (!bio->init || buf == NULL || num == 0) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + assert(b->buf != NULL); + + b->request = 0; + if (b->closed) + { + /* we already closed */ + BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); + return -1; + } + + assert(b->len <= b->size); + + if (b->len == b->size) + { + BIO_set_retry_write(bio); /* buffer is full */ + return -1; + } + + /* we can write */ + if (num > b->size - b->len) + num = b->size - b->len; + + /* now write "num" bytes */ + + rest = num; + + assert(rest > 0); + do /* one or two iterations */ + { + size_t write_offset; + size_t chunk; + + assert(b->len + rest <= b->size); + + write_offset = b->offset + b->len; + if (write_offset >= b->size) + write_offset -= b->size; + /* b->buf[write_offset] is the first byte we can write to. */ + + if (write_offset + rest <= b->size) + chunk = rest; + else + /* wrap around ring buffer */ + chunk = b->size - write_offset; + + memcpy(b->buf + write_offset, buf, chunk); + + b->len += chunk; + + assert(b->len <= b->size); + + rest -= chunk; + buf += chunk; + } + while (rest); + + return num; + } + + +static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) + { + long ret; + struct bio_bio_st *b = bio->ptr; + + assert(b != NULL); + + switch (cmd) + { + /* specific CTRL codes */ + + case BIO_C_SET_WRITE_BUF_SIZE: + if (b->peer) + { + BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); + ret = 0; + } + else if (num == 0) + { + BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); + ret = 0; + } + else + { + size_t new_size = num; + + if (b->size != new_size) + { + if (b->buf) + { + Free(b->buf); + b->buf = NULL; + } + b->size = new_size; + } + ret = 1; + } + break; + + case BIO_C_GET_WRITE_BUF_SIZE: + num = (long) b->size; + + case BIO_C_MAKE_BIO_PAIR: + { + BIO *other_bio = ptr; + + if (bio_make_pair(bio, other_bio)) + ret = 1; + else + ret = 0; + } + break; + + case BIO_C_DESTROY_BIO_PAIR: + /* Effects both BIOs in the pair -- call just once! + * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ + bio_destroy_pair(bio); + ret = 1; + break; + + case BIO_C_GET_WRITE_GUARANTEE: + /* How many bytes can the caller feed to the next write + * withouth having to keep any? */ + if (b->peer == NULL || b->closed) + ret = 0; + else + ret = (long) b->size - b->len; + break; + + case BIO_C_GET_READ_REQUEST: + /* If the peer unsuccesfully tried to read, how many bytes + * were requested? (As with BIO_CTRL_PENDING, that number + * can usually be treated as boolean.) */ + ret = (long) b->request; + break; + + case BIO_C_SHUTDOWN_WR: + /* similar to shutdown(..., SHUT_WR) */ + b->closed = 1; + ret = 1; + break; + + + /* standard CTRL codes follow */ + + case BIO_CTRL_RESET: + if (b->buf != NULL) + { + b->len = 0; + b->offset = 0; + } + ret = 0; + break; + + case BIO_CTRL_GET_CLOSE: + ret = bio->shutdown; + break; + + case BIO_CTRL_SET_CLOSE: + bio->shutdown = (int) num; + ret = 1; + break; + + case BIO_CTRL_PENDING: + if (b->peer != NULL) + { + struct bio_bio_st *peer_b = b->peer->ptr; + + ret = (long) peer_b->len; + } + else + ret = 0; + break; + + case BIO_CTRL_WPENDING: + if (b->buf != NULL) + ret = (long) b->len; + else + ret = 0; + break; + + case BIO_CTRL_DUP: + /* See BIO_dup_chain for circumstances we have to expect. */ + { + BIO *other_bio = ptr; + struct bio_bio_st *other_b; + + assert(other_bio != NULL); + other_b = other_bio->ptr; + assert(other_b != NULL); + + assert(other_b->buf == NULL); /* other_bio is always fresh */ + + other_b->size = b->size; + } + + ret = 1; + break; + + case BIO_CTRL_FLUSH: + ret = 1; + break; + + case BIO_CTRL_EOF: + { + BIO *other_bio = ptr; + + if (other_bio) + { + struct bio_bio_st *other_b = other_bio->ptr; + + assert(other_b != NULL); + ret = other_b->len == 0 && other_b->closed; + } + else + ret = 1; + } + break; + + default: + ret = 0; + } + return ret; + } + +static int bio_puts(BIO *bio, char *str) + { + return bio_write(bio, str, strlen(str)); + } + + +static int bio_make_pair(BIO *bio1, BIO *bio2) + { + struct bio_bio_st *b1, *b2; + + assert(bio1 != NULL); + assert(bio2 != NULL); + + b1 = bio1->ptr; + b2 = bio2->ptr; + + if (b1->peer != NULL || b2->peer != NULL) + { + BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); + return 0; + } + + if (b1->buf == NULL) + { + b1->buf = Malloc(b1->size); + if (b1->buf == NULL) + { + BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + return 0; + } + b1->len = 0; + b1->offset = 0; + } + + if (b2->buf == NULL) + { + b2->buf = Malloc(b2->size); + if (b2->buf == NULL) + { + BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + return 0; + } + b2->len = 0; + b2->offset = 0; + } + + b1->peer = bio2; + b1->closed = 0; + b1->request = 0; + b2->peer = bio1; + b2->closed = 0; + b2->request = 0; + + bio1->init = 1; + bio2->init = 1; + + return 1; + } + +static void bio_destroy_pair(BIO *bio) + { + struct bio_bio_st *b = bio->ptr; + + if (b != NULL) + { + BIO *peer_bio = b->peer; + + if (peer_bio != NULL) + { + struct bio_bio_st *peer_b = peer_bio->ptr; + + assert(peer_b != NULL); + assert(peer_b->peer == bio); + + peer_b->peer = NULL; + peer_bio->init = 0; + assert(peer_b->buf != NULL); + peer_b->len = 0; + peer_b->offset = 0; + + b->peer = NULL; + bio->init = 0; + assert(b->buf != NULL); + b->len = 0; + b->offset = 0; + } + } + } + + +/* Exported convenience functions */ +int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, + BIO **bio2_p, size_t writebuf2) + { + BIO *bio1 = NULL, *bio2 = NULL; + long r; + int ret = 0; + + bio1 = BIO_new(BIO_s_bio()); + if (bio1 == NULL) + goto err; + bio2 = BIO_new(BIO_s_bio()); + if (bio2 == NULL) + goto err; + + if (writebuf1) + { + r = BIO_set_write_buf_size(bio1, writebuf1); + if (!r) + goto err; + } + if (writebuf2) + { + r = BIO_set_write_buf_size(bio2, writebuf2); + if (!r) + goto err; + } + + r = BIO_make_bio_pair(bio1, bio2); + if (!r) + goto err; + ret = 1; + + err: + if (ret == 0) + { + if (bio1) + { + BIO_free(bio1); + bio1 = NULL; + } + if (bio2) + { + BIO_free(bio2); + bio2 = NULL; + } + } + + *bio1_p = bio1; + *bio2_p = bio2; + return ret; + } + +size_t BIO_ctrl_get_write_guarantee(BIO *bio) + { + return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); + } + +size_t BIO_ctrl_get_read_request(BIO *bio) + { + return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); + } diff --git a/src/lib/libcrypto/bio/bss_log.c b/src/lib/libcrypto/bio/bss_log.c new file mode 100644 index 0000000000..db82e757e7 --- /dev/null +++ b/src/lib/libcrypto/bio/bss_log.c @@ -0,0 +1,232 @@ +/* crypto/bio/bss_log.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 + * 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). + * + */ + +/* + Why BIO_s_log? + + BIO_s_log is useful for system daemons (or services under NT). + It is one-way BIO, it sends all stuff to syslogd (or event log + under NT). + +*/ + + +#include +#include + +#ifndef WIN32 +#ifdef __ultrix +#include +#else +#include +#endif +#endif + +#include "cryptlib.h" +#include +#include +#ifndef NO_SYSLOG + + +static int MS_CALLBACK slg_write(BIO *h,char *buf,int num); +static int MS_CALLBACK slg_puts(BIO *h,char *str); +static long MS_CALLBACK slg_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int MS_CALLBACK slg_new(BIO *h); +static int MS_CALLBACK slg_free(BIO *data); +static int xopenlog(BIO* bp, const char* name, int level); +static int xcloselog(BIO* bp); + +static BIO_METHOD methods_slg= + { + BIO_TYPE_MEM,"syslog", + slg_write, + NULL, + slg_puts, + NULL, + slg_ctrl, + slg_new, + slg_free, + }; + +BIO_METHOD *BIO_s_log(void) + { + return(&methods_slg); + } + +static int MS_CALLBACK slg_new(BIO *bi) + { + bi->init=1; + bi->num=0; + bi->ptr=NULL; +#ifndef WIN32 + xopenlog(bi, "application", LOG_DAEMON); +#else + xopenlog(bi, "application", 0); +#endif + return(1); + } + +static int MS_CALLBACK slg_free(BIO *a) + { + if (a == NULL) return(0); + xcloselog(a); + return(1); + } + +static int MS_CALLBACK slg_write(BIO *b, char *in, int inl) + { + int ret= inl; + char* buf= in; + char* pp; +#if defined(WIN32) + LPTSTR lpszStrings[1]; + WORD evtype= EVENTLOG_ERROR_TYPE; +#else + int priority; +#endif + + if((buf= (char *)Malloc(inl+ 1)) == NULL){ + return(0); + } + strncpy(buf, in, inl); + buf[inl]= '\0'; +#if defined(WIN32) + if(strncmp(buf, "ERR ", 4) == 0){ + evtype= EVENTLOG_ERROR_TYPE; + pp= buf+ 4; + }else if(strncmp(buf, "WAR ", 4) == 0){ + evtype= EVENTLOG_WARNING_TYPE; + pp= buf+ 4; + }else if(strncmp(buf, "INF ", 4) == 0){ + evtype= EVENTLOG_INFORMATION_TYPE; + pp= buf+ 4; + }else{ + evtype= EVENTLOG_ERROR_TYPE; + pp= buf; + } + lpszStrings[0]= pp; + + if(b->ptr) + ReportEvent(b->ptr, evtype, 0, 1024, NULL, 1, 0, + lpszStrings, NULL); +#else + if(strncmp(buf, "ERR ", 4) == 0){ + priority= LOG_ERR; + pp= buf+ 4; + }else if(strncmp(buf, "WAR ", 4) == 0){ + priority= LOG_WARNING; + pp= buf+ 4; + }else if(strncmp(buf, "INF ", 4) == 0){ + priority= LOG_INFO; + pp= buf+ 4; + }else{ + priority= LOG_ERR; + pp= buf; + } + + syslog(priority, "%s", pp); +#endif + Free(buf); + return(ret); + } + +static long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, char *ptr) + { + switch (cmd) + { + case BIO_CTRL_SET: + xcloselog(b); + xopenlog(b, ptr, num); + break; + default: + break; + } + return(0); + } + +static int MS_CALLBACK slg_puts(BIO *bp, char *str) + { + int n,ret; + + n=strlen(str); + ret=slg_write(bp,str,n); + return(ret); + } + +static int xopenlog(BIO* bp, const char* name, int level) +{ +#if defined(WIN32) + if((bp->ptr= (char *)RegisterEventSource(NULL, name)) == NULL){ + return(0); + } +#else + openlog(name, LOG_PID|LOG_CONS, level); +#endif + return(1); +} + +static int xcloselog(BIO* bp) +{ +#if defined(WIN32) + if(bp->ptr) + DeregisterEventSource((HANDLE)(bp->ptr)); + bp->ptr= NULL; +#else + closelog(); +#endif + return(1); +} + +#endif diff --git a/src/lib/libcrypto/bn/asm/co-586.pl b/src/lib/libcrypto/bn/asm/co-586.pl new file mode 100644 index 0000000000..5d962cb957 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/co-586.pl @@ -0,0 +1,286 @@ +#!/usr/local/bin/perl + +push(@INC,"perlasm","../../perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],$0); + +&bn_mul_comba("bn_mul_comba8",8); +&bn_mul_comba("bn_mul_comba4",4); +&bn_sqr_comba("bn_sqr_comba8",8); +&bn_sqr_comba("bn_sqr_comba4",4); + +&asm_finish(); + +sub mul_add_c + { + local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("mul a[$ai]*b[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + &mul("edx"); + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # laod next a + &mov("eax",&wparam(0)) if $pos > 0; # load r[] + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0; # laod next b + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a + } + +sub sqr_add_c + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb); + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + } + +sub sqr_add_c2 + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$a,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add("eax","eax"); + ### + &adc("edx","edx"); + ### + &adc($c2,0); + &add($c0,"eax"); + &adc($c1,"edx"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + &adc($c2,0); + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb); + ### + } + +sub bn_mul_comba + { + local($name,$num)=@_; + local($a,$b,$c0,$c1,$c2); + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($tot,$end); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $b="edi"; + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + &push("esi"); + &mov($a,&wparam(1)); + &push("edi"); + &mov($b,&wparam(2)); + &push("ebp"); + &push("ebx"); + + &xor($c0,$c0); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + &xor($c1,$c1); + &mov("edx",&DWP(0,$b,"",0)); # load the first second + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("################## Calculate word $i"); + + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($j+1) == $end) + { + $v=1; + $v=2 if (($i+1) == $tot); + } + else + { $v=0; } + if (($j+1) != $end) + { + $na=($ai-1); + $nb=($bi+1); + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } +#printf STDERR "[$ai,$bi] -> [$na,$nb]\n"; + &mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb); + if ($v) + { + &comment("saved r[$i]"); + # &mov("eax",&wparam(0)); + # &mov(&DWP($i*4,"eax","",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &comment("save r[$i]"); + # &mov("eax",&wparam(0)); + &mov(&DWP($i*4,"eax","",0),$c0); + + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + +sub bn_sqr_comba + { + local($name,$num)=@_; + local($r,$a,$c0,$c1,$c2)=@_; + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($b,$tot,$end,$half); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $r="edi"; + + &push("esi"); + &push("edi"); + &push("ebp"); + &push("ebx"); + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &xor($c0,$c0); + &xor($c1,$c1); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("############### Calculate word $i"); + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($ai-1) < ($bi+1)) + { + $v=1; + $v=2 if ($i+1) == $tot; + } + else + { $v=0; } + if (!$v) + { + $na=$ai-1; + $nb=$bi+1; + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } + if ($ai == $bi) + { + &sqr_add_c($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + else + { + &sqr_add_c2($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + if ($v) + { + &comment("saved r[$i]"); + #&mov(&DWP($i*4,$r,"",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + last; + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &mov(&DWP($i*4,$r,"",0),$c0); + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } diff --git a/src/lib/libcrypto/bn/asm/ia64.S b/src/lib/libcrypto/bn/asm/ia64.S new file mode 100644 index 0000000000..ae56066310 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/ia64.S @@ -0,0 +1,1498 @@ +.explicit +.text +.ident "ia64.S, Version 1.1" +.ident "IA-64 ISA artwork by Andy Polyakov " + +// +// ==================================================================== +// Written by Andy Polyakov for the OpenSSL +// project. +// +// Rights for redistribution and usage in source and binary forms are +// granted according to the OpenSSL license. Warranty of any kind is +// disclaimed. +// ==================================================================== +// + +// Q. How much faster does it get? +// A. Here is the output from 'openssl speed rsa dsa' for vanilla +// 0.9.6a compiled with gcc version 2.96 20000731 (Red Hat +// Linux 7.1 2.96-81): +// +// sign verify sign/s verify/s +// rsa 512 bits 0.0036s 0.0003s 275.3 2999.2 +// rsa 1024 bits 0.0203s 0.0011s 49.3 894.1 +// rsa 2048 bits 0.1331s 0.0040s 7.5 250.9 +// rsa 4096 bits 0.9270s 0.0147s 1.1 68.1 +// sign verify sign/s verify/s +// dsa 512 bits 0.0035s 0.0043s 288.3 234.8 +// dsa 1024 bits 0.0111s 0.0135s 90.0 74.2 +// +// And here is similar output but for this assembler +// implementation:-) +// +// sign verify sign/s verify/s +// rsa 512 bits 0.0021s 0.0001s 549.4 9638.5 +// rsa 1024 bits 0.0055s 0.0002s 183.8 4481.1 +// rsa 2048 bits 0.0244s 0.0006s 41.4 1726.3 +// rsa 4096 bits 0.1295s 0.0018s 7.7 561.5 +// sign verify sign/s verify/s +// dsa 512 bits 0.0012s 0.0013s 891.9 756.6 +// dsa 1024 bits 0.0023s 0.0028s 440.4 376.2 +// +// Yes, you may argue that it's not fair comparison as it's +// possible to craft the C implementation with BN_UMULT_HIGH +// inline assembler macro. But of course! Here is the output +// with the macro: +// +// sign verify sign/s verify/s +// rsa 512 bits 0.0020s 0.0002s 495.0 6561.0 +// rsa 1024 bits 0.0086s 0.0004s 116.2 2235.7 +// rsa 2048 bits 0.0519s 0.0015s 19.3 667.3 +// rsa 4096 bits 0.3464s 0.0053s 2.9 187.7 +// sign verify sign/s verify/s +// dsa 512 bits 0.0016s 0.0020s 613.1 510.5 +// dsa 1024 bits 0.0045s 0.0054s 221.0 183.9 +// +// My code is still way faster, huh:-) And I believe that even +// higher performance can be achieved. Note that as keys get +// longer, performance gain is larger. Why? According to the +// profiler there is another player in the field, namely +// BN_from_montgomery consuming larger and larger portion of CPU +// time as keysize decreases. I therefore consider putting effort +// to assembler implementation of the following routine: +// +// void bn_mul_add_mont (BN_ULONG *rp,BN_ULONG *np,int nl,BN_ULONG n0) +// { +// int i,j; +// BN_ULONG v; +// +// for (i=0; i= 0,num,bn_mul_add_words_exit ; if (num <= 0) then exit + LDO 128(%sp),%sp ; bump stack + + ; + ; The loop is unrolled twice, so if there is only 1 number + ; then go straight to the cleanup code. + ; + CMPIB,= 1,num,bn_mul_add_words_single_top + FLDD -72(%sp),fw ; load up w into fp register fw (fw_h/fw_l) + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; + ; PA-RISC 2.0 chips have two fully pipelined multipliers, thus + ; two 32-bit mutiplies can be issued per cycle. + ; +bn_mul_add_words_unroll2 + + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + FLDD 8(a_ptr),t_float_1 ; load up 64-bit value (fr8L) ht(L)/lt(R) + LDD 0(r_ptr),rp_val ; rp[0] + LDD 8(r_ptr),rp_val_1 ; rp[1] + + XMPYU fht_0,fw_l,fm1 ; m1[0] = fht_0*fw_l + XMPYU fht_1,fw_l,fm1_1 ; m1[1] = fht_1*fw_l + FSTD fm1,-16(%sp) ; -16(sp) = m1[0] + FSTD fm1_1,-48(%sp) ; -48(sp) = m1[1] + + XMPYU flt_0,fw_h,fm ; m[0] = flt_0*fw_h + XMPYU flt_1,fw_h,fm_1 ; m[1] = flt_1*fw_h + FSTD fm,-8(%sp) ; -8(sp) = m[0] + FSTD fm_1,-40(%sp) ; -40(sp) = m[1] + + XMPYU fht_0,fw_h,ht_temp ; ht_temp = fht_0*fw_h + XMPYU fht_1,fw_h,ht_temp_1 ; ht_temp_1 = fht_1*fw_h + FSTD ht_temp,-24(%sp) ; -24(sp) = ht_temp + FSTD ht_temp_1,-56(%sp) ; -56(sp) = ht_temp_1 + + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + XMPYU flt_1,fw_l,lt_temp_1 ; lt_temp = lt*fw_l + FSTD lt_temp,-32(%sp) ; -32(sp) = lt_temp + FSTD lt_temp_1,-64(%sp) ; -64(sp) = lt_temp_1 + + LDD -8(%sp),m_0 ; m[0] + LDD -40(%sp),m_1 ; m[1] + LDD -16(%sp),m1_0 ; m1[0] + LDD -48(%sp),m1_1 ; m1[1] + + LDD -24(%sp),ht_0 ; ht[0] + LDD -56(%sp),ht_1 ; ht[1] + ADD,L m1_0,m_0,tmp_0 ; tmp_0 = m[0] + m1[0]; + ADD,L m1_1,m_1,tmp_1 ; tmp_1 = m[1] + m1[1]; + + LDD -32(%sp),lt_0 + LDD -64(%sp),lt_1 + CMPCLR,*>>= tmp_0,m1_0, %r0 ; if (m[0] < m1[0]) + ADD,L ht_0,top_overflow,ht_0 ; ht[0] += (1<<32) + + CMPCLR,*>>= tmp_1,m1_1,%r0 ; if (m[1] < m1[1]) + ADD,L ht_1,top_overflow,ht_1 ; ht[1] += (1<<32) + EXTRD,U tmp_0,31,32,m_0 ; m[0]>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1[0] = m[0]<<32 + + EXTRD,U tmp_1,31,32,m_1 ; m[1]>>32 + DEPD,Z tmp_1,31,32,m1_1 ; m1[1] = m[1]<<32 + ADD,L ht_0,m_0,ht_0 ; ht[0]+= (m[0]>>32) + ADD,L ht_1,m_1,ht_1 ; ht[1]+= (m[1]>>32) + + ADD lt_0,m1_0,lt_0 ; lt[0] = lt[0]+m1[0]; + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + ADD lt_1,m1_1,lt_1 ; lt[1] = lt[1]+m1[1]; + ADD,DC ht_1,%r0,ht_1 ; ht[1]++ + + ADD %ret0,lt_0,lt_0 ; lt[0] = lt[0] + c; + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + ADD lt_0,rp_val,lt_0 ; lt[0] = lt[0]+rp[0] + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + + LDO -2(num),num ; num = num - 2; + ADD ht_0,lt_1,lt_1 ; lt[1] = lt[1] + ht_0 (c); + ADD,DC ht_1,%r0,ht_1 ; ht[1]++ + STD lt_0,0(r_ptr) ; rp[0] = lt[0] + + ADD lt_1,rp_val_1,lt_1 ; lt[1] = lt[1]+rp[1] + ADD,DC ht_1,%r0,%ret0 ; ht[1]++ + LDO 16(a_ptr),a_ptr ; a_ptr += 2 + + STD lt_1,8(r_ptr) ; rp[1] = lt[1] + CMPIB,<= 2,num,bn_mul_add_words_unroll2 ; go again if more to do + LDO 16(r_ptr),r_ptr ; r_ptr += 2 + + CMPIB,=,N 0,num,bn_mul_add_words_exit ; are we done, or cleanup last one + + ; + ; Top of loop aligned on 64-byte boundary + ; +bn_mul_add_words_single_top + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + LDD 0(r_ptr),rp_val ; rp[0] + LDO 8(a_ptr),a_ptr ; a_ptr++ + XMPYU fht_0,fw_l,fm1 ; m1 = ht*fw_l + FSTD fm1,-16(%sp) ; -16(sp) = m1 + XMPYU flt_0,fw_h,fm ; m = lt*fw_h + FSTD fm,-8(%sp) ; -8(sp) = m + XMPYU fht_0,fw_h,ht_temp ; ht_temp = ht*fw_h + FSTD ht_temp,-24(%sp) ; -24(sp) = ht + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + FSTD lt_temp,-32(%sp) ; -32(sp) = lt + + LDD -8(%sp),m_0 + LDD -16(%sp),m1_0 ; m1 = temp1 + ADD,L m_0,m1_0,tmp_0 ; tmp_0 = m + m1; + LDD -24(%sp),ht_0 + LDD -32(%sp),lt_0 + + CMPCLR,*>>= tmp_0,m1_0,%r0 ; if (m < m1) + ADD,L ht_0,top_overflow,ht_0 ; ht += (1<<32) + + EXTRD,U tmp_0,31,32,m_0 ; m>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1 = m<<32 + + ADD,L ht_0,m_0,ht_0 ; ht+= (m>>32) + ADD lt_0,m1_0,tmp_0 ; tmp_0 = lt+m1; + ADD,DC ht_0,%r0,ht_0 ; ht++ + ADD %ret0,tmp_0,lt_0 ; lt = lt + c; + ADD,DC ht_0,%r0,ht_0 ; ht++ + ADD lt_0,rp_val,lt_0 ; lt = lt+rp[0] + ADD,DC ht_0,%r0,%ret0 ; ht++ + STD lt_0,0(r_ptr) ; rp[0] = lt + +bn_mul_add_words_exit + .EXIT + LDD -80(%sp),%r9 ; restore r9 + LDD -88(%sp),%r8 ; restore r8 + LDD -96(%sp),%r7 ; restore r7 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 ; restore r3 + .PROCEND ;in=23,24,25,26,29;out=28; + +;---------------------------------------------------------------------------- +; +;BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) +; +; arg0 = rp +; arg1 = ap +; arg2 = num +; arg3 = w + +bn_mul_words + .proc + .callinfo frame=128 + .entry + .EXPORT bn_mul_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + + STD %r7,32(%sp) ; save r7 + COPY %r0,%ret0 ; return 0 by default + DEPDI,Z 1,31,1,top_overflow ; top_overflow = 1 << 32 + STD w,56(%sp) ; w on stack + + CMPIB,>= 0,num,bn_mul_words_exit + LDO 128(%sp),%sp ; bump stack + + ; + ; See if only 1 word to do, thus just do cleanup + ; + CMPIB,= 1,num,bn_mul_words_single_top + FLDD -72(%sp),fw ; load up w into fp register fw (fw_h/fw_l) + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; + ; PA-RISC 2.0 chips have two fully pipelined multipliers, thus + ; two 32-bit mutiplies can be issued per cycle. + ; +bn_mul_words_unroll2 + + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + FLDD 8(a_ptr),t_float_1 ; load up 64-bit value (fr8L) ht(L)/lt(R) + XMPYU fht_0,fw_l,fm1 ; m1[0] = fht_0*fw_l + XMPYU fht_1,fw_l,fm1_1 ; m1[1] = ht*fw_l + + FSTD fm1,-16(%sp) ; -16(sp) = m1 + FSTD fm1_1,-48(%sp) ; -48(sp) = m1 + XMPYU flt_0,fw_h,fm ; m = lt*fw_h + XMPYU flt_1,fw_h,fm_1 ; m = lt*fw_h + + FSTD fm,-8(%sp) ; -8(sp) = m + FSTD fm_1,-40(%sp) ; -40(sp) = m + XMPYU fht_0,fw_h,ht_temp ; ht_temp = fht_0*fw_h + XMPYU fht_1,fw_h,ht_temp_1 ; ht_temp = ht*fw_h + + FSTD ht_temp,-24(%sp) ; -24(sp) = ht + FSTD ht_temp_1,-56(%sp) ; -56(sp) = ht + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + XMPYU flt_1,fw_l,lt_temp_1 ; lt_temp = lt*fw_l + + FSTD lt_temp,-32(%sp) ; -32(sp) = lt + FSTD lt_temp_1,-64(%sp) ; -64(sp) = lt + LDD -8(%sp),m_0 + LDD -40(%sp),m_1 + + LDD -16(%sp),m1_0 + LDD -48(%sp),m1_1 + LDD -24(%sp),ht_0 + LDD -56(%sp),ht_1 + + ADD,L m1_0,m_0,tmp_0 ; tmp_0 = m + m1; + ADD,L m1_1,m_1,tmp_1 ; tmp_1 = m + m1; + LDD -32(%sp),lt_0 + LDD -64(%sp),lt_1 + + CMPCLR,*>>= tmp_0,m1_0, %r0 ; if (m < m1) + ADD,L ht_0,top_overflow,ht_0 ; ht += (1<<32) + CMPCLR,*>>= tmp_1,m1_1,%r0 ; if (m < m1) + ADD,L ht_1,top_overflow,ht_1 ; ht += (1<<32) + + EXTRD,U tmp_0,31,32,m_0 ; m>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1 = m<<32 + EXTRD,U tmp_1,31,32,m_1 ; m>>32 + DEPD,Z tmp_1,31,32,m1_1 ; m1 = m<<32 + + ADD,L ht_0,m_0,ht_0 ; ht+= (m>>32) + ADD,L ht_1,m_1,ht_1 ; ht+= (m>>32) + ADD lt_0,m1_0,lt_0 ; lt = lt+m1; + ADD,DC ht_0,%r0,ht_0 ; ht++ + + ADD lt_1,m1_1,lt_1 ; lt = lt+m1; + ADD,DC ht_1,%r0,ht_1 ; ht++ + ADD %ret0,lt_0,lt_0 ; lt = lt + c (ret0); + ADD,DC ht_0,%r0,ht_0 ; ht++ + + ADD ht_0,lt_1,lt_1 ; lt = lt + c (ht_0) + ADD,DC ht_1,%r0,ht_1 ; ht++ + STD lt_0,0(r_ptr) ; rp[0] = lt + STD lt_1,8(r_ptr) ; rp[1] = lt + + COPY ht_1,%ret0 ; carry = ht + LDO -2(num),num ; num = num - 2; + LDO 16(a_ptr),a_ptr ; ap += 2 + CMPIB,<= 2,num,bn_mul_words_unroll2 + LDO 16(r_ptr),r_ptr ; rp++ + + CMPIB,=,N 0,num,bn_mul_words_exit ; are we done? + + ; + ; Top of loop aligned on 64-byte boundary + ; +bn_mul_words_single_top + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + + XMPYU fht_0,fw_l,fm1 ; m1 = ht*fw_l + FSTD fm1,-16(%sp) ; -16(sp) = m1 + XMPYU flt_0,fw_h,fm ; m = lt*fw_h + FSTD fm,-8(%sp) ; -8(sp) = m + XMPYU fht_0,fw_h,ht_temp ; ht_temp = ht*fw_h + FSTD ht_temp,-24(%sp) ; -24(sp) = ht + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + FSTD lt_temp,-32(%sp) ; -32(sp) = lt + + LDD -8(%sp),m_0 + LDD -16(%sp),m1_0 + ADD,L m_0,m1_0,tmp_0 ; tmp_0 = m + m1; + LDD -24(%sp),ht_0 + LDD -32(%sp),lt_0 + + CMPCLR,*>>= tmp_0,m1_0,%r0 ; if (m < m1) + ADD,L ht_0,top_overflow,ht_0 ; ht += (1<<32) + + EXTRD,U tmp_0,31,32,m_0 ; m>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1 = m<<32 + + ADD,L ht_0,m_0,ht_0 ; ht+= (m>>32) + ADD lt_0,m1_0,lt_0 ; lt= lt+m1; + ADD,DC ht_0,%r0,ht_0 ; ht++ + + ADD %ret0,lt_0,lt_0 ; lt = lt + c; + ADD,DC ht_0,%r0,ht_0 ; ht++ + + COPY ht_0,%ret0 ; copy carry + STD lt_0,0(r_ptr) ; rp[0] = lt + +bn_mul_words_exit + .EXIT + LDD -96(%sp),%r7 ; restore r7 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 ; restore r3 + .PROCEND ;in=23,24,25,26,29;out=28; + +;---------------------------------------------------------------------------- +; +;void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num) +; +; arg0 = rp +; arg1 = ap +; arg2 = num +; + +bn_sqr_words + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_sqr_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + NOP + STD %r5,16(%sp) ; save r5 + + CMPIB,>= 0,num,bn_sqr_words_exit + LDO 128(%sp),%sp ; bump stack + + ; + ; If only 1, the goto straight to cleanup + ; + CMPIB,= 1,num,bn_sqr_words_single_top + DEPDI,Z -1,32,33,high_mask ; Create Mask 0xffffffff80000000L + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; + +bn_sqr_words_unroll2 + FLDD 0(a_ptr),t_float_0 ; a[0] + FLDD 8(a_ptr),t_float_1 ; a[1] + XMPYU fht_0,flt_0,fm ; m[0] + XMPYU fht_1,flt_1,fm_1 ; m[1] + + FSTD fm,-24(%sp) ; store m[0] + FSTD fm_1,-56(%sp) ; store m[1] + XMPYU flt_0,flt_0,lt_temp ; lt[0] + XMPYU flt_1,flt_1,lt_temp_1 ; lt[1] + + FSTD lt_temp,-16(%sp) ; store lt[0] + FSTD lt_temp_1,-48(%sp) ; store lt[1] + XMPYU fht_0,fht_0,ht_temp ; ht[0] + XMPYU fht_1,fht_1,ht_temp_1 ; ht[1] + + FSTD ht_temp,-8(%sp) ; store ht[0] + FSTD ht_temp_1,-40(%sp) ; store ht[1] + LDD -24(%sp),m_0 + LDD -56(%sp),m_1 + + AND m_0,high_mask,tmp_0 ; m[0] & Mask + AND m_1,high_mask,tmp_1 ; m[1] & Mask + DEPD,Z m_0,30,31,m_0 ; m[0] << 32+1 + DEPD,Z m_1,30,31,m_1 ; m[1] << 32+1 + + LDD -16(%sp),lt_0 + LDD -48(%sp),lt_1 + EXTRD,U tmp_0,32,33,tmp_0 ; tmp_0 = m[0]&Mask >> 32-1 + EXTRD,U tmp_1,32,33,tmp_1 ; tmp_1 = m[1]&Mask >> 32-1 + + LDD -8(%sp),ht_0 + LDD -40(%sp),ht_1 + ADD,L ht_0,tmp_0,ht_0 ; ht[0] += tmp_0 + ADD,L ht_1,tmp_1,ht_1 ; ht[1] += tmp_1 + + ADD lt_0,m_0,lt_0 ; lt = lt+m + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + STD lt_0,0(r_ptr) ; rp[0] = lt[0] + STD ht_0,8(r_ptr) ; rp[1] = ht[1] + + ADD lt_1,m_1,lt_1 ; lt = lt+m + ADD,DC ht_1,%r0,ht_1 ; ht[1]++ + STD lt_1,16(r_ptr) ; rp[2] = lt[1] + STD ht_1,24(r_ptr) ; rp[3] = ht[1] + + LDO -2(num),num ; num = num - 2; + LDO 16(a_ptr),a_ptr ; ap += 2 + CMPIB,<= 2,num,bn_sqr_words_unroll2 + LDO 32(r_ptr),r_ptr ; rp += 4 + + CMPIB,=,N 0,num,bn_sqr_words_exit ; are we done? + + ; + ; Top of loop aligned on 64-byte boundary + ; +bn_sqr_words_single_top + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + + XMPYU fht_0,flt_0,fm ; m + FSTD fm,-24(%sp) ; store m + + XMPYU flt_0,flt_0,lt_temp ; lt + FSTD lt_temp,-16(%sp) ; store lt + + XMPYU fht_0,fht_0,ht_temp ; ht + FSTD ht_temp,-8(%sp) ; store ht + + LDD -24(%sp),m_0 ; load m + AND m_0,high_mask,tmp_0 ; m & Mask + DEPD,Z m_0,30,31,m_0 ; m << 32+1 + LDD -16(%sp),lt_0 ; lt + + LDD -8(%sp),ht_0 ; ht + EXTRD,U tmp_0,32,33,tmp_0 ; tmp_0 = m&Mask >> 32-1 + ADD m_0,lt_0,lt_0 ; lt = lt+m + ADD,L ht_0,tmp_0,ht_0 ; ht += tmp_0 + ADD,DC ht_0,%r0,ht_0 ; ht++ + + STD lt_0,0(r_ptr) ; rp[0] = lt + STD ht_0,8(r_ptr) ; rp[1] = ht + +bn_sqr_words_exit + .EXIT + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + .PROCEND ;in=23,24,25,26,29;out=28; + + +;---------------------------------------------------------------------------- +; +;BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +; +; arg0 = rp +; arg1 = ap +; arg2 = bp +; arg3 = n + +t .reg %r22 +b .reg %r21 +l .reg %r20 + +bn_add_words + .proc + .entry + .callinfo + .EXPORT bn_add_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .align 64 + + CMPIB,>= 0,n,bn_add_words_exit + COPY %r0,%ret0 ; return 0 by default + + ; + ; If 2 or more numbers do the loop + ; + CMPIB,= 1,n,bn_add_words_single_top + NOP + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; +bn_add_words_unroll2 + LDD 0(a_ptr),t + LDD 0(b_ptr),b + ADD t,%ret0,t ; t = t+c; + ADD,DC %r0,%r0,%ret0 ; set c to carry + ADD t,b,l ; l = t + b[0] + ADD,DC %ret0,%r0,%ret0 ; c+= carry + STD l,0(r_ptr) + + LDD 8(a_ptr),t + LDD 8(b_ptr),b + ADD t,%ret0,t ; t = t+c; + ADD,DC %r0,%r0,%ret0 ; set c to carry + ADD t,b,l ; l = t + b[0] + ADD,DC %ret0,%r0,%ret0 ; c+= carry + STD l,8(r_ptr) + + LDO -2(n),n + LDO 16(a_ptr),a_ptr + LDO 16(b_ptr),b_ptr + + CMPIB,<= 2,n,bn_add_words_unroll2 + LDO 16(r_ptr),r_ptr + + CMPIB,=,N 0,n,bn_add_words_exit ; are we done? + +bn_add_words_single_top + LDD 0(a_ptr),t + LDD 0(b_ptr),b + + ADD t,%ret0,t ; t = t+c; + ADD,DC %r0,%r0,%ret0 ; set c to carry (could use CMPCLR??) + ADD t,b,l ; l = t + b[0] + ADD,DC %ret0,%r0,%ret0 ; c+= carry + STD l,0(r_ptr) + +bn_add_words_exit + .EXIT + BVE (%rp) + NOP + .PROCEND ;in=23,24,25,26,29;out=28; + +;---------------------------------------------------------------------------- +; +;BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +; +; arg0 = rp +; arg1 = ap +; arg2 = bp +; arg3 = n + +t1 .reg %r22 +t2 .reg %r21 +sub_tmp1 .reg %r20 +sub_tmp2 .reg %r19 + + +bn_sub_words + .proc + .callinfo + .EXPORT bn_sub_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + CMPIB,>= 0,n,bn_sub_words_exit + COPY %r0,%ret0 ; return 0 by default + + ; + ; If 2 or more numbers do the loop + ; + CMPIB,= 1,n,bn_sub_words_single_top + NOP + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; +bn_sub_words_unroll2 + LDD 0(a_ptr),t1 + LDD 0(b_ptr),t2 + SUB t1,t2,sub_tmp1 ; t3 = t1-t2; + SUB sub_tmp1,%ret0,sub_tmp1 ; t3 = t3- c; + + CMPCLR,*>> t1,t2,sub_tmp2 ; clear if t1 > t2 + LDO 1(%r0),sub_tmp2 + + CMPCLR,*= t1,t2,%r0 + COPY sub_tmp2,%ret0 + STD sub_tmp1,0(r_ptr) + + LDD 8(a_ptr),t1 + LDD 8(b_ptr),t2 + SUB t1,t2,sub_tmp1 ; t3 = t1-t2; + SUB sub_tmp1,%ret0,sub_tmp1 ; t3 = t3- c; + CMPCLR,*>> t1,t2,sub_tmp2 ; clear if t1 > t2 + LDO 1(%r0),sub_tmp2 + + CMPCLR,*= t1,t2,%r0 + COPY sub_tmp2,%ret0 + STD sub_tmp1,8(r_ptr) + + LDO -2(n),n + LDO 16(a_ptr),a_ptr + LDO 16(b_ptr),b_ptr + + CMPIB,<= 2,n,bn_sub_words_unroll2 + LDO 16(r_ptr),r_ptr + + CMPIB,=,N 0,n,bn_sub_words_exit ; are we done? + +bn_sub_words_single_top + LDD 0(a_ptr),t1 + LDD 0(b_ptr),t2 + SUB t1,t2,sub_tmp1 ; t3 = t1-t2; + SUB sub_tmp1,%ret0,sub_tmp1 ; t3 = t3- c; + CMPCLR,*>> t1,t2,sub_tmp2 ; clear if t1 > t2 + LDO 1(%r0),sub_tmp2 + + CMPCLR,*= t1,t2,%r0 + COPY sub_tmp2,%ret0 + + STD sub_tmp1,0(r_ptr) + +bn_sub_words_exit + .EXIT + BVE (%rp) + NOP + .PROCEND ;in=23,24,25,26,29;out=28; + +;------------------------------------------------------------------------------ +; +; unsigned long bn_div_words(unsigned long h, unsigned long l, unsigned long d) +; +; arg0 = h +; arg1 = l +; arg2 = d +; +; This is mainly just modified assembly from the compiler, thus the +; lack of variable names. +; +;------------------------------------------------------------------------------ +bn_div_words + .proc + .callinfo CALLER,FRAME=272,ENTRY_GR=%r10,SAVE_RP,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_div_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .IMPORT BN_num_bits_word,CODE,NO_RELOCATION + .IMPORT __iob,DATA + .IMPORT fprintf,CODE,NO_RELOCATION + .IMPORT abort,CODE,NO_RELOCATION + .IMPORT $$div2U,MILLICODE + .entry + STD %r2,-16(%r30) + STD,MA %r3,352(%r30) + STD %r4,-344(%r30) + STD %r5,-336(%r30) + STD %r6,-328(%r30) + STD %r7,-320(%r30) + STD %r8,-312(%r30) + STD %r9,-304(%r30) + STD %r10,-296(%r30) + + STD %r27,-288(%r30) ; save gp + + COPY %r24,%r3 ; save d + COPY %r26,%r4 ; save h (high 64-bits) + LDO -1(%r0),%ret0 ; return -1 by default + + CMPB,*= %r0,%arg2,$D3 ; if (d == 0) + COPY %r25,%r5 ; save l (low 64-bits) + + LDO -48(%r30),%r29 ; create ap + .CALL ;in=26,29;out=28; + B,L BN_num_bits_word,%r2 + COPY %r3,%r26 + LDD -288(%r30),%r27 ; restore gp + LDI 64,%r21 + + CMPB,= %r21,%ret0,$00000012 ;if (i == 64) (forward) + COPY %ret0,%r24 ; i + MTSARCM %r24 + DEPDI,Z -1,%sar,1,%r29 + CMPB,*<<,N %r29,%r4,bn_div_err_case ; if (h > 1<= d) + SUB %r4,%r3,%r4 ; h -= d + CMPB,= %r31,%r0,$0000001A ; if (i) + COPY %r0,%r10 ; ret = 0 + MTSARCM %r31 ; i to shift + DEPD,Z %r3,%sar,64,%r3 ; d <<= i; + SUBI 64,%r31,%r19 ; 64 - i; redundent + MTSAR %r19 ; (64 -i) to shift + SHRPD %r4,%r5,%sar,%r4 ; l>> (64-i) + MTSARCM %r31 ; i to shift + DEPD,Z %r5,%sar,64,%r5 ; l <<= i; + +$0000001A + DEPDI,Z -1,31,32,%r19 + EXTRD,U %r3,31,32,%r6 ; dh=(d&0xfff)>>32 + EXTRD,U %r3,63,32,%r8 ; dl = d&0xffffff + LDO 2(%r0),%r9 + STD %r3,-280(%r30) ; "d" to stack + +$0000001C + DEPDI,Z -1,63,32,%r29 ; + EXTRD,U %r4,31,32,%r31 ; h >> 32 + CMPB,*=,N %r31,%r6,$D2 ; if ((h>>32) != dh)(forward) div + COPY %r4,%r26 + EXTRD,U %r4,31,32,%r25 + COPY %r6,%r24 + .CALL ;in=23,24,25,26;out=20,21,22,28,29; (MILLICALL) + B,L $$div2U,%r2 + EXTRD,U %r6,31,32,%r23 + DEPD %r28,31,32,%r29 +$D2 + STD %r29,-272(%r30) ; q + AND %r5,%r19,%r24 ; t & 0xffffffff00000000; + EXTRD,U %r24,31,32,%r24 ; ??? + FLDD -272(%r30),%fr7 ; q + FLDD -280(%r30),%fr8 ; d + XMPYU %fr8L,%fr7L,%fr10 + FSTD %fr10,-256(%r30) + XMPYU %fr8L,%fr7R,%fr22 + FSTD %fr22,-264(%r30) + XMPYU %fr8R,%fr7L,%fr11 + XMPYU %fr8R,%fr7R,%fr23 + FSTD %fr11,-232(%r30) + FSTD %fr23,-240(%r30) + LDD -256(%r30),%r28 + DEPD,Z %r28,31,32,%r2 + LDD -264(%r30),%r20 + ADD,L %r20,%r2,%r31 + LDD -232(%r30),%r22 + DEPD,Z %r22,31,32,%r22 + LDD -240(%r30),%r21 + B $00000024 ; enter loop + ADD,L %r21,%r22,%r23 + +$0000002A + LDO -1(%r29),%r29 + SUB %r23,%r8,%r23 +$00000024 + SUB %r4,%r31,%r25 + AND %r25,%r19,%r26 + CMPB,*<>,N %r0,%r26,$00000046 ; (forward) + DEPD,Z %r25,31,32,%r20 + OR %r20,%r24,%r21 + CMPB,*<<,N %r21,%r23,$0000002A ;(backward) + SUB %r31,%r6,%r31 +;-------------Break path--------------------- + +$00000046 + DEPD,Z %r23,31,32,%r25 ;tl + EXTRD,U %r23,31,32,%r26 ;t + AND %r25,%r19,%r24 ;tl = (tl<<32)&0xfffffff0000000L + ADD,L %r31,%r26,%r31 ;th += t; + CMPCLR,*>>= %r5,%r24,%r0 ;if (l>32)); + DEPD,Z %r29,31,32,%r10 ; ret = q<<32 + b $0000001C + DEPD,Z %r28,31,32,%r5 ; l = l << 32 + +$D1 + OR %r10,%r29,%r28 ; ret |= q +$D3 + LDD -368(%r30),%r2 +$D0 + LDD -296(%r30),%r10 + LDD -304(%r30),%r9 + LDD -312(%r30),%r8 + LDD -320(%r30),%r7 + LDD -328(%r30),%r6 + LDD -336(%r30),%r5 + LDD -344(%r30),%r4 + BVE (%r2) + .EXIT + LDD,MB -352(%r30),%r3 + +bn_div_err_case + MFIA %r6 + ADDIL L'bn_div_words-bn_div_err_case,%r6,%r1 + LDO R'bn_div_words-bn_div_err_case(%r1),%r6 + ADDIL LT'__iob,%r27,%r1 + LDD RT'__iob(%r1),%r26 + ADDIL L'C$4-bn_div_words,%r6,%r1 + LDO R'C$4-bn_div_words(%r1),%r25 + LDO 64(%r26),%r26 + .CALL ;in=24,25,26,29;out=28; + B,L fprintf,%r2 + LDO -48(%r30),%r29 + LDD -288(%r30),%r27 + .CALL ;in=29; + B,L abort,%r2 + LDO -48(%r30),%r29 + LDD -288(%r30),%r27 + B $D0 + LDD -368(%r30),%r2 + .PROCEND ;in=24,25,26,29;out=28; + +;---------------------------------------------------------------------------- +; +; Registers to hold 64-bit values to manipulate. The "L" part +; of the register corresponds to the upper 32-bits, while the "R" +; part corresponds to the lower 32-bits +; +; Note, that when using b6 and b7, the code must save these before +; using them because they are callee save registers +; +; +; Floating point registers to use to save values that +; are manipulated. These don't collide with ftemp1-6 and +; are all caller save registers +; +a0 .reg %fr22 +a0L .reg %fr22L +a0R .reg %fr22R + +a1 .reg %fr23 +a1L .reg %fr23L +a1R .reg %fr23R + +a2 .reg %fr24 +a2L .reg %fr24L +a2R .reg %fr24R + +a3 .reg %fr25 +a3L .reg %fr25L +a3R .reg %fr25R + +a4 .reg %fr26 +a4L .reg %fr26L +a4R .reg %fr26R + +a5 .reg %fr27 +a5L .reg %fr27L +a5R .reg %fr27R + +a6 .reg %fr28 +a6L .reg %fr28L +a6R .reg %fr28R + +a7 .reg %fr29 +a7L .reg %fr29L +a7R .reg %fr29R + +b0 .reg %fr30 +b0L .reg %fr30L +b0R .reg %fr30R + +b1 .reg %fr31 +b1L .reg %fr31L +b1R .reg %fr31R + +; +; Temporary floating point variables, these are all caller save +; registers +; +ftemp1 .reg %fr4 +ftemp2 .reg %fr5 +ftemp3 .reg %fr6 +ftemp4 .reg %fr7 + +; +; The B set of registers when used. +; + +b2 .reg %fr8 +b2L .reg %fr8L +b2R .reg %fr8R + +b3 .reg %fr9 +b3L .reg %fr9L +b3R .reg %fr9R + +b4 .reg %fr10 +b4L .reg %fr10L +b4R .reg %fr10R + +b5 .reg %fr11 +b5L .reg %fr11L +b5R .reg %fr11R + +b6 .reg %fr12 +b6L .reg %fr12L +b6R .reg %fr12R + +b7 .reg %fr13 +b7L .reg %fr13L +b7R .reg %fr13R + +c1 .reg %r21 ; only reg +temp1 .reg %r20 ; only reg +temp2 .reg %r19 ; only reg +temp3 .reg %r31 ; only reg + +m1 .reg %r28 +c2 .reg %r23 +high_one .reg %r1 +ht .reg %r6 +lt .reg %r5 +m .reg %r4 +c3 .reg %r3 + +SQR_ADD_C .macro A0L,A0R,C1,C2,C3 + XMPYU A0L,A0R,ftemp1 ; m + FSTD ftemp1,-24(%sp) ; store m + + XMPYU A0R,A0R,ftemp2 ; lt + FSTD ftemp2,-16(%sp) ; store lt + + XMPYU A0L,A0L,ftemp3 ; ht + FSTD ftemp3,-8(%sp) ; store ht + + LDD -24(%sp),m ; load m + AND m,high_mask,temp2 ; m & Mask + DEPD,Z m,30,31,temp3 ; m << 32+1 + LDD -16(%sp),lt ; lt + + LDD -8(%sp),ht ; ht + EXTRD,U temp2,32,33,temp1 ; temp1 = m&Mask >> 32-1 + ADD temp3,lt,lt ; lt = lt+m + ADD,L ht,temp1,ht ; ht += temp1 + ADD,DC ht,%r0,ht ; ht++ + + ADD C1,lt,C1 ; c1=c1+lt + ADD,DC ht,%r0,ht ; ht++ + + ADD C2,ht,C2 ; c2=c2+ht + ADD,DC C3,%r0,C3 ; c3++ +.endm + +SQR_ADD_C2 .macro A0L,A0R,A1L,A1R,C1,C2,C3 + XMPYU A0L,A1R,ftemp1 ; m1 = bl*ht + FSTD ftemp1,-16(%sp) ; + XMPYU A0R,A1L,ftemp2 ; m = bh*lt + FSTD ftemp2,-8(%sp) ; + XMPYU A0R,A1R,ftemp3 ; lt = bl*lt + FSTD ftemp3,-32(%sp) + XMPYU A0L,A1L,ftemp4 ; ht = bh*ht + FSTD ftemp4,-24(%sp) ; + + LDD -8(%sp),m ; r21 = m + LDD -16(%sp),m1 ; r19 = m1 + ADD,L m,m1,m ; m+m1 + + DEPD,Z m,31,32,temp3 ; (m+m1<<32) + LDD -24(%sp),ht ; r24 = ht + + CMPCLR,*>>= m,m1,%r0 ; if (m < m1) + ADD,L ht,high_one,ht ; ht+=high_one + + EXTRD,U m,31,32,temp1 ; m >> 32 + LDD -32(%sp),lt ; lt + ADD,L ht,temp1,ht ; ht+= m>>32 + ADD lt,temp3,lt ; lt = lt+m1 + ADD,DC ht,%r0,ht ; ht++ + + ADD ht,ht,ht ; ht=ht+ht; + ADD,DC C3,%r0,C3 ; add in carry (c3++) + + ADD lt,lt,lt ; lt=lt+lt; + ADD,DC ht,%r0,ht ; add in carry (ht++) + + ADD C1,lt,C1 ; c1=c1+lt + ADD,DC,*NUV ht,%r0,ht ; add in carry (ht++) + LDO 1(C3),C3 ; bump c3 if overflow,nullify otherwise + + ADD C2,ht,C2 ; c2 = c2 + ht + ADD,DC C3,%r0,C3 ; add in carry (c3++) +.endm + +; +;void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a) +; arg0 = r_ptr +; arg1 = a_ptr +; + +bn_sqr_comba8 + .PROC + .CALLINFO FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_sqr_comba8,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .ENTRY + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z -1,32,33,high_mask ; Create Mask 0xffffffff80000000L + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + FLDD 32(a_ptr),a4 + FLDD 40(a_ptr),a5 + FLDD 48(a_ptr),a6 + FLDD 56(a_ptr),a7 + + SQR_ADD_C a0L,a0R,c1,c2,c3 + STD c1,0(r_ptr) ; r[0] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a1L,a1R,a0L,a0R,c2,c3,c1 + STD c2,8(r_ptr) ; r[1] = c2; + COPY %r0,c2 + + SQR_ADD_C a1L,a1R,c3,c1,c2 + SQR_ADD_C2 a2L,a2R,a0L,a0R,c3,c1,c2 + STD c3,16(r_ptr) ; r[2] = c3; + COPY %r0,c3 + + SQR_ADD_C2 a3L,a3R,a0L,a0R,c1,c2,c3 + SQR_ADD_C2 a2L,a2R,a1L,a1R,c1,c2,c3 + STD c1,24(r_ptr) ; r[3] = c1; + COPY %r0,c1 + + SQR_ADD_C a2L,a2R,c2,c3,c1 + SQR_ADD_C2 a3L,a3R,a1L,a1R,c2,c3,c1 + SQR_ADD_C2 a4L,a4R,a0L,a0R,c2,c3,c1 + STD c2,32(r_ptr) ; r[4] = c2; + COPY %r0,c2 + + SQR_ADD_C2 a5L,a5R,a0L,a0R,c3,c1,c2 + SQR_ADD_C2 a4L,a4R,a1L,a1R,c3,c1,c2 + SQR_ADD_C2 a3L,a3R,a2L,a2R,c3,c1,c2 + STD c3,40(r_ptr) ; r[5] = c3; + COPY %r0,c3 + + SQR_ADD_C a3L,a3R,c1,c2,c3 + SQR_ADD_C2 a4L,a4R,a2L,a2R,c1,c2,c3 + SQR_ADD_C2 a5L,a5R,a1L,a1R,c1,c2,c3 + SQR_ADD_C2 a6L,a6R,a0L,a0R,c1,c2,c3 + STD c1,48(r_ptr) ; r[6] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a7L,a7R,a0L,a0R,c2,c3,c1 + SQR_ADD_C2 a6L,a6R,a1L,a1R,c2,c3,c1 + SQR_ADD_C2 a5L,a5R,a2L,a2R,c2,c3,c1 + SQR_ADD_C2 a4L,a4R,a3L,a3R,c2,c3,c1 + STD c2,56(r_ptr) ; r[7] = c2; + COPY %r0,c2 + + SQR_ADD_C a4L,a4R,c3,c1,c2 + SQR_ADD_C2 a5L,a5R,a3L,a3R,c3,c1,c2 + SQR_ADD_C2 a6L,a6R,a2L,a2R,c3,c1,c2 + SQR_ADD_C2 a7L,a7R,a1L,a1R,c3,c1,c2 + STD c3,64(r_ptr) ; r[8] = c3; + COPY %r0,c3 + + SQR_ADD_C2 a7L,a7R,a2L,a2R,c1,c2,c3 + SQR_ADD_C2 a6L,a6R,a3L,a3R,c1,c2,c3 + SQR_ADD_C2 a5L,a5R,a4L,a4R,c1,c2,c3 + STD c1,72(r_ptr) ; r[9] = c1; + COPY %r0,c1 + + SQR_ADD_C a5L,a5R,c2,c3,c1 + SQR_ADD_C2 a6L,a6R,a4L,a4R,c2,c3,c1 + SQR_ADD_C2 a7L,a7R,a3L,a3R,c2,c3,c1 + STD c2,80(r_ptr) ; r[10] = c2; + COPY %r0,c2 + + SQR_ADD_C2 a7L,a7R,a4L,a4R,c3,c1,c2 + SQR_ADD_C2 a6L,a6R,a5L,a5R,c3,c1,c2 + STD c3,88(r_ptr) ; r[11] = c3; + COPY %r0,c3 + + SQR_ADD_C a6L,a6R,c1,c2,c3 + SQR_ADD_C2 a7L,a7R,a5L,a5R,c1,c2,c3 + STD c1,96(r_ptr) ; r[12] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a7L,a7R,a6L,a6R,c2,c3,c1 + STD c2,104(r_ptr) ; r[13] = c2; + COPY %r0,c2 + + SQR_ADD_C a7L,a7R,c3,c1,c2 + STD c3, 112(r_ptr) ; r[14] = c3 + STD c1, 120(r_ptr) ; r[15] = c1 + + .EXIT + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + +;----------------------------------------------------------------------------- +; +;void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a) +; arg0 = r_ptr +; arg1 = a_ptr +; + +bn_sqr_comba4 + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_sqr_comba4,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z -1,32,33,high_mask ; Create Mask 0xffffffff80000000L + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + FLDD 32(a_ptr),a4 + FLDD 40(a_ptr),a5 + FLDD 48(a_ptr),a6 + FLDD 56(a_ptr),a7 + + SQR_ADD_C a0L,a0R,c1,c2,c3 + + STD c1,0(r_ptr) ; r[0] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a1L,a1R,a0L,a0R,c2,c3,c1 + + STD c2,8(r_ptr) ; r[1] = c2; + COPY %r0,c2 + + SQR_ADD_C a1L,a1R,c3,c1,c2 + SQR_ADD_C2 a2L,a2R,a0L,a0R,c3,c1,c2 + + STD c3,16(r_ptr) ; r[2] = c3; + COPY %r0,c3 + + SQR_ADD_C2 a3L,a3R,a0L,a0R,c1,c2,c3 + SQR_ADD_C2 a2L,a2R,a1L,a1R,c1,c2,c3 + + STD c1,24(r_ptr) ; r[3] = c1; + COPY %r0,c1 + + SQR_ADD_C a2L,a2R,c2,c3,c1 + SQR_ADD_C2 a3L,a3R,a1L,a1R,c2,c3,c1 + + STD c2,32(r_ptr) ; r[4] = c2; + COPY %r0,c2 + + SQR_ADD_C2 a3L,a3R,a2L,a2R,c3,c1,c2 + STD c3,40(r_ptr) ; r[5] = c3; + COPY %r0,c3 + + SQR_ADD_C a3L,a3R,c1,c2,c3 + STD c1,48(r_ptr) ; r[6] = c1; + STD c2,56(r_ptr) ; r[7] = c2; + + .EXIT + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + + +;--------------------------------------------------------------------------- + +MUL_ADD_C .macro A0L,A0R,B0L,B0R,C1,C2,C3 + XMPYU A0L,B0R,ftemp1 ; m1 = bl*ht + FSTD ftemp1,-16(%sp) ; + XMPYU A0R,B0L,ftemp2 ; m = bh*lt + FSTD ftemp2,-8(%sp) ; + XMPYU A0R,B0R,ftemp3 ; lt = bl*lt + FSTD ftemp3,-32(%sp) + XMPYU A0L,B0L,ftemp4 ; ht = bh*ht + FSTD ftemp4,-24(%sp) ; + + LDD -8(%sp),m ; r21 = m + LDD -16(%sp),m1 ; r19 = m1 + ADD,L m,m1,m ; m+m1 + + DEPD,Z m,31,32,temp3 ; (m+m1<<32) + LDD -24(%sp),ht ; r24 = ht + + CMPCLR,*>>= m,m1,%r0 ; if (m < m1) + ADD,L ht,high_one,ht ; ht+=high_one + + EXTRD,U m,31,32,temp1 ; m >> 32 + LDD -32(%sp),lt ; lt + ADD,L ht,temp1,ht ; ht+= m>>32 + ADD lt,temp3,lt ; lt = lt+m1 + ADD,DC ht,%r0,ht ; ht++ + + ADD C1,lt,C1 ; c1=c1+lt + ADD,DC ht,%r0,ht ; bump c3 if overflow,nullify otherwise + + ADD C2,ht,C2 ; c2 = c2 + ht + ADD,DC C3,%r0,C3 ; add in carry (c3++) +.endm + + +; +;void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +; arg0 = r_ptr +; arg1 = a_ptr +; arg2 = b_ptr +; + +bn_mul_comba8 + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_mul_comba8,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + FSTD %fr12,32(%sp) ; save r6 + FSTD %fr13,40(%sp) ; save r7 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + FLDD 32(a_ptr),a4 + FLDD 40(a_ptr),a5 + FLDD 48(a_ptr),a6 + FLDD 56(a_ptr),a7 + + FLDD 0(b_ptr),b0 + FLDD 8(b_ptr),b1 + FLDD 16(b_ptr),b2 + FLDD 24(b_ptr),b3 + FLDD 32(b_ptr),b4 + FLDD 40(b_ptr),b5 + FLDD 48(b_ptr),b6 + FLDD 56(b_ptr),b7 + + MUL_ADD_C a0L,a0R,b0L,b0R,c1,c2,c3 + STD c1,0(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a0L,a0R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b0L,b0R,c2,c3,c1 + STD c2,8(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a2L,a2R,b0L,b0R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a0L,a0R,b2L,b2R,c3,c1,c2 + STD c3,16(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a0L,a0R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a1L,a1R,b2L,b2R,c1,c2,c3 + MUL_ADD_C a2L,a2R,b1L,b1R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b0L,b0R,c1,c2,c3 + STD c1,24(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a4L,a4R,b0L,b0R,c2,c3,c1 + MUL_ADD_C a3L,a3R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a2L,a2R,b2L,b2R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b3L,b3R,c2,c3,c1 + MUL_ADD_C a0L,a0R,b4L,b4R,c2,c3,c1 + STD c2,32(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a0L,a0R,b5L,b5R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b4L,b4R,c3,c1,c2 + MUL_ADD_C a2L,a2R,b3L,b3R,c3,c1,c2 + MUL_ADD_C a3L,a3R,b2L,b2R,c3,c1,c2 + MUL_ADD_C a4L,a4R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a5L,a5R,b0L,b0R,c3,c1,c2 + STD c3,40(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a6L,a6R,b0L,b0R,c1,c2,c3 + MUL_ADD_C a5L,a5R,b1L,b1R,c1,c2,c3 + MUL_ADD_C a4L,a4R,b2L,b2R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a2L,a2R,b4L,b4R,c1,c2,c3 + MUL_ADD_C a1L,a1R,b5L,b5R,c1,c2,c3 + MUL_ADD_C a0L,a0R,b6L,b6R,c1,c2,c3 + STD c1,48(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a0L,a0R,b7L,b7R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b6L,b6R,c2,c3,c1 + MUL_ADD_C a2L,a2R,b5L,b5R,c2,c3,c1 + MUL_ADD_C a3L,a3R,b4L,b4R,c2,c3,c1 + MUL_ADD_C a4L,a4R,b3L,b3R,c2,c3,c1 + MUL_ADD_C a5L,a5R,b2L,b2R,c2,c3,c1 + MUL_ADD_C a6L,a6R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a7L,a7R,b0L,b0R,c2,c3,c1 + STD c2,56(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a7L,a7R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a6L,a6R,b2L,b2R,c3,c1,c2 + MUL_ADD_C a5L,a5R,b3L,b3R,c3,c1,c2 + MUL_ADD_C a4L,a4R,b4L,b4R,c3,c1,c2 + MUL_ADD_C a3L,a3R,b5L,b5R,c3,c1,c2 + MUL_ADD_C a2L,a2R,b6L,b6R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b7L,b7R,c3,c1,c2 + STD c3,64(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a2L,a2R,b7L,b7R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b6L,b6R,c1,c2,c3 + MUL_ADD_C a4L,a4R,b5L,b5R,c1,c2,c3 + MUL_ADD_C a5L,a5R,b4L,b4R,c1,c2,c3 + MUL_ADD_C a6L,a6R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a7L,a7R,b2L,b2R,c1,c2,c3 + STD c1,72(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a7L,a7R,b3L,b3R,c2,c3,c1 + MUL_ADD_C a6L,a6R,b4L,b4R,c2,c3,c1 + MUL_ADD_C a5L,a5R,b5L,b5R,c2,c3,c1 + MUL_ADD_C a4L,a4R,b6L,b6R,c2,c3,c1 + MUL_ADD_C a3L,a3R,b7L,b7R,c2,c3,c1 + STD c2,80(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a4L,a4R,b7L,b7R,c3,c1,c2 + MUL_ADD_C a5L,a5R,b6L,b6R,c3,c1,c2 + MUL_ADD_C a6L,a6R,b5L,b5R,c3,c1,c2 + MUL_ADD_C a7L,a7R,b4L,b4R,c3,c1,c2 + STD c3,88(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a7L,a7R,b5L,b5R,c1,c2,c3 + MUL_ADD_C a6L,a6R,b6L,b6R,c1,c2,c3 + MUL_ADD_C a5L,a5R,b7L,b7R,c1,c2,c3 + STD c1,96(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a6L,a6R,b7L,b7R,c2,c3,c1 + MUL_ADD_C a7L,a7R,b6L,b6R,c2,c3,c1 + STD c2,104(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a7L,a7R,b7L,b7R,c3,c1,c2 + STD c3,112(r_ptr) + STD c1,120(r_ptr) + + .EXIT + FLDD -88(%sp),%fr13 + FLDD -96(%sp),%fr12 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + +;----------------------------------------------------------------------------- +; +;void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +; arg0 = r_ptr +; arg1 = a_ptr +; arg2 = b_ptr +; + +bn_mul_comba4 + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_mul_comba4,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + FSTD %fr12,32(%sp) ; save r6 + FSTD %fr13,40(%sp) ; save r7 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + + FLDD 0(b_ptr),b0 + FLDD 8(b_ptr),b1 + FLDD 16(b_ptr),b2 + FLDD 24(b_ptr),b3 + + MUL_ADD_C a0L,a0R,b0L,b0R,c1,c2,c3 + STD c1,0(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a0L,a0R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b0L,b0R,c2,c3,c1 + STD c2,8(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a2L,a2R,b0L,b0R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a0L,a0R,b2L,b2R,c3,c1,c2 + STD c3,16(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a0L,a0R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a1L,a1R,b2L,b2R,c1,c2,c3 + MUL_ADD_C a2L,a2R,b1L,b1R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b0L,b0R,c1,c2,c3 + STD c1,24(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a3L,a3R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a2L,a2R,b2L,b2R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b3L,b3R,c2,c3,c1 + STD c2,32(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a2L,a2R,b3L,b3R,c3,c1,c2 + MUL_ADD_C a3L,a3R,b2L,b2R,c3,c1,c2 + STD c3,40(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a3L,a3R,b3L,b3R,c1,c2,c3 + STD c1,48(r_ptr) + STD c2,56(r_ptr) + + .EXIT + FLDD -88(%sp),%fr13 + FLDD -96(%sp),%fr12 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + + + .SPACE $TEXT$ + .SUBSPA $CODE$ + .SPACE $PRIVATE$,SORT=16 + .IMPORT $global$,DATA + .SPACE $TEXT$ + .SUBSPA $CODE$ + .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=0x2c,SORT=16 +C$4 + .ALIGN 8 + .STRINGZ "Division would overflow (%d)\n" + .END diff --git a/src/lib/libcrypto/bn/asm/sparcv8.S b/src/lib/libcrypto/bn/asm/sparcv8.S new file mode 100644 index 0000000000..88c5dc480a --- /dev/null +++ b/src/lib/libcrypto/bn/asm/sparcv8.S @@ -0,0 +1,1458 @@ +.ident "sparcv8.s, Version 1.4" +.ident "SPARC v8 ISA artwork by Andy Polyakov " + +/* + * ==================================================================== + * Written by Andy Polyakov for the OpenSSL + * project. + * + * Rights for redistribution and usage in source and binary forms are + * granted according to the OpenSSL license. Warranty of any kind is + * disclaimed. + * ==================================================================== + */ + +/* + * This is my modest contributon to OpenSSL project (see + * http://www.openssl.org/ for more information about it) and is + * a drop-in SuperSPARC ISA replacement for crypto/bn/bn_asm.c + * module. For updates see http://fy.chalmers.se/~appro/hpe/. + * + * See bn_asm.sparc.v8plus.S for more details. + */ + +/* + * Revision history. + * + * 1.1 - new loop unrolling model(*); + * 1.2 - made gas friendly; + * 1.3 - fixed problem with /usr/ccs/lib/cpp; + * 1.4 - some retunes; + * + * (*) see bn_asm.sparc.v8plus.S for details + */ + +.section ".text",#alloc,#execinstr +.file "bn_asm.sparc.v8.S" + +.align 32 + +.global bn_mul_add_words +/* + * BN_ULONG bn_mul_add_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_add_words: + cmp %o2,0 + bg,a .L_bn_mul_add_words_proceed + ld [%o1],%g2 + retl + clr %o0 + +.L_bn_mul_add_words_proceed: + andcc %o2,-4,%g0 + bz .L_bn_mul_add_words_tail + clr %o5 + +.L_bn_mul_add_words_loop: + ld [%o0],%o4 + ld [%o1+4],%g3 + umul %o3,%g2,%g2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + st %o4,[%o0] + addx %g1,0,%o5 + + ld [%o0+4],%o4 + ld [%o1+8],%g2 + umul %o3,%g3,%g3 + dec 4,%o2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g3,%o4 + st %o4,[%o0+4] + addx %g1,0,%o5 + + ld [%o0+8],%o4 + ld [%o1+12],%g3 + umul %o3,%g2,%g2 + inc 16,%o1 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + st %o4,[%o0+8] + addx %g1,0,%o5 + + ld [%o0+12],%o4 + umul %o3,%g3,%g3 + inc 16,%o0 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g3,%o4 + st %o4,[%o0-4] + addx %g1,0,%o5 + andcc %o2,-4,%g0 + bnz,a .L_bn_mul_add_words_loop + ld [%o1],%g2 + + tst %o2 + bnz,a .L_bn_mul_add_words_tail + ld [%o1],%g2 +.L_bn_mul_add_words_return: + retl + mov %o5,%o0 + nop + +.L_bn_mul_add_words_tail: + ld [%o0],%o4 + umul %o3,%g2,%g2 + addcc %o4,%o5,%o4 + rd %y,%g1 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_add_words_return + st %o4,[%o0] + + ld [%o1+4],%g2 + ld [%o0+4],%o4 + umul %o3,%g2,%g2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_add_words_return + st %o4,[%o0+4] + + ld [%o1+8],%g2 + ld [%o0+8],%o4 + umul %o3,%g2,%g2 + rd %y,%g1 + addcc %o4,%o5,%o4 + addx %g1,0,%g1 + addcc %o4,%g2,%o4 + st %o4,[%o0+8] + retl + addx %g1,0,%o0 + +.type bn_mul_add_words,#function +.size bn_mul_add_words,(.-bn_mul_add_words) + +.align 32 + +.global bn_mul_words +/* + * BN_ULONG bn_mul_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_words: + cmp %o2,0 + bg,a .L_bn_mul_words_proceeed + ld [%o1],%g2 + retl + clr %o0 + +.L_bn_mul_words_proceeed: + andcc %o2,-4,%g0 + bz .L_bn_mul_words_tail + clr %o5 + +.L_bn_mul_words_loop: + ld [%o1+4],%g3 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + addx %g1,0,%o5 + st %g2,[%o0] + + ld [%o1+8],%g2 + umul %o3,%g3,%g3 + addcc %g3,%o5,%g3 + rd %y,%g1 + dec 4,%o2 + addx %g1,0,%o5 + st %g3,[%o0+4] + + ld [%o1+12],%g3 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + inc 16,%o1 + st %g2,[%o0+8] + addx %g1,0,%o5 + + umul %o3,%g3,%g3 + addcc %g3,%o5,%g3 + rd %y,%g1 + inc 16,%o0 + addx %g1,0,%o5 + st %g3,[%o0-4] + andcc %o2,-4,%g0 + nop + bnz,a .L_bn_mul_words_loop + ld [%o1],%g2 + + tst %o2 + bnz,a .L_bn_mul_words_tail + ld [%o1],%g2 +.L_bn_mul_words_return: + retl + mov %o5,%o0 + nop + +.L_bn_mul_words_tail: + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_words_return + st %g2,[%o0] + nop + + ld [%o1+4],%g2 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + addx %g1,0,%o5 + deccc %o2 + bz .L_bn_mul_words_return + st %g2,[%o0+4] + + ld [%o1+8],%g2 + umul %o3,%g2,%g2 + addcc %g2,%o5,%g2 + rd %y,%g1 + st %g2,[%o0+8] + retl + addx %g1,0,%o0 + +.type bn_mul_words,#function +.size bn_mul_words,(.-bn_mul_words) + +.align 32 +.global bn_sqr_words +/* + * void bn_sqr_words(r,a,n) + * BN_ULONG *r,*a; + * int n; + */ +bn_sqr_words: + cmp %o2,0 + bg,a .L_bn_sqr_words_proceeed + ld [%o1],%g2 + retl + clr %o0 + +.L_bn_sqr_words_proceeed: + andcc %o2,-4,%g0 + bz .L_bn_sqr_words_tail + clr %o5 + +.L_bn_sqr_words_loop: + ld [%o1+4],%g3 + umul %g2,%g2,%o4 + st %o4,[%o0] + rd %y,%o5 + st %o5,[%o0+4] + + ld [%o1+8],%g2 + umul %g3,%g3,%o4 + dec 4,%o2 + st %o4,[%o0+8] + rd %y,%o5 + st %o5,[%o0+12] + nop + + ld [%o1+12],%g3 + umul %g2,%g2,%o4 + st %o4,[%o0+16] + rd %y,%o5 + inc 16,%o1 + st %o5,[%o0+20] + + umul %g3,%g3,%o4 + inc 32,%o0 + st %o4,[%o0-8] + rd %y,%o5 + st %o5,[%o0-4] + andcc %o2,-4,%g2 + bnz,a .L_bn_sqr_words_loop + ld [%o1],%g2 + + tst %o2 + nop + bnz,a .L_bn_sqr_words_tail + ld [%o1],%g2 +.L_bn_sqr_words_return: + retl + clr %o0 + +.L_bn_sqr_words_tail: + umul %g2,%g2,%o4 + st %o4,[%o0] + deccc %o2 + rd %y,%o5 + bz .L_bn_sqr_words_return + st %o5,[%o0+4] + + ld [%o1+4],%g2 + umul %g2,%g2,%o4 + st %o4,[%o0+8] + deccc %o2 + rd %y,%o5 + nop + bz .L_bn_sqr_words_return + st %o5,[%o0+12] + + ld [%o1+8],%g2 + umul %g2,%g2,%o4 + st %o4,[%o0+16] + rd %y,%o5 + st %o5,[%o0+20] + retl + clr %o0 + +.type bn_sqr_words,#function +.size bn_sqr_words,(.-bn_sqr_words) + +.align 32 + +.global bn_div_words +/* + * BN_ULONG bn_div_words(h,l,d) + * BN_ULONG h,l,d; + */ +bn_div_words: + wr %o0,%y + udiv %o1,%o2,%o0 + retl + nop + +.type bn_div_words,#function +.size bn_div_words,(.-bn_div_words) + +.align 32 + +.global bn_add_words +/* + * BN_ULONG bn_add_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_add_words: + cmp %o3,0 + bg,a .L_bn_add_words_proceed + ld [%o1],%o4 + retl + clr %o0 + +.L_bn_add_words_proceed: + andcc %o3,-4,%g0 + bz .L_bn_add_words_tail + clr %g1 + ba .L_bn_add_words_warn_loop + addcc %g0,0,%g0 ! clear carry flag + +.L_bn_add_words_loop: + ld [%o1],%o4 +.L_bn_add_words_warn_loop: + ld [%o2],%o5 + ld [%o1+4],%g3 + ld [%o2+4],%g4 + dec 4,%o3 + addxcc %o5,%o4,%o5 + st %o5,[%o0] + + ld [%o1+8],%o4 + ld [%o2+8],%o5 + inc 16,%o1 + addxcc %g3,%g4,%g3 + st %g3,[%o0+4] + + ld [%o1-4],%g3 + ld [%o2+12],%g4 + inc 16,%o2 + addxcc %o5,%o4,%o5 + st %o5,[%o0+8] + + inc 16,%o0 + addxcc %g3,%g4,%g3 + st %g3,[%o0-4] + addx %g0,0,%g1 + andcc %o3,-4,%g0 + bnz,a .L_bn_add_words_loop + addcc %g1,-1,%g0 + + tst %o3 + bnz,a .L_bn_add_words_tail + ld [%o1],%o4 +.L_bn_add_words_return: + retl + mov %g1,%o0 + +.L_bn_add_words_tail: + addcc %g1,-1,%g0 + ld [%o2],%o5 + addxcc %o5,%o4,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_add_words_return + st %o5,[%o0] + + ld [%o1+4],%o4 + addcc %g1,-1,%g0 + ld [%o2+4],%o5 + addxcc %o5,%o4,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_add_words_return + st %o5,[%o0+4] + + ld [%o1+8],%o4 + addcc %g1,-1,%g0 + ld [%o2+8],%o5 + addxcc %o5,%o4,%o5 + st %o5,[%o0+8] + retl + addx %g0,0,%o0 + +.type bn_add_words,#function +.size bn_add_words,(.-bn_add_words) + +.align 32 + +.global bn_sub_words +/* + * BN_ULONG bn_sub_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_sub_words: + cmp %o3,0 + bg,a .L_bn_sub_words_proceed + ld [%o1],%o4 + retl + clr %o0 + +.L_bn_sub_words_proceed: + andcc %o3,-4,%g0 + bz .L_bn_sub_words_tail + clr %g1 + ba .L_bn_sub_words_warm_loop + addcc %g0,0,%g0 ! clear carry flag + +.L_bn_sub_words_loop: + ld [%o1],%o4 +.L_bn_sub_words_warm_loop: + ld [%o2],%o5 + ld [%o1+4],%g3 + ld [%o2+4],%g4 + dec 4,%o3 + subxcc %o4,%o5,%o5 + st %o5,[%o0] + + ld [%o1+8],%o4 + ld [%o2+8],%o5 + inc 16,%o1 + subxcc %g3,%g4,%g4 + st %g4,[%o0+4] + + ld [%o1-4],%g3 + ld [%o2+12],%g4 + inc 16,%o2 + subxcc %o4,%o5,%o5 + st %o5,[%o0+8] + + inc 16,%o0 + subxcc %g3,%g4,%g4 + st %g4,[%o0-4] + addx %g0,0,%g1 + andcc %o3,-4,%g0 + bnz,a .L_bn_sub_words_loop + addcc %g1,-1,%g0 + + tst %o3 + nop + bnz,a .L_bn_sub_words_tail + ld [%o1],%o4 +.L_bn_sub_words_return: + retl + mov %g1,%o0 + +.L_bn_sub_words_tail: + addcc %g1,-1,%g0 + ld [%o2],%o5 + subxcc %o4,%o5,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_sub_words_return + st %o5,[%o0] + nop + + ld [%o1+4],%o4 + addcc %g1,-1,%g0 + ld [%o2+4],%o5 + subxcc %o4,%o5,%o5 + addx %g0,0,%g1 + deccc %o3 + bz .L_bn_sub_words_return + st %o5,[%o0+4] + + ld [%o1+8],%o4 + addcc %g1,-1,%g0 + ld [%o2+8],%o5 + subxcc %o4,%o5,%o5 + st %o5,[%o0+8] + retl + addx %g0,0,%o0 + +.type bn_sub_words,#function +.size bn_sub_words,(.-bn_sub_words) + +#define FRAME_SIZE -96 + +/* + * Here is register usage map for *all* routines below. + */ +#define t_1 %o0 +#define t_2 %o1 +#define c_1 %o2 +#define c_2 %o3 +#define c_3 %o4 + +#define ap(I) [%i1+4*I] +#define bp(I) [%i2+4*I] +#define rp(I) [%i0+4*I] + +#define a_0 %l0 +#define a_1 %l1 +#define a_2 %l2 +#define a_3 %l3 +#define a_4 %l4 +#define a_5 %l5 +#define a_6 %l6 +#define a_7 %l7 + +#define b_0 %i3 +#define b_1 %i4 +#define b_2 %i5 +#define b_3 %o5 +#define b_4 %g1 +#define b_5 %g2 +#define b_6 %g3 +#define b_7 %g4 + +.align 32 +.global bn_mul_comba8 +/* + * void bn_mul_comba8(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba8: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + ld bp(0),b_0 + umul a_0,b_0,c_1 !=!mul_add_c(a[0],b[0],c1,c2,c3); + ld bp(1),b_1 + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + umul a_0,b_1,t_1 !=!mul_add_c(a[0],b[1],c2,c3,c1); + ld ap(1),a_1 + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc %g0,t_2,c_3 != + addx %g0,%g0,c_1 + ld ap(2),a_2 + umul a_1,b_0,t_1 !mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + st c_2,rp(1) !r[1]=c2; + addx c_1,%g0,c_1 != + + umul a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx %g0,%g0,c_2 + ld bp(2),b_2 + umul a_1,b_1,t_1 !mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + ld bp(3),b_3 + addx c_2,%g0,c_2 != + umul a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + st c_3,rp(2) !r[2]=c3; + + umul a_0,b_3,t_1 !mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + umul a_1,b_2,t_1 !=!mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + ld ap(3),a_3 + umul a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + ld ap(4),a_4 + umul a_3,b_0,t_1 !mul_add_c(a[3],b[0],c1,c2,c3);!= + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_4,b_0,t_1 !mul_add_c(a[4],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + umul a_3,b_1,t_1 !mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_2,b_2,t_1 !=!mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + ld bp(4),b_4 + umul a_1,b_3,t_1 !mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + ld bp(5),b_5 + umul a_0,b_4,t_1 !=!mul_add_c(a[0],b[4],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(4) !r[4]=c2; + + umul a_0,b_5,t_1 !mul_add_c(a[0],b[5],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + umul a_1,b_4,t_1 !mul_add_c(a[1],b[4],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_2,b_3,t_1 !=!mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + ld ap(5),a_5 + umul a_4,b_1,t_1 !mul_add_c(a[4],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + ld ap(6),a_6 + addx c_2,%g0,c_2 != + umul a_5,b_0,t_1 !mul_add_c(a[5],b[0],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + st c_3,rp(5) !r[5]=c3; + + umul a_6,b_0,t_1 !mul_add_c(a[6],b[0],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + umul a_5,b_1,t_1 !=!mul_add_c(a[5],b[1],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_4,b_2,t_1 !mul_add_c(a[4],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + umul a_3,b_3,t_1 !mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_2,b_4,t_1 !mul_add_c(a[2],b[4],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + ld bp(6),b_6 + addx c_3,%g0,c_3 != + umul a_1,b_5,t_1 !mul_add_c(a[1],b[5],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + ld bp(7),b_7 + umul a_0,b_6,t_1 !mul_add_c(a[0],b[6],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + st c_1,rp(6) !r[6]=c1; + addx c_3,%g0,c_3 != + + umul a_0,b_7,t_1 !mul_add_c(a[0],b[7],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx %g0,%g0,c_1 + umul a_1,b_6,t_1 !mul_add_c(a[1],b[6],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_2,b_5,t_1 !mul_add_c(a[2],b[5],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_3,b_4,t_1 !=!mul_add_c(a[3],b[4],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + umul a_4,b_3,t_1 !mul_add_c(a[4],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_5,b_2,t_1 !mul_add_c(a[5],b[2],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + ld ap(7),a_7 + umul a_6,b_1,t_1 !=!mul_add_c(a[6],b[1],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + umul a_7,b_0,t_1 !mul_add_c(a[7],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + st c_2,rp(7) !r[7]=c2; + + umul a_7,b_1,t_1 !mul_add_c(a[7],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + umul a_6,b_2,t_1 !=!mul_add_c(a[6],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_5,b_3,t_1 !mul_add_c(a[5],b[3],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + umul a_4,b_4,t_1 !mul_add_c(a[4],b[4],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_3,b_5,t_1 !mul_add_c(a[3],b[5],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_2,b_6,t_1 !=!mul_add_c(a[2],b[6],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_1,b_7,t_1 !mul_add_c(a[1],b[7],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 ! + addx c_2,%g0,c_2 + st c_3,rp(8) !r[8]=c3; + + umul a_2,b_7,t_1 !mul_add_c(a[2],b[7],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + umul a_3,b_6,t_1 !=!mul_add_c(a[3],b[6],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_4,b_5,t_1 !mul_add_c(a[4],b[5],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + umul a_5,b_4,t_1 !mul_add_c(a[5],b[4],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_6,b_3,t_1 !mul_add_c(a[6],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_7,b_2,t_1 !=!mul_add_c(a[7],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(9) !r[9]=c1; + + umul a_7,b_3,t_1 !mul_add_c(a[7],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + umul a_6,b_4,t_1 !mul_add_c(a[6],b[4],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_5,b_5,t_1 !=!mul_add_c(a[5],b[5],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + umul a_4,b_6,t_1 !mul_add_c(a[4],b[6],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_3,b_7,t_1 !mul_add_c(a[3],b[7],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(10) !r[10]=c2; + + umul a_4,b_7,t_1 !=!mul_add_c(a[4],b[7],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 != + umul a_5,b_6,t_1 !mul_add_c(a[5],b[6],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + umul a_6,b_5,t_1 !mul_add_c(a[6],b[5],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_7,b_4,t_1 !mul_add_c(a[7],b[4],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(11) !r[11]=c3; + addx c_2,%g0,c_2 != + + umul a_7,b_5,t_1 !mul_add_c(a[7],b[5],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + umul a_6,b_6,t_1 !mul_add_c(a[6],b[6],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_5,b_7,t_1 !mul_add_c(a[5],b[7],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + st c_1,rp(12) !r[12]=c1; + addx c_3,%g0,c_3 != + + umul a_6,b_7,t_1 !mul_add_c(a[6],b[7],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 != + addx %g0,%g0,c_1 + umul a_7,b_6,t_1 !mul_add_c(a[7],b[6],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(13) !r[13]=c2; + + umul a_7,b_7,t_1 !=!mul_add_c(a[7],b[7],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + nop != + st c_3,rp(14) !r[14]=c3; + st c_1,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 + +.type bn_mul_comba8,#function +.size bn_mul_comba8,(.-bn_mul_comba8) + +.align 32 + +.global bn_mul_comba4 +/* + * void bn_mul_comba4(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba4: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + ld bp(0),b_0 + umul a_0,b_0,c_1 !=!mul_add_c(a[0],b[0],c1,c2,c3); + ld bp(1),b_1 + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + umul a_0,b_1,t_1 !=!mul_add_c(a[0],b[1],c2,c3,c1); + ld ap(1),a_1 + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc %g0,t_2,c_3 + addx %g0,%g0,c_1 + ld ap(2),a_2 + umul a_1,b_0,t_1 !=!mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(1) !r[1]=c2; + + umul a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + ld bp(2),b_2 + umul a_1,b_1,t_1 !=!mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + ld bp(3),b_3 + umul a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + st c_3,rp(2) !r[2]=c3; + + umul a_0,b_3,t_1 !=!mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 != + umul a_1,b_2,t_1 !mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + ld ap(3),a_3 + umul a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_3,b_0,t_1 !=!mul_add_c(a[3],b[0],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_3,b_1,t_1 !mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + umul a_2,b_2,t_1 !mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + umul a_1,b_3,t_1 !=!mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(4) !r[4]=c2; + + umul a_2,b_3,t_1 !mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + umul a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(5) !r[5]=c3; + addx c_2,%g0,c_2 != + + umul a_3,b_3,t_1 !mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + st c_1,rp(6) !r[6]=c1; + st c_2,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_mul_comba4,#function +.size bn_mul_comba4,(.-bn_mul_comba4) + +.align 32 + +.global bn_sqr_comba8 +bn_sqr_comba8: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + ld ap(1),a_1 + umul a_0,a_0,c_1 !=!sqr_add_c(a,0,c1,c2,c3); + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + ld ap(2),a_2 + umul a_0,a_1,t_1 !=!sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc %g0,t_2,c_3 + addx %g0,%g0,c_1 != + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 + st c_2,rp(1) !r[1]=c2; + addx c_1,%g0,c_1 != + + umul a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + ld ap(3),a_3 + umul a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + st c_3,rp(2) !r[2]=c3; + + umul a_0,a_3,t_1 !=!sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 != + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + ld ap(4),a_4 + addx c_3,%g0,c_3 != + umul a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_4,a_0,t_1 !sqr_add_c2(a,4,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + ld ap(5),a_5 + umul a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + st c_2,rp(4) !r[4]=c2; + addx c_1,%g0,c_1 != + + umul a_0,a_5,t_1 !sqr_add_c2(a,5,0,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + umul a_1,a_4,t_1 !sqr_add_c2(a,4,1,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + ld ap(6),a_6 + umul a_2,a_3,t_1 !sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + st c_3,rp(5) !r[5]=c3; + + umul a_6,a_0,t_1 !sqr_add_c2(a,6,0,c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_5,a_1,t_1 !sqr_add_c2(a,5,1,c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + umul a_4,a_2,t_1 !sqr_add_c2(a,4,2,c1,c2,c3); + addcc c_1,t_1,c_1 != + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 != + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 + ld ap(7),a_7 + umul a_3,a_3,t_1 !=!sqr_add_c(a,3,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(6) !r[6]=c1; + + umul a_0,a_7,t_1 !sqr_add_c2(a,7,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_1,a_6,t_1 !sqr_add_c2(a,6,1,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_2,a_5,t_1 !sqr_add_c2(a,5,2,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_3,a_4,t_1 !sqr_add_c2(a,4,3,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + st c_2,rp(7) !r[7]=c2; + + umul a_7,a_1,t_1 !sqr_add_c2(a,7,1,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_6,a_2,t_1 !sqr_add_c2(a,6,2,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_5,a_3,t_1 !sqr_add_c2(a,5,3,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + addcc c_3,t_1,c_3 != + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_4,a_4,t_1 !sqr_add_c(a,4,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(8) !r[8]=c3; + addx c_2,%g0,c_2 != + + umul a_2,a_7,t_1 !sqr_add_c2(a,7,2,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_3,a_6,t_1 !sqr_add_c2(a,6,3,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_4,a_5,t_1 !sqr_add_c2(a,5,4,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(9) !r[9]=c1; + + umul a_7,a_3,t_1 !sqr_add_c2(a,7,3,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_6,a_4,t_1 !sqr_add_c2(a,6,4,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_5,a_5,t_1 !sqr_add_c(a,5,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(10) !r[10]=c2; + + umul a_4,a_7,t_1 !=!sqr_add_c2(a,7,4,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 != + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 + umul a_5,a_6,t_1 !=!sqr_add_c2(a,6,5,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx c_2,%g0,c_2 != + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + st c_3,rp(11) !r[11]=c3; + addx c_2,%g0,c_2 != + + umul a_7,a_5,t_1 !sqr_add_c2(a,7,5,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_6,a_6,t_1 !sqr_add_c(a,6,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + st c_1,rp(12) !r[12]=c1; + + umul a_6,a_7,t_1 !sqr_add_c2(a,7,6,c2,c3,c1); + addcc c_2,t_1,c_2 != + rd %y,t_2 + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 != + addxcc c_3,t_2,c_3 + st c_2,rp(13) !r[13]=c2; + addx c_1,%g0,c_1 != + + umul a_7,a_7,t_1 !sqr_add_c(a,7,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 != + st c_3,rp(14) !r[14]=c3; + st c_1,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba8,#function +.size bn_sqr_comba8,(.-bn_sqr_comba8) + +.align 32 + +.global bn_sqr_comba4 +/* + * void bn_sqr_comba4(r,a) + * BN_ULONG *r,*a; + */ +bn_sqr_comba4: + save %sp,FRAME_SIZE,%sp + ld ap(0),a_0 + umul a_0,a_0,c_1 !sqr_add_c(a,0,c1,c2,c3); + ld ap(1),a_1 != + rd %y,c_2 + st c_1,rp(0) !r[0]=c1; + + ld ap(2),a_2 + umul a_0,a_1,t_1 !=!sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 + addxcc %g0,t_2,c_3 + addx %g0,%g0,c_1 != + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 != + st c_2,rp(1) !r[1]=c2; + + umul a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 != + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 != + addx c_2,%g0,c_2 + ld ap(3),a_3 + umul a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_3,t_1,c_3 != + rd %y,t_2 + addxcc c_1,t_2,c_1 + st c_3,rp(2) !r[2]=c3; + addx c_2,%g0,c_2 != + + umul a_0,a_3,t_1 !sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx %g0,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + umul a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + addx c_3,%g0,c_3 + addcc c_1,t_1,c_1 + addxcc c_2,t_2,c_2 + addx c_3,%g0,c_3 != + st c_1,rp(3) !r[3]=c1; + + umul a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx %g0,%g0,c_1 + addcc c_2,t_1,c_2 + addxcc c_3,t_2,c_3 != + addx c_1,%g0,c_1 + umul a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_2,t_1,c_2 + rd %y,t_2 != + addxcc c_3,t_2,c_3 + addx c_1,%g0,c_1 + st c_2,rp(4) !r[4]=c2; + + umul a_2,a_3,t_1 !=!sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_3,t_1,c_3 + rd %y,t_2 + addxcc c_1,t_2,c_1 + addx %g0,%g0,c_2 != + addcc c_3,t_1,c_3 + addxcc c_1,t_2,c_1 + st c_3,rp(5) !r[5]=c3; + addx c_2,%g0,c_2 != + + umul a_3,a_3,t_1 !sqr_add_c(a,3,c1,c2,c3); + addcc c_1,t_1,c_1 + rd %y,t_2 + addxcc c_2,t_2,c_2 != + st c_1,rp(6) !r[6]=c1; + st c_2,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba4,#function +.size bn_sqr_comba4,(.-bn_sqr_comba4) + +.align 32 diff --git a/src/lib/libcrypto/bn/asm/sparcv8plus.S b/src/lib/libcrypto/bn/asm/sparcv8plus.S new file mode 100644 index 0000000000..0074dfdb75 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/sparcv8plus.S @@ -0,0 +1,1535 @@ +.ident "sparcv8plus.s, Version 1.4" +.ident "SPARC v9 ISA artwork by Andy Polyakov " + +/* + * ==================================================================== + * Written by Andy Polyakov for the OpenSSL + * project. + * + * Rights for redistribution and usage in source and binary forms are + * granted according to the OpenSSL license. Warranty of any kind is + * disclaimed. + * ==================================================================== + */ + +/* + * This is my modest contributon to OpenSSL project (see + * http://www.openssl.org/ for more information about it) and is + * a drop-in UltraSPARC ISA replacement for crypto/bn/bn_asm.c + * module. For updates see http://fy.chalmers.se/~appro/hpe/. + * + * Questions-n-answers. + * + * Q. How to compile? + * A. With SC4.x/SC5.x: + * + * cc -xarch=v8plus -c bn_asm.sparc.v8plus.S -o bn_asm.o + * + * and with gcc: + * + * gcc -mcpu=ultrasparc -c bn_asm.sparc.v8plus.S -o bn_asm.o + * + * or if above fails (it does if you have gas installed): + * + * gcc -E bn_asm.sparc.v8plus.S | as -xarch=v8plus /dev/fd/0 -o bn_asm.o + * + * Quick-n-dirty way to fuse the module into the library. + * Provided that the library is already configured and built + * (in 0.9.2 case with no-asm option): + * + * # cd crypto/bn + * # cp /some/place/bn_asm.sparc.v8plus.S . + * # cc -xarch=v8plus -c bn_asm.sparc.v8plus.S -o bn_asm.o + * # make + * # cd ../.. + * # make; make test + * + * Quick-n-dirty way to get rid of it: + * + * # cd crypto/bn + * # touch bn_asm.c + * # make + * # cd ../.. + * # make; make test + * + * Q. V8plus achitecture? What kind of beast is that? + * A. Well, it's rather a programming model than an architecture... + * It's actually v9-compliant, i.e. *any* UltraSPARC, CPU under + * special conditions, namely when kernel doesn't preserve upper + * 32 bits of otherwise 64-bit registers during a context switch. + * + * Q. Why just UltraSPARC? What about SuperSPARC? + * A. Original release did target UltraSPARC only. Now SuperSPARC + * version is provided along. Both version share bn_*comba[48] + * implementations (see comment later in code for explanation). + * But what's so special about this UltraSPARC implementation? + * Why didn't I let compiler do the job? Trouble is that most of + * available compilers (well, SC5.0 is the only exception) don't + * attempt to take advantage of UltraSPARC's 64-bitness under + * 32-bit kernels even though it's perfectly possible (see next + * question). + * + * Q. 64-bit registers under 32-bit kernels? Didn't you just say it + * doesn't work? + * A. You can't adress *all* registers as 64-bit wide:-( The catch is + * that you actually may rely upon %o0-%o5 and %g1-%g4 being fully + * preserved if you're in a leaf function, i.e. such never calling + * any other functions. All functions in this module are leaf and + * 10 registers is a handful. And as a matter of fact none-"comba" + * routines don't require even that much and I could even afford to + * not allocate own stack frame for 'em:-) + * + * Q. What about 64-bit kernels? + * A. What about 'em? Just kidding:-) Pure 64-bit version is currently + * under evaluation and development... + * + * Q. What about shared libraries? + * A. What about 'em? Kidding again:-) Code does *not* contain any + * code position dependencies and it's safe to include it into + * shared library as is. + * + * Q. How much faster does it go? + * A. Do you have a good benchmark? In either case below is what I + * experience with crypto/bn/expspeed.c test program: + * + * v8plus module on U10/300MHz against bn_asm.c compiled with: + * + * cc-5.0 -xarch=v8plus -xO5 -xdepend +7-12% + * cc-4.2 -xarch=v8plus -xO5 -xdepend +25-35% + * egcs-1.1.2 -mcpu=ultrasparc -O3 +35-45% + * + * v8 module on SS10/60MHz against bn_asm.c compiled with: + * + * cc-5.0 -xarch=v8 -xO5 -xdepend +7-10% + * cc-4.2 -xarch=v8 -xO5 -xdepend +10% + * egcs-1.1.2 -mv8 -O3 +35-45% + * + * As you can see it's damn hard to beat the new Sun C compiler + * and it's in first place GNU C users who will appreciate this + * assembler implementation:-) + */ + +/* + * Revision history. + * + * 1.0 - initial release; + * 1.1 - new loop unrolling model(*); + * - some more fine tuning; + * 1.2 - made gas friendly; + * - updates to documentation concerning v9; + * - new performance comparison matrix; + * 1.3 - fixed problem with /usr/ccs/lib/cpp; + * 1.4 - native V9 bn_*_comba[48] implementation (15% more efficient) + * resulting in slight overall performance kick; + * - some retunes; + * - support for GNU as added; + * + * (*) Originally unrolled loop looked like this: + * for (;;) { + * op(p+0); if (--n==0) break; + * op(p+1); if (--n==0) break; + * op(p+2); if (--n==0) break; + * op(p+3); if (--n==0) break; + * p+=4; + * } + * I unroll according to following: + * while (n&~3) { + * op(p+0); op(p+1); op(p+2); op(p+3); + * p+=4; n=-4; + * } + * if (n) { + * op(p+0); if (--n==0) return; + * op(p+2); if (--n==0) return; + * op(p+3); return; + * } + */ + +/* + * GNU assembler can't stand stuw:-( + */ +#define stuw st + +.section ".text",#alloc,#execinstr +.file "bn_asm.sparc.v8plus.S" + +.align 32 + +.global bn_mul_add_words +/* + * BN_ULONG bn_mul_add_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_add_words: + brgz,a %o2,.L_bn_mul_add_words_proceed + lduw [%o1],%g2 + retl + clr %o0 + +.L_bn_mul_add_words_proceed: + srl %o3,%g0,%o3 ! clruw %o3 + andcc %o2,-4,%g0 + bz,pn %icc,.L_bn_mul_add_words_tail + clr %o5 + +.L_bn_mul_add_words_loop: ! wow! 32 aligned! + lduw [%o0],%g1 + lduw [%o1+4],%g3 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + nop + add %o4,%g2,%o4 + stuw %o4,[%o0] + srlx %o4,32,%o5 + + lduw [%o0+4],%g1 + lduw [%o1+8],%g2 + mulx %o3,%g3,%g3 + add %g1,%o5,%o4 + dec 4,%o2 + add %o4,%g3,%o4 + stuw %o4,[%o0+4] + srlx %o4,32,%o5 + + lduw [%o0+8],%g1 + lduw [%o1+12],%g3 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + inc 16,%o1 + add %o4,%g2,%o4 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + + lduw [%o0+12],%g1 + mulx %o3,%g3,%g3 + add %g1,%o5,%o4 + inc 16,%o0 + add %o4,%g3,%o4 + andcc %o2,-4,%g0 + stuw %o4,[%o0-4] + srlx %o4,32,%o5 + bnz,a,pt %icc,.L_bn_mul_add_words_loop + lduw [%o1],%g2 + + brnz,a,pn %o2,.L_bn_mul_add_words_tail + lduw [%o1],%g2 +.L_bn_mul_add_words_return: + retl + mov %o5,%o0 + +.L_bn_mul_add_words_tail: + lduw [%o0],%g1 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + dec %o2 + add %o4,%g2,%o4 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_add_words_return + stuw %o4,[%o0] + + lduw [%o1+4],%g2 + lduw [%o0+4],%g1 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + dec %o2 + add %o4,%g2,%o4 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_add_words_return + stuw %o4,[%o0+4] + + lduw [%o1+8],%g2 + lduw [%o0+8],%g1 + mulx %o3,%g2,%g2 + add %g1,%o5,%o4 + add %o4,%g2,%o4 + stuw %o4,[%o0+8] + retl + srlx %o4,32,%o0 + +.type bn_mul_add_words,#function +.size bn_mul_add_words,(.-bn_mul_add_words) + +.align 32 + +.global bn_mul_words +/* + * BN_ULONG bn_mul_words(rp,ap,num,w) + * BN_ULONG *rp,*ap; + * int num; + * BN_ULONG w; + */ +bn_mul_words: + brgz,a %o2,.L_bn_mul_words_proceeed + lduw [%o1],%g2 + retl + clr %o0 + +.L_bn_mul_words_proceeed: + srl %o3,%g0,%o3 ! clruw %o3 + andcc %o2,-4,%g0 + bz,pn %icc,.L_bn_mul_words_tail + clr %o5 + +.L_bn_mul_words_loop: ! wow! 32 aligned! + lduw [%o1+4],%g3 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + nop + stuw %o4,[%o0] + srlx %o4,32,%o5 + + lduw [%o1+8],%g2 + mulx %o3,%g3,%g3 + add %g3,%o5,%o4 + dec 4,%o2 + stuw %o4,[%o0+4] + srlx %o4,32,%o5 + + lduw [%o1+12],%g3 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + inc 16,%o1 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + + mulx %o3,%g3,%g3 + add %g3,%o5,%o4 + inc 16,%o0 + stuw %o4,[%o0-4] + srlx %o4,32,%o5 + andcc %o2,-4,%g0 + bnz,a,pt %icc,.L_bn_mul_words_loop + lduw [%o1],%g2 + nop + nop + + brnz,a,pn %o2,.L_bn_mul_words_tail + lduw [%o1],%g2 +.L_bn_mul_words_return: + retl + mov %o5,%o0 + +.L_bn_mul_words_tail: + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + dec %o2 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_words_return + stuw %o4,[%o0] + + lduw [%o1+4],%g2 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + dec %o2 + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_mul_words_return + stuw %o4,[%o0+4] + + lduw [%o1+8],%g2 + mulx %o3,%g2,%g2 + add %g2,%o5,%o4 + stuw %o4,[%o0+8] + retl + srlx %o4,32,%o0 + +.type bn_mul_words,#function +.size bn_mul_words,(.-bn_mul_words) + +.align 32 +.global bn_sqr_words +/* + * void bn_sqr_words(r,a,n) + * BN_ULONG *r,*a; + * int n; + */ +bn_sqr_words: + brgz,a %o2,.L_bn_sqr_words_proceeed + lduw [%o1],%g2 + retl + clr %o0 + +.L_bn_sqr_words_proceeed: + andcc %o2,-4,%g0 + nop + bz,pn %icc,.L_bn_sqr_words_tail + nop + +.L_bn_sqr_words_loop: ! wow! 32 aligned! + lduw [%o1+4],%g3 + mulx %g2,%g2,%o4 + stuw %o4,[%o0] + srlx %o4,32,%o5 + stuw %o5,[%o0+4] + nop + + lduw [%o1+8],%g2 + mulx %g3,%g3,%o4 + dec 4,%o2 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + stuw %o5,[%o0+12] + + lduw [%o1+12],%g3 + mulx %g2,%g2,%o4 + srlx %o4,32,%o5 + stuw %o4,[%o0+16] + inc 16,%o1 + stuw %o5,[%o0+20] + + mulx %g3,%g3,%o4 + inc 32,%o0 + stuw %o4,[%o0-8] + srlx %o4,32,%o5 + andcc %o2,-4,%g2 + stuw %o5,[%o0-4] + bnz,a,pt %icc,.L_bn_sqr_words_loop + lduw [%o1],%g2 + nop + + brnz,a,pn %o2,.L_bn_sqr_words_tail + lduw [%o1],%g2 +.L_bn_sqr_words_return: + retl + clr %o0 + +.L_bn_sqr_words_tail: + mulx %g2,%g2,%o4 + dec %o2 + stuw %o4,[%o0] + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_sqr_words_return + stuw %o5,[%o0+4] + + lduw [%o1+4],%g2 + mulx %g2,%g2,%o4 + dec %o2 + stuw %o4,[%o0+8] + srlx %o4,32,%o5 + brz,pt %o2,.L_bn_sqr_words_return + stuw %o5,[%o0+12] + + lduw [%o1+8],%g2 + mulx %g2,%g2,%o4 + srlx %o4,32,%o5 + stuw %o4,[%o0+16] + stuw %o5,[%o0+20] + retl + clr %o0 + +.type bn_sqr_words,#function +.size bn_sqr_words,(.-bn_sqr_words) + +.align 32 +.global bn_div_words +/* + * BN_ULONG bn_div_words(h,l,d) + * BN_ULONG h,l,d; + */ +bn_div_words: + sllx %o0,32,%o0 + or %o0,%o1,%o0 + udivx %o0,%o2,%o0 + retl + srl %o0,%g0,%o0 ! clruw %o0 + +.type bn_div_words,#function +.size bn_div_words,(.-bn_div_words) + +.align 32 + +.global bn_add_words +/* + * BN_ULONG bn_add_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_add_words: + brgz,a %o3,.L_bn_add_words_proceed + lduw [%o1],%o4 + retl + clr %o0 + +.L_bn_add_words_proceed: + andcc %o3,-4,%g0 + bz,pn %icc,.L_bn_add_words_tail + addcc %g0,0,%g0 ! clear carry flag + nop + +.L_bn_add_words_loop: ! wow! 32 aligned! + dec 4,%o3 + lduw [%o2],%o5 + lduw [%o1+4],%g1 + lduw [%o2+4],%g2 + lduw [%o1+8],%g3 + lduw [%o2+8],%g4 + addccc %o5,%o4,%o5 + stuw %o5,[%o0] + + lduw [%o1+12],%o4 + lduw [%o2+12],%o5 + inc 16,%o1 + addccc %g1,%g2,%g1 + stuw %g1,[%o0+4] + + inc 16,%o2 + addccc %g3,%g4,%g3 + stuw %g3,[%o0+8] + + inc 16,%o0 + addccc %o5,%o4,%o5 + stuw %o5,[%o0-4] + and %o3,-4,%g1 + brnz,a,pt %g1,.L_bn_add_words_loop + lduw [%o1],%o4 + + brnz,a,pn %o3,.L_bn_add_words_tail + lduw [%o1],%o4 +.L_bn_add_words_return: + clr %o0 + retl + movcs %icc,1,%o0 + nop + +.L_bn_add_words_tail: + lduw [%o2],%o5 + dec %o3 + addccc %o5,%o4,%o5 + brz,pt %o3,.L_bn_add_words_return + stuw %o5,[%o0] + + lduw [%o1+4],%o4 + lduw [%o2+4],%o5 + dec %o3 + addccc %o5,%o4,%o5 + brz,pt %o3,.L_bn_add_words_return + stuw %o5,[%o0+4] + + lduw [%o1+8],%o4 + lduw [%o2+8],%o5 + addccc %o5,%o4,%o5 + stuw %o5,[%o0+8] + clr %o0 + retl + movcs %icc,1,%o0 + +.type bn_add_words,#function +.size bn_add_words,(.-bn_add_words) + +.global bn_sub_words +/* + * BN_ULONG bn_sub_words(rp,ap,bp,n) + * BN_ULONG *rp,*ap,*bp; + * int n; + */ +bn_sub_words: + brgz,a %o3,.L_bn_sub_words_proceed + lduw [%o1],%o4 + retl + clr %o0 + +.L_bn_sub_words_proceed: + andcc %o3,-4,%g0 + bz,pn %icc,.L_bn_sub_words_tail + addcc %g0,0,%g0 ! clear carry flag + nop + +.L_bn_sub_words_loop: ! wow! 32 aligned! + dec 4,%o3 + lduw [%o2],%o5 + lduw [%o1+4],%g1 + lduw [%o2+4],%g2 + lduw [%o1+8],%g3 + lduw [%o2+8],%g4 + subccc %o4,%o5,%o5 + stuw %o5,[%o0] + + lduw [%o1+12],%o4 + lduw [%o2+12],%o5 + inc 16,%o1 + subccc %g1,%g2,%g2 + stuw %g2,[%o0+4] + + inc 16,%o2 + subccc %g3,%g4,%g4 + stuw %g4,[%o0+8] + + inc 16,%o0 + subccc %o4,%o5,%o5 + stuw %o5,[%o0-4] + and %o3,-4,%g1 + brnz,a,pt %g1,.L_bn_sub_words_loop + lduw [%o1],%o4 + + brnz,a,pn %o3,.L_bn_sub_words_tail + lduw [%o1],%o4 +.L_bn_sub_words_return: + clr %o0 + retl + movcs %icc,1,%o0 + nop + +.L_bn_sub_words_tail: ! wow! 32 aligned! + lduw [%o2],%o5 + dec %o3 + subccc %o4,%o5,%o5 + brz,pt %o3,.L_bn_sub_words_return + stuw %o5,[%o0] + + lduw [%o1+4],%o4 + lduw [%o2+4],%o5 + dec %o3 + subccc %o4,%o5,%o5 + brz,pt %o3,.L_bn_sub_words_return + stuw %o5,[%o0+4] + + lduw [%o1+8],%o4 + lduw [%o2+8],%o5 + subccc %o4,%o5,%o5 + stuw %o5,[%o0+8] + clr %o0 + retl + movcs %icc,1,%o0 + +.type bn_sub_words,#function +.size bn_sub_words,(.-bn_sub_words) + +/* + * Code below depends on the fact that upper parts of the %l0-%l7 + * and %i0-%i7 are zeroed by kernel after context switch. In + * previous versions this comment stated that "the trouble is that + * it's not feasible to implement the mumbo-jumbo in less V9 + * instructions:-(" which apparently isn't true thanks to + * 'bcs,a %xcc,.+8; inc %rd' pair. But the performance improvement + * results not from the shorter code, but from elimination of + * multicycle none-pairable 'rd %y,%rd' instructions. + * + * Andy. + */ + +#define FRAME_SIZE -96 + +/* + * Here is register usage map for *all* routines below. + */ +#define t_1 %o0 +#define t_2 %o1 +#define c_12 %o2 +#define c_3 %o3 + +#define ap(I) [%i1+4*I] +#define bp(I) [%i2+4*I] +#define rp(I) [%i0+4*I] + +#define a_0 %l0 +#define a_1 %l1 +#define a_2 %l2 +#define a_3 %l3 +#define a_4 %l4 +#define a_5 %l5 +#define a_6 %l6 +#define a_7 %l7 + +#define b_0 %i3 +#define b_1 %i4 +#define b_2 %i5 +#define b_3 %o4 +#define b_4 %o5 +#define b_5 %o7 +#define b_6 %g1 +#define b_7 %g4 + +.align 32 +.global bn_mul_comba8 +/* + * void bn_mul_comba8(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba8: + save %sp,FRAME_SIZE,%sp + mov 1,t_2 + lduw ap(0),a_0 + sllx t_2,32,t_2 + lduw bp(0),b_0 != + lduw bp(1),b_1 + mulx a_0,b_0,t_1 !mul_add_c(a[0],b[0],c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !=!r[0]=c1; + + lduw ap(1),a_1 + mulx a_0,b_1,t_1 !mul_add_c(a[0],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(2),a_2 + mulx a_1,b_0,t_1 !=!mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(2),b_2 != + mulx a_1,b_1,t_1 !mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(3),b_3 + mulx a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 != + + mulx a_0,b_3,t_1 !mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_2,t_1 !=!mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(4),a_4 + mulx a_3,b_0,t_1 !=!mul_add_c(a[3],b[0],c1,c2,c3);!= + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(3) !r[3]=c1; + or c_12,c_3,c_12 + + mulx a_4,b_0,t_1 !mul_add_c(a[4],b[0],c2,c3,c1); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_1,t_1 !=!mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,b_2,t_1 !=!mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(4),b_4 != + mulx a_1,b_3,t_1 !mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(5),b_5 + mulx a_0,b_4,t_1 !mul_add_c(a[0],b[4],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !r[4]=c2; + or c_12,c_3,c_12 != + + mulx a_0,b_5,t_1 !mul_add_c(a[0],b[5],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_4,t_1 !mul_add_c(a[1],b[4],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_2,b_3,t_1 !mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(5),a_5 + mulx a_4,b_1,t_1 !mul_add_c(a[4],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(6),a_6 + mulx a_5,b_0,t_1 !=!mul_add_c(a[5],b[0],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(5) !r[5]=c3; + or c_12,c_3,c_12 + + mulx a_6,b_0,t_1 !mul_add_c(a[6],b[0],c1,c2,c3); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,b_1,t_1 !=!mul_add_c(a[5],b[1],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,b_2,t_1 !=!mul_add_c(a[4],b[2],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_3,t_1 !=!mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,b_4,t_1 !=!mul_add_c(a[2],b[4],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(6),b_6 != + mulx a_1,b_5,t_1 !mul_add_c(a[1],b[5],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(7),b_7 + mulx a_0,b_6,t_1 !mul_add_c(a[0],b[6],c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(6) !r[6]=c1; + or c_12,c_3,c_12 != + + mulx a_0,b_7,t_1 !mul_add_c(a[0],b[7],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_6,t_1 !mul_add_c(a[1],b[6],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_2,b_5,t_1 !mul_add_c(a[2],b[5],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_3,b_4,t_1 !mul_add_c(a[3],b[4],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_4,b_3,t_1 !mul_add_c(a[4],b[3],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_2,t_1 !mul_add_c(a[5],b[2],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(7),a_7 + mulx a_6,b_1,t_1 !=!mul_add_c(a[6],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_7,b_0,t_1 !=!mul_add_c(a[7],b[0],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(7) !r[7]=c2; + or c_12,c_3,c_12 + + mulx a_7,b_1,t_1 !=!mul_add_c(a[7],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_6,b_2,t_1 !mul_add_c(a[6],b[2],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_5,b_3,t_1 !mul_add_c(a[5],b[3],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_4,b_4,t_1 !mul_add_c(a[4],b[4],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_3,b_5,t_1 !mul_add_c(a[3],b[5],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_2,b_6,t_1 !mul_add_c(a[2],b[6],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_1,b_7,t_1 !mul_add_c(a[1],b[7],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + srlx t_1,32,c_12 + stuw t_1,rp(8) !r[8]=c3; + or c_12,c_3,c_12 + + mulx a_2,b_7,t_1 !=!mul_add_c(a[2],b[7],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + mulx a_3,b_6,t_1 !mul_add_c(a[3],b[6],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_4,b_5,t_1 !mul_add_c(a[4],b[5],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_4,t_1 !mul_add_c(a[5],b[4],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_3,t_1 !mul_add_c(a[6],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_7,b_2,t_1 !mul_add_c(a[7],b[2],c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(9) !r[9]=c1; + or c_12,c_3,c_12 != + + mulx a_7,b_3,t_1 !mul_add_c(a[7],b[3],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_4,t_1 !mul_add_c(a[6],b[4],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_5,t_1 !mul_add_c(a[5],b[5],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_4,b_6,t_1 !mul_add_c(a[4],b[6],c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_3,b_7,t_1 !mul_add_c(a[3],b[7],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(10) !r[10]=c2; + or c_12,c_3,c_12 != + + mulx a_4,b_7,t_1 !mul_add_c(a[4],b[7],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_6,t_1 !mul_add_c(a[5],b[6],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_5,t_1 !mul_add_c(a[6],b[5],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_7,b_4,t_1 !mul_add_c(a[7],b[4],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(11) !r[11]=c3; + or c_12,c_3,c_12 != + + mulx a_7,b_5,t_1 !mul_add_c(a[7],b[5],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_6,b_6,t_1 !mul_add_c(a[6],b[6],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_5,b_7,t_1 !mul_add_c(a[5],b[7],c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(12) !r[12]=c1; + or c_12,c_3,c_12 != + + mulx a_6,b_7,t_1 !mul_add_c(a[6],b[7],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_7,b_6,t_1 !mul_add_c(a[7],b[6],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + st t_1,rp(13) !r[13]=c2; + or c_12,c_3,c_12 != + + mulx a_7,b_7,t_1 !mul_add_c(a[7],b[7],c3,c1,c2); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 != + stuw t_1,rp(14) !r[14]=c3; + stuw c_12,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 != + +.type bn_mul_comba8,#function +.size bn_mul_comba8,(.-bn_mul_comba8) + +.align 32 + +.global bn_mul_comba4 +/* + * void bn_mul_comba4(r,a,b) + * BN_ULONG *r,*a,*b; + */ +bn_mul_comba4: + save %sp,FRAME_SIZE,%sp + lduw ap(0),a_0 + mov 1,t_2 + lduw bp(0),b_0 + sllx t_2,32,t_2 != + lduw bp(1),b_1 + mulx a_0,b_0,t_1 !mul_add_c(a[0],b[0],c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !=!r[0]=c1; + + lduw ap(1),a_1 + mulx a_0,b_1,t_1 !mul_add_c(a[0],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(2),a_2 + mulx a_1,b_0,t_1 !=!mul_add_c(a[1],b[0],c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 != + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,b_0,t_1 !mul_add_c(a[2],b[0],c3,c1,c2); + addcc c_12,t_1,c_12 != + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw bp(2),b_2 != + mulx a_1,b_1,t_1 !mul_add_c(a[1],b[1],c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 != + lduw bp(3),b_3 + mulx a_0,b_2,t_1 !mul_add_c(a[0],b[2],c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 != + + mulx a_0,b_3,t_1 !mul_add_c(a[0],b[3],c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + mulx a_1,b_2,t_1 !mul_add_c(a[1],b[2],c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 != + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_2,b_1,t_1 !mul_add_c(a[2],b[1],c1,c2,c3); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_0,t_1 !mul_add_c(a[3],b[0],c1,c2,c3);!= + addcc c_12,t_1,t_1 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(3) !=!r[3]=c1; + or c_12,c_3,c_12 + + mulx a_3,b_1,t_1 !mul_add_c(a[3],b[1],c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,b_2,t_1 !mul_add_c(a[2],b[2],c2,c3,c1); + addcc c_12,t_1,c_12 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,b_3,t_1 !mul_add_c(a[1],b[3],c2,c3,c1); + addcc c_12,t_1,t_1 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !=!r[4]=c2; + or c_12,c_3,c_12 + + mulx a_2,b_3,t_1 !mul_add_c(a[2],b[3],c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,b_2,t_1 !mul_add_c(a[3],b[2],c3,c1,c2); + addcc c_12,t_1,t_1 != + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(5) !=!r[5]=c3; + or c_12,c_3,c_12 + + mulx a_3,b_3,t_1 !mul_add_c(a[3],b[3],c1,c2,c3); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 != + stuw t_1,rp(6) !r[6]=c1; + stuw c_12,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_mul_comba4,#function +.size bn_mul_comba4,(.-bn_mul_comba4) + +.align 32 + +.global bn_sqr_comba8 +bn_sqr_comba8: + save %sp,FRAME_SIZE,%sp + mov 1,t_2 + lduw ap(0),a_0 + sllx t_2,32,t_2 + lduw ap(1),a_1 + mulx a_0,a_0,t_1 !sqr_add_c(a,0,c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !r[0]=c1; + + lduw ap(2),a_2 + mulx a_0,a_1,t_1 !=!sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 + + mulx a_0,a_3,t_1 !sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(4),a_4 + mulx a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + st t_1,rp(3) !r[3]=c1; + or c_12,c_3,c_12 + + mulx a_4,a_0,t_1 !sqr_add_c2(a,4,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(5),a_5 + mulx a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !r[4]=c2; + or c_12,c_3,c_12 + + mulx a_0,a_5,t_1 !sqr_add_c2(a,5,0,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,a_4,t_1 !sqr_add_c2(a,4,1,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(6),a_6 + mulx a_2,a_3,t_1 !sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(5) !r[5]=c3; + or c_12,c_3,c_12 + + mulx a_6,a_0,t_1 !sqr_add_c2(a,6,0,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_1,t_1 !sqr_add_c2(a,5,1,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,a_2,t_1 !sqr_add_c2(a,4,2,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(7),a_7 + mulx a_3,a_3,t_1 !=!sqr_add_c(a,3,c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(6) !r[6]=c1; + or c_12,c_3,c_12 + + mulx a_0,a_7,t_1 !sqr_add_c2(a,7,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,a_6,t_1 !sqr_add_c2(a,6,1,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,a_5,t_1 !sqr_add_c2(a,5,2,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,a_4,t_1 !sqr_add_c2(a,4,3,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(7) !r[7]=c2; + or c_12,c_3,c_12 + + mulx a_7,a_1,t_1 !sqr_add_c2(a,7,1,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_6,a_2,t_1 !sqr_add_c2(a,6,2,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_3,t_1 !sqr_add_c2(a,5,3,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,a_4,t_1 !sqr_add_c(a,4,c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(8) !r[8]=c3; + or c_12,c_3,c_12 + + mulx a_2,a_7,t_1 !sqr_add_c2(a,7,2,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_3,a_6,t_1 !sqr_add_c2(a,6,3,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_4,a_5,t_1 !sqr_add_c2(a,5,4,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(9) !r[9]=c1; + or c_12,c_3,c_12 + + mulx a_7,a_3,t_1 !sqr_add_c2(a,7,3,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_6,a_4,t_1 !sqr_add_c2(a,6,4,c2,c3,c1); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_5,t_1 !sqr_add_c(a,5,c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(10) !r[10]=c2; + or c_12,c_3,c_12 + + mulx a_4,a_7,t_1 !sqr_add_c2(a,7,4,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_5,a_6,t_1 !sqr_add_c2(a,6,5,c3,c1,c2); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(11) !r[11]=c3; + or c_12,c_3,c_12 + + mulx a_7,a_5,t_1 !sqr_add_c2(a,7,5,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_6,a_6,t_1 !sqr_add_c(a,6,c1,c2,c3); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(12) !r[12]=c1; + or c_12,c_3,c_12 + + mulx a_6,a_7,t_1 !sqr_add_c2(a,7,6,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(13) !r[13]=c2; + or c_12,c_3,c_12 + + mulx a_7,a_7,t_1 !sqr_add_c(a,7,c3,c1,c2); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 + stuw t_1,rp(14) !r[14]=c3; + stuw c_12,rp(15) !r[15]=c1; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba8,#function +.size bn_sqr_comba8,(.-bn_sqr_comba8) + +.align 32 + +.global bn_sqr_comba4 +/* + * void bn_sqr_comba4(r,a) + * BN_ULONG *r,*a; + */ +bn_sqr_comba4: + save %sp,FRAME_SIZE,%sp + mov 1,t_2 + lduw ap(0),a_0 + sllx t_2,32,t_2 + lduw ap(1),a_1 + mulx a_0,a_0,t_1 !sqr_add_c(a,0,c1,c2,c3); + srlx t_1,32,c_12 + stuw t_1,rp(0) !r[0]=c1; + + lduw ap(2),a_2 + mulx a_0,a_1,t_1 !sqr_add_c2(a,1,0,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(1) !r[1]=c2; + or c_12,c_3,c_12 + + mulx a_2,a_0,t_1 !sqr_add_c2(a,2,0,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + lduw ap(3),a_3 + mulx a_1,a_1,t_1 !sqr_add_c(a,1,c3,c1,c2); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(2) !r[2]=c3; + or c_12,c_3,c_12 + + mulx a_0,a_3,t_1 !sqr_add_c2(a,3,0,c1,c2,c3); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_1,a_2,t_1 !sqr_add_c2(a,2,1,c1,c2,c3); + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(3) !r[3]=c1; + or c_12,c_3,c_12 + + mulx a_3,a_1,t_1 !sqr_add_c2(a,3,1,c2,c3,c1); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,c_12 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + mulx a_2,a_2,t_1 !sqr_add_c(a,2,c2,c3,c1); + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(4) !r[4]=c2; + or c_12,c_3,c_12 + + mulx a_2,a_3,t_1 !sqr_add_c2(a,3,2,c3,c1,c2); + addcc c_12,t_1,c_12 + clr c_3 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + addcc c_12,t_1,t_1 + bcs,a %xcc,.+8 + add c_3,t_2,c_3 + srlx t_1,32,c_12 + stuw t_1,rp(5) !r[5]=c3; + or c_12,c_3,c_12 + + mulx a_3,a_3,t_1 !sqr_add_c(a,3,c1,c2,c3); + addcc c_12,t_1,t_1 + srlx t_1,32,c_12 + stuw t_1,rp(6) !r[6]=c1; + stuw c_12,rp(7) !r[7]=c2; + + ret + restore %g0,%g0,%o0 + +.type bn_sqr_comba4,#function +.size bn_sqr_comba4,(.-bn_sqr_comba4) + +.align 32 diff --git a/src/lib/libcrypto/bn/asm/x86.pl b/src/lib/libcrypto/bn/asm/x86.pl new file mode 100644 index 0000000000..1bc4f1bb27 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86.pl @@ -0,0 +1,28 @@ +#!/usr/local/bin/perl + +push(@INC,"perlasm","../../perlasm"); +require "x86asm.pl"; + +require("x86/mul_add.pl"); +require("x86/mul.pl"); +require("x86/sqr.pl"); +require("x86/div.pl"); +require("x86/add.pl"); +require("x86/sub.pl"); +require("x86/comba.pl"); + +&asm_init($ARGV[0],$0); + +&bn_mul_add_words("bn_mul_add_words"); +&bn_mul_words("bn_mul_words"); +&bn_sqr_words("bn_sqr_words"); +&bn_div_words("bn_div_words"); +&bn_add_words("bn_add_words"); +&bn_sub_words("bn_sub_words"); +&bn_mul_comba("bn_mul_comba8",8); +&bn_mul_comba("bn_mul_comba4",4); +&bn_sqr_comba("bn_sqr_comba8",8); +&bn_sqr_comba("bn_sqr_comba4",4); + +&asm_finish(); + diff --git a/src/lib/libcrypto/bn/asm/x86/add.pl b/src/lib/libcrypto/bn/asm/x86/add.pl new file mode 100644 index 0000000000..0b5cf583e3 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/add.pl @@ -0,0 +1,76 @@ +#!/usr/local/bin/perl +# x86 assember + +sub bn_add_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &add($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &add($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &add($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &add($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *a + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +1; diff --git a/src/lib/libcrypto/bn/asm/x86/comba.pl b/src/lib/libcrypto/bn/asm/x86/comba.pl new file mode 100644 index 0000000000..2291253629 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/comba.pl @@ -0,0 +1,277 @@ +#!/usr/local/bin/perl +# x86 assember + +sub mul_add_c + { + local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("mul a[$ai]*b[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + &mul("edx"); + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # laod next a + &mov("eax",&wparam(0)) if $pos > 0; # load r[] + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0; # laod next b + &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a + } + +sub sqr_add_c + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$b,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add($c0,"eax"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + ### + &adc($c1,"edx"); + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb); + ### + &adc($c2,0); + # is pos > 1, it means it is the last loop + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + } + +sub sqr_add_c2 + { + local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_; + + # pos == -1 if eax and edx are pre-loaded, 0 to load from next + # words, and 1 if load return value + + &comment("sqr a[$ai]*a[$bi]"); + + # "eax" and "edx" will always be pre-loaded. + # &mov("eax",&DWP($ai*4,$a,"",0)) ; + # &mov("edx",&DWP($bi*4,$a,"",0)); + + if ($ai == $bi) + { &mul("eax");} + else + { &mul("edx");} + &add("eax","eax"); + ### + &adc("edx","edx"); + ### + &adc($c2,0); + &add($c0,"eax"); + &adc($c1,"edx"); + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a + &mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b + &adc($c2,0); + &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[]; + &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb); + ### + } + +sub bn_mul_comba + { + local($name,$num)=@_; + local($a,$b,$c0,$c1,$c2); + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($tot,$end); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $b="edi"; + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + &push("esi"); + &mov($a,&wparam(1)); + &push("edi"); + &mov($b,&wparam(2)); + &push("ebp"); + &push("ebx"); + + &xor($c0,$c0); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + &xor($c1,$c1); + &mov("edx",&DWP(0,$b,"",0)); # load the first second + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("################## Calculate word $i"); + + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($j+1) == $end) + { + $v=1; + $v=2 if (($i+1) == $tot); + } + else + { $v=0; } + if (($j+1) != $end) + { + $na=($ai-1); + $nb=($bi+1); + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } +#printf STDERR "[$ai,$bi] -> [$na,$nb]\n"; + &mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb); + if ($v) + { + &comment("saved r[$i]"); + # &mov("eax",&wparam(0)); + # &mov(&DWP($i*4,"eax","",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &comment("save r[$i]"); + # &mov("eax",&wparam(0)); + &mov(&DWP($i*4,"eax","",0),$c0); + + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + +sub bn_sqr_comba + { + local($name,$num)=@_; + local($r,$a,$c0,$c1,$c2)=@_; + local($i,$as,$ae,$bs,$be,$ai,$bi); + local($b,$tot,$end,$half); + + &function_begin_B($name,""); + + $c0="ebx"; + $c1="ecx"; + $c2="ebp"; + $a="esi"; + $r="edi"; + + &push("esi"); + &push("edi"); + &push("ebp"); + &push("ebx"); + &mov($r,&wparam(0)); + &mov($a,&wparam(1)); + &xor($c0,$c0); + &xor($c1,$c1); + &mov("eax",&DWP(0,$a,"",0)); # load the first word + + $as=0; + $ae=0; + $bs=0; + $be=0; + $tot=$num+$num-1; + + for ($i=0; $i<$tot; $i++) + { + $ai=$as; + $bi=$bs; + $end=$be+1; + + &comment("############### Calculate word $i"); + for ($j=$bs; $j<$end; $j++) + { + &xor($c2,$c2) if ($j == $bs); + if (($ai-1) < ($bi+1)) + { + $v=1; + $v=2 if ($i+1) == $tot; + } + else + { $v=0; } + if (!$v) + { + $na=$ai-1; + $nb=$bi+1; + } + else + { + $na=$as+($i < ($num-1)); + $nb=$bs+($i >= ($num-1)); + } + if ($ai == $bi) + { + &sqr_add_c($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + else + { + &sqr_add_c2($r,$a,$ai,$bi, + $c0,$c1,$c2,$v,$i,$na,$nb); + } + if ($v) + { + &comment("saved r[$i]"); + #&mov(&DWP($i*4,$r,"",0),$c0); + ($c0,$c1,$c2)=($c1,$c2,$c0); + last; + } + $ai--; + $bi++; + } + $as++ if ($i < ($num-1)); + $ae++ if ($i >= ($num-1)); + + $bs++ if ($i >= ($num-1)); + $be++ if ($i < ($num-1)); + } + &mov(&DWP($i*4,$r,"",0),$c0); + &pop("ebx"); + &pop("ebp"); + &pop("edi"); + &pop("esi"); + &ret(); + &function_end_B($name); + } + +1; diff --git a/src/lib/libcrypto/bn/asm/x86/div.pl b/src/lib/libcrypto/bn/asm/x86/div.pl new file mode 100644 index 0000000000..0e90152caa --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/div.pl @@ -0,0 +1,15 @@ +#!/usr/local/bin/perl +# x86 assember + +sub bn_div_words + { + local($name)=@_; + + &function_begin($name,""); + &mov("edx",&wparam(0)); # + &mov("eax",&wparam(1)); # + &mov("ebx",&wparam(2)); # + &div("ebx"); + &function_end($name); + } +1; diff --git a/src/lib/libcrypto/bn/asm/x86/mul.pl b/src/lib/libcrypto/bn/asm/x86/mul.pl new file mode 100644 index 0000000000..674cb9b055 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/mul.pl @@ -0,0 +1,77 @@ +#!/usr/local/bin/perl +# x86 assember + +sub bn_mul_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $Low="eax"; + $High="edx"; + $a="ebx"; + $w="ecx"; + $r="edi"; + $c="esi"; + $num="ebp"; + + &xor($c,$c); # clear carry + &mov($r,&wparam(0)); # + &mov($a,&wparam(1)); # + &mov($num,&wparam(2)); # + &mov($w,&wparam(3)); # + + &and($num,0xfffffff8); # num / 8 + &jz(&label("mw_finish")); + + &set_label("mw_loop",0); + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + + &mov("eax",&DWP($i,$a,"",0)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + # XXX + + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t); + + &mov($c,"edx"); # c= H(t); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jz(&label("mw_finish")); + &jmp(&label("mw_loop")); + + &set_label("mw_finish",0); + &mov($num,&wparam(2)); # get num + &and($num,7); + &jnz(&label("mw_finish2")); + &jmp(&label("mw_end")); + + &set_label("mw_finish2",1); + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0));# *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + # XXX + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t); + &mov($c,"edx"); # c= H(t); + &dec($num) if ($i != 7-1); + &jz(&label("mw_end")) if ($i != 7-1); + } + &set_label("mw_end",0); + &mov("eax",$c); + + &function_end($name); + } + +1; diff --git a/src/lib/libcrypto/bn/asm/x86/mul_add.pl b/src/lib/libcrypto/bn/asm/x86/mul_add.pl new file mode 100644 index 0000000000..61830d3a90 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/mul_add.pl @@ -0,0 +1,87 @@ +#!/usr/local/bin/perl +# x86 assember + +sub bn_mul_add_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $Low="eax"; + $High="edx"; + $a="ebx"; + $w="ebp"; + $r="edi"; + $c="esi"; + + &xor($c,$c); # clear carry + &mov($r,&wparam(0)); # + + &mov("ecx",&wparam(2)); # + &mov($a,&wparam(1)); # + + &and("ecx",0xfffffff8); # num / 8 + &mov($w,&wparam(3)); # + + &push("ecx"); # Up the stack for a tmp variable + + &jz(&label("maw_finish")); + + &set_label("maw_loop",0); + + &mov(&swtmp(0),"ecx"); # + + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + + &mov("eax",&DWP($i,$a,"",0)); # *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+= *r + &mov($c,&DWP($i,$r,"",0)); # L(t)+= *r + &adc("edx",0); # H(t)+=carry + &add("eax",$c); # L(t)+=c + &adc("edx",0); # H(t)+=carry + &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t); + &mov($c,"edx"); # c= H(t); + } + + &comment(""); + &mov("ecx",&swtmp(0)); # + &add($a,32); + &add($r,32); + &sub("ecx",8); + &jnz(&label("maw_loop")); + + &set_label("maw_finish",0); + &mov("ecx",&wparam(2)); # get num + &and("ecx",7); + &jnz(&label("maw_finish2")); # helps branch prediction + &jmp(&label("maw_end")); + + &set_label("maw_finish2",1); + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0));# *a + &mul($w); # *a * w + &add("eax",$c); # L(t)+=c + &mov($c,&DWP($i*4,$r,"",0)); # L(t)+= *r + &adc("edx",0); # H(t)+=carry + &add("eax",$c); + &adc("edx",0); # H(t)+=carry + &dec("ecx") if ($i != 7-1); + &mov(&DWP($i*4,$r,"",0),"eax"); # *r= L(t); + &mov($c,"edx"); # c= H(t); + &jz(&label("maw_end")) if ($i != 7-1); + } + &set_label("maw_end",0); + &mov("eax",$c); + + &pop("ecx"); # clear variable from + + &function_end($name); + } + +1; diff --git a/src/lib/libcrypto/bn/asm/x86/sqr.pl b/src/lib/libcrypto/bn/asm/x86/sqr.pl new file mode 100644 index 0000000000..1f90993cf6 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/sqr.pl @@ -0,0 +1,60 @@ +#!/usr/local/bin/perl +# x86 assember + +sub bn_sqr_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $r="esi"; + $a="edi"; + $num="ebx"; + + &mov($r,&wparam(0)); # + &mov($a,&wparam(1)); # + &mov($num,&wparam(2)); # + + &and($num,0xfffffff8); # num / 8 + &jz(&label("sw_finish")); + + &set_label("sw_loop",0); + for ($i=0; $i<32; $i+=4) + { + &comment("Round $i"); + &mov("eax",&DWP($i,$a,"",0)); # *a + # XXX + &mul("eax"); # *a * *a + &mov(&DWP($i*2,$r,"",0),"eax"); # + &mov(&DWP($i*2+4,$r,"",0),"edx");# + } + + &comment(""); + &add($a,32); + &add($r,64); + &sub($num,8); + &jnz(&label("sw_loop")); + + &set_label("sw_finish",0); + &mov($num,&wparam(2)); # get num + &and($num,7); + &jz(&label("sw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov("eax",&DWP($i*4,$a,"",0)); # *a + # XXX + &mul("eax"); # *a * *a + &mov(&DWP($i*8,$r,"",0),"eax"); # + &dec($num) if ($i != 7-1); + &mov(&DWP($i*8+4,$r,"",0),"edx"); + &jz(&label("sw_end")) if ($i != 7-1); + } + &set_label("sw_end",0); + + &function_end($name); + } + +1; diff --git a/src/lib/libcrypto/bn/asm/x86/sub.pl b/src/lib/libcrypto/bn/asm/x86/sub.pl new file mode 100644 index 0000000000..837b0e1b07 --- /dev/null +++ b/src/lib/libcrypto/bn/asm/x86/sub.pl @@ -0,0 +1,76 @@ +#!/usr/local/bin/perl +# x86 assember + +sub bn_sub_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *a + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +1; diff --git a/src/lib/libcrypto/bn/bn.h b/src/lib/libcrypto/bn/bn.h new file mode 100644 index 0000000000..f935e1ca79 --- /dev/null +++ b/src/lib/libcrypto/bn/bn.h @@ -0,0 +1,467 @@ +/* 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 nornal cc. This would + * be a common occurance 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 assember code. */ +#if defined(MSDOS) || defined(WINDOWS) || 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 relevent + * assember 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 +#else +#define BN_ULLONG unsigned long long +#endif +#define BN_ULONG unsigned long +#define BN_LONG long +#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 +typedef struct bignum_ctx + { + int tos; + BIGNUM bn[BN_CTX_NUM+1]; + int flags; + } 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 use_word; /* 0 for word form, 1 for long form */ + int ri; /* number of bits in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* The inverse of N */ + BN_ULONG n0; /* word form of inverse, normally only one of + * Ni or n0 is defined */ + 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 (5) + +#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) */ + +#define bn_expand(n,b) ((((((b+BN_BITS2-1))/BN_BITS2)) <= (n)->max)?\ + (n):bn_expand2((n),(b)/BN_BITS2+1)) +#define bn_wexpand(n,b) (((b) <= (n)->max)?(n):bn_expand2((n),(b))) + +#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; \ + } \ + } + +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); +int BN_rand(BIGNUM *rnd, int bits, int top,int bottom); +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, BIGNUM *a, 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(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_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 WIN16 +int BN_print_fp(FILE *fp, BIGNUM *a); +#endif +#ifdef HEADER_BIO_H +int BN_print(BIO *fp, const BIGNUM *a); +#else +int BN_print(char *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_expand2(BIGNUM *b, int bits); +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 strong,BIGNUM *add, + BIGNUM *rem,void (*callback)(int,int,void *),void *cb_arg); +int BN_is_prime(BIGNUM *p,int nchecks,void (*callback)(int,int,void *), + BN_CTX *ctx,void *cb_arg); +void ERR_load_BN_strings(void ); + +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); + +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); + +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 */ + +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); + + +/* 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_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_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_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_NOT_INITIALIZED 107 +#define BN_R_NO_INVERSE 108 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/bn/bn_asm.c b/src/lib/libcrypto/bn/bn_asm.c new file mode 100644 index 0000000000..4d3da16a0c --- /dev/null +++ b/src/lib/libcrypto/bn/bn_asm.c @@ -0,0 +1,802 @@ +/* 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.] + */ + +#include +#include "cryptlib.h" +#include "bn_lcl.h" + +#ifdef BN_LLONG + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) + { + BN_ULONG c1=0; + + bn_check_num(num); + if (num <= 0) return(c1); + + for (;;) + { + mul_add(rp[0],ap[0],w,c1); + if (--num == 0) break; + mul_add(rp[1],ap[1],w,c1); + if (--num == 0) break; + mul_add(rp[2],ap[2],w,c1); + if (--num == 0) break; + mul_add(rp[3],ap[3],w,c1); + if (--num == 0) break; + ap+=4; + rp+=4; + } + + return(c1); + } + +BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) + { + BN_ULONG c1=0; + + bn_check_num(num); + if (num <= 0) return(c1); + + /* for (;;) */ + while (1) /* circumvent egcs-1.1.2 bug */ + { + mul(rp[0],ap[0],w,c1); + if (--num == 0) break; + mul(rp[1],ap[1],w,c1); + if (--num == 0) break; + mul(rp[2],ap[2],w,c1); + if (--num == 0) break; + mul(rp[3],ap[3],w,c1); + if (--num == 0) break; + ap+=4; + rp+=4; + } + return(c1); + } + +void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) + { + bn_check_num(n); + if (n <= 0) return; + for (;;) + { + BN_ULLONG t; + + t=(BN_ULLONG)(a[0])*(a[0]); + r[0]=Lw(t); r[1]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[1])*(a[1]); + r[2]=Lw(t); r[3]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[2])*(a[2]); + r[4]=Lw(t); r[5]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[3])*(a[3]); + r[6]=Lw(t); r[7]=Hw(t); + if (--n == 0) break; + + a+=4; + r+=8; + } + } + +#else + +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; + + bn_check_num(num); + 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; + + bn_check_num(num); + 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) + { + bn_check_num(n); + 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 + +#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)<>=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_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) + { + BN_ULONG c,l,t; + + bn_check_num(n); + 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_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) + { + BN_ULONG t1,t2; + int c=0; + + bn_check_num(n); + 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 + +#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) +#else +#define mul_add_c(a,b,c0,c1,c2) \ + t1=LBITS(a); t2=HBITS(a); \ + bl=LBITS(b); bh=HBITS(b); \ + mul64(t1,t2,bl,bh); \ + 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) \ + t1=LBITS(a); t2=HBITS(a); \ + bl=LBITS(b); bh=HBITS(b); \ + mul64(t1,t2,bl,bh); \ + if (t2 & BN_TBIT) c2++; \ + t2=(t2+t2)&BN_MASK2; \ + if (t1 & BN_TBIT) t2++; \ + t1=(t1+t1)&BN_MASK2; \ + 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) \ + sqr64(t1,t2,(a)[i]); \ + 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) +#endif + +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) + { +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + mul_add_c(a[0],b[0],c1,c2,c3); + r[0]=c1; + c1=0; + mul_add_c(a[0],b[1],c2,c3,c1); + mul_add_c(a[1],b[0],c2,c3,c1); + r[1]=c2; + c2=0; + mul_add_c(a[2],b[0],c3,c1,c2); + mul_add_c(a[1],b[1],c3,c1,c2); + mul_add_c(a[0],b[2],c3,c1,c2); + r[2]=c3; + c3=0; + mul_add_c(a[0],b[3],c1,c2,c3); + mul_add_c(a[1],b[2],c1,c2,c3); + mul_add_c(a[2],b[1],c1,c2,c3); + mul_add_c(a[3],b[0],c1,c2,c3); + r[3]=c1; + c1=0; + mul_add_c(a[4],b[0],c2,c3,c1); + mul_add_c(a[3],b[1],c2,c3,c1); + mul_add_c(a[2],b[2],c2,c3,c1); + mul_add_c(a[1],b[3],c2,c3,c1); + mul_add_c(a[0],b[4],c2,c3,c1); + r[4]=c2; + c2=0; + mul_add_c(a[0],b[5],c3,c1,c2); + mul_add_c(a[1],b[4],c3,c1,c2); + mul_add_c(a[2],b[3],c3,c1,c2); + mul_add_c(a[3],b[2],c3,c1,c2); + mul_add_c(a[4],b[1],c3,c1,c2); + mul_add_c(a[5],b[0],c3,c1,c2); + r[5]=c3; + c3=0; + mul_add_c(a[6],b[0],c1,c2,c3); + mul_add_c(a[5],b[1],c1,c2,c3); + mul_add_c(a[4],b[2],c1,c2,c3); + mul_add_c(a[3],b[3],c1,c2,c3); + mul_add_c(a[2],b[4],c1,c2,c3); + mul_add_c(a[1],b[5],c1,c2,c3); + mul_add_c(a[0],b[6],c1,c2,c3); + r[6]=c1; + c1=0; + mul_add_c(a[0],b[7],c2,c3,c1); + mul_add_c(a[1],b[6],c2,c3,c1); + mul_add_c(a[2],b[5],c2,c3,c1); + mul_add_c(a[3],b[4],c2,c3,c1); + mul_add_c(a[4],b[3],c2,c3,c1); + mul_add_c(a[5],b[2],c2,c3,c1); + mul_add_c(a[6],b[1],c2,c3,c1); + mul_add_c(a[7],b[0],c2,c3,c1); + r[7]=c2; + c2=0; + mul_add_c(a[7],b[1],c3,c1,c2); + mul_add_c(a[6],b[2],c3,c1,c2); + mul_add_c(a[5],b[3],c3,c1,c2); + mul_add_c(a[4],b[4],c3,c1,c2); + mul_add_c(a[3],b[5],c3,c1,c2); + mul_add_c(a[2],b[6],c3,c1,c2); + mul_add_c(a[1],b[7],c3,c1,c2); + r[8]=c3; + c3=0; + mul_add_c(a[2],b[7],c1,c2,c3); + mul_add_c(a[3],b[6],c1,c2,c3); + mul_add_c(a[4],b[5],c1,c2,c3); + mul_add_c(a[5],b[4],c1,c2,c3); + mul_add_c(a[6],b[3],c1,c2,c3); + mul_add_c(a[7],b[2],c1,c2,c3); + r[9]=c1; + c1=0; + mul_add_c(a[7],b[3],c2,c3,c1); + mul_add_c(a[6],b[4],c2,c3,c1); + mul_add_c(a[5],b[5],c2,c3,c1); + mul_add_c(a[4],b[6],c2,c3,c1); + mul_add_c(a[3],b[7],c2,c3,c1); + r[10]=c2; + c2=0; + mul_add_c(a[4],b[7],c3,c1,c2); + mul_add_c(a[5],b[6],c3,c1,c2); + mul_add_c(a[6],b[5],c3,c1,c2); + mul_add_c(a[7],b[4],c3,c1,c2); + r[11]=c3; + c3=0; + mul_add_c(a[7],b[5],c1,c2,c3); + mul_add_c(a[6],b[6],c1,c2,c3); + mul_add_c(a[5],b[7],c1,c2,c3); + r[12]=c1; + c1=0; + mul_add_c(a[6],b[7],c2,c3,c1); + mul_add_c(a[7],b[6],c2,c3,c1); + r[13]=c2; + c2=0; + mul_add_c(a[7],b[7],c3,c1,c2); + r[14]=c3; + r[15]=c1; + } + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) + { +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + mul_add_c(a[0],b[0],c1,c2,c3); + r[0]=c1; + c1=0; + mul_add_c(a[0],b[1],c2,c3,c1); + mul_add_c(a[1],b[0],c2,c3,c1); + r[1]=c2; + c2=0; + mul_add_c(a[2],b[0],c3,c1,c2); + mul_add_c(a[1],b[1],c3,c1,c2); + mul_add_c(a[0],b[2],c3,c1,c2); + r[2]=c3; + c3=0; + mul_add_c(a[0],b[3],c1,c2,c3); + mul_add_c(a[1],b[2],c1,c2,c3); + mul_add_c(a[2],b[1],c1,c2,c3); + mul_add_c(a[3],b[0],c1,c2,c3); + r[3]=c1; + c1=0; + mul_add_c(a[3],b[1],c2,c3,c1); + mul_add_c(a[2],b[2],c2,c3,c1); + mul_add_c(a[1],b[3],c2,c3,c1); + r[4]=c2; + c2=0; + mul_add_c(a[2],b[3],c3,c1,c2); + mul_add_c(a[3],b[2],c3,c1,c2); + r[5]=c3; + c3=0; + mul_add_c(a[3],b[3],c1,c2,c3); + r[6]=c1; + r[7]=c2; + } + +void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a) + { +#ifdef BN_LLONG + BN_ULLONG t,tt; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + sqr_add_c(a,0,c1,c2,c3); + r[0]=c1; + c1=0; + sqr_add_c2(a,1,0,c2,c3,c1); + r[1]=c2; + c2=0; + sqr_add_c(a,1,c3,c1,c2); + sqr_add_c2(a,2,0,c3,c1,c2); + r[2]=c3; + c3=0; + sqr_add_c2(a,3,0,c1,c2,c3); + sqr_add_c2(a,2,1,c1,c2,c3); + r[3]=c1; + c1=0; + sqr_add_c(a,2,c2,c3,c1); + sqr_add_c2(a,3,1,c2,c3,c1); + sqr_add_c2(a,4,0,c2,c3,c1); + r[4]=c2; + c2=0; + sqr_add_c2(a,5,0,c3,c1,c2); + sqr_add_c2(a,4,1,c3,c1,c2); + sqr_add_c2(a,3,2,c3,c1,c2); + r[5]=c3; + c3=0; + sqr_add_c(a,3,c1,c2,c3); + sqr_add_c2(a,4,2,c1,c2,c3); + sqr_add_c2(a,5,1,c1,c2,c3); + sqr_add_c2(a,6,0,c1,c2,c3); + r[6]=c1; + c1=0; + sqr_add_c2(a,7,0,c2,c3,c1); + sqr_add_c2(a,6,1,c2,c3,c1); + sqr_add_c2(a,5,2,c2,c3,c1); + sqr_add_c2(a,4,3,c2,c3,c1); + r[7]=c2; + c2=0; + sqr_add_c(a,4,c3,c1,c2); + sqr_add_c2(a,5,3,c3,c1,c2); + sqr_add_c2(a,6,2,c3,c1,c2); + sqr_add_c2(a,7,1,c3,c1,c2); + r[8]=c3; + c3=0; + sqr_add_c2(a,7,2,c1,c2,c3); + sqr_add_c2(a,6,3,c1,c2,c3); + sqr_add_c2(a,5,4,c1,c2,c3); + r[9]=c1; + c1=0; + sqr_add_c(a,5,c2,c3,c1); + sqr_add_c2(a,6,4,c2,c3,c1); + sqr_add_c2(a,7,3,c2,c3,c1); + r[10]=c2; + c2=0; + sqr_add_c2(a,7,4,c3,c1,c2); + sqr_add_c2(a,6,5,c3,c1,c2); + r[11]=c3; + c3=0; + sqr_add_c(a,6,c1,c2,c3); + sqr_add_c2(a,7,5,c1,c2,c3); + r[12]=c1; + c1=0; + sqr_add_c2(a,7,6,c2,c3,c1); + r[13]=c2; + c2=0; + sqr_add_c(a,7,c3,c1,c2); + r[14]=c3; + r[15]=c1; + } + +void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a) + { +#ifdef BN_LLONG + BN_ULLONG t,tt; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + sqr_add_c(a,0,c1,c2,c3); + r[0]=c1; + c1=0; + sqr_add_c2(a,1,0,c2,c3,c1); + r[1]=c2; + c2=0; + sqr_add_c(a,1,c3,c1,c2); + sqr_add_c2(a,2,0,c3,c1,c2); + r[2]=c3; + c3=0; + sqr_add_c2(a,3,0,c1,c2,c3); + sqr_add_c2(a,2,1,c1,c2,c3); + r[3]=c1; + c1=0; + sqr_add_c(a,2,c2,c3,c1); + sqr_add_c2(a,3,1,c2,c3,c1); + r[4]=c2; + c2=0; + sqr_add_c2(a,3,2,c3,c1,c2); + r[5]=c3; + c3=0; + sqr_add_c(a,3,c1,c2,c3); + r[6]=c1; + r[7]=c2; + } +#else + +/* hmm... is it faster just to do a multiply? */ +#undef bn_sqr_comba4 +void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a) + { + BN_ULONG t[8]; + bn_sqr_normal(r,a,4,t); + } + +#undef bn_sqr_comba8 +void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a) + { + BN_ULONG t[16]; + bn_sqr_normal(r,a,8,t); + } + +void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) + { + r[4]=bn_mul_words( &(r[0]),a,4,b[0]); + r[5]=bn_mul_add_words(&(r[1]),a,4,b[1]); + r[6]=bn_mul_add_words(&(r[2]),a,4,b[2]); + r[7]=bn_mul_add_words(&(r[3]),a,4,b[3]); + } + +void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) + { + r[ 8]=bn_mul_words( &(r[0]),a,8,b[0]); + r[ 9]=bn_mul_add_words(&(r[1]),a,8,b[1]); + r[10]=bn_mul_add_words(&(r[2]),a,8,b[2]); + r[11]=bn_mul_add_words(&(r[3]),a,8,b[3]); + r[12]=bn_mul_add_words(&(r[4]),a,8,b[4]); + r[13]=bn_mul_add_words(&(r[5]),a,8,b[5]); + r[14]=bn_mul_add_words(&(r[6]),a,8,b[6]); + r[15]=bn_mul_add_words(&(r[7]),a,8,b[7]); + } + +#endif /* BN_COMBA */ diff --git a/src/lib/libcrypto/bn/bn_ctx.c b/src/lib/libcrypto/bn/bn_ctx.c new file mode 100644 index 0000000000..46132fd180 --- /dev/null +++ b/src/lib/libcrypto/bn/bn_ctx.c @@ -0,0 +1,144 @@ +/* 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/src/lib/libcrypto/bn/bn_exp2.c b/src/lib/libcrypto/bn/bn_exp2.c new file mode 100644 index 0000000000..1132d53365 --- /dev/null +++ b/src/lib/libcrypto/bn/bn_exp2.c @@ -0,0 +1,195 @@ +#include +#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 improvment 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); + } + d= &(ctx->bn[ctx->tos++]); + r= &(ctx->bn[ctx->tos++]); + bits1=BN_num_bits(p1); + bits2=BN_num_bits(p2); + if ((bits1 == 0) && (bits2 == 0)) + { + BN_one(r); + return(1); + } + 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; ytos-=2; + for (i=0; itop == 0) ? (BN_ULONG) 0 : (n)->d[0]) + +/* Returns -2 for errors because both -1 and 0 are valid results. */ +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + int i; + int ret = -2; /* avoid 'uninitialized' warning */ + int err = 0; + BIGNUM *A, *B, *tmp; + /* In 'tab', only odd-indexed entries are relevant: + * For any odd BIGNUM n, + * tab[BN_lsw(n) & 7] + * is $(-1)^{(n^2-1)/8}$ (using TeX notation). + * Note that the sign of n does not matter. + */ + static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1}; + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + if (B == NULL) goto end; + + err = !BN_copy(A, a); + if (err) goto end; + err = !BN_copy(B, b); + if (err) goto end; + + /* + * Kronecker symbol, imlemented according to Henri Cohen, + * "A Course in Computational Algebraic Number Theory" + * (algorithm 1.4.10). + */ + + /* Cohen's step 1: */ + + if (BN_is_zero(B)) + { + ret = BN_abs_is_word(A, 1); + goto end; + } + + /* Cohen's step 2: */ + + if (!BN_is_odd(A) && !BN_is_odd(B)) + { + ret = 0; + goto end; + } + + /* now B is non-zero */ + i = 0; + while (!BN_is_bit_set(B, i)) + i++; + err = !BN_rshift(B, B, i); + if (err) goto end; + if (i & 1) + { + /* i is odd */ + /* (thus B was even, thus A must be odd!) */ + + /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ + ret = tab[BN_lsw(A) & 7]; + } + else + { + /* i is even */ + ret = 1; + } + + if (B->neg) + { + B->neg = 0; + if (A->neg) + ret = -ret; + } + + /* now B is positive and odd, so what remains to be done is + * to compute the Jacobi symbol (A/B) and multiply it by 'ret' */ + + while (1) + { + /* Cohen's step 3: */ + + /* B is positive and odd */ + + if (BN_is_zero(A)) + { + ret = BN_is_one(B) ? ret : 0; + goto end; + } + + /* now A is non-zero */ + i = 0; + while (!BN_is_bit_set(A, i)) + i++; + err = !BN_rshift(A, A, i); + if (err) goto end; + if (i & 1) + { + /* i is odd */ + /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */ + ret = ret * tab[BN_lsw(B) & 7]; + } + + /* Cohen's step 4: */ + /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */ + if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) + ret = -ret; + + /* (A, B) := (B mod |A|, |A|) */ + err = !BN_nnmod(B, B, A, ctx); + if (err) goto end; + tmp = A; A = B; B = tmp; + tmp->neg = 0; + } + + end: + BN_CTX_end(ctx); + if (err) + return -2; + else + return ret; + } diff --git a/src/lib/libcrypto/bn/bn_sqrt.c b/src/lib/libcrypto/bn/bn_sqrt.c new file mode 100644 index 0000000000..e2a1105dc8 --- /dev/null +++ b/src/lib/libcrypto/bn/bn_sqrt.c @@ -0,0 +1,387 @@ +/* crypto/bn/bn_mod.c */ +/* Written by Lenka Fibikova + * and Bodo 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). + * + */ + +#include "cryptlib.h" +#include "bn_lcl.h" + + +BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +/* Returns 'ret' such that + * ret^2 == a (mod p), + * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course + * in Algebraic Computational Number Theory", algorithm 1.5.1). + * 'p' must be prime! + * If 'a' is not a square, this is not necessarily detected by + * the algorithms; a bogus result must be expected in this case. + */ + { + BIGNUM *ret = in; + int err = 1; + int r; + BIGNUM *b, *q, *t, *x, *y; + int e, i, j; + + if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) + { + if (BN_abs_is_word(p, 2)) + { + if (ret == NULL) + ret = BN_new(); + if (ret == NULL) + goto end; + if (!BN_set_word(ret, BN_is_bit_set(a, 0))) + { + BN_free(ret); + return NULL; + } + return ret; + } + + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + return(NULL); + } + + if (BN_is_zero(a) || BN_is_one(a)) + { + if (ret == NULL) + ret = BN_new(); + if (ret == NULL) + goto end; + if (!BN_set_word(ret, BN_is_one(a))) + { + BN_free(ret); + return NULL; + } + return ret; + } + +#if 0 /* if BN_mod_sqrt is used with correct input, this just wastes time */ + r = BN_kronecker(a, p, ctx); + if (r < -1) return NULL; + if (r == -1) + { + BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + return(NULL); + } +#endif + + BN_CTX_start(ctx); + b = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto end; + + if (ret == NULL) + ret = BN_new(); + if (ret == NULL) goto end; + + /* now write |p| - 1 as 2^e*q where q is odd */ + e = 1; + while (!BN_is_bit_set(p, e)) + e++; + /* we'll set q later (if needed) */ + + if (e == 1) + { + /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse + * modulo (|p|-1)/2, and square roots can be computed + * directly by modular exponentiation. + * We have + * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), + * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. + */ + if (!BN_rshift(q, p, 2)) goto end; + q->neg = 0; + if (!BN_add_word(q, 1)) goto end; + if (!BN_mod_exp(ret, a, q, p, ctx)) goto end; + err = 0; + goto end; + } + + if (e == 2) + { + /* |p| == 5 (mod 8) + * + * In this case 2 is always a non-square since + * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. + * So if a really is a square, then 2*a is a non-square. + * Thus for + * b := (2*a)^((|p|-5)/8), + * i := (2*a)*b^2 + * we have + * i^2 = (2*a)^((1 + (|p|-5)/4)*2) + * = (2*a)^((p-1)/2) + * = -1; + * so if we set + * x := a*b*(i-1), + * then + * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) + * = a^2 * b^2 * (-2*i) + * = a*(-i)*(2*a*b^2) + * = a*(-i)*i + * = a. + * + * (This is due to A.O.L. Atkin, + * , + * November 1992.) + */ + + /* make sure that a is reduced modulo p */ + if (a->neg || BN_ucmp(a, p) >= 0) + { + if (!BN_nnmod(x, a, p, ctx)) goto end; + a = x; /* use x as temporary variable */ + } + + /* t := 2*a */ + if (!BN_mod_lshift1_quick(t, a, p)) goto end; + + /* b := (2*a)^((|p|-5)/8) */ + if (!BN_rshift(q, p, 3)) goto end; + q->neg = 0; + if (!BN_mod_exp(b, t, q, p, ctx)) goto end; + + /* y := b^2 */ + if (!BN_mod_sqr(y, b, p, ctx)) goto end; + + /* t := (2*a)*b^2 - 1*/ + if (!BN_mod_mul(t, t, y, p, ctx)) goto end; + if (!BN_sub_word(t, 1)) goto end; + + /* x = a*b*t */ + if (!BN_mod_mul(x, a, b, p, ctx)) goto end; + if (!BN_mod_mul(x, x, t, p, ctx)) goto end; + + if (!BN_copy(ret, x)) goto end; + err = 0; + goto end; + } + + /* e > 2, so we really have to use the Tonelli/Shanks algorithm. + * First, find some y that is not a square. */ + if (!BN_copy(q, p)) goto end; /* use 'q' as temp */ + q->neg = 0; + i = 2; + do + { + /* For efficiency, try small numbers first; + * if this fails, try random numbers. + */ + if (i < 22) + { + if (!BN_set_word(y, i)) goto end; + } + else + { + if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end; + if (BN_ucmp(y, p) >= 0) + { + if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end; + } + /* now 0 <= y < |p| */ + if (BN_is_zero(y)) + if (!BN_set_word(y, i)) goto end; + } + + r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ + if (r < -1) goto end; + if (r == 0) + { + /* m divides p */ + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + goto end; + } + } + while (r == 1 && ++i < 82); + + if (r != -1) + { + /* Many rounds and still no non-square -- this is more likely + * a bug than just bad luck. + * Even if p is not prime, we should have found some y + * such that r == -1. + */ + BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); + goto end; + } + + /* Here's our actual 'q': */ + if (!BN_rshift(q, q, e)) goto end; + + /* Now that we have some non-square, we can find an element + * of order 2^e by computing its q'th power. */ + if (!BN_mod_exp(y, y, q, p, ctx)) goto end; + if (BN_is_one(y)) + { + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + goto end; + } + + /* Now we know that (if p is indeed prime) there is an integer + * k, 0 <= k < 2^e, such that + * + * a^q * y^k == 1 (mod p). + * + * As a^q is a square and y is not, k must be even. + * q+1 is even, too, so there is an element + * + * X := a^((q+1)/2) * y^(k/2), + * + * and it satisfies + * + * X^2 = a^q * a * y^k + * = a, + * + * so it is the square root that we are looking for. + */ + + /* t := (q-1)/2 (note that q is odd) */ + if (!BN_rshift1(t, q)) goto end; + + /* x := a^((q-1)/2) */ + if (BN_is_zero(t)) /* special case: p = 2^e + 1 */ + { + if (!BN_nnmod(t, a, p, ctx)) goto end; + if (BN_is_zero(t)) + { + /* special case: a == 0 (mod p) */ + if (!BN_zero(ret)) goto end; + err = 0; + goto end; + } + else + if (!BN_one(x)) goto end; + } + else + { + if (!BN_mod_exp(x, a, t, p, ctx)) goto end; + if (BN_is_zero(x)) + { + /* special case: a == 0 (mod p) */ + if (!BN_zero(ret)) goto end; + err = 0; + goto end; + } + } + + /* b := a*x^2 (= a^q) */ + if (!BN_mod_sqr(b, x, p, ctx)) goto end; + if (!BN_mod_mul(b, b, a, p, ctx)) goto end; + + /* x := a*x (= a^((q+1)/2)) */ + if (!BN_mod_mul(x, x, a, p, ctx)) goto end; + + while (1) + { + /* Now b is a^q * y^k for some even k (0 <= k < 2^E + * where E refers to the original value of e, which we + * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). + * + * We have a*b = x^2, + * y^2^(e-1) = -1, + * b^2^(e-1) = 1. + */ + + if (BN_is_one(b)) + { + if (!BN_copy(ret, x)) goto end; + err = 0; + goto end; + } + + + /* find smallest i such that b^(2^i) = 1 */ + i = 1; + if (!BN_mod_sqr(t, b, p, ctx)) goto end; + while (!BN_is_one(t)) + { + i++; + if (i == e) + { + BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + goto end; + } + if (!BN_mod_mul(t, t, t, p, ctx)) goto end; + } + + + /* t := y^2^(e - i - 1) */ + if (!BN_copy(t, y)) goto end; + for (j = e - i - 1; j > 0; j--) + { + if (!BN_mod_sqr(t, t, p, ctx)) goto end; + } + if (!BN_mod_mul(y, t, t, p, ctx)) goto end; + if (!BN_mod_mul(x, x, t, p, ctx)) goto end; + if (!BN_mod_mul(b, b, y, p, ctx)) goto end; + e = i; + } + + end: + if (err) + { + if (ret != NULL && ret != in) + { + BN_clear_free(ret); + } + ret = NULL; + } + BN_CTX_end(ctx); + return ret; + } diff --git a/src/lib/libcrypto/comp/c_rle.c b/src/lib/libcrypto/comp/c_rle.c new file mode 100644 index 0000000000..1a819e3737 --- /dev/null +++ b/src/lib/libcrypto/comp/c_rle.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +static int rle_compress_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen); +static int rle_expand_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen); + +static COMP_METHOD rle_method={ + NID_rle_compression, + LN_rle_compression, + NULL, + NULL, + rle_compress_block, + rle_expand_block, + NULL, + }; + +COMP_METHOD *COMP_rle(void) + { + return(&rle_method); + } + +static int rle_compress_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen) + { + /* int i; */ + + if (olen < (ilen+1)) + { + /* ZZZZZZZZZZZZZZZZZZZZZZ */ + return(-1); + } + + *(out++)=0; + memcpy(out,in,ilen); + return(ilen+1); + } + +static int rle_expand_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen) + { + int i; + + if (olen < (ilen-1)) + { + /* ZZZZZZZZZZZZZZZZZZZZZZ */ + return(-1); + } + + i= *(in++); + if (i == 0) + { + memcpy(out,in,ilen-1); + } + return(ilen-1); + } + diff --git a/src/lib/libcrypto/comp/c_zlib.c b/src/lib/libcrypto/comp/c_zlib.c new file mode 100644 index 0000000000..6684ab4841 --- /dev/null +++ b/src/lib/libcrypto/comp/c_zlib.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +COMP_METHOD *COMP_zlib(void ); + +#ifndef ZLIB + +static COMP_METHOD zlib_method={ + NID_undef, + "(null)", + NULL, + NULL, + NULL, + NULL, + NULL, + }; + +#else + +#include + +static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen); +static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen); + +static int zz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen); + +static COMP_METHOD zlib_method={ + NID_zlib_compression, + LN_zlib_compression, + NULL, + NULL, + zlib_compress_block, + zlib_expand_block, + NULL, + }; + +static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen) + { + unsigned long l; + int i; + int clear=1; + + if (ilen > 128) + { + out[0]=1; + l=olen-1; + i=compress(&(out[1]),&l,in,(unsigned long)ilen); + if (i != Z_OK) + return(-1); + if (ilen > l) + { + clear=0; + l++; + } + } + if (clear) + { + out[0]=0; + memcpy(&(out[1]),in,ilen); + l=ilen+1; + } +fprintf(stderr,"compress(%4d)->%4d %s\n",ilen,(int)l,(clear)?"clear":"zlib"); + return((int)l); + } + +static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, + unsigned int olen, unsigned char *in, unsigned int ilen) + { + unsigned long l; + int i; + + if (in[0]) + { + l=olen; + i=zz_uncompress(out,&l,&(in[1]),(unsigned long)ilen-1); + if (i != Z_OK) + return(-1); + } + else + { + memcpy(out,&(in[1]),ilen-1); + l=ilen-1; + } + fprintf(stderr,"expand (%4d)->%4d %s\n",ilen,(int)l,in[0]?"zlib":"clear"); + return((int)l); + } + +static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} + +#endif + +COMP_METHOD *COMP_zlib(void) + { + return(&zlib_method); + } + diff --git a/src/lib/libcrypto/comp/comp.h b/src/lib/libcrypto/comp/comp.h new file mode 100644 index 0000000000..93bd9c34c8 --- /dev/null +++ b/src/lib/libcrypto/comp/comp.h @@ -0,0 +1,60 @@ + +#ifndef HEADER_COMP_H +#define HEADER_COMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct comp_method_st + { + int type; /* NID for compression library */ + const char *name; /* A text string to identify the library */ + int (*init)(); + void (*finish)(); + int (*compress)(); + int (*expand)(); + long (*ctrl)(); + } COMP_METHOD; + +typedef struct comp_ctx_st + { + COMP_METHOD *meth; + unsigned long compress_in; + unsigned long compress_out; + unsigned long expand_in; + unsigned long expand_out; + + CRYPTO_EX_DATA ex_data; + } COMP_CTX; + + +COMP_CTX *COMP_CTX_new(COMP_METHOD *meth); +void COMP_CTX_free(COMP_CTX *ctx); +int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); +int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); +COMP_METHOD *COMP_rle(void ); +#ifdef ZLIB +COMP_METHOD *COMP_zlib(void ); +#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 COMP functions. */ + +/* Function codes. */ + +/* Reason codes. */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/comp/comp_err.c b/src/lib/libcrypto/comp/comp_err.c new file mode 100644 index 0000000000..77a3f7070c --- /dev/null +++ b/src/lib/libcrypto/comp/comp_err.c @@ -0,0 +1,91 @@ +/* crypto/comp/comp_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. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA COMP_str_functs[]= + { +{0,NULL} + }; + +static ERR_STRING_DATA COMP_str_reasons[]= + { +{0,NULL} + }; + +#endif + +void ERR_load_COMP_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_COMP,COMP_str_functs); + ERR_load_strings(ERR_LIB_COMP,COMP_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/comp/comp_lib.c b/src/lib/libcrypto/comp/comp_lib.c new file mode 100644 index 0000000000..a67ef23bc0 --- /dev/null +++ b/src/lib/libcrypto/comp/comp_lib.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +COMP_CTX *COMP_CTX_new(COMP_METHOD *meth) + { + COMP_CTX *ret; + + if ((ret=(COMP_CTX *)Malloc(sizeof(COMP_CTX))) == NULL) + { + /* ZZZZZZZZZZZZZZZZ */ + return(NULL); + } + memset(ret,0,sizeof(COMP_CTX)); + ret->meth=meth; + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + Free(ret); + ret=NULL; + } +#if 0 + else + CRYPTO_new_ex_data(rsa_meth,(char *)ret,&ret->ex_data); +#endif + return(ret); + } + +void COMP_CTX_free(COMP_CTX *ctx) + { + /* CRYPTO_free_ex_data(rsa_meth,(char *)ctx,&ctx->ex_data); */ + + if(ctx == NULL) + return; + + if (ctx->meth->finish != NULL) + ctx->meth->finish(ctx); + + Free(ctx); + } + +int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen) + { + int ret; + if (ctx->meth->compress == NULL) + { + /* ZZZZZZZZZZZZZZZZZ */ + return(-1); + } + ret=ctx->meth->compress(ctx,out,olen,in,ilen); + if (ret > 0) + { + ctx->compress_in+=ilen; + ctx->compress_out+=ret; + } + return(ret); + } + +int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen) + { + int ret; + + if (ctx->meth->expand == NULL) + { + /* ZZZZZZZZZZZZZZZZZ */ + return(-1); + } + ret=ctx->meth->expand(ctx,out,olen,in,ilen); + if (ret > 0) + { + ctx->expand_in+=ilen; + ctx->expand_out+=ret; + } + return(ret); + } diff --git a/src/lib/libcrypto/conf/README b/src/lib/libcrypto/conf/README new file mode 100644 index 0000000000..ca58d0240f --- /dev/null +++ b/src/lib/libcrypto/conf/README @@ -0,0 +1,78 @@ +WARNING WARNING WARNING!!! + +This stuff is experimental, may change radically or be deleted altogether +before OpenSSL 0.9.7 release. You have been warned! + +Configuration modules. These are a set of modules which can perform +various configuration functions. + +Currently the routines should be called at most once when an application +starts up: that is before it starts any threads. + +The routines read a configuration file set up like this: + +----- +#default section +openssl_init=init_section + +[init_section] + +module1=value1 +#Second instance of module1 +module1.1=valueX +module2=value2 +module3=dso_literal +module4=dso_section + +[dso_section] + +path=/some/path/to/some/dso.so +other_stuff=other_value +---- + +When this file is loaded a configuration module with the specified +string (module* in the above example) is looked up and its init +function called as: + +int conf_init_func(CONF_IMODULE *md, CONF *cnf); + +The function can then take whatever action is appropriate, for example +further lookups based on the value. Multiple instances of the same +config module can be loaded. + +When the application closes down the modules are cleaned up by calling +an optional finish function: + +void conf_finish_func(CONF_IMODULE *md); + +The finish functions are called in reverse order: that is the last module +loaded is the first one cleaned up. + +If no module exists with a given name then an attempt is made to load +a DSO with the supplied name. This might mean that "module3" attempts +to load a DSO called libmodule3.so or module3.dll for example. An explicit +DSO name can be given by including a separate section as in the module4 example +above. + +The DSO is expected to at least contain an initialization function: + +int OPENSSL_init(CONF_IMODULE *md, CONF *cnf); + +and may also include a finish function: + +void OPENSSL_finish(CONF_IMODULE *md); + +Static modules can also be added using, + +int CONF_module_add(char *name, dso_mod_init_func *ifunc, dso_mod_finish_func *ffunc); + +where "name" is the name in the configuration file this function corresponds to. + +A set of builtin modules (currently only an ASN1 non functional test module) can be +added by calling OPENSSL_load_builtin_modules(). + +The function OPENSSL_config() is intended as a simple configuration function that +any application can call to perform various default configuration tasks. It uses the +file openssl.cnf in the usual locations. + + diff --git a/src/lib/libcrypto/conf/conf_api.c b/src/lib/libcrypto/conf/conf_api.c new file mode 100644 index 0000000000..d05a778ff6 --- /dev/null +++ b/src/lib/libcrypto/conf/conf_api.c @@ -0,0 +1,289 @@ +/* conf_api.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.] + */ + +/* Part of the code in here was originally in conf.c, which is now removed */ + +#ifndef CONF_DEBUG +# undef NDEBUG /* avoid conflicting definitions */ +# define NDEBUG +#endif + +#include +#include +#include +#include + +static void value_free_hash(CONF_VALUE *a, LHASH *conf); +static void value_free_stack(CONF_VALUE *a,LHASH *conf); +static unsigned long hash(CONF_VALUE *v); +static int cmp_conf(CONF_VALUE *a,CONF_VALUE *b); + +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(CONF *conf, char *section) + { + CONF_VALUE *v,vv; + + if ((conf == NULL) || (section == NULL)) return(NULL); + vv.name=NULL; + vv.section=section; + v=(CONF_VALUE *)lh_retrieve(conf->data,&vv); + return(v); + } + +/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ +STACK_OF(CONF_VALUE) *_CONF_get_section_values(CONF *conf, char *section) + { + CONF_VALUE *v; + + v=_CONF_get_section(conf,section); + if (v != NULL) + return((STACK_OF(CONF_VALUE) *)v->value); + else + return(NULL); + } + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value) + { + CONF_VALUE *v = NULL; + STACK_OF(CONF_VALUE) *ts; + + ts = (STACK_OF(CONF_VALUE) *)section->value; + + value->section=section->section; + if (!sk_CONF_VALUE_push(ts,value)) + { + return 0; + } + + v = (CONF_VALUE *)lh_insert(conf->data, value); + if (v != NULL) + { + sk_CONF_VALUE_delete_ptr(ts,v); + OPENSSL_free(v->name); + OPENSSL_free(v->value); + OPENSSL_free(v); + } + return 1; + } + +char *_CONF_get_string(CONF *conf, char *section, char *name) + { + CONF_VALUE *v,vv; + char *p; + + if (name == NULL) return(NULL); + if (conf != NULL) + { + if (section != NULL) + { + vv.name=name; + vv.section=section; + v=(CONF_VALUE *)lh_retrieve(conf->data,&vv); + if (v != NULL) return(v->value); + if (strcmp(section,"ENV") == 0) + { + p=Getenv(name); + if (p != NULL) return(p); + } + } + vv.section="default"; + vv.name=name; + v=(CONF_VALUE *)lh_retrieve(conf->data,&vv); + if (v != NULL) + return(v->value); + else + return(NULL); + } + else + return(Getenv(name)); + } + +long _CONF_get_number(CONF *conf, char *section, char *name) + { + char *str; + long ret=0; + + str=_CONF_get_string(conf,section,name); + if (str == NULL) return(0); + for (;;) + { + if (conf->meth->is_number(conf, *str)) + ret=ret*10+conf->meth->to_int(conf, *str); + else + return(ret); + str++; + } + } + +int _CONF_new_data(CONF *conf) + { + if (conf == NULL) + { + return 0; + } + if (conf->data == NULL) + if ((conf->data = lh_new(hash,cmp_conf)) == NULL) + { + return 0; + } + return 1; + } + +void _CONF_free_data(CONF *conf) + { + if (conf == NULL || conf->data == NULL) return; + + conf->data->down_load=0; /* evil thing to make sure the 'OPENSSL_free()' + * works as expected */ + lh_doall_arg(conf->data,(void (*)())value_free_hash,conf->data); + + /* We now have only 'section' entries in the hash table. + * Due to problems with */ + + lh_doall_arg(conf->data,(void (*)())value_free_stack,conf->data); + lh_free(conf->data); + } + +static void value_free_hash(CONF_VALUE *a, LHASH *conf) + { + if (a->name != NULL) + { + a=(CONF_VALUE *)lh_delete(conf,a); + } + } + +static void value_free_stack(CONF_VALUE *a, LHASH *conf) + { + CONF_VALUE *vv; + STACK *sk; + int i; + + if (a->name != NULL) return; + + sk=(STACK *)a->value; + for (i=sk_num(sk)-1; i>=0; i--) + { + vv=(CONF_VALUE *)sk_value(sk,i); + OPENSSL_free(vv->value); + OPENSSL_free(vv->name); + OPENSSL_free(vv); + } + if (sk != NULL) sk_free(sk); + OPENSSL_free(a->section); + OPENSSL_free(a); + } + +static unsigned long hash(CONF_VALUE *v) + { + return((lh_strhash(v->section)<<2)^lh_strhash(v->name)); + } + +static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) + { + int i; + + if (a->section != b->section) + { + i=strcmp(a->section,b->section); + if (i) return(i); + } + + if ((a->name != NULL) && (b->name != NULL)) + { + i=strcmp(a->name,b->name); + return(i); + } + else if (a->name == b->name) + return(0); + else + return((a->name == NULL)?-1:1); + } + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, char *section) + { + STACK *sk=NULL; + int ok=0,i; + CONF_VALUE *v=NULL,*vv; + + if ((sk=sk_new_null()) == NULL) + goto err; + if ((v=(CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))) == NULL) + goto err; + i=strlen(section)+1; + if ((v->section=(char *)OPENSSL_malloc(i)) == NULL) + goto err; + + memcpy(v->section,section,i); + v->name=NULL; + v->value=(char *)sk; + + vv=(CONF_VALUE *)lh_insert(conf->data,v); + assert(vv == NULL); + ok=1; +err: + if (!ok) + { + if (sk != NULL) sk_free(sk); + if (v != NULL) OPENSSL_free(v); + v=NULL; + } + return(v); + } + +IMPLEMENT_STACK_OF(CONF_VALUE) diff --git a/src/lib/libcrypto/conf/conf_api.h b/src/lib/libcrypto/conf/conf_api.h new file mode 100644 index 0000000000..a5cc17b233 --- /dev/null +++ b/src/lib/libcrypto/conf/conf_api.h @@ -0,0 +1,87 @@ +/* conf_api.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_CONF_API_H +#define HEADER_CONF_API_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, char *section); +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(CONF *conf, char *section); +/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ +STACK_OF(CONF_VALUE) *_CONF_get_section_values(CONF *conf, char *section); + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value); +char *_CONF_get_string(CONF *conf, char *section, char *name); +long _CONF_get_number(CONF *conf, char *section, char *name); + +int _CONF_new_data(CONF *conf); +void _CONF_free_data(CONF *conf); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/conf/conf_def.c b/src/lib/libcrypto/conf/conf_def.c new file mode 100644 index 0000000000..773df32c68 --- /dev/null +++ b/src/lib/libcrypto/conf/conf_def.c @@ -0,0 +1,703 @@ +/* crypto/conf/conf.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.] + */ + +/* Part of the code in here was originally in conf.c, which is now removed */ + +#include +#include +#include +#include +#include +#include +#include "conf_def.h" +#include +#include + +static char *eat_ws(CONF *conf, char *p); +static char *eat_alpha_numeric(CONF *conf, char *p); +static void clear_comments(CONF *conf, char *p); +static int str_copy(CONF *conf,char *section,char **to, char *from); +static char *scan_quote(CONF *conf, char *p); +static char *scan_dquote(CONF *conf, char *p); +#define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2))) + +static CONF *def_create(CONF_METHOD *meth); +static int def_init_default(CONF *conf); +static int def_init_WIN32(CONF *conf); +static int def_destroy(CONF *conf); +static int def_destroy_data(CONF *conf); +static int def_load(CONF *conf, BIO *bp, long *eline); +static int def_dump(CONF *conf, BIO *bp); +static int def_is_number(CONF *conf, char c); +static int def_to_int(CONF *conf, char c); + +const char *CONF_def_version="CONF_def" OPENSSL_VERSION_PTEXT; + +static CONF_METHOD default_method = { + "OpenSSL default", + def_create, + def_init_default, + def_destroy, + def_destroy_data, + def_load, + def_dump, + def_is_number, + def_to_int + }; + +static CONF_METHOD WIN32_method = { + "WIN32", + def_create, + def_init_WIN32, + def_destroy, + def_destroy_data, + def_load, + def_dump, + def_is_number, + def_to_int + }; + +CONF_METHOD *NCONF_default() + { + return &default_method; + } +CONF_METHOD *NCONF_WIN32() + { + return &WIN32_method; + } + +static CONF *def_create(CONF_METHOD *meth) + { + CONF *ret; + + ret = (CONF *)OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *)); + if (ret) + if (meth->init(ret) == 0) + { + OPENSSL_free(ret); + ret = NULL; + } + return ret; + } + +static int def_init_default(CONF *conf) + { + if (conf == NULL) + return 0; + + conf->meth = &default_method; + conf->meth_data = (void *)CONF_type_default; + conf->data = NULL; + + return 1; + } + +static int def_init_WIN32(CONF *conf) + { + if (conf == NULL) + return 0; + + conf->meth = &WIN32_method; + conf->meth_data = (void *)CONF_type_win32; + conf->data = NULL; + + return 1; + } + +static int def_destroy(CONF *conf) + { + if (def_destroy_data(conf)) + { + OPENSSL_free(conf); + return 1; + } + return 0; + } + +static int def_destroy_data(CONF *conf) + { + if (conf == NULL) + return 0; + _CONF_free_data(conf); + return 1; + } + +static int def_load(CONF *conf, BIO *in, long *line) + { +#define BUFSIZE 512 + char btmp[16]; + int bufnum=0,i,ii; + BUF_MEM *buff=NULL; + char *s,*p,*end; + int again,n; + long eline=0; + CONF_VALUE *v=NULL,*tv; + CONF_VALUE *sv=NULL; + char *section=NULL,*buf; + STACK_OF(CONF_VALUE) *section_sk=NULL,*ts; + char *start,*psection,*pname; + void *h = (void *)(conf->data); + + if ((buff=BUF_MEM_new()) == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); + goto err; + } + + section=(char *)OPENSSL_malloc(10); + if (section == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); + goto err; + } + strcpy(section,"default"); + + if (_CONF_new_data(conf) == 0) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); + goto err; + } + + sv=_CONF_new_section(conf,section); + if (sv == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + section_sk=(STACK_OF(CONF_VALUE) *)sv->value; + + bufnum=0; + for (;;) + { + again=0; + if (!BUF_MEM_grow(buff,bufnum+BUFSIZE)) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); + goto err; + } + p= &(buff->data[bufnum]); + *p='\0'; + BIO_gets(in, p, BUFSIZE-1); + p[BUFSIZE-1]='\0'; + ii=i=strlen(p); + if (i == 0) break; + while (i > 0) + { + if ((p[i-1] != '\r') && (p[i-1] != '\n')) + break; + else + i--; + } + /* we removed some trailing stuff so there is a new + * line on the end. */ + if (i == ii) + again=1; /* long line */ + else + { + p[i]='\0'; + eline++; /* another input line */ + } + + /* we now have a line with trailing \r\n removed */ + + /* i is the number of bytes */ + bufnum+=i; + + v=NULL; + /* check for line continuation */ + if (bufnum >= 1) + { + /* If we have bytes and the last char '\\' and + * second last char is not '\\' */ + p= &(buff->data[bufnum-1]); + if (IS_ESC(conf,p[0]) && + ((bufnum <= 1) || !IS_ESC(conf,p[-1]))) + { + bufnum--; + again=1; + } + } + if (again) continue; + bufnum=0; + buf=buff->data; + + clear_comments(conf, buf); + n=strlen(buf); + s=eat_ws(conf, buf); + if (IS_EOF(conf,*s)) continue; /* blank line */ + if (*s == '[') + { + char *ss; + + s++; + start=eat_ws(conf, s); + ss=start; +again: + end=eat_alpha_numeric(conf, ss); + p=eat_ws(conf, end); + if (*p != ']') + { + if (*p != '\0') + { + ss=p; + goto again; + } + CONFerr(CONF_F_CONF_LOAD_BIO, + CONF_R_MISSING_CLOSE_SQUARE_BRACKET); + goto err; + } + *end='\0'; + if (!str_copy(conf,NULL,§ion,start)) goto err; + if ((sv=_CONF_get_section(conf,section)) == NULL) + sv=_CONF_new_section(conf,section); + if (sv == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + section_sk=(STACK_OF(CONF_VALUE) *)sv->value; + continue; + } + else + { + pname=s; + psection=NULL; + end=eat_alpha_numeric(conf, s); + if ((end[0] == ':') && (end[1] == ':')) + { + *end='\0'; + end+=2; + psection=pname; + pname=end; + end=eat_alpha_numeric(conf, end); + } + p=eat_ws(conf, end); + if (*p != '=') + { + CONFerr(CONF_F_CONF_LOAD_BIO, + CONF_R_MISSING_EQUAL_SIGN); + goto err; + } + *end='\0'; + p++; + start=eat_ws(conf, p); + while (!IS_EOF(conf,*p)) + p++; + p--; + while ((p != start) && (IS_WS(conf,*p))) + p--; + p++; + *p='\0'; + + if (!(v=(CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (psection == NULL) psection=section; + v->name=(char *)OPENSSL_malloc(strlen(pname)+1); + v->value=NULL; + if (v->name == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + strcpy(v->name,pname); + if (!str_copy(conf,psection,&(v->value),start)) goto err; + + if (strcmp(psection,section) != 0) + { + if ((tv=_CONF_get_section(conf,psection)) + == NULL) + tv=_CONF_new_section(conf,psection); + if (tv == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + CONF_R_UNABLE_TO_CREATE_NEW_SECTION); + goto err; + } + ts=(STACK_OF(CONF_VALUE) *)tv->value; + } + else + { + tv=sv; + ts=section_sk; + } +#if 1 + if (_CONF_add_string(conf, tv, v) == 0) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } +#else + v->section=tv->section; + if (!sk_CONF_VALUE_push(ts,v)) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + vv=(CONF_VALUE *)lh_insert(conf->data,v); + if (vv != NULL) + { + sk_CONF_VALUE_delete_ptr(ts,vv); + OPENSSL_free(vv->name); + OPENSSL_free(vv->value); + OPENSSL_free(vv); + } +#endif + v=NULL; + } + } + if (buff != NULL) BUF_MEM_free(buff); + if (section != NULL) OPENSSL_free(section); + return(1); +err: + if (buff != NULL) BUF_MEM_free(buff); + if (section != NULL) OPENSSL_free(section); + if (line != NULL) *line=eline; + sprintf(btmp,"%ld",eline); + ERR_add_error_data(2,"line ",btmp); + if ((h != conf->data) && (conf->data != NULL)) CONF_free(conf->data); + if (v != NULL) + { + if (v->name != NULL) OPENSSL_free(v->name); + if (v->value != NULL) OPENSSL_free(v->value); + if (v != NULL) OPENSSL_free(v); + } + return(0); + } + +static void clear_comments(CONF *conf, char *p) + { + char *to; + + to=p; + for (;;) + { + if (IS_FCOMMENT(conf,*p)) + { + *p='\0'; + return; + } + if (!IS_WS(conf,*p)) + { + break; + } + p++; + } + + for (;;) + { + if (IS_COMMENT(conf,*p)) + { + *p='\0'; + return; + } + if (IS_DQUOTE(conf,*p)) + { + p=scan_dquote(conf, p); + continue; + } + if (IS_QUOTE(conf,*p)) + { + p=scan_quote(conf, p); + continue; + } + if (IS_ESC(conf,*p)) + { + p=scan_esc(conf,p); + continue; + } + if (IS_EOF(conf,*p)) + return; + else + p++; + } + } + +static int str_copy(CONF *conf, char *section, char **pto, char *from) + { + int q,r,rr=0,to=0,len=0; + char *s,*e,*rp,*p,*rrp,*np,*cp,v; + BUF_MEM *buf; + + if ((buf=BUF_MEM_new()) == NULL) return(0); + + len=strlen(from)+1; + if (!BUF_MEM_grow(buf,len)) goto err; + + for (;;) + { + if (IS_QUOTE(conf,*from)) + { + q= *from; + from++; + while (!IS_EOF(conf,*from) && (*from != q)) + { + if (IS_ESC(conf,*from)) + { + from++; + if (IS_EOF(conf,*from)) break; + } + buf->data[to++]= *(from++); + } + if (*from == q) from++; + } + else if (IS_DQUOTE(conf,*from)) + { + q= *from; + from++; + while (!IS_EOF(conf,*from)) + { + if (*from == q) + { + if (*(from+1) == q) + { + from++; + } + else + { + break; + } + } + buf->data[to++]= *(from++); + } + if (*from == q) from++; + } + else if (IS_ESC(conf,*from)) + { + from++; + v= *(from++); + if (IS_EOF(conf,v)) break; + else if (v == 'r') v='\r'; + else if (v == 'n') v='\n'; + else if (v == 'b') v='\b'; + else if (v == 't') v='\t'; + buf->data[to++]= v; + } + else if (IS_EOF(conf,*from)) + break; + else if (*from == '$') + { + /* try to expand it */ + rrp=NULL; + s= &(from[1]); + if (*s == '{') + q='}'; + else if (*s == '(') + q=')'; + else q=0; + + if (q) s++; + cp=section; + e=np=s; + while (IS_ALPHA_NUMERIC(conf,*e)) + e++; + if ((e[0] == ':') && (e[1] == ':')) + { + cp=np; + rrp=e; + rr= *e; + *rrp='\0'; + e+=2; + np=e; + while (IS_ALPHA_NUMERIC(conf,*e)) + e++; + } + r= *e; + *e='\0'; + rp=e; + if (q) + { + if (r != q) + { + CONFerr(CONF_F_STR_COPY,CONF_R_NO_CLOSE_BRACE); + goto err; + } + e++; + } + /* So at this point we have + * ns which is the start of the name string which is + * '\0' terminated. + * cs which is the start of the section string which is + * '\0' terminated. + * e is the 'next point after'. + * r and s are the chars replaced by the '\0' + * rp and sp is where 'r' and 's' came from. + */ + p=_CONF_get_string(conf,cp,np); + if (rrp != NULL) *rrp=rr; + *rp=r; + if (p == NULL) + { + CONFerr(CONF_F_STR_COPY,CONF_R_VARIABLE_HAS_NO_VALUE); + goto err; + } + BUF_MEM_grow(buf,(strlen(p)+len-(e-from))); + while (*p) + buf->data[to++]= *(p++); + from=e; + } + else + buf->data[to++]= *(from++); + } + buf->data[to]='\0'; + if (*pto != NULL) OPENSSL_free(*pto); + *pto=buf->data; + OPENSSL_free(buf); + return(1); +err: + if (buf != NULL) BUF_MEM_free(buf); + return(0); + } + +static char *eat_ws(CONF *conf, char *p) + { + while (IS_WS(conf,*p) && (!IS_EOF(conf,*p))) + p++; + return(p); + } + +static char *eat_alpha_numeric(CONF *conf, char *p) + { + for (;;) + { + if (IS_ESC(conf,*p)) + { + p=scan_esc(conf,p); + continue; + } + if (!IS_ALPHA_NUMERIC_PUNCT(conf,*p)) + return(p); + p++; + } + } + +static char *scan_quote(CONF *conf, char *p) + { + int q= *p; + + p++; + while (!(IS_EOF(conf,*p)) && (*p != q)) + { + if (IS_ESC(conf,*p)) + { + p++; + if (IS_EOF(conf,*p)) return(p); + } + p++; + } + if (*p == q) p++; + return(p); + } + + +static char *scan_dquote(CONF *conf, char *p) + { + int q= *p; + + p++; + while (!(IS_EOF(conf,*p))) + { + if (*p == q) + { + if (*(p+1) == q) + { + p++; + } + else + { + break; + } + } + p++; + } + if (*p == q) p++; + return(p); + } + +static void dump_value(CONF_VALUE *a, BIO *out) + { + if (a->name) + BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value); + else + BIO_printf(out, "[[%s]]\n", a->section); + } + +static int def_dump(CONF *conf, BIO *out) + { + lh_doall_arg(conf->data, (void (*)())dump_value, out); + return 1; + } + +static int def_is_number(CONF *conf, char c) + { + return IS_NUMBER(conf,c); + } + +static int def_to_int(CONF *conf, char c) + { + return c - '0'; + } + diff --git a/src/lib/libcrypto/conf/conf_def.h b/src/lib/libcrypto/conf/conf_def.h new file mode 100644 index 0000000000..3244d9a331 --- /dev/null +++ b/src/lib/libcrypto/conf/conf_def.h @@ -0,0 +1,145 @@ +/* crypto/conf/conf_def.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.] + */ + +/* THIS FILE WAS AUTOMAGICALLY GENERATED! + Please modify and use keysets.pl to regenerate it. */ + +#define CONF_NUMBER 1 +#define CONF_UPPER 2 +#define CONF_LOWER 4 +#define CONF_UNDER 256 +#define CONF_PUNCTUATION 512 +#define CONF_WS 16 +#define CONF_ESC 32 +#define CONF_QUOTE 64 +#define CONF_DQUOTE 1024 +#define CONF_COMMENT 128 +#define CONF_FCOMMENT 2048 +#define CONF_EOF 8 +#define CONF_ALPHA (CONF_UPPER|CONF_LOWER) +#define CONF_ALPHA_NUMERIC (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) +#define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \ + CONF_PUNCTUATION) + +#define KEYTYPES(c) ((unsigned short *)((c)->meth_data)) +#ifndef CHARSET_EBCDIC +#define IS_COMMENT(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_ALPHA_NUMERIC) +#define IS_ALPHA_NUMERIC_PUNCT(c,a) \ + (KEYTYPES(c)[(a)&0x7f]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_DQUOTE) + +#else /*CHARSET_EBCDIC*/ + +#define IS_COMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_ALPHA_NUMERIC) +#define IS_ALPHA_NUMERIC_PUNCT(c,a) \ + (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_DQUOTE) +#endif /*CHARSET_EBCDIC*/ + +static unsigned short CONF_type_default[128]={ + 0x008,0x000,0x000,0x000,0x000,0x000,0x000,0x000, + 0x000,0x010,0x010,0x000,0x000,0x010,0x000,0x000, + 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, + 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, + 0x010,0x200,0x040,0x080,0x000,0x200,0x200,0x040, + 0x000,0x000,0x200,0x200,0x200,0x200,0x200,0x200, + 0x001,0x001,0x001,0x001,0x001,0x001,0x001,0x001, + 0x001,0x001,0x000,0x200,0x000,0x000,0x000,0x200, + 0x200,0x002,0x002,0x002,0x002,0x002,0x002,0x002, + 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, + 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, + 0x002,0x002,0x002,0x000,0x020,0x000,0x200,0x100, + 0x040,0x004,0x004,0x004,0x004,0x004,0x004,0x004, + 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, + 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, + 0x004,0x004,0x004,0x000,0x200,0x000,0x200,0x000, + }; + +static unsigned short CONF_type_win32[128]={ + 0x008,0x000,0x000,0x000,0x000,0x000,0x000,0x000, + 0x000,0x010,0x010,0x000,0x000,0x010,0x000,0x000, + 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, + 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, + 0x010,0x200,0x400,0x000,0x000,0x200,0x200,0x000, + 0x000,0x000,0x200,0x200,0x200,0x200,0x200,0x200, + 0x001,0x001,0x001,0x001,0x001,0x001,0x001,0x001, + 0x001,0x001,0x000,0xA00,0x000,0x000,0x000,0x200, + 0x200,0x002,0x002,0x002,0x002,0x002,0x002,0x002, + 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, + 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, + 0x002,0x002,0x002,0x000,0x000,0x000,0x200,0x100, + 0x000,0x004,0x004,0x004,0x004,0x004,0x004,0x004, + 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, + 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, + 0x004,0x004,0x004,0x000,0x200,0x000,0x200,0x000, + }; + diff --git a/src/lib/libcrypto/conf/conf_lib.c b/src/lib/libcrypto/conf/conf_lib.c new file mode 100644 index 0000000000..4c8ca9e9ae --- /dev/null +++ b/src/lib/libcrypto/conf/conf_lib.c @@ -0,0 +1,352 @@ +/* conf_lib.c */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include +#include + +const char *CONF_version="CONF" OPENSSL_VERSION_PTEXT; + +static CONF_METHOD *default_CONF_method=NULL; + +/* The following section contains the "CONF classic" functions, + rewritten in terms of the new CONF interface. */ + +int CONF_set_default_method(CONF_METHOD *meth) + { + default_CONF_method = meth; + return 1; + } + +LHASH *CONF_load(LHASH *conf, const char *file, long *eline) + { + LHASH *ltmp; + BIO *in=NULL; + +#ifdef VMS + in=BIO_new_file(file, "r"); +#else + in=BIO_new_file(file, "rb"); +#endif + if (in == NULL) + { + CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB); + return NULL; + } + + ltmp = CONF_load_bio(conf, in, eline); + BIO_free(in); + + return ltmp; + } + +#ifndef NO_FP_API +LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline) + { + BIO *btmp; + LHASH *ltmp; + if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) { + CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB); + return NULL; + } + ltmp = CONF_load_bio(conf, btmp, eline); + BIO_free(btmp); + return ltmp; + } +#endif + +LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline) + { + CONF ctmp; + int ret; + + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(&ctmp); + ctmp.data = conf; + ret = NCONF_load_bio(&ctmp, bp, eline); + if (ret) + return ctmp.data; + return NULL; + } + +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,char *section) + { + CONF ctmp; + + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(&ctmp); + ctmp.data = conf; + return NCONF_get_section(&ctmp, section); + } + +char *CONF_get_string(LHASH *conf,char *group,char *name) + { + CONF ctmp; + + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(&ctmp); + ctmp.data = conf; + return NCONF_get_string(&ctmp, group, name); + } + +long CONF_get_number(LHASH *conf,char *group,char *name) + { + CONF ctmp; + + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(&ctmp); + ctmp.data = conf; + return NCONF_get_number(&ctmp, group, name); + } + +void CONF_free(LHASH *conf) + { + CONF ctmp; + + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(&ctmp); + ctmp.data = conf; + NCONF_free_data(&ctmp); + } + +#ifndef NO_FP_API +int CONF_dump_fp(LHASH *conf, FILE *out) + { + BIO *btmp; + int ret; + + if(!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) { + CONFerr(CONF_F_CONF_DUMP_FP,ERR_R_BUF_LIB); + return 0; + } + ret = CONF_dump_bio(conf, btmp); + BIO_free(btmp); + return ret; + } +#endif + +int CONF_dump_bio(LHASH *conf, BIO *out) + { + CONF ctmp; + + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(&ctmp); + ctmp.data = conf; + return NCONF_dump_bio(&ctmp, out); + } + +/* The following section contains the "New CONF" functions. They are + completely centralised around a new CONF structure that may contain + basically anything, but at least a method pointer and a table of data. + These functions are also written in terms of the bridge functions used + by the "CONF classic" functions, for consistency. */ + +CONF *NCONF_new(CONF_METHOD *meth) + { + CONF *ret; + + if (meth == NULL) + meth = NCONF_default(); + + ret = meth->create(meth); + if (ret == NULL) + { + CONFerr(CONF_F_NCONF_NEW,ERR_R_MALLOC_FAILURE); + return(NULL); + } + + return ret; + } + +void NCONF_free(CONF *conf) + { + if (conf == NULL) + return; + conf->meth->destroy(conf); + } + +void NCONF_free_data(CONF *conf) + { + if (conf == NULL) + return; + conf->meth->destroy_data(conf); + } + +int NCONF_load(CONF *conf, const char *file, long *eline) + { + int ret; + BIO *in=NULL; + +#ifdef VMS + in=BIO_new_file(file, "r"); +#else + in=BIO_new_file(file, "rb"); +#endif + if (in == NULL) + { + CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB); + return 0; + } + + ret = NCONF_load_bio(conf, in, eline); + BIO_free(in); + + return ret; + } + +#ifndef NO_FP_API +int NCONF_load_fp(CONF *conf, FILE *fp,long *eline) + { + BIO *btmp; + int ret; + if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) + { + CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB); + return 0; + } + ret = NCONF_load_bio(conf, btmp, eline); + BIO_free(btmp); + return ret; + } +#endif + +int NCONF_load_bio(CONF *conf, BIO *bp,long *eline) + { + if (conf == NULL) + { + CONFerr(CONF_F_NCONF_LOAD_BIO,CONF_R_NO_CONF); + return 0; + } + + return conf->meth->load(conf, bp, eline); + } + +STACK_OF(CONF_VALUE) *NCONF_get_section(CONF *conf,char *section) + { + if (conf == NULL) + { + CONFerr(CONF_F_NCONF_GET_SECTION,CONF_R_NO_CONF); + return NULL; + } + + return _CONF_get_section_values(conf, section); + } + +char *NCONF_get_string(CONF *conf,char *group,char *name) + { + if (conf == NULL) + { + CONFerr(CONF_F_NCONF_GET_STRING,CONF_R_NO_CONF); + return NULL; + } + + return _CONF_get_string(conf, group, name); + } + +long NCONF_get_number(CONF *conf,char *group,char *name) + { + if (conf == NULL) + { + CONFerr(CONF_F_NCONF_GET_NUMBER,CONF_R_NO_CONF); + return 0; + } + + return _CONF_get_number(conf, group, name); + } + +#ifndef NO_FP_API +int NCONF_dump_fp(CONF *conf, FILE *out) + { + BIO *btmp; + int ret; + if(!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) { + CONFerr(CONF_F_NCONF_DUMP_FP,ERR_R_BUF_LIB); + return 0; + } + ret = NCONF_dump_bio(conf, btmp); + BIO_free(btmp); + return ret; + } +#endif + +int NCONF_dump_bio(CONF *conf, BIO *out) + { + if (conf == NULL) + { + CONFerr(CONF_F_NCONF_DUMP_BIO,CONF_R_NO_CONF); + return 0; + } + + return conf->meth->dump(conf, out); + } + diff --git a/src/lib/libcrypto/conf/conf_mall.c b/src/lib/libcrypto/conf/conf_mall.c new file mode 100644 index 0000000000..d702af689b --- /dev/null +++ b/src/lib/libcrypto/conf/conf_mall.c @@ -0,0 +1,76 @@ +/* conf_mall.c */ +/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include "cryptlib.h" +#include +#include +#include +#include +#include + +/* Load all OpenSSL builtin modules */ + +void OPENSSL_load_builtin_modules(void) + { + /* Add builtin modules here */ + ASN1_add_oid_module(); + ENGINE_add_conf_module(); + } + diff --git a/src/lib/libcrypto/conf/conf_mod.c b/src/lib/libcrypto/conf/conf_mod.c new file mode 100644 index 0000000000..f92babc2e2 --- /dev/null +++ b/src/lib/libcrypto/conf/conf_mod.c @@ -0,0 +1,616 @@ +/* conf_mod.c */ +/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include +#include "cryptlib.h" +#include +#include +#include + + +#define DSO_mod_init_name "OPENSSL_init" +#define DSO_mod_finish_name "OPENSSL_finish" + + +/* This structure contains a data about supported modules. + * entries in this table correspond to either dynamic or + * static modules. + */ + +struct conf_module_st + { + /* DSO of this module or NULL if static */ + DSO *dso; + /* Name of the module */ + char *name; + /* Init function */ + conf_init_func *init; + /* Finish function */ + conf_finish_func *finish; + /* Number of successfully initialized modules */ + int links; + void *usr_data; + }; + + +/* This structure contains information about modules that have been + * successfully initialized. There may be more than one entry for a + * given module. + */ + +struct conf_imodule_st + { + CONF_MODULE *pmod; + char *name; + char *value; + unsigned long flags; + void *usr_data; + }; + +static STACK_OF(CONF_MODULE) *supported_modules = NULL; +static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; + +static void module_free(CONF_MODULE *md); +static void module_finish(CONF_IMODULE *imod); +static int module_run(const CONF *cnf, char *name, char *value, + unsigned long flags); +static CONF_MODULE *module_add(DSO *dso, const char *name, + conf_init_func *ifunc, conf_finish_func *ffunc); +static CONF_MODULE *module_find(char *name); +static int module_init(CONF_MODULE *pmod, char *name, char *value, + const CONF *cnf); +static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value, + unsigned long flags); + +/* Main function: load modules from a CONF structure */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags) + { + STACK_OF(CONF_VALUE) *values; + CONF_VALUE *vl; + char *vsection; + + int ret, i; + + if (!cnf) + return 1; + + if (appname == NULL) + appname = "openssl_conf"; + + vsection = NCONF_get_string(cnf, NULL, appname); + + if (!vsection) + { + ERR_clear_error(); + return 1; + } + + values = NCONF_get_section(cnf, vsection); + + if (!values) + return 0; + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) + { + vl = sk_CONF_VALUE_value(values, i); + ret = module_run(cnf, vl->name, vl->value, flags); + if (ret <= 0) + if(!(flags & CONF_MFLAGS_IGNORE_ERRORS)) + return ret; + } + + return 1; + + } + +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags) + { + char *file = NULL; + CONF *conf = NULL; + int ret = 0; + conf = NCONF_new(NULL); + if (!conf) + goto err; + + if (filename == NULL) + { + file = CONF_get1_default_config_file(); + if (!file) + goto err; + } + else + file = (char *)filename; + + if (NCONF_load(conf, file, NULL) <= 0) + { + if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) && + (ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE)) + { + ERR_clear_error(); + ret = 1; + } + goto err; + } + + ret = CONF_modules_load(conf, appname, flags); + + err: + if (filename == NULL) + OPENSSL_free(file); + NCONF_free(conf); + + return ret; + } + +static int module_run(const CONF *cnf, char *name, char *value, + unsigned long flags) + { + CONF_MODULE *md; + int ret; + + md = module_find(name); + + /* Module not found: try to load DSO */ + if (!md && !(flags & CONF_MFLAGS_NO_DSO)) + md = module_load_dso(cnf, name, value, flags); + + if (!md) + { + if (!(flags & CONF_MFLAGS_SILENT)) + { + CONFerr(CONF_F_MODULE_RUN, CONF_R_UNKNOWN_MODULE_NAME); + ERR_add_error_data(2, "module=", name); + } + return -1; + } + + ret = module_init(md, name, value, cnf); + + if (ret <= 0) + { + if (!(flags & CONF_MFLAGS_SILENT)) + { + char rcode[10]; + CONFerr(CONF_F_CONF_MODULES_LOAD, CONF_R_MODULE_INITIALIZATION_ERROR); + sprintf(rcode, "%-8d", ret); + ERR_add_error_data(6, "module=", name, ", value=", value, ", retcode=", rcode); + } + } + + return ret; + } + +/* Load a module from a DSO */ +static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value, + unsigned long flags) + { + DSO *dso = NULL; + conf_init_func *ifunc; + conf_finish_func *ffunc; + char *path = NULL; + int errcode = 0; + CONF_MODULE *md; + /* Look for alternative path in module section */ + path = NCONF_get_string(cnf, value, "path"); + if (!path) + { + ERR_get_error(); + path = name; + } + dso = DSO_load(NULL, path, NULL, 0); + if (!dso) + { + errcode = CONF_R_ERROR_LOADING_DSO; + goto err; + } + ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name); + if (!ifunc) + { + errcode = CONF_R_MISSING_INIT_FUNCTION; + goto err; + } + ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name); + /* All OK, add module */ + md = module_add(dso, name, ifunc, ffunc); + + if (!md) + goto err; + + return md; + + err: + if (dso) + DSO_free(dso); + CONFerr(CONF_F_MODULE_LOAD_DSO, errcode); + ERR_add_error_data(4, "module=", name, ", path=", path); + return NULL; + } + +/* add module to list */ +static CONF_MODULE *module_add(DSO *dso, const char *name, + conf_init_func *ifunc, conf_finish_func *ffunc) + { + CONF_MODULE *tmod = NULL; + if (supported_modules == NULL) + supported_modules = sk_CONF_MODULE_new_null(); + if (supported_modules == NULL) + return NULL; + tmod = OPENSSL_malloc(sizeof(CONF_MODULE)); + if (tmod == NULL) + return NULL; + + tmod->dso = dso; + tmod->name = BUF_strdup(name); + tmod->init = ifunc; + tmod->finish = ffunc; + tmod->links = 0; + + if (!sk_CONF_MODULE_push(supported_modules, tmod)) + { + OPENSSL_free(tmod); + return NULL; + } + + return tmod; + } + +/* Find a module from the list. We allow module names of the + * form modname.XXXX to just search for modname to allow the + * same module to be initialized more than once. + */ + +static CONF_MODULE *module_find(char *name) + { + CONF_MODULE *tmod; + int i, nchar; + char *p; + p = strrchr(name, '.'); + + if (p) + nchar = p - name; + else + nchar = strlen(name); + + for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) + { + tmod = sk_CONF_MODULE_value(supported_modules, i); + if (!strncmp(tmod->name, name, nchar)) + return tmod; + } + + return NULL; + + } + +/* initialize a module */ +static int module_init(CONF_MODULE *pmod, char *name, char *value, + const CONF *cnf) + { + int ret = 1; + int init_called = 0; + CONF_IMODULE *imod = NULL; + + /* Otherwise add initialized module to list */ + imod = OPENSSL_malloc(sizeof(CONF_IMODULE)); + if (!imod) + goto err; + + imod->pmod = pmod; + imod->name = BUF_strdup(name); + imod->value = BUF_strdup(value); + imod->usr_data = NULL; + + if (!imod->name || !imod->value) + goto memerr; + + /* Try to initialize module */ + if(pmod->init) + { + ret = pmod->init(imod, cnf); + init_called = 1; + /* Error occurred, exit */ + if (ret <= 0) + goto err; + } + + if (initialized_modules == NULL) + { + initialized_modules = sk_CONF_IMODULE_new_null(); + if (!initialized_modules) + { + CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (!sk_CONF_IMODULE_push(initialized_modules, imod)) + { + CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + pmod->links++; + + return ret; + + err: + + /* We've started the module so we'd better finish it */ + if (pmod->finish && init_called) + pmod->finish(imod); + + memerr: + if (imod) + { + if (imod->name) + OPENSSL_free(imod->name); + if (imod->value) + OPENSSL_free(imod->value); + OPENSSL_free(imod); + } + + return -1; + + } + +/* Unload any dynamic modules that have a link count of zero: + * i.e. have no active initialized modules. If 'all' is set + * then all modules are unloaded including static ones. + */ + +void CONF_modules_unload(int all) + { + int i; + CONF_MODULE *md; + CONF_modules_finish(); + /* unload modules in reverse order */ + for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) + { + md = sk_CONF_MODULE_value(supported_modules, i); + /* If static or in use and 'all' not set ignore it */ + if (((md->links > 0) || !md->dso) && !all) + continue; + /* Since we're working in reverse this is OK */ + sk_CONF_MODULE_delete(supported_modules, i); + module_free(md); + } + if (sk_CONF_MODULE_num(supported_modules) == 0) + { + sk_CONF_MODULE_free(supported_modules); + supported_modules = NULL; + } + } + +/* unload a single module */ +static void module_free(CONF_MODULE *md) + { + if (md->dso) + DSO_free(md->dso); + OPENSSL_free(md->name); + OPENSSL_free(md); + } + +/* finish and free up all modules instances */ + +void CONF_modules_finish(void) + { + CONF_IMODULE *imod; + while (sk_CONF_IMODULE_num(initialized_modules) > 0) + { + imod = sk_CONF_IMODULE_pop(initialized_modules); + module_finish(imod); + } + sk_CONF_IMODULE_free(initialized_modules); + initialized_modules = NULL; + } + +/* finish a module instance */ + +static void module_finish(CONF_IMODULE *imod) + { + if (imod->pmod->finish) + imod->pmod->finish(imod); + imod->pmod->links--; + OPENSSL_free(imod->name); + OPENSSL_free(imod->value); + OPENSSL_free(imod); + } + +/* Add a static module to OpenSSL */ + +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc) + { + if (module_add(NULL, name, ifunc, ffunc)) + return 1; + else + return 0; + } + +void CONF_modules_free(void) + { + CONF_modules_finish(); + CONF_modules_unload(1); + } + +/* Utility functions */ + +const char *CONF_imodule_get_name(const CONF_IMODULE *md) + { + return md->name; + } + +const char *CONF_imodule_get_value(const CONF_IMODULE *md) + { + return md->value; + } + +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md) + { + return md->usr_data; + } + +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data) + { + md->usr_data = usr_data; + } + +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md) + { + return md->pmod; + } + +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md) + { + return md->flags; + } + +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags) + { + md->flags = flags; + } + +void *CONF_module_get_usr_data(CONF_MODULE *pmod) + { + return pmod->usr_data; + } + +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data) + { + pmod->usr_data = usr_data; + } + +/* Return default config file name */ + +char *CONF_get1_default_config_file(void) + { + char *file; + int len; + + file = getenv("OPENSSL_CONF"); + if (file) + return BUF_strdup(file); + + len = strlen(X509_get_default_cert_area()); +#ifndef OPENSSL_SYS_VMS + len++; +#endif + len += strlen(OPENSSL_CONF); + + file = OPENSSL_malloc(len + 1); + + if (!file) + return NULL; + strcpy(file,X509_get_default_cert_area()); +#ifndef OPENSSL_SYS_VMS + strcat(file,"/"); +#endif + strcat(file,OPENSSL_CONF); + + return file; + } + +/* This function takes a list separated by 'sep' and calls the + * callback function giving the start and length of each member + * optionally stripping leading and trailing whitespace. This can + * be used to parse comma separated lists for example. + */ + +int CONF_parse_list(const char *list, int sep, int nospc, + int (*list_cb)(const char *elem, int len, void *usr), void *arg) + { + int ret; + const char *lstart, *tmpend, *p; + lstart = list; + + for(;;) + { + if (nospc) + { + while(*lstart && isspace((unsigned char)*lstart)) + lstart++; + } + p = strchr(lstart, sep); + if (p == lstart || !*lstart) + ret = list_cb(NULL, 0, arg); + else + { + if (p) + tmpend = p - 1; + else + tmpend = lstart + strlen(lstart) - 1; + if (nospc) + { + while(isspace((unsigned char)*tmpend)) + tmpend--; + } + ret = list_cb(lstart, tmpend - lstart + 1, arg); + } + if (ret <= 0) + return ret; + if (p == NULL) + return 1; + lstart = p + 1; + } + } + diff --git a/src/lib/libcrypto/conf/conf_sap.c b/src/lib/libcrypto/conf/conf_sap.c new file mode 100644 index 0000000000..97fb174303 --- /dev/null +++ b/src/lib/libcrypto/conf/conf_sap.c @@ -0,0 +1,107 @@ +/* conf_sap.c */ +/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include "cryptlib.h" +#include +#include +#include +#include +#include + +/* This is the automatic configuration loader: it is called automatically by + * OpenSSL when any of a number of standard initialisation functions are called, + * unless this is overridden by calling OPENSSL_no_config() + */ + +static int openssl_configured = 0; + +void OPENSSL_config(const char *config_name) + { + if (openssl_configured) + return; + + OPENSSL_load_builtin_modules(); + /* Need to load ENGINEs */ + ENGINE_load_builtin_engines(); + /* Add others here? */ + + + ERR_clear_error(); + if (CONF_modules_load_file(NULL, NULL, + CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) + { + BIO *bio_err; + ERR_load_crypto_strings(); + if ((bio_err=BIO_new_fp(stderr, BIO_NOCLOSE)) != NULL) + { + BIO_printf(bio_err,"Auto configuration failed\n"); + ERR_print_errors(bio_err); + BIO_free(bio_err); + } + exit(1); + } + + return; + } + +void OPENSSL_no_config() + { + openssl_configured = 1; + } diff --git a/src/lib/libcrypto/des/des.h b/src/lib/libcrypto/des/des.h new file mode 100644 index 0000000000..67f90aaf17 --- /dev/null +++ b/src/lib/libcrypto/des/des.h @@ -0,0 +1,249 @@ +/* crypto/des/des.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_DES_H +#define HEADER_DES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_DES +#error DES is disabled. +#endif + +#ifdef _KERBEROS_DES_H +#error replaces . +#endif + +#include +#include /* DES_LONG */ +#include /* OPENSSL_EXTERN */ + +typedef unsigned char des_cblock[8]; +typedef /* const */ unsigned char const_des_cblock[8]; +/* With "const", gcc 2.8.1 on Solaris thinks that des_cblock * + * and const_des_cblock * are incompatible pointer types. + * I haven't seen that warning on other systems ... I'll look + * what the standard says. */ + + +typedef struct des_ks_struct + { + union { + des_cblock cblock; + /* make sure things are correct size on machines with + * 8 byte longs */ + DES_LONG deslong[2]; + } ks; + int weak_key; + } des_key_schedule[16]; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +#define des_ecb2_encrypt(i,o,k1,k2,e) \ + des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +OPENSSL_EXTERN int des_check_key; /* defaults to false */ +OPENSSL_EXTERN int des_rw_mode; /* defaults to DES_PCBC_MODE */ +OPENSSL_EXTERN int des_set_weak_key_flag; /* set the weak key flag */ + +const char *des_options(void); +void des_ecb3_encrypt(const_des_cblock *input, des_cblock *output, + des_key_schedule ks1,des_key_schedule ks2, + des_key_schedule ks3, int enc); +DES_LONG des_cbc_cksum(const unsigned char *input,des_cblock *output, + long length,des_key_schedule schedule, + const_des_cblock *ivec); +/* des_cbc_encrypt does not update the IV! Use des_ncbc_encrypt instead. */ +void des_cbc_encrypt(const unsigned char *input,unsigned char *output, + long length,des_key_schedule schedule,des_cblock *ivec, + int enc); +void des_ncbc_encrypt(const unsigned char *input,unsigned char *output, + long length,des_key_schedule schedule,des_cblock *ivec, + int enc); +void des_xcbc_encrypt(const unsigned char *input,unsigned char *output, + long length,des_key_schedule schedule,des_cblock *ivec, + const_des_cblock *inw,const_des_cblock *outw,int enc); +void des_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits, + long length,des_key_schedule schedule,des_cblock *ivec, + int enc); +void des_ecb_encrypt(const_des_cblock *input,des_cblock *output, + des_key_schedule ks,int enc); +void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); +void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); +void des_encrypt3(DES_LONG *data, des_key_schedule ks1, + des_key_schedule ks2, des_key_schedule ks3); +void des_decrypt3(DES_LONG *data, des_key_schedule ks1, + des_key_schedule ks2, des_key_schedule ks3); +void des_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output, + long length, + des_key_schedule ks1,des_key_schedule ks2, + des_key_schedule ks3,des_cblock *ivec,int enc); +void des_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out, + long length, + des_key_schedule ks1,des_key_schedule ks2, + des_key_schedule ks3, + des_cblock *ivec1,des_cblock *ivec2, + int enc); +void des_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out, + long length,des_key_schedule ks1, + des_key_schedule ks2,des_key_schedule ks3, + des_cblock *ivec,int *num,int enc); +void des_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out, + long length,des_key_schedule ks1, + des_key_schedule ks2,des_key_schedule ks3, + des_cblock *ivec,int *num); + +void des_xwhite_in2out(const_des_cblock *des_key,const_des_cblock *in_white, + des_cblock *out_white); + +int des_enc_read(int fd,void *buf,int len,des_key_schedule sched, + des_cblock *iv); +int des_enc_write(int fd,const void *buf,int len,des_key_schedule sched, + des_cblock *iv); +char *des_fcrypt(const char *buf,const char *salt, char *ret); +char *des_crypt(const char *buf,const char *salt); +#if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) +char *crypt(const char *buf,const char *salt); +#endif +void des_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits, + long length,des_key_schedule schedule,des_cblock *ivec); +void des_pcbc_encrypt(const unsigned char *input,unsigned char *output, + long length,des_key_schedule schedule,des_cblock *ivec, + int enc); +DES_LONG des_quad_cksum(const unsigned char *input,des_cblock output[], + long length,int out_count,des_cblock *seed); +void des_random_seed(des_cblock *key); +void des_random_key(des_cblock *ret); +int des_read_password(des_cblock *key,const char *prompt,int verify); +int des_read_2passwords(des_cblock *key1,des_cblock *key2, + const char *prompt,int verify); +int des_read_pw_string(char *buf,int length,const char *prompt,int verify); +void des_set_odd_parity(des_cblock *key); +int des_is_weak_key(const_des_cblock *key); +int des_set_key(const_des_cblock *key,des_key_schedule schedule); +int des_key_sched(const_des_cblock *key,des_key_schedule schedule); +void des_string_to_key(const char *str,des_cblock *key); +void des_string_to_2keys(const char *str,des_cblock *key1,des_cblock *key2); +void des_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length, + des_key_schedule schedule,des_cblock *ivec,int *num, + int enc); +void des_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length, + des_key_schedule schedule,des_cblock *ivec,int *num); +int des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify); + +/* Extra functions from Mark Murray */ +void des_cblock_print_file(const_des_cblock *cb, FILE *fp); + +/* The following definitions provide compatibility with the MIT Kerberos + * library. The des_key_schedule structure is not binary compatible. */ + +#define _KERBEROS_DES_H + +#define KRBDES_ENCRYPT DES_ENCRYPT +#define KRBDES_DECRYPT DES_DECRYPT + +#ifdef KERBEROS +# define ENCRYPT DES_ENCRYPT +# define DECRYPT DES_DECRYPT +#endif + +#ifndef NCOMPAT +# define C_Block des_cblock +# define Key_schedule des_key_schedule +# define KEY_SZ DES_KEY_SZ +# define string_to_key des_string_to_key +# define read_pw_string des_read_pw_string +# define random_key des_random_key +# define pcbc_encrypt des_pcbc_encrypt +# define set_key des_set_key +# define key_sched des_key_sched +# define ecb_encrypt des_ecb_encrypt +# define cbc_encrypt des_cbc_encrypt +# define ncbc_encrypt des_ncbc_encrypt +# define xcbc_encrypt des_xcbc_encrypt +# define cbc_cksum des_cbc_cksum +# define quad_cksum des_quad_cksum +#endif + +typedef des_key_schedule bit_64; +#define des_fixup_key_parity des_set_odd_parity +#define des_check_key_parity check_parity + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/libcrypto/des/des_locl.h b/src/lib/libcrypto/des/des_locl.h new file mode 100644 index 0000000000..d6ea17cb68 --- /dev/null +++ b/src/lib/libcrypto/des/des_locl.h @@ -0,0 +1,408 @@ +/* crypto/des/des_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_DES_LOCL_H +#define HEADER_DES_LOCL_H + +#if defined(WIN32) || defined(WIN16) +#ifndef MSDOS +#define MSDOS +#endif +#endif + +#include +#include + +#include + +#ifndef MSDOS +#if !defined(VMS) || defined(__DECC) +#include OPENSSL_UNISTD +#include +#endif +#endif +#include + +#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ +#include +#include +#include +#include +#endif + +#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) +#include +#endif + +#define ITERATIONS 16 +#define HALF_ITERATIONS 8 + +/* used in des_read and des_write */ +#define MAXWRITE (1024*16) +#define BSIZE (MAXWRITE+4) + +#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ + case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ + case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ + case 5: l2|=((DES_LONG)(*(--(c)))); \ + case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ + case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ + case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ + case 1: l1|=((DES_LONG)(*(--(c)))); \ + } \ + } + +#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)) + +/* replacements for htonl and ntohl since I have no idea what to do + * when faced with machines with 8 byte longs. */ +#define HDRSIZE 4 + +#define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))) + +#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)) + +/* NOTE - c is not incremented as per l2c */ +#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); \ + } \ + } + +#if defined(WIN32) +#define ROTATE(a,n) (_lrotr(a,n)) +#else +#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) +#endif + +/* Don't worry about the LOAD_DATA() stuff, that is used by + * fcrypt() to add it's little bit to the front */ + +#ifdef DES_FCRYPT + +#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ + { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } + +#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + t=R^(R>>16L); \ + u=t&E0; t&=E1; \ + tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ + tmp=(t<<16); t^=R^s[S+1]; t^=tmp +#else +#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) +#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + u=R^s[S ]; \ + t=R^s[S+1] +#endif + +/* The changes to this macro may help or hinder, depending on the + * compiler and the achitecture. gcc2 always seems to do well :-). + * Inspired by Dana How + * DO NOT use the alternative version on machines with 8 byte longs. + * It does not seem to work on the Alpha, even when DES_LONG is 4 + * bytes, probably an issue of accessing non-word aligned objects :-( */ +#ifdef DES_PTR + +/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there + * is no reason to not xor all the sub items together. This potentially + * saves a register since things can be xored directly into L */ + +#if defined(DES_RISC1) || defined(DES_RISC2) +#ifdef DES_RISC1 +#define D_ENCRYPT(LL,R,S) { \ + unsigned int u1,u2,u3; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u2=(int)u>>8L; \ + u1=(int)u&0xfc; \ + u2&=0xfc; \ + t=ROTATE(t,4); \ + u>>=16L; \ + LL^= *(const DES_LONG *)(des_SP +u1); \ + LL^= *(const DES_LONG *)(des_SP+0x200+u2); \ + u3=(int)(u>>8L); \ + u1=(int)u&0xfc; \ + u3&=0xfc; \ + LL^= *(const DES_LONG *)(des_SP+0x400+u1); \ + LL^= *(const DES_LONG *)(des_SP+0x600+u3); \ + u2=(int)t>>8L; \ + u1=(int)t&0xfc; \ + u2&=0xfc; \ + t>>=16L; \ + LL^= *(const DES_LONG *)(des_SP+0x100+u1); \ + LL^= *(const DES_LONG *)(des_SP+0x300+u2); \ + u3=(int)t>>8L; \ + u1=(int)t&0xfc; \ + u3&=0xfc; \ + LL^= *(const DES_LONG *)(des_SP+0x500+u1); \ + LL^= *(const DES_LONG *)(des_SP+0x700+u3); } +#endif +#ifdef DES_RISC2 +#define D_ENCRYPT(LL,R,S) { \ + unsigned int u1,u2,s1,s2; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u2=(int)u>>8L; \ + u1=(int)u&0xfc; \ + u2&=0xfc; \ + t=ROTATE(t,4); \ + LL^= *(const DES_LONG *)(des_SP +u1); \ + LL^= *(const DES_LONG *)(des_SP+0x200+u2); \ + s1=(int)(u>>16L); \ + s2=(int)(u>>24L); \ + s1&=0xfc; \ + s2&=0xfc; \ + LL^= *(const DES_LONG *)(des_SP+0x400+s1); \ + LL^= *(const DES_LONG *)(des_SP+0x600+s2); \ + u2=(int)t>>8L; \ + u1=(int)t&0xfc; \ + u2&=0xfc; \ + LL^= *(const DES_LONG *)(des_SP+0x100+u1); \ + LL^= *(const DES_LONG *)(des_SP+0x300+u2); \ + s1=(int)(t>>16L); \ + s2=(int)(t>>24L); \ + s1&=0xfc; \ + s2&=0xfc; \ + LL^= *(const DES_LONG *)(des_SP+0x500+s1); \ + LL^= *(const DES_LONG *)(des_SP+0x700+s2); } +#endif +#else +#define D_ENCRYPT(LL,R,S) { \ + LOAD_DATA_tmp(R,S,u,t,E0,E1); \ + t=ROTATE(t,4); \ + LL^= \ + *(const DES_LONG *)(des_SP +((u )&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x200+((u>> 8L)&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x400+((u>>16L)&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x600+((u>>24L)&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x100+((t )&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x300+((t>> 8L)&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x500+((t>>16L)&0xfc))^ \ + *(const DES_LONG *)(des_SP+0x700+((t>>24L)&0xfc)); } +#endif + +#else /* original version */ + +#if defined(DES_RISC1) || defined(DES_RISC2) +#ifdef DES_RISC1 +#define D_ENCRYPT(LL,R,S) {\ + unsigned int u1,u2,u3; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u>>=2L; \ + t=ROTATE(t,6); \ + u2=(int)u>>8L; \ + u1=(int)u&0x3f; \ + u2&=0x3f; \ + u>>=16L; \ + LL^=des_SPtrans[0][u1]; \ + LL^=des_SPtrans[2][u2]; \ + u3=(int)u>>8L; \ + u1=(int)u&0x3f; \ + u3&=0x3f; \ + LL^=des_SPtrans[4][u1]; \ + LL^=des_SPtrans[6][u3]; \ + u2=(int)t>>8L; \ + u1=(int)t&0x3f; \ + u2&=0x3f; \ + t>>=16L; \ + LL^=des_SPtrans[1][u1]; \ + LL^=des_SPtrans[3][u2]; \ + u3=(int)t>>8L; \ + u1=(int)t&0x3f; \ + u3&=0x3f; \ + LL^=des_SPtrans[5][u1]; \ + LL^=des_SPtrans[7][u3]; } +#endif +#ifdef DES_RISC2 +#define D_ENCRYPT(LL,R,S) {\ + unsigned int u1,u2,s1,s2; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u>>=2L; \ + t=ROTATE(t,6); \ + u2=(int)u>>8L; \ + u1=(int)u&0x3f; \ + u2&=0x3f; \ + LL^=des_SPtrans[0][u1]; \ + LL^=des_SPtrans[2][u2]; \ + s1=(int)u>>16L; \ + s2=(int)u>>24L; \ + s1&=0x3f; \ + s2&=0x3f; \ + LL^=des_SPtrans[4][s1]; \ + LL^=des_SPtrans[6][s2]; \ + u2=(int)t>>8L; \ + u1=(int)t&0x3f; \ + u2&=0x3f; \ + LL^=des_SPtrans[1][u1]; \ + LL^=des_SPtrans[3][u2]; \ + s1=(int)t>>16; \ + s2=(int)t>>24L; \ + s1&=0x3f; \ + s2&=0x3f; \ + LL^=des_SPtrans[5][s1]; \ + LL^=des_SPtrans[7][s2]; } +#endif + +#else + +#define D_ENCRYPT(LL,R,S) {\ + LOAD_DATA_tmp(R,S,u,t,E0,E1); \ + t=ROTATE(t,4); \ + LL^=\ + des_SPtrans[0][(u>> 2L)&0x3f]^ \ + des_SPtrans[2][(u>>10L)&0x3f]^ \ + des_SPtrans[4][(u>>18L)&0x3f]^ \ + des_SPtrans[6][(u>>26L)&0x3f]^ \ + des_SPtrans[1][(t>> 2L)&0x3f]^ \ + des_SPtrans[3][(t>>10L)&0x3f]^ \ + des_SPtrans[5][(t>>18L)&0x3f]^ \ + des_SPtrans[7][(t>>26L)&0x3f]; } +#endif +#endif + + /* IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + + 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + + The output has been subject to swaps of the form + 0 1 -> 3 1 but the odd and even bits have been put into + 2 3 2 0 + different words. The main trick is to remember that + t=((l>>size)^r)&(mask); + r^=t; + l^=(t<>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +#define IP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ + PERM_OP(l,r,tt,16,0x0000ffffL); \ + PERM_OP(r,l,tt, 2,0x33333333L); \ + PERM_OP(l,r,tt, 8,0x00ff00ffL); \ + PERM_OP(r,l,tt, 1,0x55555555L); \ + } + +#define FP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(l,r,tt, 1,0x55555555L); \ + PERM_OP(r,l,tt, 8,0x00ff00ffL); \ + PERM_OP(l,r,tt, 2,0x33333333L); \ + PERM_OP(r,l,tt,16,0x0000ffffL); \ + PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ + } + +OPENSSL_EXTERN const DES_LONG des_SPtrans[8][64]; + +void fcrypt_body(DES_LONG *out,des_key_schedule ks, + DES_LONG Eswap0, DES_LONG Eswap1); +#endif diff --git a/src/lib/libcrypto/des/ede_cbcm_enc.c b/src/lib/libcrypto/des/ede_cbcm_enc.c new file mode 100644 index 0000000000..c53062481d --- /dev/null +++ b/src/lib/libcrypto/des/ede_cbcm_enc.c @@ -0,0 +1,197 @@ +/* ede_cbcm_enc.c */ +/* Written by Ben Laurie for the OpenSSL + * project 13 Feb 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). + * + */ + +/* + +This is an implementation of Triple DES Cipher Block Chaining with Output +Feedback Masking, by Coppersmith, Johnson and Matyas, (IBM and Certicom). + +Note that there is a known attack on this by Biham and Knudsen but it takes +a lot of work: + +http://www.cs.technion.ac.il/users/wwwb/cgi-bin/tr-get.cgi/1998/CS/CS0928.ps.gz + +*/ + +#ifndef NO_DESCBCM +#include "des_locl.h" + +void des_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, + long length, des_key_schedule ks1, des_key_schedule ks2, + des_key_schedule ks3, des_cblock *ivec1, des_cblock *ivec2, + int enc) + { + register DES_LONG tin0,tin1; + register DES_LONG tout0,tout1,xor0,xor1,m0,m1; + register long l=length; + DES_LONG tin[2]; + unsigned char *iv1,*iv2; + + iv1 = &(*ivec1)[0]; + iv2 = &(*ivec2)[0]; + + if (enc) + { + c2l(iv1,m0); + c2l(iv1,m1); + c2l(iv2,tout0); + c2l(iv2,tout1); + for (l-=8; l>=-7; l-=8) + { + tin[0]=m0; + tin[1]=m1; + des_encrypt(tin,ks3,1); + m0=tin[0]; + m1=tin[1]; + + if(l < 0) + { + c2ln(in,tin0,tin1,l+8); + } + else + { + c2l(in,tin0); + c2l(in,tin1); + } + tin0^=tout0; + tin1^=tout1; + + tin[0]=tin0; + tin[1]=tin1; + des_encrypt(tin,ks1,1); + tin[0]^=m0; + tin[1]^=m1; + des_encrypt(tin,ks2,0); + tin[0]^=m0; + tin[1]^=m1; + des_encrypt(tin,ks1,1); + tout0=tin[0]; + tout1=tin[1]; + + l2c(tout0,out); + l2c(tout1,out); + } + iv1=&(*ivec1)[0]; + l2c(m0,iv1); + l2c(m1,iv1); + + iv2=&(*ivec2)[0]; + l2c(tout0,iv2); + l2c(tout1,iv2); + } + else + { + register DES_LONG t0,t1; + + c2l(iv1,m0); + c2l(iv1,m1); + c2l(iv2,xor0); + c2l(iv2,xor1); + for (l-=8; l>=-7; l-=8) + { + tin[0]=m0; + tin[1]=m1; + des_encrypt(tin,ks3,1); + m0=tin[0]; + m1=tin[1]; + + c2l(in,tin0); + c2l(in,tin1); + + t0=tin0; + t1=tin1; + + tin[0]=tin0; + tin[1]=tin1; + des_encrypt(tin,ks1,0); + tin[0]^=m0; + tin[1]^=m1; + des_encrypt(tin,ks2,1); + tin[0]^=m0; + tin[1]^=m1; + des_encrypt(tin,ks1,0); + tout0=tin[0]; + tout1=tin[1]; + + tout0^=xor0; + tout1^=xor1; + if(l < 0) + { + l2cn(tout0,tout1,out,l+8); + } + else + { + l2c(tout0,out); + l2c(tout1,out); + } + xor0=t0; + xor1=t1; + } + + iv1=&(*ivec1)[0]; + l2c(m0,iv1); + l2c(m1,iv1); + + iv2=&(*ivec2)[0]; + l2c(xor0,iv2); + l2c(xor1,iv2); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } +#endif diff --git a/src/lib/libcrypto/dh/dh_asn1.c b/src/lib/libcrypto/dh/dh_asn1.c new file mode 100644 index 0000000000..769b5b68c5 --- /dev/null +++ b/src/lib/libcrypto/dh/dh_asn1.c @@ -0,0 +1,87 @@ +/* dh_asn1.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include + +/* Override the default free and new methods */ +static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if(operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)DH_new(); + if(*pval) return 2; + return 0; + } else if(operation == ASN1_OP_FREE_PRE) { + DH_free((DH *)*pval); + *pval = NULL; + return 2; + } + return 1; +} + +ASN1_SEQUENCE_cb(DHparams, dh_cb) = { + ASN1_SIMPLE(DH, p, BIGNUM), + ASN1_SIMPLE(DH, g, BIGNUM), + ASN1_OPT(DH, length, ZLONG), +} ASN1_SEQUENCE_END_cb(DH, DHparams) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams) diff --git a/src/lib/libcrypto/doc/DH_generate_key.pod b/src/lib/libcrypto/doc/DH_generate_key.pod new file mode 100644 index 0000000000..920995b2e5 --- /dev/null +++ b/src/lib/libcrypto/doc/DH_generate_key.pod @@ -0,0 +1,50 @@ +=pod + +=head1 NAME + +DH_generate_key, DH_compute_key - perform Diffie-Hellman key exchange + +=head1 SYNOPSIS + + #include + + int DH_generate_key(DH *dh); + + int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh); + +=head1 DESCRIPTION + +DH_generate_key() performs the first step of a Diffie-Hellman key +exchange by generating private and public DH values. By calling +DH_compute_key(), these are combined with the other party's public +value to compute the shared key. + +DH_generate_key() expects B to contain the shared parameters +Bp> and Bg>. It generates a random private DH value +unless Bpriv_key> is already set, and computes the +corresponding public value Bpub_key>, which can then be +published. + +DH_compute_key() computes the shared secret from the private DH value +in B and the other party's public value in B and stores +it in B. B must point to B bytes of memory. + +=head1 RETURN VALUES + +DH_generate_key() returns 1 on success, 0 otherwise. + +DH_compute_key() returns the size of the shared secret on success, -1 +on error. + +The error codes can be obtained by L. + +=head1 SEE ALSO + +L, L, L, L + +=head1 HISTORY + +DH_generate_key() and DH_compute_key() are available in all versions +of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/DH_generate_parameters.pod b/src/lib/libcrypto/doc/DH_generate_parameters.pod new file mode 100644 index 0000000000..a7d0c75f0c --- /dev/null +++ b/src/lib/libcrypto/doc/DH_generate_parameters.pod @@ -0,0 +1,72 @@ +=pod + +=head1 NAME + +DH_generate_parameters, DH_check - generate and check Diffie-Hellman parameters + +=head1 SYNOPSIS + + #include + + DH *DH_generate_parameters(int prime_len, int generator, + void (*callback)(int, int, void *), void *cb_arg); + + int DH_check(DH *dh, int *codes); + +=head1 DESCRIPTION + +DH_generate_parameters() generates Diffie-Hellman parameters that can +be shared among a group of users, and returns them in a newly +allocated B structure. The pseudo-random number generator must be +seeded prior to calling DH_generate_parameters(). + +B is the length in bits of the safe prime to be generated. +B is a small number E 1, typically 2 or 5. + +A callback function may be used to provide feedback about the progress +of the key generation. If B is not B, it will be +called as described in L while a random prime +number is generated, and when a prime has been found, B is called. + +DH_check() validates Diffie-Hellman parameters. It checks that B

is +a safe prime, and that B is a suitable generator. In the case of an +error, the bit flags DH_CHECK_P_NOT_SAFE_PRIME or +DH_NOT_SUITABLE_GENERATOR are set in B<*codes>. +DH_UNABLE_TO_CHECK_GENERATOR is set if the generator cannot be +checked, i.e. it does not equal 2 or 5. + +=head1 RETURN VALUES + +DH_generate_parameters() returns a pointer to the DH structure, or +NULL if the parameter generation fails. The error codes can be +obtained by L. + +DH_check() returns 1 if the check could be performed, 0 otherwise. + +=head1 NOTES + +DH_generate_parameters() may run for several hours before finding a +suitable prime. + +The parameters generated by DH_generate_parameters() are not to be +used in signature schemes. + +=head1 BUGS + +If B is not 2 or 5, Bg>=B is not +a usable generator. + +=head1 SEE ALSO + +L, L, L, L + +=head1 HISTORY + +DH_check() is available in all versions of SSLeay and OpenSSL. +The B argument to DH_generate_parameters() was added in SSLeay 0.9.0. + +In versions before OpenSSL 0.9.5, DH_CHECK_P_NOT_STRONG_PRIME is used +instead of DH_CHECK_P_NOT_SAFE_PRIME. + +=cut diff --git a/src/lib/libcrypto/doc/DH_get_ex_new_index.pod b/src/lib/libcrypto/doc/DH_get_ex_new_index.pod new file mode 100644 index 0000000000..82e2548bcd --- /dev/null +++ b/src/lib/libcrypto/doc/DH_get_ex_new_index.pod @@ -0,0 +1,36 @@ +=pod + +=head1 NAME + +DH_get_ex_new_index, DH_set_ex_data, DH_get_ex_data - add application specific data to DH structures + +=head1 SYNOPSIS + + #include + + 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); + + char *DH_get_ex_data(DH *d, int idx); + +=head1 DESCRIPTION + +These functions handle application specific data in DH +structures. Their usage is identical to that of +RSA_get_ex_new_index(), RSA_set_ex_data() and RSA_get_ex_data() +as described in L. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +DH_get_ex_new_index(), DH_set_ex_data() and DH_get_ex_data() are +available since OpenSSL 0.9.5. + +=cut diff --git a/src/lib/libcrypto/doc/DH_new.pod b/src/lib/libcrypto/doc/DH_new.pod new file mode 100644 index 0000000000..64624b9d15 --- /dev/null +++ b/src/lib/libcrypto/doc/DH_new.pod @@ -0,0 +1,40 @@ +=pod + +=head1 NAME + +DH_new, DH_free - allocate and free DH objects + +=head1 SYNOPSIS + + #include + + DH* DH_new(void); + + void DH_free(DH *dh); + +=head1 DESCRIPTION + +DH_new() allocates and initializes a B structure. + +DH_free() frees the B structure and its components. The values are +erased before the memory is returned to the system. + +=head1 RETURN VALUES + +If the allocation fails, DH_new() returns B and sets an error +code that can be obtained by L. Otherwise it returns +a pointer to the newly allocated structure. + +DH_free() returns no value. + +=head1 SEE ALSO + +L, L, +L, +L + +=head1 HISTORY + +DH_new() and DH_free() are available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/DH_set_method.pod b/src/lib/libcrypto/doc/DH_set_method.pod new file mode 100644 index 0000000000..dca41d8dbc --- /dev/null +++ b/src/lib/libcrypto/doc/DH_set_method.pod @@ -0,0 +1,99 @@ +=pod + +=head1 NAME + +DH_set_default_method, DH_get_default_method, DH_set_method, +DH_new_method, DH_OpenSSL - select DH method + +=head1 SYNOPSIS + + #include + + 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_METHOD *DH_OpenSSL(void); + +=head1 DESCRIPTION + +A B specifies the functions that OpenSSL uses for Diffie-Hellman +operations. By modifying the method, alternative implementations +such as hardware accelerators may be used. + +Initially, the default is to use the OpenSSL internal implementation. +DH_OpenSSL() returns a pointer to that method. + +DH_set_default_method() makes B the default method for all B +structures created later. + +DH_get_default_method() returns a pointer to the current default +method. + +DH_set_method() selects B for all operations using the structure B. + +DH_get_method() returns a pointer to the method currently selected +for B. + +DH_new_method() allocates and initializes a B structure so that +B will be used for the DH operations. If B is B, +the default method is used. + +=head1 THE DH_METHOD STRUCTURE + + typedef struct dh_meth_st + { + /* name of the implementation */ + const char *name; + + /* generate private and public DH values for key agreement */ + int (*generate_key)(DH *dh); + + /* compute shared secret */ + int (*compute_key)(unsigned char *key, BIGNUM *pub_key, DH *dh); + + /* compute r = a ^ p mod m. May be NULL */ + int (*bn_mod_exp)(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + + /* called at DH_new */ + int (*init)(DH *dh); + + /* called at DH_free */ + int (*finish)(DH *dh); + + int flags; + + char *app_data; /* ?? */ + + } DH_METHOD; + +=head1 RETURN VALUES + +DH_OpenSSL(), DH_get_default_method() and DH_get_method() return +pointers to the respective Bs. + +DH_set_default_method() returns no value. + +DH_set_method() returns a pointer to the B previously +associated with B. + +DH_new_method() returns B and sets an error code that can be +obtained by L if the allocation fails. Otherwise it +returns a pointer to the newly allocated structure. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +DH_set_default_method(), DH_get_default_method(), DH_set_method(), +DH_new_method() and DH_OpenSSL() were added in OpenSSL 0.9.4. + +=cut diff --git a/src/lib/libcrypto/doc/DH_size.pod b/src/lib/libcrypto/doc/DH_size.pod new file mode 100644 index 0000000000..97f26fda78 --- /dev/null +++ b/src/lib/libcrypto/doc/DH_size.pod @@ -0,0 +1,33 @@ +=pod + +=head1 NAME + +DH_size - get Diffie-Hellman prime size + +=head1 SYNOPSIS + + #include + + int DH_size(DH *dh); + +=head1 DESCRIPTION + +This function returns the Diffie-Hellman size in bytes. It can be used +to determine how much memory must be allocated for the shared secret +computed by DH_compute_key(). + +Bp> must not be B. + +=head1 RETURN VALUE + +The size in bytes. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +DH_size() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_SIG_new.pod b/src/lib/libcrypto/doc/DSA_SIG_new.pod new file mode 100644 index 0000000000..671655554a --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_SIG_new.pod @@ -0,0 +1,39 @@ +=pod + +=head1 NAME + +DSA_SIG_new, DSA_SIG_free - allocate and free DSA signature objects + +=head1 SYNOPSIS + + #include + + DSA_SIG *DSA_SIG_new(void); + + void DSA_SIG_free(DSA_SIG *a); + +=head1 DESCRIPTION + +DSA_SIG_new() allocates and initializes a B structure. + +DSA_SIG_free() frees the B structure and its components. The +values are erased before the memory is returned to the system. + +=head1 RETURN VALUES + +If the allocation fails, DSA_SIG_new() returns B and sets an +error code that can be obtained by +L. Otherwise it returns a pointer +to the newly allocated structure. + +DSA_SIG_free() returns no value. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +DSA_SIG_new() and DSA_SIG_free() were added in OpenSSL 0.9.3. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_do_sign.pod b/src/lib/libcrypto/doc/DSA_do_sign.pod new file mode 100644 index 0000000000..a24fd5714e --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_do_sign.pod @@ -0,0 +1,47 @@ +=pod + +=head1 NAME + +DSA_do_sign, DSA_do_verify - raw DSA signature operations + +=head1 SYNOPSIS + + #include + + 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); + +=head1 DESCRIPTION + +DSA_do_sign() computes a digital signature on the B byte message +digest B using the private key B and returns it in a +newly allocated B structure. + +L may be used to precompute part +of the signing operation in case signature generation is +time-critical. + +DSA_do_verify() verifies that the signature B matches a given +message digest B of size B. B is the signer's public +key. + +=head1 RETURN VALUES + +DSA_do_sign() returns the signature, NULL on error. DSA_do_verify() +returns 1 for a valid signature, 0 for an incorrect signature and -1 +on error. The error codes can be obtained by +L. + +=head1 SEE ALSO + +L, L, L, +L, +L + +=head1 HISTORY + +DSA_do_sign() and DSA_do_verify() were added in OpenSSL 0.9.3. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_dup_DH.pod b/src/lib/libcrypto/doc/DSA_dup_DH.pod new file mode 100644 index 0000000000..29cb1075d1 --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_dup_DH.pod @@ -0,0 +1,36 @@ +=pod + +=head1 NAME + +DSA_dup_DH - create a DH structure out of DSA structure + +=head1 SYNOPSIS + + #include + + DH * DSA_dup_DH(DSA *r); + +=head1 DESCRIPTION + +DSA_dup_DH() duplicates DSA parameters/keys as DH parameters/keys. q +is lost during that conversion, but the resulting DH parameters +contain its length. + +=head1 RETURN VALUE + +DSA_dup_DH() returns the new B structure, and NULL on error. The +error codes can be obtained by L. + +=head1 NOTE + +Be careful to avoid small subgroup attacks when using this. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +DSA_dup_DH() was added in OpenSSL 0.9.4. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_generate_key.pod b/src/lib/libcrypto/doc/DSA_generate_key.pod new file mode 100644 index 0000000000..52890db5be --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_generate_key.pod @@ -0,0 +1,33 @@ +=pod + +=head1 NAME + +DSA_generate_key - generate DSA key pair + +=head1 SYNOPSIS + + #include + + int DSA_generate_key(DSA *a); + +=head1 DESCRIPTION + +DSA_generate_key() expects B to contain DSA parameters. It generates +a new key pair and stores it in Bpub_key> and Bpriv_key>. + +The PRNG must be seeded prior to calling DSA_generate_key(). + +=head1 RETURN VALUE + +DSA_generate_key() returns 1 on success, 0 otherwise. +The error codes can be obtained by L. + +=head1 SEE ALSO + +L, L, L, L + +=head1 HISTORY + +DSA_generate_key() is available since SSLeay 0.8. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_generate_parameters.pod b/src/lib/libcrypto/doc/DSA_generate_parameters.pod new file mode 100644 index 0000000000..43f60b0eb9 --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_generate_parameters.pod @@ -0,0 +1,105 @@ +=pod + +=head1 NAME + +DSA_generate_parameters - generate DSA parameters + +=head1 SYNOPSIS + + #include + + 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); + +=head1 DESCRIPTION + +DSA_generate_parameters() generates primes p and q and a generator g +for use in the DSA. + +B is the length of the prime to be generated; the DSS allows a +maximum of 1024 bits. + +If B is B or B E 20, the primes will be +generated at random. Otherwise, the seed is used to generate +them. If the given seed does not yield a prime q, a new random +seed is chosen and placed at B. + +DSA_generate_parameters() places the iteration count in +*B and a counter used for finding a generator in +*B, unless these are B. + +A callback function may be used to provide feedback about the progress +of the key generation. If B is not B, it will be +called as follows: + +=over 4 + +=item * + +When a candidate for q is generated, B is called +(m is 0 for the first candidate). + +=item * + +When a candidate for q has passed a test by trial division, +B is called. +While a candidate for q is tested by Miller-Rabin primality tests, +B is called in the outer loop +(once for each witness that confirms that the candidate may be prime); +i is the loop counter (starting at 0). + +=item * + +When a prime q has been found, B and +B are called. + +=item * + +Before a candidate for p (other than the first) is generated and tested, +B is called. + +=item * + +When a candidate for p has passed the test by trial division, +B is called. +While it is tested by the Miller-Rabin primality test, +B is called in the outer loop +(once for each witness that confirms that the candidate may be prime). +i is the loop counter (starting at 0). + +=item * + +When p has been found, B is called. + +=item * + +When the generator has been found, B is called. + +=back + +=head1 RETURN VALUE + +DSA_generate_parameters() returns a pointer to the DSA structure, or +B if the parameter generation fails. The error codes can be +obtained by L. + +=head1 BUGS + +Seed lengths E 20 are not supported. + +=head1 SEE ALSO + +L, L, L, +L + +=head1 HISTORY + +DSA_generate_parameters() appeared in SSLeay 0.8. The B +argument was added in SSLeay 0.9.0. +In versions up to OpenSSL 0.9.4, B was called +in the inner loop of the Miller-Rabin test whenever it reached the +squaring step (the parameters to B did not reveal how many +witnesses had been tested); since OpenSSL 0.9.5, B +is called as in BN_is_prime(3), i.e. once for each witness. +=cut diff --git a/src/lib/libcrypto/doc/DSA_get_ex_new_index.pod b/src/lib/libcrypto/doc/DSA_get_ex_new_index.pod new file mode 100644 index 0000000000..4612e708ec --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_get_ex_new_index.pod @@ -0,0 +1,36 @@ +=pod + +=head1 NAME + +DSA_get_ex_new_index, DSA_set_ex_data, DSA_get_ex_data - add application specific data to DSA structures + +=head1 SYNOPSIS + + #include + + 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); + + char *DSA_get_ex_data(DSA *d, int idx); + +=head1 DESCRIPTION + +These functions handle application specific data in DSA +structures. Their usage is identical to that of +RSA_get_ex_new_index(), RSA_set_ex_data() and RSA_get_ex_data() +as described in L. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +DSA_get_ex_new_index(), DSA_set_ex_data() and DSA_get_ex_data() are +available since OpenSSL 0.9.5. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_new.pod b/src/lib/libcrypto/doc/DSA_new.pod new file mode 100644 index 0000000000..7dde54445b --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_new.pod @@ -0,0 +1,41 @@ +=pod + +=head1 NAME + +DSA_new, DSA_free - allocate and free DSA objects + +=head1 SYNOPSIS + + #include + + DSA* DSA_new(void); + + void DSA_free(DSA *dsa); + +=head1 DESCRIPTION + +DSA_new() allocates and initializes a B structure. + +DSA_free() frees the B structure and its components. The values are +erased before the memory is returned to the system. + +=head1 RETURN VALUES + +If the allocation fails, DSA_new() returns B and sets an error +code that can be obtained by +L. Otherwise it returns a pointer +to the newly allocated structure. + +DSA_free() returns no value. + +=head1 SEE ALSO + +L, L, +L, +L + +=head1 HISTORY + +DSA_new() and DSA_free() are available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_set_method.pod b/src/lib/libcrypto/doc/DSA_set_method.pod new file mode 100644 index 0000000000..0b13ec9237 --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_set_method.pod @@ -0,0 +1,111 @@ +=pod + +=head1 NAME + +DSA_set_default_method, DSA_get_default_method, DSA_set_method, +DSA_new_method, DSA_OpenSSL - select RSA method + +=head1 SYNOPSIS + + #include + + void DSA_set_default_method(DSA_METHOD *meth); + + DSA_METHOD *DSA_get_default_method(void); + + DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *meth); + + DSA *DSA_new_method(DSA_METHOD *meth); + + DSA_METHOD *DSA_OpenSSL(void); + +=head1 DESCRIPTION + +A B specifies the functions that OpenSSL uses for DSA +operations. By modifying the method, alternative implementations +such as hardware accelerators may be used. + +Initially, the default is to use the OpenSSL internal implementation. +DSA_OpenSSL() returns a pointer to that method. + +DSA_set_default_method() makes B the default method for all B +structures created later. + +DSA_get_default_method() returns a pointer to the current default +method. + +DSA_set_method() selects B for all operations using the structure B. + +DSA_get_method() returns a pointer to the method currently selected +for B. + +DSA_new_method() allocates and initializes a B structure so that +B will be used for the DSA operations. If B is B, +the default method is used. + +=head1 THE DSA_METHOD STRUCTURE + +struct + { + /* name of the implementation */ + const char *name; + + /* sign */ + DSA_SIG *(*dsa_do_sign)(const unsigned char *dgst, int dlen, + DSA *dsa); + + /* pre-compute k^-1 and r */ + int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); + + /* verify */ + int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + + /* compute rr = a1^p1 * a2^p2 mod m. May be NULL */ + 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); + + /* compute r = a ^ p mod m. May be NULL */ + int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx); + + /* called at DSA_new */ + int (*init)(DSA *DSA); + + /* called at DSA_free */ + int (*finish)(DSA *DSA); + + int flags; + + char *app_data; /* ?? */ + + } DSA_METHOD; + +=head1 RETURN VALUES + +DSA_OpenSSL(), DSA_get_default_method() and DSA_get_method() return +pointers to the respective Bs. + +DSA_set_default_method() returns no value. + +DSA_set_method() returns a pointer to the B previously +associated with B. + +DSA_new_method() returns B and sets an error code that can be +obtained by L if the allocation +fails. Otherwise it returns a pointer to the newly allocated +structure. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +DSA_set_default_method(), DSA_get_default_method(), DSA_set_method(), +DSA_new_method() and DSA_OpenSSL() were added in OpenSSL 0.9.4. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_sign.pod b/src/lib/libcrypto/doc/DSA_sign.pod new file mode 100644 index 0000000000..f6e60a8ca3 --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_sign.pod @@ -0,0 +1,66 @@ +=pod + +=head1 NAME + +DSA_sign, DSA_sign_setup, DSA_verify - DSA signatures + +=head1 SYNOPSIS + + #include + + int DSA_sign(int type, const unsigned char *dgst, int len, + unsigned char *sigret, unsigned int *siglen, DSA *dsa); + + int DSA_sign_setup(DSA *dsa, BN_CTX *ctx, BIGNUM **kinvp, + BIGNUM **rp); + + int DSA_verify(int type, const unsigned char *dgst, int len, + unsigned char *sigbuf, int siglen, DSA *dsa); + +=head1 DESCRIPTION + +DSA_sign() computes a digital signature on the B byte message +digest B using the private key B and places its ASN.1 DER +encoding at B. The length of the signature is places in +*B. B must point to DSA_size(B) bytes of memory. + +DSA_sign_setup() may be used to precompute part of the signing +operation in case signature generation is time-critical. It expects +B to contain DSA parameters. It places the precomputed values +in newly allocated Bs at *B and *B, after freeing +the old ones unless *B and *B are NULL. These values may +be passed to DSA_sign() in Bkinv> and Br>. +B is a pre-allocated B or NULL. + +DSA_verify() verifies that the signature B of size B +matches a given message digest B of size B. +B is the signer's public key. + +The B parameter is ignored. + +The PRNG must be seeded before DSA_sign() (or DSA_sign_setup()) +is called. + +=head1 RETURN VALUES + +DSA_sign() and DSA_sign_setup() return 1 on success, 0 on error. +DSA_verify() returns 1 for a valid signature, 0 for an incorrect +signature and -1 on error. The error codes can be obtained by +L. + +=head1 CONFORMING TO + +US Federal Information Processing Standard FIPS 186 (Digital Signature +Standard, DSS), ANSI X9.30 + +=head1 SEE ALSO + +L, L, L, +L + +=head1 HISTORY + +DSA_sign() and DSA_verify() are available in all versions of SSLeay. +DSA_sign_setup() was added in SSLeay 0.8. + +=cut diff --git a/src/lib/libcrypto/doc/DSA_size.pod b/src/lib/libcrypto/doc/DSA_size.pod new file mode 100644 index 0000000000..23b6320a4d --- /dev/null +++ b/src/lib/libcrypto/doc/DSA_size.pod @@ -0,0 +1,33 @@ +=pod + +=head1 NAME + +DSA_size - get DSA signature size + +=head1 SYNOPSIS + + #include + + int DSA_size(DSA *dsa); + +=head1 DESCRIPTION + +This function returns the size of an ASN.1 encoded DSA signature in +bytes. It can be used to determine how much memory must be allocated +for a DSA signature. + +Bq> must not be B. + +=head1 RETURN VALUE + +The size in bytes. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +DSA_size() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_GET_LIB.pod b/src/lib/libcrypto/doc/ERR_GET_LIB.pod new file mode 100644 index 0000000000..2a129da036 --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_GET_LIB.pod @@ -0,0 +1,51 @@ +=pod + +=head1 NAME + +ERR_GET_LIB, ERR_GET_FUNC, ERR_GET_REASON - get library, function and +reason code + +=head1 SYNOPSIS + + #include + + int ERR_GET_LIB(unsigned long e); + + int ERR_GET_FUNC(unsigned long e); + + int ERR_GET_REASON(unsigned long e); + +=head1 DESCRIPTION + +The error code returned by ERR_get_error() consists of a library +number, function code and reason code. ERR_GET_LIB(), ERR_GET_FUNC() +and ERR_GET_REASON() can be used to extract these. + +The library number and function code describe where the error +occurred, the reason code is the information about what went wrong. + +Each sub-library of OpenSSL has a unique library number; function and +reason codes are unique within each sub-library. Note that different +libraries may use the same value to signal different functions and +reasons. + +B reason codes such as B are globally +unique. However, when checking for sub-library specific reason codes, +be sure to also compare the library number. + +ERR_GET_LIB(), ERR_GET_FUNC() and ERR_GET_REASON() are macros. + +=head1 RETURN VALUES + +The library number, function code and reason code respectively. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +ERR_GET_LIB(), ERR_GET_FUNC() and ERR_GET_REASON() are available in +all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_clear_error.pod b/src/lib/libcrypto/doc/ERR_clear_error.pod new file mode 100644 index 0000000000..566e1f4e31 --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_clear_error.pod @@ -0,0 +1,29 @@ +=pod + +=head1 NAME + +ERR_clear_error - clear the error queue + +=head1 SYNOPSIS + + #include + + void ERR_clear_error(void); + +=head1 DESCRIPTION + +ERR_clear_error() empties the current thread's error queue. + +=head1 RETURN VALUES + +ERR_clear_error() has no return value. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +ERR_clear_error() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_error_string.pod b/src/lib/libcrypto/doc/ERR_error_string.pod new file mode 100644 index 0000000000..0d2417599c --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_error_string.pod @@ -0,0 +1,65 @@ +=pod + +=head1 NAME + +ERR_error_string - obtain human-readable error message + +=head1 SYNOPSIS + + #include + + 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); + +=head1 DESCRIPTION + +ERR_error_string() generates a human-readable string representing the +error code B, and places it at B. B must be at least 120 +bytes long. If B is B, the error string is placed in a +static buffer. + +The string will have the following format: + + error:[error code]:[library name]:[function name]:[reason string] + +I is an 8 digit hexadecimal number, I, +I and I are ASCII text. + +ERR_lib_error_string(), ERR_func_error_string() and +ERR_reason_error_string() return the library name, function +name and reason string respectively. + +The OpenSSL error strings should be loaded by calling +L or, for SSL +applications, L +first. +If there is no text string registered for the given error code, +the error string will contain the numeric code. + +L can be used to print +all error codes currently in the queue. + +=head1 RETURN VALUES + +ERR_error_string() returns a pointer to a static buffer containing the +string if B, B otherwise. + +ERR_lib_error_string(), ERR_func_error_string() and +ERR_reason_error_string() return the strings, and B if +none is registered for the error code. + +=head1 SEE ALSO + +L, L, +L, +L +L + +=head1 HISTORY + +ERR_error_string() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_get_error.pod b/src/lib/libcrypto/doc/ERR_get_error.pod new file mode 100644 index 0000000000..75ece00d97 --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_get_error.pod @@ -0,0 +1,62 @@ +=pod + +=head1 NAME + +ERR_get_error, ERR_peek_error - obtain error code + +=head1 SYNOPSIS + + #include + + unsigned long ERR_get_error(void); + unsigned long ERR_peek_error(void); + + unsigned long ERR_get_error_line(const char **file, int *line); + unsigned long ERR_peek_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_line_data(const char **file, int *line, + const char **data, int *flags); + +=head1 DESCRIPTION + +ERR_get_error() returns the last error code from the thread's error +queue and removes the entry. This function can be called repeatedly +until there are no more error codes to return. + +ERR_peek_error() returns the last error code from the thread's +error queue without modifying it. + +See L for obtaining information about +location and reason of the error, and +L for human-readable error +messages. + +ERR_get_error_line() and ERR_peek_error_line() are the same as the +above, but they additionally store the file name and line number where +the error occurred in *B and *B, unless these are B. + +ERR_get_error_line_data() and ERR_peek_error_line_data() store +additional data and flags associated with the error code in *B +and *B, unless these are B. *B contains a string +if *B&B. If it has been allocated by Malloc(), +*B&B is true. + +=head1 RETURN VALUES + +The error code, or 0 if there is no error in the queue. + +=head1 SEE ALSO + +L, L, +L + +=head1 HISTORY + +ERR_get_error(), ERR_peek_error(), ERR_get_error_line() and +ERR_peek_error_line() are available in all versions of SSLeay and +OpenSSL. ERR_get_error_line_data() and ERR_peek_error_line_data() +were added in SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_load_crypto_strings.pod b/src/lib/libcrypto/doc/ERR_load_crypto_strings.pod new file mode 100644 index 0000000000..9bdec75a46 --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_load_crypto_strings.pod @@ -0,0 +1,46 @@ +=pod + +=head1 NAME + +ERR_load_crypto_strings, SSL_load_error_strings, ERR_free_strings - +load and free error strings + +=head1 SYNOPSIS + + #include + + void ERR_load_crypto_strings(void); + void ERR_free_strings(void); + + #include + + void SSL_load_error_strings(void); + +=head1 DESCRIPTION + +ERR_load_crypto_strings() registers the error strings for all +B functions. SSL_load_error_strings() does the same, +but also registers the B error strings. + +One of these functions should be called before generating +textual error messages. However, this is not required when memory +usage is an issue. + +ERR_free_strings() frees all previously loaded error strings. + +=head1 RETURN VALUES + +ERR_load_crypto_strings(), SSL_load_error_strings() and +ERR_free_strings() return no values. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +ERR_load_error_strings(), SSL_load_error_strings() and +ERR_free_strings() are available in all versions of SSLeay and +OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_load_strings.pod b/src/lib/libcrypto/doc/ERR_load_strings.pod new file mode 100644 index 0000000000..5acdd0edbc --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_load_strings.pod @@ -0,0 +1,54 @@ +=pod + +=head1 NAME + +ERR_load_strings, ERR_PACK, ERR_get_next_error_library - load +arbitrary error strings + +=head1 SYNOPSIS + + #include + + void ERR_load_strings(int lib, ERR_STRING_DATA str[]); + + int ERR_get_next_error_library(void); + + unsigned long ERR_PACK(int lib, int func, int reason); + +=head1 DESCRIPTION + +ERR_load_strings() registers error strings for library number B. + +B is an array of error string data: + + typedef struct ERR_string_data_st + { + unsigned long error; + char *string; + } ERR_STRING_DATA; + +The error code is generated from the library number and a function and +reason code: B = ERR_PACK(B, B, B). +ERR_PACK() is a macro. + +The last entry in the array is {0,0}. + +ERR_get_next_error_library() can be used to assign library numbers +to user libraries at runtime. + +=head1 RETURN VALUE + +ERR_load_strings() returns no value. ERR_PACK() return the error code. +ERR_get_next_error_library() returns a new library number. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +ERR_load_error_strings() and ERR_PACK() are available in all versions +of SSLeay and OpenSSL. ERR_get_next_error_library() was added in +SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_print_errors.pod b/src/lib/libcrypto/doc/ERR_print_errors.pod new file mode 100644 index 0000000000..b100a5fa2b --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_print_errors.pod @@ -0,0 +1,51 @@ +=pod + +=head1 NAME + +ERR_print_errors, ERR_print_errors_fp - print error messages + +=head1 SYNOPSIS + + #include + + void ERR_print_errors(BIO *bp); + void ERR_print_errors_fp(FILE *fp); + +=head1 DESCRIPTION + +ERR_print_errors() is a convenience function that prints the error +strings for all errors that OpenSSL has recorded to B, thus +emptying the error queue. + +ERR_print_errors_fp() is the same, except that the output goes to a +B. + + +The error strings will have the following format: + + [pid]:error:[error code]:[library name]:[function name]:[reason string]:[file name]:[line]:[optional text message] + +I is an 8 digit hexadecimal number. I, +I and I are ASCII text, as is I if one was set for the respective error code. + +If there is no text string registered for the given error code, +the error string will contain the numeric code. + +=head1 RETURN VALUES + +ERR_print_errors() and ERR_print_errors_fp() return no values. + +=head1 SEE ALSO + +L, L, +L, +L, +L + +=head1 HISTORY + +ERR_print_errors() and ERR_print_errors_fp() +are available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_put_error.pod b/src/lib/libcrypto/doc/ERR_put_error.pod new file mode 100644 index 0000000000..acd241fbe4 --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_put_error.pod @@ -0,0 +1,44 @@ +=pod + +=head1 NAME + +ERR_put_error, ERR_add_error_data - record an error + +=head1 SYNOPSIS + + #include + + void ERR_put_error(int lib, int func, int reason, const char *file, + int line); + + void ERR_add_error_data(int num, ...); + +=head1 DESCRIPTION + +ERR_put_error() adds an error code to the thread's error queue. It +signals that the error of reason code B occurred in function +B of library B, in line number B of B. +This function is usually called by a macro. + +ERR_add_error_data() associates the concatenation of its B string +arguments with the error code added last. + +L can be used to register +error strings so that the application can a generate human-readable +error messages for the error code. + +=head1 RETURN VALUES + +ERR_put_error() and ERR_add_error_data() return +no values. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +ERR_put_error() is available in all versions of SSLeay and OpenSSL. +ERR_add_error_data() was added in SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/ERR_remove_state.pod b/src/lib/libcrypto/doc/ERR_remove_state.pod new file mode 100644 index 0000000000..ebcdc0f5a5 --- /dev/null +++ b/src/lib/libcrypto/doc/ERR_remove_state.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +ERR_remove_state - free a thread's error queue + +=head1 SYNOPSIS + + #include + + void ERR_remove_state(unsigned long pid); + +=head1 DESCRIPTION + +ERR_remove_state() frees the error queue associated with thread B. +If B == 0, the current thread will have its error queue removed. + +Since error queue data structures are allocated automatically for new +threads, they must be freed when threads are terminated in oder to +avoid memory leaks. + +=head1 RETURN VALUE + +ERR_remove_state() returns no value. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +ERR_remove_state() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/EVP_BytesToKey.pod b/src/lib/libcrypto/doc/EVP_BytesToKey.pod new file mode 100644 index 0000000000..5ce4add082 --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_BytesToKey.pod @@ -0,0 +1,67 @@ +=pod + +=head1 NAME + + EVP_BytesToKey - password based encryption routine + +=head1 SYNOPSIS + + #include + + int EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md, + const unsigned char *salt, + const unsigned char *data, int datal, int count, + unsigned char *key,unsigned char *iv); + +=head1 DESCRIPTION + +EVP_BytesToKey() derives a key and IV from various parameters. B is +the cipher to derive the key and IV for. B is the message digest to use. +The B paramter is used as a salt in the derivation: it should point to +an 8 byte buffer or NULL if no salt is used. B is a buffer containing +B bytes which is used to derive the keying data. B is the +iteration count to use. The derived key and IV will be written to B +and B respectively. + +=head1 NOTES + +A typical application of this function is to derive keying material for an +encryption algorithm from a password in the B parameter. + +Increasing the B parameter slows down the algorithm which makes it +harder for an attacker to peform a brute force attack using a large number +of candidate passwords. + +If the total key and IV length is less than the digest length and +B is used then the derivation algorithm is compatible with PKCS#5 v1.5 +otherwise a non standard extension is used to derive the extra data. + +Newer applications should use more standard algorithms such as PKCS#5 +v2.0 for key derivation. + +=head1 KEY DERIVATION ALGORITHM + +The key and IV is derived by concatenating D_1, D_2, etc until +enough data is available for the key and IV. D_i is defined as: + + D_i = HASH^count(D_(i-1) || data || salt) + +where || denotes concatentaion, D_0 is empty, HASH is the digest +algorithm in use, HASH^1(data) is simply HASH(data), HASH^2(data) +is HASH(HASH(data)) and so on. + +The initial bytes are used for the key and the subsequent bytes for +the IV. + +=head1 RETURN VALUES + +EVP_BytesToKey() returns the size of the derived key in bytes. + +=head1 SEE ALSO + +L, L, +L, + +=head1 HISTORY + +=cut diff --git a/src/lib/libcrypto/doc/EVP_DigestInit.pod b/src/lib/libcrypto/doc/EVP_DigestInit.pod new file mode 100644 index 0000000000..345b1ddfa7 --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_DigestInit.pod @@ -0,0 +1,197 @@ +=pod + +=head1 NAME + +EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal - EVP digest routines + +=head1 SYNOPSIS + + #include + + 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); + + #define EVP_MAX_MD_SIZE (16+20) /* The SSLv3 md5+sha1 type */ + + int EVP_MD_CTX_copy(EVP_MD_CTX *out,EVP_MD_CTX *in); + + #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) + + 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); + + const EVP_MD *EVP_get_digestbyname(const char *name); + #define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) + #define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a)) + +=head1 DESCRIPTION + +The EVP digest routines are a high level interface to message digests. + +EVP_DigestInit() initialises a digest context B to use a digest +B: this will typically be supplied by a function such as +EVP_sha1(). + +EVP_DigestUpdate() hashes B bytes of data at B into the +digest context B. This funtion can be called several times on the +same B to hash additional data. + +EVP_DigestFinal() retrieves the digest value from B and places +it in B. If the B parameter is not NULL then the number of +bytes of data written (i.e. the length of the digest) will be written +to the integer at B, at most B bytes will be written. +After calling EVP_DigestFinal() no additional calls to EVP_DigestUpdate() +can be made, but EVP_DigestInit() can be called to initialiase a new +digest operation. + +EVP_MD_CTX_copy() can be used to copy the message digest state from +B to B. This is useful if large amounts of data are to be +hashed which only differ in the last few bytes. + +EVP_MD_size() and EVP_MD_CTX_size() return the size of the message digest +when passed an B or an B structure, i.e. the size of the +hash. + +EVP_MD_block_size() and EVP_MD_CTX_block_size() return the block size of the +message digest when passed an B or an B structure. + +EVP_MD_type() and EVP_MD_CTX_type() return the NID of the OBJECT IDENTIFIER +representing the given message digest when passed an B structure. +For example EVP_MD_type(EVP_sha1()) returns B. This function is +normally used when setting ASN1 OIDs. + +EVP_MD_CTX_md() returns the B structure corresponding to the passed +B. + +EVP_MD_pkey_type() returns the NID of the public key signing algorithm associated +with this digest. For example EVP_sha1() is associated with RSA so this will +return B. This "link" between digests and signature +algorithms may not be retained in future versions of OpenSSL. + +EVP_md2(), EVP_md5(), EVP_sha(), EVP_sha1(), EVP_mdc2() and EVP_ripemd160() +return B structures for the MD2, MD5, SHA, SHA1, MDC2 and RIPEMD160 digest +algorithms respectively. The associated signature algorithm is RSA in each case. + +EVP_dss() and EVP_dss1() return B structures for SHA and SHA1 digest +algorithms but using DSS (DSA) for the signature algorithm. + +EVP_md_null() is a "null" message digest that does nothing: i.e. the hash it +returns is of zero length. + +EVP_get_digestbyname(), EVP_get_digestbynid() and EVP_get_digestbyobj() +return an B structure when passed a digest name, a digest NID or +an ASN1_OBJECT structure respectively. The digest table must be initialised +using, for example, OpenSSL_add_all_digests() for these functions to work. + +=head1 RETURN VALUES + +EVP_DigestInit(), EVP_DigestUpdate() and EVP_DigestFinal() do not return values. + +EVP_MD_CTX_copy() returns 1 if successful or 0 for failure. + +EVP_MD_type(), EVP_MD_pkey_type() and EVP_MD_type() return the NID of the +corresponding OBJECT IDENTIFIER or NID_undef if none exists. + +EVP_MD_size(), EVP_MD_block_size(), EVP_MD_CTX_size(e), EVP_MD_size(), +EVP_MD_CTX_block_size() and EVP_MD_block_size() return the digest or block +size in bytes. + +EVP_md_null(), EVP_md2(), EVP_md5(), EVP_sha(), EVP_sha1(), EVP_dss(), +EVP_dss1(), EVP_mdc2() and EVP_ripemd160() return pointers to the +corresponding EVP_MD structures. + +EVP_get_digestbyname(), EVP_get_digestbynid() and EVP_get_digestbyobj() +return either an B structure or NULL if an error occurs. + +=head1 NOTES + +The B interface to message digests should almost always be used in +preference to the low level interfaces. This is because the code then becomes +transparent to the digest used and much more flexible. + +SHA1 is the digest of choice for new applications. The other digest algorithms +are still in common use. + +=head1 EXAMPLE + +This example digests the data "Test Message\n" and "Hello World\n", using the +digest name passed on the command line. + + #include + #include + + main(int argc, char *argv[]) + { + EVP_MD_CTX mdctx; + const EVP_MD *md; + char mess1[] = "Test Message\n"; + char mess2[] = "Hello World\n"; + unsigned char md_value[EVP_MAX_MD_SIZE]; + int md_len, i; + + OpenSSL_add_all_digests(); + + if(!argv[1]) { + printf("Usage: mdtest digestname\n"); + exit(1); + } + + md = EVP_get_digestbyname(argv[1]); + + if(!md) { + printf("Unknown message digest %s\n", argv[1]); + exit(1); + } + + EVP_DigestInit(&mdctx, md); + EVP_DigestUpdate(&mdctx, mess1, strlen(mess1)); + EVP_DigestUpdate(&mdctx, mess2, strlen(mess2)); + EVP_DigestFinal(&mdctx, md_value, &md_len); + + printf("Digest is: "); + for(i = 0; i < md_len; i++) printf("%02x", md_value[i]); + printf("\n"); + } + +=head1 BUGS + +Several of the functions do not return values: maybe they should. Although the +internal digest operations will never fail some future hardware based operations +might. + +The link between digests and signing algorithms results in a situation where +EVP_sha1() must be used with RSA and EVP_dss1() must be used with DSS +even though they are identical digests. + +The size of an B structure is determined at compile time: this results +in code that must be recompiled if the size of B increases. + +=head1 SEE ALSO + +L, L, L, +L, L, L, +L, L + +=head1 HISTORY + +EVP_DigestInit(), EVP_DigestUpdate() and EVP_DigestFinal() are +available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/EVP_EncryptInit.pod b/src/lib/libcrypto/doc/EVP_EncryptInit.pod new file mode 100644 index 0000000000..77ed4ccdba --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_EncryptInit.pod @@ -0,0 +1,224 @@ +=pod + +=head1 NAME + +EVP_EncryptInit, EVP_EncryptUpdate, EVP_EncryptFinal - EVP cipher routines + +=head1 SYNOPSIS + + #include + + 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); + + void EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); + + const EVP_CIPHER *EVP_get_cipherbyname(const char *name); + #define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) + #define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) + + #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) + + int EVP_CIPHER_type(const EVP_CIPHER *ctx); + #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_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) + + 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); + +=head1 DESCRIPTION + +The EVP cipher routines are a high level interface to certain +symmetric ciphers. + +EVP_EncryptInit() initialises a cipher context B for encryption +with cipher B. B is normally supplied by a function such +as EVP_des_cbc() . B is the symmetric key to use and B is the +IV to use (if necessary), the actual number of bytes used for the +key and IV depends on the cipher. It is possible to set all parameters +to NULL except B in an initial call and supply the remaining +parameters in subsequent calls. This is normally done when the +EVP_CIPHER_asn1_to_param() function is called to set the cipher +parameters from an ASN1 AlgorithmIdentifier and the key from a +different source. + +EVP_EncryptUpdate() encrypts B bytes from the buffer B and +writes the encrypted version to B. This function can be called +multiple times to encrypt successive blocks of data. The amount +of data written depends on the block alignment of the encrypted data: +as a result the amount of data written may be anything from zero bytes +to (inl + cipher_block_size - 1) so B should contain sufficient +room. The actual number of bytes written is placed in B. + +EVP_EncryptFinal() encrypts the "final" data, that is any data that +remains in a partial block. It uses L (aka PKCS +padding). The encrypted final data is written to B which should +have sufficient space for one cipher block. The number of bytes written +is placed in B. After this function is called the encryption operation +is finished and no further calls to EVP_EncryptUpdate() should be made. + +EVP_DecryptInit(), EVP_DecryptUpdate() and EVP_DecryptFinal() are the +corresponding decryption operations. EVP_DecryptFinal() will return an +error code if the final block is not correctly formatted. The parameters +and restrictions are identical to the encryption operations except that +the decrypted data buffer B passed to EVP_DecryptUpdate() should +have sufficient room for (B + cipher_block_size) bytes unless the +cipher block size is 1 in which case B bytes is sufficient. + +EVP_CipherInit(), EVP_CipherUpdate() and EVP_CipherFinal() are functions +that can be used for decryption or encryption. The operation performed +depends on the value of the B parameter. It should be set to 1 for +encryption and 0 for decryption. + +EVP_CIPHER_CTX_cleanup() clears all information from a cipher context. +It should be called after all operations using a cipher are complete +so sensitive information does not remain in memory. + +EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj() +return an EVP_CIPHER structure when passed a cipher name, a NID or an +ASN1_OBJECT structure. + +EVP_CIPHER_nid() and EVP_CIPHER_CTX_nid() return the NID of a cipher when +passed an B or B structure. The actual NID +value is an internal value which may not have a corresponding OBJECT +IDENTIFIER. + +EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key +length of a cipher when passed an B or B +structure. The constant B is the maximum key length +for all ciphers. + +EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV +length of a cipher when passed an B or B. +It will return zero if the cipher does not use an IV. The constant +B is the maximum IV length for all ciphers. + +EVP_CIPHER_block_size() and EVP_CIPHER_CTX_block_size() return the block +size of a cipher when passed an B or B +structure. The constant B is also the maximum block +length for all ciphers. + +EVP_CIPHER_type() and EVP_CIPHER_CTX_type() return the type of the passed +cipher or context. This "type" is the actual NID of the cipher OBJECT +IDENTIFIER as such it ignores the cipher parameters and 40 bit RC2 and +128 bit RC2 have the same NID. If the cipher does not have an object +identifier or does not have ASN1 support this function will return +B. + +EVP_CIPHER_CTX_cipher() returns the B structure when passed +an B structure. + +EVP_CIPHER_param_to_asn1() sets the AlgorithmIdentifier "parameter" based +on the passed cipher. This will typically include any parameters and an +IV. The cipher IV (if any) must be set when this call is made. This call +should be made before the cipher is actually "used" (before any +EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example). This function +may fail if the cipher does not have any ASN1 support. + +EVP_CIPHER_asn1_to_param() sets the cipher parameters based on an ASN1 +AlgorithmIdentifier "parameter". The precise effect depends on the cipher +In the case of RC2, for example, it will set the IV and effective key length. +This function should be called after the base cipher type is set but before +the key is set. For example EVP_CipherInit() will be called with the IV and +key set to NULL, EVP_CIPHER_asn1_to_param() will be called and finally +EVP_CipherInit() again with all parameters except the key set to NULL. It is +possible for this function to fail if the cipher does not have any ASN1 support +or the parameters cannot be set (for example the RC2 effective key length +does not have an B structure). + +=head1 RETURN VALUES + +EVP_EncryptInit(), EVP_EncryptUpdate() and EVP_EncryptFinal() do not return +values. + +EVP_DecryptInit() and EVP_DecryptUpdate() do not return values. +EVP_DecryptFinal() returns 0 if the decrypt failed or 1 for success. + +EVP_CipherInit() and EVP_CipherUpdate() do not return values. +EVP_CipherFinal() returns 1 for a decryption failure or 1 for success, if +the operation is encryption then it always returns 1. + +EVP_CIPHER_CTX_cleanup() does not return a value. + +EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj() +return an B structure or NULL on error. + +EVP_CIPHER_nid() and EVP_CIPHER_CTX_nid() return a NID. + +EVP_CIPHER_block_size() and EVP_CIPHER_CTX_block_size() return the block +size. + +EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key +length. + +EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV +length or zero if the cipher does not use an IV. + +EVP_CIPHER_type() and EVP_CIPHER_CTX_type() return the NID of the cipher's +OBJECT IDENTIFIER or NID_undef if it has no defined OBJECT IDENTIFIER. + +EVP_CIPHER_CTX_cipher() returns an B structure. + +EVP_CIPHER_param_to_asn1() and EVP_CIPHER_asn1_to_param() return 1 for +success or zero for failure. + +=head1 NOTES + +Where possible the B interface to symmetric ciphers should be used in +preference to the low level interfaces. This is because the code then becomes +transparent to the cipher used and much more flexible. + +PKCS padding works by adding B padding bytes of value B to make the total +length of the encrypted data a multiple of the block size. Padding is always +added so if the data is already a multiple of the block size B will equal +the block size. For example if the block size is 8 and 11 bytes are to be +encrypted then 5 padding bytes of value 5 will be added. + +When decrypting the final block is checked to see if it has the correct form. + +Although the decryption operation can produce an error, it is not a strong +test that the input data or key is correct. A random block has better than +1 in 256 chance of being of the correct format and problems with the +input data earlier on will not produce a final decrypt error. + +=head1 BUGS + +The current B cipher interface is not as flexible as it should be. Only +certain "spot" encryption algorithms can be used for ciphers which have various +parameters associated with them (RC2, RC5 for example) this is inadequate. + +Several of the functions do not return error codes because the software versions +can never fail. This is not true of hardware versions. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +=cut diff --git a/src/lib/libcrypto/doc/EVP_OpenInit.pod b/src/lib/libcrypto/doc/EVP_OpenInit.pod new file mode 100644 index 0000000000..9707a4b399 --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_OpenInit.pod @@ -0,0 +1,51 @@ +=pod + +=head1 NAME + +EVP_OpenInit, EVP_OpenUpdate, EVP_OpenFinal - EVP envelope decryption + +=head1 SYNOPSIS + + #include + + int EVP_OpenInit(EVP_CIPHER_CTX *ctx,EVP_CIPHER *type,unsigned char *ek, + int ekl,unsigned char *iv,EVP_PKEY *priv); + void EVP_OpenUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, unsigned char *in, int inl); + void EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); + +=head1 DESCRIPTION + +The EVP envelope routines are a high level interface to envelope +decryption. They decrypt a public key encrypted symmetric key and +then decrypt data using it. + +EVP_OpenInit() initialises a cipher context B for decryption +with cipher B. It decrypts the encrypted symmetric key of length +B bytes passed in the B parameter using the private key B. +The IV is supplied in the B parameter. + +EVP_OpenUpdate() and EVP_OpenFinal() have exactly the same properties +as the EVP_DecryptUpdate() and EVP_DecryptFinal() routines, as +documented on the L manual +page. + +=head1 RETURN VALUES + +EVP_OpenInit() returns -1 on error or an non zero integer (actually the +recovered secret key size) if successful. + +EVP_SealUpdate() does not return a value. + +EVP_SealFinal() returns 0 if the decrypt failed or 1 for success. + +=head1 SEE ALSO + +L,L +L, +L + +=head1 HISTORY + +=cut diff --git a/src/lib/libcrypto/doc/EVP_SealInit.pod b/src/lib/libcrypto/doc/EVP_SealInit.pod new file mode 100644 index 0000000000..1579d110fa --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_SealInit.pod @@ -0,0 +1,70 @@ +=pod + +=head1 NAME + +EVP_SealInit, EVP_SealUpdate, EVP_SealFinal - EVP envelope encryption + +=head1 SYNOPSIS + + #include + + 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_SealUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, unsigned char *in, int inl); + void EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); + +=head1 DESCRIPTION + +The EVP envelope routines are a high level interface to envelope +encryption. They generate a random key and then "envelope" it by +using public key encryption. Data can then be encrypted using this +key. + +EVP_SealInit() initialises a cipher context B for encryption +with cipher B using a random secret key and IV supplied in +the B parameter. B is normally supplied by a function such +as EVP_des_cbc(). The secret key is encrypted using one or more public +keys, this allows the same encrypted data to be decrypted using any +of the corresponding private keys. B is an array of buffers where +the public key encrypted secret key will be written, each buffer must +contain enough room for the corresponding encrypted key: that is +B must have room for B bytes. The actual +size of each encrypted secret key is written to the array B. B is +an array of B public keys. + +EVP_SealUpdate() and EVP_SealFinal() have exactly the same properties +as the EVP_EncryptUpdate() and EVP_EncryptFinal() routines, as +documented on the L manual +page. + +=head1 RETURN VALUES + +EVP_SealInit() returns -1 on error or B if successful. + +EVP_SealUpdate() and EVP_SealFinal() do not return values. + +=head1 NOTES + +Because a random secret key is generated the random number generator +must be seeded before calling EVP_SealInit(). + +The public key must be RSA because it is the only OpenSSL public key +algorithm that supports key transport. + +Envelope encryption is the usual method of using public key encryption +on large amounts of data, this is because public key encryption is slow +but symmetric encryption is fast. So symmetric encryption is used for +bulk encryption and the small random symmetric key used is transferred +using public key encryption. + +=head1 SEE ALSO + +L,L +L, +L + +=head1 HISTORY + +=cut diff --git a/src/lib/libcrypto/doc/EVP_SignInit.pod b/src/lib/libcrypto/doc/EVP_SignInit.pod new file mode 100644 index 0000000000..bbc9203c9c --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_SignInit.pod @@ -0,0 +1,85 @@ +=pod + +=head1 NAME + +EVP_SignInit, EVP_SignUpdate, EVP_SignFinal - EVP signing functions + +=head1 SYNOPSIS + + #include + + void EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type); + void EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); + int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *sig,unsigned int *s, EVP_PKEY *pkey); + + int EVP_PKEY_size(EVP_PKEY *pkey); + +=head1 DESCRIPTION + +The EVP signature routines are a high level interface to digital +signatures. + +EVP_SignInit() initialises a signing context B to using digest +B: this will typically be supplied by a function such as +EVP_sha1(). + +EVP_SignUpdate() hashes B bytes of data at B into the +signature context B. This funtion can be called several times on the +same B to include additional data. + +EVP_SignFinal() signs the data in B using the private key B +and places the signature in B. If the B parameter is not NULL +then the number of bytes of data written (i.e. the length of the signature) +will be written to the integer at B, at most EVP_PKEY_size(pkey) bytes +will be written. After calling EVP_SignFinal() no additional calls to +EVP_SignUpdate() can be made, but EVP_SignInit() can be called to initialiase +a new signature operation. + +EVP_PKEY_size() returns the maximum size of a signature in bytes. The actual +signature returned by EVP_SignFinal() may be smaller. + +=head1 RETURN VALUES + +EVP_SignInit() and EVP_SignUpdate() do not return values. + +EVP_SignFinal() returns 1 for success and 0 for failure. + +EVP_PKEY_size() returns the maximum size of a signature in bytes. + +The error codes can be obtained by L. + +=head1 NOTES + +The B interface to digital signatures should almost always be used in +preference to the low level interfaces. This is because the code then becomes +transparent to the algorithm used and much more flexible. + +Due to the link between message digests and public key algorithms the correct +digest algorithm must be used with the correct public key type. A list of +algorithms and associated public key algorithms appears in +L. + +When signing with DSA private keys the random number generator must be seeded +or the operation will fail. The random number generator does not need to be +seeded for RSA signatures. + +=head1 BUGS + +Several of the functions do not return values: maybe they should. Although the +internal digest operations will never fail some future hardware based operations +might. + +=head1 SEE ALSO + +L, +L, L, +L, L, L, +L, L, L, +L, L + +=head1 HISTORY + +EVP_SignInit(), EVP_SignUpdate() and EVP_SignFinal() are +available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/EVP_VerifyInit.pod b/src/lib/libcrypto/doc/EVP_VerifyInit.pod new file mode 100644 index 0000000000..3b5e07f4ad --- /dev/null +++ b/src/lib/libcrypto/doc/EVP_VerifyInit.pod @@ -0,0 +1,71 @@ +=pod + +=head1 NAME + +EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal - EVP signature verification functions + +=head1 SYNOPSIS + + #include + + void EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); + void EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); + int EVP_VerifyFinal(EVP_MD_CTX *ctx,unsigned char *sigbuf, unsigned int siglen,EVP_PKEY *pkey); + +=head1 DESCRIPTION + +The EVP signature verification routines are a high level interface to digital +signatures. + +EVP_VerifyInit() initialises a verification context B to using digest +B: this will typically be supplied by a function such as EVP_sha1(). + +EVP_VerifyUpdate() hashes B bytes of data at B into the +verification context B. This funtion can be called several times on the +same B to include additional data. + +EVP_VerifyFinal() verifies the data in B using the public key B +and against the B bytes at B. After calling EVP_VerifyFinal() +no additional calls to EVP_VerifyUpdate() can be made, but EVP_VerifyInit() +can be called to initialiase a new verification operation. + +=head1 RETURN VALUES + +EVP_VerifyInit() and EVP_VerifyUpdate() do not return values. + +EVP_VerifyFinal() returns 1 for a correct signature, 0 for failure and -1 if some +other error occurred. + +The error codes can be obtained by L. + +=head1 NOTES + +The B interface to digital signatures should almost always be used in +preference to the low level interfaces. This is because the code then becomes +transparent to the algorithm used and much more flexible. + +Due to the link between message digests and public key algorithms the correct +digest algorithm must be used with the correct public key type. A list of +algorithms and associated public key algorithms appears in +L. + +=head1 BUGS + +Several of the functions do not return values: maybe they should. Although the +internal digest operations will never fail some future hardware based operations +might. + +=head1 SEE ALSO + +L, +L, L, +L, L, L, +L, L, L, +L, L + +=head1 HISTORY + +EVP_VerifyInit(), EVP_VerifyUpdate() and EVP_VerifyFinal() are +available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod b/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod new file mode 100644 index 0000000000..b0b1058d19 --- /dev/null +++ b/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod @@ -0,0 +1,46 @@ +=pod + +=head1 NAME + +OPENSSL_VERSION_NUMBER, SSLeay - get OpenSSL version number + +=head1 SYNOPSIS + + #include + #define OPENSSL_VERSION_NUMBER 0xnnnnnnnnnL + + #include + long SSLeay(void); + +=head1 DESCRIPTION + +OPENSSL_VERSION_NUMBER is a numeric release version identifier: + + MMNNFFRBB major minor fix final beta/patch + +for example + + 0x000904100 == 0.9.4 release + 0x000905000 == 0.9.5 dev + +Versions prior to 0.9.3 have identifiers E 0x0930. +For backward compatibility, SSLEAY_VERSION_NUMBER is also defined. + +SSLeay() returns this number. The return value can be compared to the +macro to make sure that the correct version of the library has been +loaded, especially when using DLLs on Windows systems. + +=head1 RETURN VALUE + +The version number. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +SSLeay() and SSLEAY_VERSION_NUMBER are available in all versions of SSLeay and OpenSSL. +OPENSSL_VERSION_NUMBER is available in all versions of OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod b/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod new file mode 100644 index 0000000000..1300fe190c --- /dev/null +++ b/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod @@ -0,0 +1,65 @@ +=pod + +=head1 NAME + +OpenSSL_add_all_algorithms() - add algorithms to internal table + +=head1 SYNOPSIS + + #include + + void OpenSSL_add_all_algorithms(void); + void OpenSSL_add_all_ciphers(void); + void OpenSSL_add_all_digests(void); + + void EVP_cleanup(void); + +=head1 DESCRIPTION + +OpenSSL keeps an internal table of digest algorithms and ciphers. It uses +this table to lookup ciphers via functions such as EVP_get_cipher_byname(). + +OpenSSL_add_all_digests() adds all digest algorithms to the table. + +OpenSSL_add_all_algorithms() adds all algorithms to the table (digests and +ciphers). + +OpenSSL_add_all_ciphers() adds all encryption algorithms to the table including +password based encryption algorithms. + +EVP_cleanup() removes all ciphers and digests from the table. + +=head1 RETURN VALUES + +None of the functions return a value. + +=head1 NOTES + +A typical application will will call OpenSSL_add_all_algorithms() initially and +EVP_cleanup() before exiting. + +An application does not need to add algorithms to use them explicitly, for example +by EVP_sha1(). It just needs to add them if it (or any of the functions it calls) +needs to lookup algorithms. + +The cipher and digest lookup functions are used in many parts of the library. If +the table is not initialised several functions will misbehave and complain they +cannot find algorithms. This includes the PEM, PKCS#12, SSL and S/MIME libraries. +This is a common query in the OpenSSL mailing lists. + +Calling OpenSSL_add_all_algorithms() links in all algorithms: as a result a +statically linked executable can be quite large. If this is important it is possible +to just add the required ciphers and digests. + +=head1 BUGS + +Although the functions do not return error codes it is possible for them to fail. +This will only happen as a result of a memory allocation failure so this is not +too much of a problem in practice. + +=head1 SEE ALSO + +L, L, +L + +=cut diff --git a/src/lib/libcrypto/doc/RAND_add.pod b/src/lib/libcrypto/doc/RAND_add.pod new file mode 100644 index 0000000000..0a13ec2a92 --- /dev/null +++ b/src/lib/libcrypto/doc/RAND_add.pod @@ -0,0 +1,68 @@ +=pod + +=head1 NAME + +RAND_add, RAND_seed, RAND_screen - add entropy to the PRNG + +=head1 SYNOPSIS + + #include + + void RAND_seed(const void *buf, int num); + + void RAND_add(const void *buf, int num, double entropy); + + int RAND_status(void); + + void RAND_screen(void); + +=head1 DESCRIPTION + +RAND_add() mixes the B bytes at B into the PRNG state. Thus, +if the data at B are unpredictable to an adversary, this +increases the uncertainty about the state and makes the PRNG output +less predictable. Suitable input comes from user interaction (random +key presses, mouse movements) and certain hardware events. The +B argument is (the lower bound of) an estimate of how much +randomness is contained in B, measured in bytes. Details about +sources of randomness and how to estimate their entropy can be found +in the literature, e.g. RFC 1750. + +RAND_add() may be called with sensitive data such as user entered +passwords. The seed values cannot be recovered from the PRNG output. + +OpenSSL makes sure that the PRNG state is unique for each thread. On +systems that provide C, the randomness device is used +to seed the PRNG transparently. However, on all other systems, the +application is responsible for seeding the PRNG by calling RAND_add(), +L +or L. + +RAND_seed() is equivalent to RAND_add() when B. + +The RAND_screen() function is available for the convenience of Windows +programmers. It adds the current contents of the screen to the PRNG. +For applications that can catch Windows events, seeding the PRNG with +the parameters of B events is a significantly better +source of randomness. It should be noted that both methods cannot be +used on servers that run without user interaction. + +=head1 RETURN VALUES + +RAND_status() returns 1 if the PRNG has been seeded with enough data, +0 otherwise. + +The other functions do not return values. + +=head1 SEE ALSO + +L, L, +L, L + +=head1 HISTORY + +RAND_seed() and RAND_screen() are available in all versions of SSLeay +and OpenSSL. RAND_add() and RAND_status() have been added in OpenSSL +0.9.5. + +=cut diff --git a/src/lib/libcrypto/doc/RAND_bytes.pod b/src/lib/libcrypto/doc/RAND_bytes.pod new file mode 100644 index 0000000000..b6ebd50527 --- /dev/null +++ b/src/lib/libcrypto/doc/RAND_bytes.pod @@ -0,0 +1,46 @@ +=pod + +=head1 NAME + +RAND_bytes, RAND_pseudo_bytes - generate random data + +=head1 SYNOPSIS + + #include + + int RAND_bytes(unsigned char *buf, int num); + + int RAND_pseudo_bytes(unsigned char *buf, int num); + +=head1 DESCRIPTION + +RAND_bytes() puts B cryptographically strong pseudo-random bytes +into B. An error occurs if the PRNG has not been seeded with +enough randomness to ensure an unpredictable byte sequence. + +RAND_pseudo_bytes() puts B pseudo-random bytes into B. +Pseudo-random byte sequences generated by RAND_pseudo_bytes() will be +unique if they are of sufficient length, but are not necessarily +unpredictable. They can be used for non-cryptographic purposes and for +certain purposes in cryptographic protocols, but usually not for key +generation etc. + +=head1 RETURN VALUES + +RAND_bytes() returns 1 on success, 0 otherwise. The error code can be +obtained by L. RAND_pseudo_bytes() returns 1 if the +bytes generated are cryptographically strong, 0 otherwise. Both +functions return -1 if they are not supported by the current RAND +method. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +RAND_bytes() is available in all versions of SSLeay and OpenSSL. It +has a return value since OpenSSL 0.9.5. RAND_pseudo_bytes() was added +in OpenSSL 0.9.5. + +=cut diff --git a/src/lib/libcrypto/doc/RAND_cleanup.pod b/src/lib/libcrypto/doc/RAND_cleanup.pod new file mode 100644 index 0000000000..3a8f0749a8 --- /dev/null +++ b/src/lib/libcrypto/doc/RAND_cleanup.pod @@ -0,0 +1,29 @@ +=pod + +=head1 NAME + +RAND_cleanup - erase the PRNG state + +=head1 SYNOPSIS + + #include + + void RAND_cleanup(void); + +=head1 DESCRIPTION + +RAND_cleanup() erases the memory used by the PRNG. + +=head1 RETURN VALUE + +RAND_cleanup() returns no value. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +RAND_cleanup() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/RAND_load_file.pod b/src/lib/libcrypto/doc/RAND_load_file.pod new file mode 100644 index 0000000000..8dd700ca3d --- /dev/null +++ b/src/lib/libcrypto/doc/RAND_load_file.pod @@ -0,0 +1,53 @@ +=pod + +=head1 NAME + +RAND_load_file, RAND_write_file, RAND_file_name - PRNG seed file + +=head1 SYNOPSIS + + #include + + const char *RAND_file_name(char *buf, int num); + + int RAND_load_file(const char *filename, long max_bytes); + + int RAND_write_file(const char *filename); + +=head1 DESCRIPTION + +RAND_file_name() generates a default path for the random seed +file. B points to a buffer of size B in which to store the +filename. The seed file is $RANDFILE if that environment variable is +set, $HOME/.rnd otherwise. If $HOME is not set either, or B is +too small for the path name, an error occurs. + +RAND_load_file() reads a number of bytes from file B and +adds them to the PRNG. If B is non-negative, +up to to B are read; starting with OpenSSL 0.9.5, +if B is -1, the complete file is read. + +RAND_write_file() writes a number of random bytes (currently 1024) to +file B which can be used to initialize the PRNG by calling +RAND_load_file() in a later session. + +=head1 RETURN VALUES + +RAND_load_file() returns the number of bytes read. + +RAND_write_file() returns the number of bytes written, and -1 if the +bytes written were generated without appropriate seed. + +RAND_file_name() returns a pointer to B on success, and NULL on +error. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +RAND_load_file(), RAND_write_file() and RAND_file_name() are available in +all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/RAND_set_rand_method.pod b/src/lib/libcrypto/doc/RAND_set_rand_method.pod new file mode 100644 index 0000000000..466e9b8767 --- /dev/null +++ b/src/lib/libcrypto/doc/RAND_set_rand_method.pod @@ -0,0 +1,57 @@ +=pod + +=head1 NAME + +RAND_set_rand_method, RAND_get_rand_method, RAND_SSLeay - select RAND method + +=head1 SYNOPSIS + + #include + + void RAND_set_rand_method(RAND_METHOD *meth); + + RAND_METHOD *RAND_get_rand_method(void); + + RAND_METHOD *RAND_SSLeay(void); + +=head1 DESCRIPTION + +A B specifies the functions that OpenSSL uses for random +number generation. By modifying the method, alternative +implementations such as hardware RNGs may be used. Initially, the +default is to use the OpenSSL internal implementation. RAND_SSLeay() +returns a pointer to that method. + +RAND_set_rand_method() sets the RAND method to B. +RAND_get_rand_method() returns a pointer to the current method. + +=head1 THE RAND_METHOD STRUCTURE + + 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, int entropy); + int (*pseudorand)(unsigned char *buf, int num); + } RAND_METHOD; + +The components point to the implementation of RAND_seed(), +RAND_bytes(), RAND_cleanup(), RAND_add() and RAND_pseudo_rand(). +Each component may be NULL if the function is not implemented. + +=head1 RETURN VALUES + +RAND_set_rand_method() returns no value. RAND_get_rand_method() and +RAND_SSLeay() return pointers to the respective methods. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +RAND_set_rand_method(), RAND_get_rand_method() and RAND_SSLeay() are +available in all versions of OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_blinding_on.pod b/src/lib/libcrypto/doc/RSA_blinding_on.pod new file mode 100644 index 0000000000..fd2c69abd8 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_blinding_on.pod @@ -0,0 +1,43 @@ +=pod + +=head1 NAME + +RSA_blinding_on, RSA_blinding_off - protect the RSA operation from timing attacks + +=head1 SYNOPSIS + + #include + + int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); + + void RSA_blinding_off(RSA *rsa); + +=head1 DESCRIPTION + +RSA is vulnerable to timing attacks. In a setup where attackers can +measure the time of RSA decryption or signature operations, blinding +must be used to protect the RSA operation from that attack. + +RSA_blinding_on() turns blinding on for key B and generates a +random blinding factor. B is B or a pre-allocated and +initialized B. The random number generator must be seeded +prior to calling RSA_blinding_on(). + +RSA_blinding_off() turns blinding off and frees the memory used for +the blinding factor. + +=head1 RETURN VALUES + +RSA_blinding_on() returns 1 on success, and 0 if an error occurred. + +RSA_blinding_off() returns no value. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +RSA_blinding_on() and RSA_blinding_off() appeared in SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_check_key.pod b/src/lib/libcrypto/doc/RSA_check_key.pod new file mode 100644 index 0000000000..79fed753ad --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_check_key.pod @@ -0,0 +1,39 @@ +=pod + +=head1 NAME + +RSA_check_key - validate private RSA keys + +=head1 SYNOPSIS + + #include + + int RSA_check_key(RSA *rsa); + +=head1 DESCRIPTION + +This function validates RSA keys. It checks that B

and B are +in fact prime, and that B. + +It also checks that B, +and that B, B and B are set correctly or are B. + +The key's public components may not be B. + +=head1 RETURN VALUE + +RSA_check_key() returns 1 if B is a valid RSA key, and 0 otherwise. +-1 is returned if an error occurs while checking the key. + +If the key is invalid or an error occurred, the reason code can be +obtained using L. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +RSA_check() appeared in OpenSSL 0.9.4. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_generate_key.pod b/src/lib/libcrypto/doc/RSA_generate_key.pod new file mode 100644 index 0000000000..fdaddbcb13 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_generate_key.pod @@ -0,0 +1,68 @@ +=pod + +=head1 NAME + +RSA_generate_key - generate RSA key pair + +=head1 SYNOPSIS + + #include + + RSA *RSA_generate_key(int num, unsigned long e, + void (*callback)(int,int,void *), void *cb_arg); + +=head1 DESCRIPTION + +RSA_generate_key() generates a key pair and returns it in a newly +allocated B structure. The pseudo-random number generator must +be seeded prior to calling RSA_generate_key(). + +The modulus size will be B bits, and the public exponent will be +B. Key sizes with B E 1024 should be considered insecure. +The exponent is an odd number, typically 3 or 65535. + +A callback function may be used to provide feedback about the +progress of the key generation. If B is not B, it +will be called as follows: + +=over 4 + +=item * + +While a random prime number is generated, it is called as +described in L. + +=item * + +When the n-th randomly generated prime is rejected as not +suitable for the key, B is called. + +=item * + +When a random p has been found with p-1 relatively prime to B, +it is called as B. + +=back + +The process is then repeated for prime q with B. + +=head1 RETURN VALUE + +If key generation fails, RSA_generate_key() returns B; the +error codes can be obtained by L. + +=head1 BUGS + +B is used with two different meanings. + +RSA_generate_key() goes into an infinite loop for illegal input values. + +=head1 SEE ALSO + +L, L, L, L + +=head1 HISTORY + +The B argument was added in SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod b/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod new file mode 100644 index 0000000000..920dc76325 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod @@ -0,0 +1,122 @@ +=pod + +=head1 NAME + +RSA_get_ex_new_index, RSA_set_ex_data, RSA_get_ex_data - add application specific data to RSA structures + +=head1 SYNOPSIS + + #include + + 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); + + int new_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); + + void free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); + + int dup_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, + int idx, long argl, void *argp); + +=head1 DESCRIPTION + +Several OpenSSL structures can have application specific data attached to them. +This has several potential uses, it can be used to cache data associated with +a structure (for example the hash of some part of the structure) or some +additional data (for example a handle to the data in an external library). + +Since the application data can be anything at all it is passed and retrieved +as a B type. + +The B function is initially called to "register" some +new application specific data. It takes three optional function pointers which +are called when the parent structure (in this case an RSA structure) is +initially created, when it is copied and when it is freed up. If any or all of +these function pointer arguments are not used they should be set to NULL. The +precise manner in which these function pointers are called is described in more +detail below. B also takes additional long and pointer +parameters which will be passed to the supplied functions but which otherwise +have no special meaning. It returns an B which should be stored +(typically in a static variable) and passed used in the B parameter in +the remaining functions. Each successful call to B +will return an index greater than any previously returned, this is important +because the optional functions are called in order of increasing index value. + +B is used to set application specific data, the data is +supplied in the B parameter and its precise meaning is up to the +application. + +B is used to retrieve application specific data. The data +is returned to the application, this will be the same value as supplied to +a previous B call. + +B is called when a structure is initially allocated (for example +with B. The parent structure members will not have any meaningful +values at this point. This function will typically be used to allocate any +application specific structure. + +B is called when a structure is being freed up. The dynamic parent +structure members should not be accessed because they will be freed up when +this function is called. + +B and B take the same parameters. B is a +pointer to the parent RSA structure. B is a the application specific data +(this wont be of much use in B. B is a pointer to the +B structure from the parent RSA structure: the functions +B and B can be called to manipulate +it. The B parameter is the index: this will be the same value returned by +B when the functions were initially registered. Finally +the B and B parameters are the values originally passed to the same +corresponding parameters when B was called. + +B is called when a structure is being copied. Pointers to the +destination and source B structures are passed in the B and +B parameters respectively. The B parameter is passed a pointer to +the source application data when the function is called, when the function returns +the value is copied to the destination: the application can thus modify the data +pointed to by B and have different values in the source and destination. +The B, B and B parameters are the same as those in B +and B. + +=head1 RETURN VALUES + +B returns a new index or -1 on failure (note 0 is a valid +index value). + +B returns 1 on success or 0 on failure. + +B returns the application data or 0 on failure. 0 may also +be valid application data but currently it can only fail if given an invalid B +parameter. + +B and B should return 0 for failure and 1 for success. + +On failure an error code can be obtained from L. + +=head1 BUGS + +B is currently never called. + +The return value of B is ignored. + +The B function isn't very useful because no meaningful values are +present in the parent RSA structure when it is called. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +RSA_get_ex_new_index(), RSA_set_ex_data() and RSA_get_ex_data() are +available since SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_new.pod b/src/lib/libcrypto/doc/RSA_new.pod new file mode 100644 index 0000000000..f16490ea6a --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_new.pod @@ -0,0 +1,38 @@ +=pod + +=head1 NAME + +RSA_new, RSA_free - allocate and free RSA objects + +=head1 SYNOPSIS + + #include + + RSA * RSA_new(void); + + void RSA_free(RSA *rsa); + +=head1 DESCRIPTION + +RSA_new() allocates and initializes an B structure. + +RSA_free() frees the B structure and its components. The key is +erased before the memory is returned to the system. + +=head1 RETURN VALUES + +If the allocation fails, RSA_new() returns B and sets an error +code that can be obtained by L. Otherwise it returns +a pointer to the newly allocated structure. + +RSA_free() returns no value. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +RSA_new() and RSA_free() are available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_padding_add_PKCS1_type_1.pod b/src/lib/libcrypto/doc/RSA_padding_add_PKCS1_type_1.pod new file mode 100644 index 0000000000..b8f678fe72 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_padding_add_PKCS1_type_1.pod @@ -0,0 +1,124 @@ +=pod + +=head1 NAME + +RSA_padding_add_PKCS1_type_1, RSA_padding_check_PKCS1_type_1, +RSA_padding_add_PKCS1_type_2, RSA_padding_check_PKCS1_type_2, +RSA_padding_add_PKCS1_OAEP, RSA_padding_check_PKCS1_OAEP, +RSA_padding_add_SSLv23, RSA_padding_check_SSLv23, +RSA_padding_add_none, RSA_padding_check_none - asymmetric encryption +padding + +=head1 SYNOPSIS + + #include + + 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); + +=head1 DESCRIPTION + +The RSA_padding_xxx_xxx() functions are called from the RSA encrypt, +decrypt, sign and verify functions. Normally they should not be called +from application programs. + +However, they can also be called directly to implement padding for other +asymmetric ciphers. RSA_padding_add_PKCS1_OAEP() and +RSA_padding_check_PKCS1_OAEP() may be used in an application combined +with B in order to implement OAEP with an encoding +parameter. + +RSA_padding_add_xxx() encodes B bytes from B so as to fit into +B bytes and stores the result at B. An error occurs if B +does not meet the size requirements of the encoding method. + +The following encoding methods are implemented: + +=over 4 + +=item PKCS1_type_1 + +PKCS #1 v2.0 EMSA-PKCS1-v1_5 (PKCS #1 v1.5 block type 1); used for signatures + +=item PKCS1_type_2 + +PKCS #1 v2.0 EME-PKCS1-v1_5 (PKCS #1 v1.5 block type 2) + +=item PKCS1_OAEP + +PKCS #1 v2.0 EME-OAEP + +=item SSLv23 + +PKCS #1 EME-PKCS1-v1_5 with SSL-specific modification + +=item none + +simply copy the data + +=back + +The random number generator must be seeded prior to calling +RSA_padding_add_xxx(). + +RSA_padding_check_xxx() verifies that the B bytes at B contain +a valid encoding for a B byte RSA key in the respective +encoding method and stores the recovered data of at most B bytes +(for B: of size B) +at B. + +For RSA_padding_xxx_OAEP(), B

points to the encoding parameter +of length B. B

may be B if B is 0. + +=head1 RETURN VALUES + +The RSA_padding_add_xxx() functions return 1 on success, 0 on error. +The RSA_padding_check_xxx() functions return the length of the +recovered data, -1 on error. Error codes can be obtained by calling +L. + +=head1 SEE ALSO + +L, +L, +L, L + +=head1 HISTORY + +RSA_padding_add_PKCS1_type_1(), RSA_padding_check_PKCS1_type_1(), +RSA_padding_add_PKCS1_type_2(), RSA_padding_check_PKCS1_type_2(), +RSA_padding_add_SSLv23(), RSA_padding_check_SSLv23(), +RSA_padding_add_none() and RSA_padding_check_none() appeared in +SSLeay 0.9.0. + +RSA_padding_add_PKCS1_OAEP() and RSA_padding_check_PKCS1_OAEP() were +added in OpenSSL 0.9.2b. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_print.pod b/src/lib/libcrypto/doc/RSA_print.pod new file mode 100644 index 0000000000..dd968a5274 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_print.pod @@ -0,0 +1,48 @@ +=pod + +=head1 NAME + +RSA_print, RSA_print_fp, DHparams_print, DHparams_print_fp - print +cryptographic parameters + +=head1 SYNOPSIS + + #include + + int RSA_print(BIO *bp, RSA *x, int offset); + int RSA_print_fp(FILE *fp, RSA *x, int offset); + + #include + + int DSAparams_print(BIO *bp, DSA *x); + int DSAparams_print_fp(FILE *fp, DSA *x); + int DSA_print(BIO *bp, DSA *x, int offset); + int DSA_print_fp(FILE *fp, DSA *x, int offset); + + #include + + int DHparams_print(BIO *bp, DH *x); + int DHparams_print_fp(FILE *fp, DH *x); + +=head1 DESCRIPTION + +A human-readable hexadecimal output of the components of the RSA +key, DSA parameters or key or DH parameters is printed to B or B. + +The output lines are indented by B spaces. + +=head1 RETURN VALUES + +These functions return 1 on success, 0 on error. + +=head1 SEE ALSO + +L, L, L, L + +=head1 HISTORY + +RSA_print(), RSA_print_fp(), DSA_print(), DSA_print_fp(), DH_print(), +DH_print_fp() are available in all versions of SSLeay and OpenSSL. +DSAparams_print() and DSAparams_print_pf() were added in SSLeay 0.8. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_private_encrypt.pod b/src/lib/libcrypto/doc/RSA_private_encrypt.pod new file mode 100644 index 0000000000..6861a98a10 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_private_encrypt.pod @@ -0,0 +1,69 @@ +=pod + +=head1 NAME + +RSA_private_encrypt, RSA_public_decrypt - low level signature operations + +=head1 SYNOPSIS + + #include + + 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); + +=head1 DESCRIPTION + +These functions handle RSA signatures at a low level. + +RSA_private_encrypt() signs the B bytes at B (usually a +message digest with an algorithm identifier) using the private key +B and stores the signature in B. B must point to +B bytes of memory. + +B denotes one of the following modes: + +=over 4 + +=item RSA_PKCS1_PADDING + +PKCS #1 v1.5 padding. This function does not handle the +B specified in PKCS #1. When generating or +verifying PKCS #1 signatures, L and L should be +used. + +=item RSA_NO_PADDING + +Raw RSA signature. This mode should I be used to implement +cryptographically sound padding modes in the application code. +Signing user data directly with RSA is insecure. + +=back + +RSA_public_decrypt() recovers the message digest from the B +bytes long signature at B using the signer's public key +B. B must point to a memory section large enough to hold the +message digest (which is smaller than B). B is the padding mode that was used to sign the data. + +=head1 RETURN VALUES + +RSA_private_encrypt() returns the size of the signature (i.e., +RSA_size(rsa)). RSA_public_decrypt() returns the size of the +recovered message digest. + +On error, -1 is returned; the error codes can be +obtained by L. + +=head1 SEE ALSO + +L, L, L, L + +=head1 HISTORY + +The B argument was added in SSLeay 0.8. RSA_NO_PADDING is +available since SSLeay 0.9.0. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_public_encrypt.pod b/src/lib/libcrypto/doc/RSA_public_encrypt.pod new file mode 100644 index 0000000000..910c4752b8 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_public_encrypt.pod @@ -0,0 +1,86 @@ +=pod + +=head1 NAME + +RSA_public_encrypt, RSA_private_decrypt - RSA public key cryptography + +=head1 SYNOPSIS + + #include + + int RSA_public_encrypt(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); + +=head1 DESCRIPTION + +RSA_public_encrypt() encrypts the B bytes at B (usually a +session key) using the public key B and stores the ciphertext in +B. B must point to RSA_size(B) bytes of memory. + +B denotes one of the following modes: + +=over 4 + +=item RSA_PKCS1_PADDING + +PKCS #1 v1.5 padding. This currently is the most widely used mode. + +=item RSA_PKCS1_OAEP_PADDING + +EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty +encoding parameter. This mode is recommended for all new applications. + +=item RSA_SSLV23_PADDING + +PKCS #1 v1.5 padding with an SSL-specific modification that denotes +that the server is SSL3 capable. + +=item RSA_NO_PADDING + +Raw RSA encryption. This mode should I be used to implement +cryptographically sound padding modes in the application code. +Encrypting user data directly with RSA is insecure. + +=back + +B must be less than RSA_size(B) - 11 for the PKCS #1 v1.5 +based padding modes, and less than RSA_size(B) - 21 for +RSA_PKCS1_OAEP_PADDING. The random number generator must be seeded +prior to calling RSA_public_encrypt(). + +RSA_private_decrypt() decrypts the B bytes at B using the +private key B and stores the plaintext in B. B must point +to a memory section large enough to hold the decrypted data (which is +smaller than RSA_size(B)). B is the padding mode that +was used to encrypt the data. + +=head1 RETURN VALUES + +RSA_public_encrypt() returns the size of the encrypted data (i.e., +RSA_size(B)). RSA_private_decrypt() returns the size of the +recovered plaintext. + +On error, -1 is returned; the error codes can be +obtained by L. + +=head1 CONFORMING TO + +SSL, PKCS #1 v2.0 + +=head1 SEE ALSO + +L, L, L, L + +=head1 NOTES + +The L method supports only the RSA_PKCS1_PADDING mode. + +=head1 HISTORY + +The B argument was added in SSLeay 0.8. RSA_NO_PADDING is +available since SSLeay 0.9.0, OAEP was added in OpenSSL 0.9.2b. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_set_method.pod b/src/lib/libcrypto/doc/RSA_set_method.pod new file mode 100644 index 0000000000..deb1183a23 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_set_method.pod @@ -0,0 +1,153 @@ +=pod + +=head1 NAME + +RSA_set_default_method, RSA_get_default_method, RSA_set_method, +RSA_get_method, RSA_PKCS1_SSLeay, RSA_PKCS1_RSAref, +RSA_PKCS1_null_method, RSA_flags, RSA_new_method - select RSA method + +=head1 SYNOPSIS + + #include + + void RSA_set_default_method(RSA_METHOD *meth); + + RSA_METHOD *RSA_get_default_method(void); + + RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth); + + RSA_METHOD *RSA_get_method(RSA *rsa); + + RSA_METHOD *RSA_PKCS1_SSLeay(void); + + RSA_METHOD *RSA_PKCS1_RSAref(void); + + RSA_METHOD *RSA_null_method(void); + + int RSA_flags(RSA *rsa); + + RSA *RSA_new_method(RSA_METHOD *method); + +=head1 DESCRIPTION + +An B specifies the functions that OpenSSL uses for RSA +operations. By modifying the method, alternative implementations +such as hardware accelerators may be used. + +Initially, the default is to use the OpenSSL internal implementation, +unless OpenSSL was configured with the C or C<-DRSA_NULL> +options. RSA_PKCS1_SSLeay() returns a pointer to that method. + +RSA_PKCS1_RSAref() returns a pointer to a method that uses the RSAref +library. This is the default method in the C configuration; +the function is not available in other configurations. +RSA_null_method() returns a pointer to a method that does not support +the RSA transformation. It is the default if OpenSSL is compiled with +C<-DRSA_NULL>. These methods may be useful in the USA because of a +patent on the RSA cryptosystem. + +RSA_set_default_method() makes B the default method for all B +structures created later. + +RSA_get_default_method() returns a pointer to the current default +method. + +RSA_set_method() selects B for all operations using the key +B. + +RSA_get_method() returns a pointer to the method currently selected +for B. + +RSA_flags() returns the B that are set for B's current method. + +RSA_new_method() allocates and initializes an B structure so that +B will be used for the RSA operations. If B is B, +the default method is used. + +=head1 THE RSA_METHOD STRUCTURE + + typedef struct rsa_meth_st + { + /* name of the implementation */ + const char *name; + + /* encrypt */ + int (*rsa_pub_enc)(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + + /* verify arbitrary data */ + int (*rsa_pub_dec)(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + + /* sign arbitrary data */ + int (*rsa_priv_enc)(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + + /* decrypt */ + int (*rsa_priv_dec)(int flen, unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + + /* compute r0 = r0 ^ I mod rsa->n. May be NULL */ + int (*rsa_mod_exp)(BIGNUM *r0, BIGNUM *I, RSA *rsa); + + /* compute r = a ^ p mod m. May be NULL */ + int (*bn_mod_exp)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + + /* called at RSA_new */ + int (*init)(RSA *rsa); + + /* called at RSA_free */ + int (*finish)(RSA *rsa); + + /* RSA_FLAG_EXT_PKEY - rsa_mod_exp is called for private key + * operations, even if p,q,dmp1,dmq1,iqmp + * are NULL + * RSA_FLAG_SIGN_VER - enable rsa_sign and rsa_verify + * RSA_METHOD_FLAG_NO_CHECK - don't check pub/private match + */ + int flags; + + char *app_data; /* ?? */ + + /* sign. For backward compatibility, this is used only + * if (flags & RSA_FLAG_SIGN_VER) + */ + int (*rsa_sign)(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); + + /* verify. For backward compatibility, this is used only + * if (flags & RSA_FLAG_SIGN_VER) + */ + int (*rsa_verify)(int type, unsigned char *m, unsigned int m_len, + unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + + } RSA_METHOD; + +=head1 RETURN VALUES + +RSA_PKCS1_SSLeay(), RSA_PKCS1_RSAref(), RSA_PKCS1_null_method(), +RSA_get_default_method() and RSA_get_method() return pointers to the +respective Bs. + +RSA_set_default_method() returns no value. + +RSA_set_method() returns a pointer to the B previously +associated with B. + +RSA_new_method() returns B and sets an error code that can be +obtained by L if the allocation fails. Otherwise it +returns a pointer to the newly allocated structure. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +RSA_new_method() and RSA_set_default_method() appeared in SSLeay 0.8. +RSA_get_default_method(), RSA_set_method() and RSA_get_method() as +well as the rsa_sign and rsa_verify components of RSA_METHOD were +added in OpenSSL 0.9.4. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_sign.pod b/src/lib/libcrypto/doc/RSA_sign.pod new file mode 100644 index 0000000000..f0bf6eea1b --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_sign.pod @@ -0,0 +1,62 @@ +=pod + +=head1 NAME + +RSA_sign, RSA_verify - RSA signatures + +=head1 SYNOPSIS + + #include + + 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); + +=head1 DESCRIPTION + +RSA_sign() signs the message digest B of size B using the +private key B as specified in PKCS #1 v2.0. It stores the +signature in B and the signature size in B. B +must point to RSA_size(B) bytes of memory. + +B denotes the message digest algorithm that was used to generate +B. It usually is one of B, B and B; +see L for details. If B is B, +an SSL signature (MD5 and SHA1 message digests with PKCS #1 padding +and no algorithm identifier) is created. + +RSA_verify() verifies that the signature B of size B +matches a given message digest B of size B. B denotes +the message digest algorithm that was used to generate the signature. +B is the signer's public key. + +=head1 RETURN VALUES + +RSA_sign() returns 1 on success, 0 otherwise. RSA_verify() returns 1 +on successful verification, 0 otherwise. + +The error codes can be obtained by L. + +=head1 BUGS + +Certain signatures with an improper algorithm identifier are accepted +for compatibility with SSLeay 0.4.5 :-) + +=head1 CONFORMING TO + +SSL, PKCS #1 v2.0 + +=head1 SEE ALSO + +L, L, L, +L, +L + +=head1 HISTORY + +RSA_sign() and RSA_verify() are available in all versions of SSLeay +and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_sign_ASN1_OCTET_STRING.pod b/src/lib/libcrypto/doc/RSA_sign_ASN1_OCTET_STRING.pod new file mode 100644 index 0000000000..df9ceb339a --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_sign_ASN1_OCTET_STRING.pod @@ -0,0 +1,59 @@ +=pod + +=head1 NAME + +RSA_sign_ASN1_OCTET_STRING, RSA_verify_ASN1_OCTET_STRING - RSA signatures + +=head1 SYNOPSIS + + #include + + int RSA_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m, + unsigned int m_len, unsigned char *sigret, unsigned int *siglen, + RSA *rsa); + + int RSA_verify_ASN1_OCTET_STRING(int dummy, unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + RSA *rsa); + +=head1 DESCRIPTION + +RSA_sign_ASN1_OCTET_STRING() signs the octet string B of size +B using the private key B represented in DER using PKCS #1 +padding. It stores the signature in B and the signature size +in B. B must point to B bytes of +memory. + +B is ignored. + +The random number generator must be seeded prior to calling RSA_sign_ASN1_OCTET_STRING(). + +RSA_verify_ASN1_OCTET_STRING() verifies that the signature B +of size B is the DER representation of a given octet string +B of size B. B is ignored. B is the signer's +public key. + +=head1 RETURN VALUES + +RSA_sign_ASN1_OCTET_STRING() returns 1 on success, 0 otherwise. +RSA_verify_ASN1_OCTET_STRING() returns 1 on successful verification, 0 +otherwise. + +The error codes can be obtained by L. + +=head1 BUGS + +These functions serve no recognizable purpose. + +=head1 SEE ALSO + +L, L, L, +L, L, +L + +=head1 HISTORY + +RSA_sign_ASN1_OCTET_STRING() and RSA_verify_ASN1_OCTET_STRING() were +added in SSLeay 0.8. + +=cut diff --git a/src/lib/libcrypto/doc/RSA_size.pod b/src/lib/libcrypto/doc/RSA_size.pod new file mode 100644 index 0000000000..b36b4d58d5 --- /dev/null +++ b/src/lib/libcrypto/doc/RSA_size.pod @@ -0,0 +1,33 @@ +=pod + +=head1 NAME + +RSA_size - get RSA modulus size + +=head1 SYNOPSIS + + #include + + int RSA_size(RSA *rsa); + +=head1 DESCRIPTION + +This function returns the RSA modulus size in bytes. It can be used to +determine how much memory must be allocated for an RSA encrypted +value. + +Bn> must not be B. + +=head1 RETURN VALUE + +The size in bytes. + +=head1 SEE ALSO + +L + +=head1 HISTORY + +RSA_size() is available in all versions of SSLeay and OpenSSL. + +=cut diff --git a/src/lib/libcrypto/doc/bn.pod b/src/lib/libcrypto/doc/bn.pod new file mode 100644 index 0000000000..1504a1c92d --- /dev/null +++ b/src/lib/libcrypto/doc/bn.pod @@ -0,0 +1,148 @@ +=pod + +=head1 NAME + +bn - multiprecision integer arithmetics + +=head1 SYNOPSIS + + #include + + BIGNUM *BN_new(void); + void BN_free(BIGNUM *a); + void BN_init(BIGNUM *); + void BN_clear(BIGNUM *a); + void BN_clear_free(BIGNUM *a); + + BN_CTX *BN_CTX_new(void); + void BN_CTX_init(BN_CTX *c); + void BN_CTX_free(BN_CTX *c); + + BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); + BIGNUM *BN_dup(const BIGNUM *a); + + int BN_num_bytes(const BIGNUM *a); + int BN_num_bits(const BIGNUM *a); + int BN_num_bits_word(BN_ULONG w); + + int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b); + int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); + int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, + BN_CTX *ctx); + int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx); + int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); + int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); + 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_gcd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); + + int BN_add_word(BIGNUM *a, BN_ULONG w); + int BN_sub_word(BIGNUM *a, BN_ULONG w); + int BN_mul_word(BIGNUM *a, BN_ULONG w); + BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); + BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); + + int BN_cmp(BIGNUM *a, BIGNUM *b); + int BN_ucmp(BIGNUM *a, BIGNUM *b); + int BN_is_zero(BIGNUM *a); + int BN_is_one(BIGNUM *a); + int BN_is_word(BIGNUM *a, BN_ULONG w); + int BN_is_odd(BIGNUM *a); + + int BN_zero(BIGNUM *a); + int BN_one(BIGNUM *a); + BIGNUM *BN_value_one(void); + int BN_set_word(BIGNUM *a, unsigned long w); + unsigned long BN_get_word(BIGNUM *a); + + int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); + int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); + + 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_set_bit(BIGNUM *a, int n); + int BN_clear_bit(BIGNUM *a, int n); + int BN_is_bit_set(const BIGNUM *a, int n); + int BN_mask_bits(BIGNUM *a, int n); + int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); + int BN_lshift1(BIGNUM *r, BIGNUM *a); + int BN_rshift(BIGNUM *r, BIGNUM *a, int n); + int BN_rshift1(BIGNUM *r, BIGNUM *a); + + int BN_bn2bin(const BIGNUM *a, unsigned char *to); + BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); + 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_print(BIO *fp, const BIGNUM *a); + int BN_print_fp(FILE *fp, const BIGNUM *a); + int BN_bn2mpi(const BIGNUM *a, unsigned char *to); + BIGNUM *BN_mpi2bn(unsigned char *s, int len, BIGNUM *ret); + + BIGNUM *BN_mod_inverse(BIGNUM *r, BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + + BN_RECP_CTX *BN_RECP_CTX_new(void); + void BN_RECP_CTX_init(BN_RECP_CTX *recp); + void BN_RECP_CTX_free(BN_RECP_CTX *recp); + int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *m, BN_CTX *ctx); + int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *a, BIGNUM *b, + BN_RECP_CTX *recp, BN_CTX *ctx); + + BN_MONT_CTX *BN_MONT_CTX_new(void); + void BN_MONT_CTX_init(BN_MONT_CTX *ctx); + void BN_MONT_CTX_free(BN_MONT_CTX *mont); + int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *m, BN_CTX *ctx); + BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from); + 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); + int BN_to_montgomery(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); + + +=head1 DESCRIPTION + +This library performs arithmetic operations on integers of arbitrary +size. It was written for use in public key cryptography, such as RSA +and Diffie-Hellman. + +It uses dynamic memory allocation for storing its data structures. +That means that there is no limit on the size of the numbers +manipulated by these functions, but return values must always be +checked in case a memory allocation error has occurred. + +The basic object in this library is a B. It is used to hold a +single large integer. This type should be considered opaque and fields +should not be modified or accessed directly. + +The creation of B objects is described in L; +L describes most of the arithmetic operations. +Comparison is described in L; L +describes certain assignments, L the generation of +random numbers, L deals with prime +numbers and L with bit operations. The conversion +of Bs to external formats is described in L. + +=head1 SEE ALSO + +L, +L, L, L, L, +L, L, +L, L, +L, L, +L, L, L, +L, L, +L, L, +L, +L + +=cut diff --git a/src/lib/libcrypto/doc/d2i_DHparams.pod b/src/lib/libcrypto/doc/d2i_DHparams.pod new file mode 100644 index 0000000000..a6d1743d39 --- /dev/null +++ b/src/lib/libcrypto/doc/d2i_DHparams.pod @@ -0,0 +1,30 @@ +=pod + +=head1 NAME + +d2i_DHparams, i2d_DHparams - ... + +=head1 SYNOPSIS + + #include + + DH *d2i_DHparams(DH **a, unsigned char **pp, long length); + int i2d_DHparams(DH *a, unsigned char **pp); + +=head1 DESCRIPTION + +... + +=head1 RETURN VALUES + +... + +=head1 SEE ALSO + +... + +=head1 HISTORY + +... + +=cut diff --git a/src/lib/libcrypto/doc/d2i_RSAPublicKey.pod b/src/lib/libcrypto/doc/d2i_RSAPublicKey.pod new file mode 100644 index 0000000000..ff4d0d57db --- /dev/null +++ b/src/lib/libcrypto/doc/d2i_RSAPublicKey.pod @@ -0,0 +1,39 @@ +=pod + +=head1 NAME + +d2i_RSAPublicKey, i2d_RSAPublicKey, d2i_RSAPrivateKey, i2d_RSAPrivateKey, i2d_Netscape_RSA, d2i_Netscape_RSA - ... + +=head1 SYNOPSIS + + #include + + 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); + + int i2d_Netscape_RSA(RSA *a, unsigned char **pp, int (*cb)()); + + RSA * d2i_Netscape_RSA(RSA **a, unsigned char **pp, long length, int (*cb)()); + +=head1 DESCRIPTION + +... + +=head1 RETURN VALUES + +... + +=head1 SEE ALSO + +... + +=head1 HISTORY + +... + +=cut diff --git a/src/lib/libcrypto/doc/dh.pod b/src/lib/libcrypto/doc/dh.pod new file mode 100644 index 0000000000..0a9b7c03a2 --- /dev/null +++ b/src/lib/libcrypto/doc/dh.pod @@ -0,0 +1,68 @@ +=pod + +=head1 NAME + +dh - Diffie-Hellman key agreement + +=head1 SYNOPSIS + + #include + + DH * DH_new(void); + void DH_free(DH *dh); + + int DH_size(DH *dh); + + 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); + + 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_METHOD *DH_OpenSSL(void); + + int DH_get_ex_new_index(long argl, char *argp, int (*new_func)(), + int (*dup_func)(), void (*free_func)()); + int DH_set_ex_data(DH *d, int idx, char *arg); + char *DH_get_ex_data(DH *d, int idx); + + DH * d2i_DHparams(DH **a, unsigned char **pp, long length); + int i2d_DHparams(DH *a, unsigned char **pp); + + int DHparams_print_fp(FILE *fp, DH *x); + int DHparams_print(BIO *bp, DH *x); + +=head1 DESCRIPTION + +These functions implement the Diffie-Hellman key agreement protocol. +The generation of shared DH parameters is described in +L; L describes how +to perform a key agreement. + +The B structure consists of several BIGNUM components. + + struct + { + BIGNUM *p; // prime number (shared) + BIGNUM *g; // generator of Z_p (shared) + BIGNUM *priv_key; // private DH value x + BIGNUM *pub_key; // public DH value g^x + // ... + }; + DH + +=head1 SEE ALSO + +L, L, L, L, +L, L, L, +L, L, +L, +L, L, +L + +=cut diff --git a/src/lib/libcrypto/doc/dsa.pod b/src/lib/libcrypto/doc/dsa.pod new file mode 100644 index 0000000000..2c09244899 --- /dev/null +++ b/src/lib/libcrypto/doc/dsa.pod @@ -0,0 +1,104 @@ +=pod + +=head1 NAME + +dsa - Digital Signature Algorithm + +=head1 SYNOPSIS + + #include + + DSA * DSA_new(void); + void DSA_free(DSA *dsa); + + int DSA_size(DSA *dsa); + + 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); + + DH * DSA_dup_DH(DSA *r); + + int DSA_generate_key(DSA *dsa); + + int DSA_sign(int dummy, const unsigned char *dgst, int len, + unsigned char *sigret, unsigned int *siglen, DSA *dsa); + int DSA_sign_setup(DSA *dsa, BN_CTX *ctx, BIGNUM **kinvp, + BIGNUM **rp); + int DSA_verify(int dummy, const unsigned char *dgst, int len, + unsigned char *sigbuf, int siglen, DSA *dsa); + + void DSA_set_default_method(DSA_METHOD *meth); + DSA_METHOD *DSA_get_default_method(void); + DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *meth); + DSA *DSA_new_method(DSA_METHOD *meth); + DSA_METHOD *DSA_OpenSSL(void); + + int DSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), + int (*dup_func)(), void (*free_func)()); + int DSA_set_ex_data(DSA *d, int idx, char *arg); + char *DSA_get_ex_data(DSA *d, int idx); + + 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); + + 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); + int i2d_DSAPublicKey(DSA *a, unsigned char **pp); + int i2d_DSAPrivateKey(DSA *a, unsigned char **pp); + int i2d_DSAparams(DSA *a,unsigned char **pp); + + int DSAparams_print(BIO *bp, DSA *x); + int DSAparams_print_fp(FILE *fp, DSA *x); + int DSA_print(BIO *bp, DSA *x, int off); + int DSA_print_fp(FILE *bp, DSA *x, int off); + +=head1 DESCRIPTION + +These functions implement the Digital Signature Algorithm (DSA). The +generation of shared DSA parameters is described in +L; +L describes how to +generate a signature key. Signature generation and verification are +described in L. + +The B structure consists of several BIGNUM components. + + struct + { + BIGNUM *p; // prime number (public) + BIGNUM *q; // 160-bit subprime, q | p-1 (public) + BIGNUM *g; // generator of subgroup (public) + BIGNUM *priv_key; // private key x + BIGNUM *pub_key; // public key y = g^x + // ... + } + DSA; + +In public keys, B is NULL. + +=head1 CONFORMING TO + +US Federal Information Processing Standard FIPS 186 (Digital Signature +Standard, DSS), ANSI X9.30 + +=head1 SEE ALSO + +L, L, L, L, +L, L, L, +L, +L, +L, +L, +L, L, +L, +L + +=cut diff --git a/src/lib/libcrypto/doc/evp.pod b/src/lib/libcrypto/doc/evp.pod new file mode 100644 index 0000000000..f089dd49a2 --- /dev/null +++ b/src/lib/libcrypto/doc/evp.pod @@ -0,0 +1,37 @@ +=pod + +=head1 NAME + +evp - high-level cryptographic functions + +=head1 SYNOPSIS + + #include + +=head1 DESCRIPTION + +The EVP library provided a high-level interface to cryptographic +functions. + +BI<...> and BI<...> provide public key encryption +and decryption to implement digital "envelopes". + +The BI<...> and BI<...> functions implement +digital signatures. + +Symmetric encryption is available with the BI<...> +functions. The BI<...> functions provide message digests. + +Algorithms are loaded with OpenSSL_add_all_algorithms(3). + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L, +L + +=cut diff --git a/src/lib/libcrypto/doc/lh_stats.pod b/src/lib/libcrypto/doc/lh_stats.pod new file mode 100644 index 0000000000..3eeaa72e52 --- /dev/null +++ b/src/lib/libcrypto/doc/lh_stats.pod @@ -0,0 +1,60 @@ +=pod + +=head1 NAME + +lh_stats, lh_node_stats, lh_node_usage_stats, lh_stats_bio, +lh_node_stats_bio, lh_node_usage_stats_bio - LHASH statistics + +=head1 SYNOPSIS + + #include + + void lh_stats(LHASH *table, FILE *out); + void lh_node_stats(LHASH *table, FILE *out); + void lh_node_usage_stats(LHASH *table, FILE *out); + + void lh_stats_bio(LHASH *table, BIO *out); + void lh_node_stats_bio(LHASH *table, BIO *out); + void lh_node_usage_stats_bio(LHASH *table, BIO *out); + +=head1 DESCRIPTION + +The B structure records statistics about most aspects of +accessing the hash table. This is mostly a legacy of Eric Young +writing this library for the reasons of implementing what looked like +a nice algorithm rather than for a particular software product. + +lh_stats() prints out statistics on the size of the hash table, how +many entries are in it, and the number and result of calls to the +routines in this library. + +lh_node_stats() prints the number of entries for each 'bucket' in the +hash table. + +lh_node_usage_stats() prints out a short summary of the state of the +hash table. It prints the 'load' and the 'actual load'. The load is +the average number of data items per 'bucket' in the hash table. The +'actual load' is the average number of items per 'bucket', but only +for buckets which contain entries. So the 'actual load' is the +average number of searches that will need to find an item in the hash +table, while the 'load' is the average number that will be done to +record a miss. + +lh_stats_bio(), lh_node_stats_bio() and lh_node_usage_stats_bio() +are the same as the above, except that the output goes to a B. + +=head1 RETURN VALUES + +These functions do not return values. + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +These functions are available in all versions of SSLeay and OpenSSL. + +This manpage is derived from the SSLeay documentation. + +=cut diff --git a/src/lib/libcrypto/doc/rsa.pod b/src/lib/libcrypto/doc/rsa.pod new file mode 100644 index 0000000000..0486c044a6 --- /dev/null +++ b/src/lib/libcrypto/doc/rsa.pod @@ -0,0 +1,115 @@ +=pod + +=head1 NAME + +rsa - RSA public key cryptosystem + +=head1 SYNOPSIS + + #include + + RSA * RSA_new(void); + void RSA_free(RSA *rsa); + + int RSA_public_encrypt(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); + + 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); + + int RSA_size(RSA *rsa); + + RSA *RSA_generate_key(int num, unsigned long e, + void (*callback)(int,int,void *), void *cb_arg); + + int RSA_check_key(RSA *rsa); + + int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); + void RSA_blinding_off(RSA *rsa); + + void RSA_set_default_method(RSA_METHOD *meth); + RSA_METHOD *RSA_get_default_method(void); + RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth); + RSA_METHOD *RSA_get_method(RSA *rsa); + RSA_METHOD *RSA_PKCS1_SSLeay(void); + RSA_METHOD *RSA_PKCS1_RSAref(void); + RSA_METHOD *RSA_null_method(void); + int RSA_flags(RSA *rsa); + RSA *RSA_new_method(RSA_METHOD *method); + + int RSA_print(BIO *bp, RSA *x, int offset); + int RSA_print_fp(FILE *fp, RSA *x, int offset); + + int RSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), + int (*dup_func)(), void (*free_func)()); + int RSA_set_ex_data(RSA *r,int idx,char *arg); + char *RSA_get_ex_data(RSA *r, int idx); + + 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_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m, + unsigned int m_len, unsigned char *sigret, unsigned int *siglen, + RSA *rsa); + int RSA_verify_ASN1_OCTET_STRING(int dummy, unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + RSA *rsa); + +=head1 DESCRIPTION + +These functions implement RSA public key encryption and signatures +as defined in PKCS #1 v2.0 [RFC 2437]. + +The B structure consists of several BIGNUM components. It can +contain public as well as private RSA keys: + + struct + { + BIGNUM *n; // public modulus + BIGNUM *e; // public exponent + BIGNUM *d; // private exponent + BIGNUM *p; // secret prime factor + BIGNUM *q; // secret prime factor + BIGNUM *dmp1; // d mod (p-1) + BIGNUM *dmq1; // d mod (q-1) + BIGNUM *iqmp; // q^-1 mod p + // ... + }; + RSA + +In public keys, the private exponent and the related secret values are +B. + +B, B and B may be B in private keys, but the +RSA operations are much faster when these values are available. + +=head1 CONFORMING TO + +SSL, PKCS #1 v2.0 + +=head1 PATENTS + +RSA is covered by a US patent which expires in September 2000. + +=head1 SEE ALSO + +L, L, L, L, +L, L, +L, +L, L, +L, +L, +L, +L, L, +L, +L, +L, +L + +=cut diff --git a/src/lib/libcrypto/dsa/dsa_asn1.c b/src/lib/libcrypto/dsa/dsa_asn1.c new file mode 100644 index 0000000000..7523b21654 --- /dev/null +++ b/src/lib/libcrypto/dsa/dsa_asn1.c @@ -0,0 +1,96 @@ +/* crypto/dsa/dsa_asn1.c */ + +#include +#include "cryptlib.h" +#include +#include +#include + +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); +} + +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; + 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) ASN1_BIT_STRING_free(bs); + return(NULL); +} diff --git a/src/lib/libcrypto/dsa/dsa_ossl.c b/src/lib/libcrypto/dsa/dsa_ossl.c new file mode 100644 index 0000000000..b51cf6ad8d --- /dev/null +++ b/src/lib/libcrypto/dsa/dsa_ossl.c @@ -0,0 +1,321 @@ +/* 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 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 +}; + +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/src/lib/libcrypto/dso/dso.h b/src/lib/libcrypto/dso/dso.h new file mode 100644 index 0000000000..bed7c464a6 --- /dev/null +++ b/src/lib/libcrypto/dso/dso.h @@ -0,0 +1,250 @@ +/* dso.h */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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). + * + */ + +#ifndef HEADER_DSO_H +#define HEADER_DSO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* These values are used as commands to DSO_ctrl() */ +#define DSO_CTRL_GET_FLAGS 1 +#define DSO_CTRL_SET_FLAGS 2 +#define DSO_CTRL_OR_FLAGS 3 + +/* These flags control the translation of file-names from canonical to + * native. Eg. in the CryptoSwift support, the "dl" and "dlfcn" + * methods will translate "swift" -> "libswift.so" whereas the "win32" + * method will translate "swift" -> "swift.dll". NB: Until I can figure + * out how to be more "conventional" with this, the methods will only + * honour this flag if it looks like it was passed a file without any + * path and if the filename is small enough. + */ +#define DSO_FLAG_NAME_TRANSLATION 0x01 + +/* The following flag controls the translation of symbol names to upper + * case. This is currently only being implemented for OpenVMS. + */ +#define DSO_FLAG_UPCASE_SYMBOL 0x02 + + +typedef void (*DSO_FUNC_TYPE)(void); + +typedef struct dso_st DSO; + +typedef struct dso_meth_st + { + const char *name; + /* Loads a shared library */ + int (*dso_load)(DSO *dso, const char *filename); + /* Unloads a shared library */ + int (*dso_unload)(DSO *dso); + /* Binds a variable */ + void *(*dso_bind_var)(DSO *dso, const char *symname); + /* Binds a function - assumes a return type of DSO_FUNC_TYPE. + * This should be cast to the real function prototype by the + * caller. Platforms that don't have compatible representations + * for different prototypes (this is possible within ANSI C) + * are highly unlikely to have shared libraries at all, let + * alone a DSO_METHOD implemented for them. */ + DSO_FUNC_TYPE (*dso_bind_func)(DSO *dso, const char *symname); + +/* I don't think this would actually be used in any circumstances. */ +#if 0 + /* Unbinds a variable */ + int (*dso_unbind_var)(DSO *dso, char *symname, void *symptr); + /* Unbinds a function */ + int (*dso_unbind_func)(DSO *dso, char *symname, DSO_FUNC_TYPE symptr); +#endif + /* The generic (yuck) "ctrl()" function. NB: Negative return + * values (rather than zero) indicate errors. */ + long (*dso_ctrl)(DSO *dso, int cmd, long larg, void *parg); + + /* [De]Initialisation handlers. */ + int (*init)(DSO *dso); + int (*finish)(DSO *dso); + } DSO_METHOD; + +/**********************************************************************/ +/* The low-level handle type used to refer to a loaded shared library */ + +struct dso_st + { + DSO_METHOD *meth; + /* Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS + * doesn't use anything but will need to cache the filename + * for use in the dso_bind handler. All in all, let each + * method control its own destiny. "Handles" and such go in + * a STACK. */ + STACK *meth_data; + int references; + int flags; + /* For use by applications etc ... use this for your bits'n'pieces, + * don't touch meth_data! */ + CRYPTO_EX_DATA ex_data; + }; + + +DSO * DSO_new(void); +DSO * DSO_new_method(DSO_METHOD *method); +int DSO_free(DSO *dso); +int DSO_flags(DSO *dso); +int DSO_up(DSO *dso); +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg); + +void DSO_set_default_method(DSO_METHOD *meth); +DSO_METHOD *DSO_get_default_method(void); +DSO_METHOD *DSO_get_method(DSO *dso); +DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth); + +/* The all-singing all-dancing load function, you normally pass NULL + * for the first and third parameters. Use DSO_up and DSO_free for + * subsequent reference count handling. Any flags passed in will be set + * in the constructed DSO after its init() function but before the + * load operation. This will be done with; + * DSO_ctrl(dso, DSO_CTRL_SET_FLAGS, flags, NULL); */ +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags); + +/* This function binds to a variable inside a shared library. */ +void *DSO_bind_var(DSO *dso, const char *symname); + +/* This function binds to a function inside a shared library. */ +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname); + +/* This method is the default, but will beg, borrow, or steal whatever + * method should be the default on any particular platform (including + * DSO_METH_null() if necessary). */ +DSO_METHOD *DSO_METHOD_openssl(void); + +/* This method is defined for all platforms - if a platform has no + * DSO support then this will be the only method! */ +DSO_METHOD *DSO_METHOD_null(void); + +/* If DSO_DLFCN is defined, the standard dlfcn.h-style functions + * (dlopen, dlclose, dlsym, etc) will be used and incorporated into + * this method. If not, this method will return NULL. */ +DSO_METHOD *DSO_METHOD_dlfcn(void); + +/* If DSO_DL is defined, the standard dl.h-style functions (shl_load, + * shl_unload, shl_findsym, etc) will be used and incorporated into + * this method. If not, this method will return NULL. */ +DSO_METHOD *DSO_METHOD_dl(void); + +/* If WIN32 is defined, use DLLs. If not, return NULL. */ +DSO_METHOD *DSO_METHOD_win32(void); + +/* If VMS is defined, use shared images. If not, return NULL. */ +DSO_METHOD *DSO_METHOD_vms(void); + +void ERR_load_DSO_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 DSO functions. */ + +/* Function codes. */ +#define DSO_F_DLFCN_BIND_FUNC 100 +#define DSO_F_DLFCN_BIND_VAR 101 +#define DSO_F_DLFCN_CTRL 102 +#define DSO_F_DLFCN_LOAD 103 +#define DSO_F_DLFCN_UNLOAD 104 +#define DSO_F_DL_BIND_FUNC 105 +#define DSO_F_DL_BIND_VAR 106 +#define DSO_F_DL_CTRL 107 +#define DSO_F_DL_LOAD 108 +#define DSO_F_DL_UNLOAD 109 +#define DSO_F_DSO_BIND_FUNC 110 +#define DSO_F_DSO_BIND_VAR 111 +#define DSO_F_DSO_CTRL 112 +#define DSO_F_DSO_FREE 113 +#define DSO_F_DSO_LOAD 114 +#define DSO_F_DSO_NEW_METHOD 115 +#define DSO_F_DSO_UP 116 +#define DSO_F_VMS_BIND_VAR 122 +#define DSO_F_VMS_CTRL 123 +#define DSO_F_VMS_LOAD 124 +#define DSO_F_VMS_UNLOAD 125 +#define DSO_F_WIN32_BIND_FUNC 117 +#define DSO_F_WIN32_BIND_VAR 118 +#define DSO_F_WIN32_CTRL 119 +#define DSO_F_WIN32_LOAD 120 +#define DSO_F_WIN32_UNLOAD 121 + +/* Reason codes. */ +#define DSO_R_CTRL_FAILED 100 +#define DSO_R_FILENAME_TOO_BIG 109 +#define DSO_R_FINISH_FAILED 101 +#define DSO_R_LOAD_FAILED 102 +#define DSO_R_NULL_HANDLE 103 +#define DSO_R_STACK_ERROR 104 +#define DSO_R_SYM_FAILURE 105 +#define DSO_R_UNKNOWN_COMMAND 106 +#define DSO_R_UNLOAD_FAILED 107 +#define DSO_R_UNSUPPORTED 108 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/dso/dso_dlfcn.c b/src/lib/libcrypto/dso/dso_dlfcn.c new file mode 100644 index 0000000000..e709c721cc --- /dev/null +++ b/src/lib/libcrypto/dso/dso_dlfcn.c @@ -0,0 +1,276 @@ +/* dso_dlfcn.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 + +#ifndef DSO_DLFCN +DSO_METHOD *DSO_METHOD_dlfcn(void) + { + return NULL; + } +#else + +#ifdef HAVE_DLFCN_H +#include +#endif + +/* Part of the hack in "dlfcn_load" ... */ +#define DSO_MAX_TRANSLATED_SIZE 256 + +static int dlfcn_load(DSO *dso, const char *filename); +static int dlfcn_unload(DSO *dso); +static void *dlfcn_bind_var(DSO *dso, const char *symname); +static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); +#if 0 +static int dlfcn_unbind(DSO *dso, char *symname, void *symptr); +static int dlfcn_init(DSO *dso); +static int dlfcn_finish(DSO *dso); +#endif +static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); + +static DSO_METHOD dso_meth_dlfcn = { + "OpenSSL 'dlfcn' shared library method", + dlfcn_load, + dlfcn_unload, + dlfcn_bind_var, + dlfcn_bind_func, +/* For now, "unbind" doesn't exist */ +#if 0 + NULL, /* unbind_var */ + NULL, /* unbind_func */ +#endif + dlfcn_ctrl, + NULL, /* init */ + NULL /* finish */ + }; + +DSO_METHOD *DSO_METHOD_dlfcn(void) + { + return(&dso_meth_dlfcn); + } + +/* Prior to using the dlopen() function, we should decide on the flag + * we send. There's a few different ways of doing this and it's a + * messy venn-diagram to match up which platforms support what. So + * as we don't have autoconf yet, I'm implementing a hack that could + * be hacked further relatively easily to deal with cases as we find + * them. Initially this is to cope with OpenBSD. */ +#ifdef __OpenBSD__ +# ifdef DL_LAZY +# define DLOPEN_FLAG DL_LAZY +# else +# ifdef RTLD_NOW +# define DLOPEN_FLAG RTLD_NOW +# else +# define DLOPEN_FLAG 0 +# endif +# endif +#else +# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */ +#endif + +/* For this DSO_METHOD, our meth_data STACK will contain; + * (i) the handle (void*) returned from dlopen(). + */ + +static int dlfcn_load(DSO *dso, const char *filename) + { + void *ptr; + char translated[DSO_MAX_TRANSLATED_SIZE]; + int len; + + /* NB: This is a hideous hack, but I'm not yet sure what + * to replace it with. This attempts to convert any filename, + * that looks like it has no path information, into a + * translated form, e. "blah" -> "libblah.so" */ + len = strlen(filename); + if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && + (len + 6 < DSO_MAX_TRANSLATED_SIZE) && + (strstr(filename, "/") == NULL)) + { + sprintf(translated, "lib%s.so", filename); + ptr = dlopen(translated, DLOPEN_FLAG); + } + else + { + ptr = dlopen(filename, DLOPEN_FLAG); + } + if(ptr == NULL) + { + DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); + return(0); + } + if(!sk_push(dso->meth_data, (char *)ptr)) + { + DSOerr(DSO_F_DLFCN_LOAD,DSO_R_STACK_ERROR); + dlclose(ptr); + return(0); + } + return(1); + } + +static int dlfcn_unload(DSO *dso) + { + void *ptr; + if(dso == NULL) + { + DSOerr(DSO_F_DLFCN_UNLOAD,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if(sk_num(dso->meth_data) < 1) + return(1); + ptr = (void *)sk_pop(dso->meth_data); + if(ptr == NULL) + { + DSOerr(DSO_F_DLFCN_UNLOAD,DSO_R_NULL_HANDLE); + /* Should push the value back onto the stack in + * case of a retry. */ + sk_push(dso->meth_data, (char *)ptr); + return(0); + } + /* For now I'm not aware of any errors associated with dlclose() */ + dlclose(ptr); + return(1); + } + +static void *dlfcn_bind_var(DSO *dso, const char *symname) + { + void *ptr, *sym; + + if((dso == NULL) || (symname == NULL)) + { + DSOerr(DSO_F_DLFCN_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(sk_num(dso->meth_data) < 1) + { + DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_STACK_ERROR); + return(NULL); + } + ptr = (void *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); + if(ptr == NULL) + { + DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_NULL_HANDLE); + return(NULL); + } + sym = dlsym(ptr, symname); + if(sym == NULL) + { + DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_SYM_FAILURE); + return(NULL); + } + return(sym); + } + +static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) + { + void *ptr; + DSO_FUNC_TYPE sym; + + if((dso == NULL) || (symname == NULL)) + { + DSOerr(DSO_F_DLFCN_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(sk_num(dso->meth_data) < 1) + { + DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_STACK_ERROR); + return(NULL); + } + ptr = (void *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); + if(ptr == NULL) + { + DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_NULL_HANDLE); + return(NULL); + } + sym = (DSO_FUNC_TYPE)dlsym(ptr, symname); + if(sym == NULL) + { + DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); + return(NULL); + } + return(sym); + } + +static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg) + { + if(dso == NULL) + { + DSOerr(DSO_F_DLFCN_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return(-1); + } + switch(cmd) + { + case DSO_CTRL_GET_FLAGS: + return dso->flags; + case DSO_CTRL_SET_FLAGS: + dso->flags = (int)larg; + return(0); + case DSO_CTRL_OR_FLAGS: + dso->flags |= (int)larg; + return(0); + default: + break; + } + DSOerr(DSO_F_DLFCN_CTRL,DSO_R_UNKNOWN_COMMAND); + return(-1); + } + +#endif /* DSO_DLFCN */ diff --git a/src/lib/libcrypto/dso/dso_err.c b/src/lib/libcrypto/dso/dso_err.c new file mode 100644 index 0000000000..a3d7321c9b --- /dev/null +++ b/src/lib/libcrypto/dso/dso_err.c @@ -0,0 +1,128 @@ +/* crypto/dso/dso_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 DSO_str_functs[]= + { +{ERR_PACK(0,DSO_F_DLFCN_BIND_FUNC,0), "DLFCN_BIND_FUNC"}, +{ERR_PACK(0,DSO_F_DLFCN_BIND_VAR,0), "DLFCN_BIND_VAR"}, +{ERR_PACK(0,DSO_F_DLFCN_CTRL,0), "DLFCN_CTRL"}, +{ERR_PACK(0,DSO_F_DLFCN_LOAD,0), "DLFCN_LOAD"}, +{ERR_PACK(0,DSO_F_DLFCN_UNLOAD,0), "DLFCN_UNLOAD"}, +{ERR_PACK(0,DSO_F_DL_BIND_FUNC,0), "DL_BIND_FUNC"}, +{ERR_PACK(0,DSO_F_DL_BIND_VAR,0), "DL_BIND_VAR"}, +{ERR_PACK(0,DSO_F_DL_CTRL,0), "DL_CTRL"}, +{ERR_PACK(0,DSO_F_DL_LOAD,0), "DL_LOAD"}, +{ERR_PACK(0,DSO_F_DL_UNLOAD,0), "DL_UNLOAD"}, +{ERR_PACK(0,DSO_F_DSO_BIND_FUNC,0), "DSO_bind_func"}, +{ERR_PACK(0,DSO_F_DSO_BIND_VAR,0), "DSO_bind_var"}, +{ERR_PACK(0,DSO_F_DSO_CTRL,0), "DSO_ctrl"}, +{ERR_PACK(0,DSO_F_DSO_FREE,0), "DSO_free"}, +{ERR_PACK(0,DSO_F_DSO_LOAD,0), "DSO_load"}, +{ERR_PACK(0,DSO_F_DSO_NEW_METHOD,0), "DSO_new_method"}, +{ERR_PACK(0,DSO_F_DSO_UP,0), "DSO_up"}, +{ERR_PACK(0,DSO_F_VMS_BIND_VAR,0), "VMS_BIND_VAR"}, +{ERR_PACK(0,DSO_F_VMS_CTRL,0), "VMS_CTRL"}, +{ERR_PACK(0,DSO_F_VMS_LOAD,0), "VMS_LOAD"}, +{ERR_PACK(0,DSO_F_VMS_UNLOAD,0), "VMS_UNLOAD"}, +{ERR_PACK(0,DSO_F_WIN32_BIND_FUNC,0), "WIN32_BIND_FUNC"}, +{ERR_PACK(0,DSO_F_WIN32_BIND_VAR,0), "WIN32_BIND_VAR"}, +{ERR_PACK(0,DSO_F_WIN32_CTRL,0), "WIN32_CTRL"}, +{ERR_PACK(0,DSO_F_WIN32_LOAD,0), "WIN32_LOAD"}, +{ERR_PACK(0,DSO_F_WIN32_UNLOAD,0), "WIN32_UNLOAD"}, +{0,NULL} + }; + +static ERR_STRING_DATA DSO_str_reasons[]= + { +{DSO_R_CTRL_FAILED ,"control command failed"}, +{DSO_R_FILENAME_TOO_BIG ,"filename too big"}, +{DSO_R_FINISH_FAILED ,"cleanup method function failed"}, +{DSO_R_LOAD_FAILED ,"could not load the shared library"}, +{DSO_R_NULL_HANDLE ,"a null shared library handle was used"}, +{DSO_R_STACK_ERROR ,"the meth_data stack is corrupt"}, +{DSO_R_SYM_FAILURE ,"could not bind to the requested symbol name"}, +{DSO_R_UNKNOWN_COMMAND ,"unknown control command"}, +{DSO_R_UNLOAD_FAILED ,"could not unload the shared library"}, +{DSO_R_UNSUPPORTED ,"functionality not supported"}, +{0,NULL} + }; + +#endif + +void ERR_load_DSO_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_DSO,DSO_str_functs); + ERR_load_strings(ERR_LIB_DSO,DSO_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/dso/dso_lib.c b/src/lib/libcrypto/dso/dso_lib.c new file mode 100644 index 0000000000..acd166697e --- /dev/null +++ b/src/lib/libcrypto/dso/dso_lib.c @@ -0,0 +1,306 @@ +/* dso_lib.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "cryptlib.h" +#include + +static DSO_METHOD *default_DSO_meth = NULL; + +DSO *DSO_new(void) + { + return(DSO_new_method(NULL)); + } + +void DSO_set_default_method(DSO_METHOD *meth) + { + default_DSO_meth = meth; + } + +DSO_METHOD *DSO_get_default_method(void) + { + return(default_DSO_meth); + } + +DSO_METHOD *DSO_get_method(DSO *dso) + { + return(dso->meth); + } + +DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth) + { + DSO_METHOD *mtmp; + mtmp = dso->meth; + dso->meth = meth; + return(mtmp); + } + +DSO *DSO_new_method(DSO_METHOD *meth) + { + DSO *ret; + + if(default_DSO_meth == NULL) + /* We default to DSO_METH_openssl() which in turn defaults + * to stealing the "best available" method. Will fallback + * to DSO_METH_null() in the worst case. */ + default_DSO_meth = DSO_METHOD_openssl(); + ret = (DSO *)OPENSSL_malloc(sizeof(DSO)); + if(ret == NULL) + { + DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE); + return(NULL); + } + memset(ret, 0, sizeof(DSO)); + ret->meth_data = sk_new_null(); + if((ret->meth_data = sk_new_null()) == NULL) + { + /* sk_new doesn't generate any errors so we do */ + DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return(NULL); + } + if(meth == NULL) + ret->meth = default_DSO_meth; + else + ret->meth = meth; + ret->references = 1; + if((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + OPENSSL_free(ret); + ret=NULL; + } + return(ret); + } + +int DSO_free(DSO *dso) + { + int i; + + if(dso == NULL) + { + DSOerr(DSO_F_DSO_FREE,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + + i=CRYPTO_add(&dso->references,-1,CRYPTO_LOCK_DSO); +#ifdef REF_PRINT + REF_PRINT("DSO",dso); +#endif + if(i > 0) return(1); +#ifdef REF_CHECK + if(i < 0) + { + fprintf(stderr,"DSO_free, bad reference count\n"); + abort(); + } +#endif + + if((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) + { + DSOerr(DSO_F_DSO_FREE,DSO_R_UNLOAD_FAILED); + return(0); + } + + if((dso->meth->finish != NULL) && !dso->meth->finish(dso)) + { + DSOerr(DSO_F_DSO_FREE,DSO_R_FINISH_FAILED); + return(0); + } + + sk_free(dso->meth_data); + + OPENSSL_free(dso); + return(1); + } + +int DSO_flags(DSO *dso) + { + return((dso == NULL) ? 0 : dso->flags); + } + + +int DSO_up(DSO *dso) + { + if (dso == NULL) + { + DSOerr(DSO_F_DSO_UP,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + + CRYPTO_add(&dso->references,1,CRYPTO_LOCK_DSO); + return(1); + } + +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags) + { + DSO *ret; + int allocated = 0; + + if(filename == NULL) + { + DSOerr(DSO_F_DSO_LOAD,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(dso == NULL) + { + ret = DSO_new_method(meth); + if(ret == NULL) + { + DSOerr(DSO_F_DSO_LOAD,ERR_R_MALLOC_FAILURE); + return(NULL); + } + allocated = 1; + } + else + ret = dso; + /* Bleurgh ... have to check for negative return values for + * errors. */ + if(DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_CTRL_FAILED); + if(allocated) + DSO_free(ret); + return(NULL); + } + if(ret->meth->dso_load == NULL) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_UNSUPPORTED); + if(allocated) + DSO_free(ret); + return(NULL); + } + if(!ret->meth->dso_load(ret, filename)) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_LOAD_FAILED); + if(allocated) + DSO_free(ret); + return(NULL); + } + /* Load succeeded */ + return(ret); + } + +void *DSO_bind_var(DSO *dso, const char *symname) + { + void *ret = NULL; + + if((dso == NULL) || (symname == NULL)) + { + DSOerr(DSO_F_DSO_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(dso->meth->dso_bind_var == NULL) + { + DSOerr(DSO_F_DSO_BIND_VAR,DSO_R_UNSUPPORTED); + return(NULL); + } + if((ret = dso->meth->dso_bind_var(dso, symname)) == NULL) + { + DSOerr(DSO_F_DSO_BIND_VAR,DSO_R_SYM_FAILURE); + return(NULL); + } + /* Success */ + return(ret); + } + +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname) + { + DSO_FUNC_TYPE ret = NULL; + + if((dso == NULL) || (symname == NULL)) + { + DSOerr(DSO_F_DSO_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(dso->meth->dso_bind_func == NULL) + { + DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_UNSUPPORTED); + return(NULL); + } + if((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) + { + DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_SYM_FAILURE); + return(NULL); + } + /* Success */ + return(ret); + } + +/* I don't really like these *_ctrl functions very much to be perfectly + * honest. For one thing, I think I have to return a negative value for + * any error because possible DSO_ctrl() commands may return values + * such as "size"s that can legitimately be zero (making the standard + * "if(DSO_cmd(...))" form that works almost everywhere else fail at + * odd times. I'd prefer "output" values to be passed by reference and + * the return value as success/failure like usual ... but we conform + * when we must... :-) */ +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return(-1); + } + if((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) + { + DSOerr(DSO_F_DSO_CTRL,DSO_R_UNSUPPORTED); + return(-1); + } + return(dso->meth->dso_ctrl(dso,cmd,larg,parg)); + } diff --git a/src/lib/libcrypto/dso/dso_null.c b/src/lib/libcrypto/dso/dso_null.c new file mode 100644 index 0000000000..fa13a7cb0f --- /dev/null +++ b/src/lib/libcrypto/dso/dso_null.c @@ -0,0 +1,86 @@ +/* dso_null.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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). + * + */ + +/* This "NULL" method is provided as the fallback for systems that have + * no appropriate support for "shared-libraries". */ + +#include +#include "cryptlib.h" +#include + +static DSO_METHOD dso_meth_null = { + "NULL shared library method", + NULL, /* load */ + NULL, /* unload */ + NULL, /* bind_var */ + NULL, /* bind_func */ +/* For now, "unbind" doesn't exist */ +#if 0 + NULL, /* unbind_var */ + NULL, /* unbind_func */ +#endif + NULL, /* ctrl */ + NULL, /* init */ + NULL /* finish */ + }; + +DSO_METHOD *DSO_METHOD_null(void) + { + return(&dso_meth_null); + } + diff --git a/src/lib/libcrypto/dso/dso_openssl.c b/src/lib/libcrypto/dso/dso_openssl.c new file mode 100644 index 0000000000..a4395ebffe --- /dev/null +++ b/src/lib/libcrypto/dso/dso_openssl.c @@ -0,0 +1,81 @@ +/* dso_openssl.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 + +/* We just pinch the method from an appropriate "default" method. */ + +DSO_METHOD *DSO_METHOD_openssl(void) + { +#ifdef DEF_DSO_METHOD + return(DEF_DSO_METHOD()); +#elif defined(DSO_DLFCN) + return(DSO_METHOD_dlfcn()); +#elif defined(DSO_DL) + return(DSO_METHOD_dl()); +#elif defined(DSO_WIN32) + return(DSO_METHOD_win32()); +#elif defined(DSO_VMS) + return(DSO_METHOD_vms()); +#else + return(DSO_METHOD_null()); +#endif + } + diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h new file mode 100644 index 0000000000..a52d4edf14 --- /dev/null +++ b/src/lib/libcrypto/ec/ec.h @@ -0,0 +1,245 @@ +/* crypto/ec/ec.h */ +/* ==================================================================== + * Copyright (c) 1998-2001 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_EC_H +#define HEADER_EC_H + +#ifdef OPENSSL_NO_EC +#error EC is disabled. +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum { + /* values as defined in X9.62 (ECDSA) and elsewhere */ + POINT_CONVERSION_COMPRESSED = 2, + POINT_CONVERSION_UNCOMPRESSED = 4, + POINT_CONVERSION_HYBRID = 6 +} point_conversion_form_t; + + +typedef struct ec_method_st EC_METHOD; + +typedef struct ec_group_st + /* + EC_METHOD *meth; + -- field definition + -- curve coefficients + -- optional generator with associated information (order, cofactor) + -- optional extra data (TODO: precomputed table for fast computation of multiples of generator) + */ + EC_GROUP; + +typedef struct ec_point_st EC_POINT; + + +/* EC_METHODs for curves over GF(p). + * EC_GFp_simple_method provides the basis for the optimized methods. + */ +const EC_METHOD *EC_GFp_simple_method(void); +const EC_METHOD *EC_GFp_mont_method(void); +#if 0 +const EC_METHOD *EC_GFp_recp_method(void); /* TODO */ +const EC_METHOD *EC_GFp_nist_method(void); /* TODO */ +#endif + + +EC_GROUP *EC_GROUP_new(const EC_METHOD *); +void EC_GROUP_free(EC_GROUP *); +void EC_GROUP_clear_free(EC_GROUP *); +int EC_GROUP_copy(EC_GROUP *, const EC_GROUP *); + +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *); + + +/* We don't have types for field specifications and field elements in general. + * Otherwise we could declare + * int EC_GROUP_set_curve(EC_GROUP *, .....); + */ +int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); + +/* EC_GROUP_new_GFp() calls EC_GROUP_new() and EC_GROUP_set_GFp() + * after choosing an appropriate EC_METHOD */ +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); + +int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor); +EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *); +int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *); +int EC_GROUP_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *); + +EC_POINT *EC_POINT_new(const EC_GROUP *); +void EC_POINT_free(EC_POINT *); +void EC_POINT_clear_free(EC_POINT *); +int EC_POINT_copy(EC_POINT *, const EC_POINT *); + +const EC_METHOD *EC_POINT_method_of(const EC_POINT *); + +int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *); +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, BN_CTX *); +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, BN_CTX *); + +size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); +int EC_POINT_oct2point(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); + +int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); +int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); +int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); + +int EC_POINT_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int EC_POINT_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int EC_POINT_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *); + +int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); + + +int EC_POINTs_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, size_t num, const EC_POINT *[], const BIGNUM *[], BN_CTX *); +int EC_POINT_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, const EC_POINT *, const BIGNUM *, BN_CTX *); +int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *); + + + +/* 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. + */ +void ERR_load_EC_strings(void); + +/* Error codes for the EC functions. */ + +/* Function codes. */ +#define EC_F_COMPUTE_WNAF 143 +#define EC_F_EC_GFP_MONT_FIELD_DECODE 133 +#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 +#define EC_F_EC_GFP_MONT_FIELD_MUL 131 +#define EC_F_EC_GFP_MONT_FIELD_SQR 132 +#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100 +#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101 +#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 +#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 +#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 +#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 +#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105 +#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128 +#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129 +#define EC_F_EC_GROUP_COPY 106 +#define EC_F_EC_GROUP_GET0_GENERATOR 139 +#define EC_F_EC_GROUP_GET_COFACTOR 140 +#define EC_F_EC_GROUP_GET_CURVE_GFP 130 +#define EC_F_EC_GROUP_GET_EXTRA_DATA 107 +#define EC_F_EC_GROUP_GET_ORDER 141 +#define EC_F_EC_GROUP_NEW 108 +#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142 +#define EC_F_EC_GROUP_SET_CURVE_GFP 109 +#define EC_F_EC_GROUP_SET_EXTRA_DATA 110 +#define EC_F_EC_GROUP_SET_GENERATOR 111 +#define EC_F_EC_POINTS_MAKE_AFFINE 136 +#define EC_F_EC_POINTS_MUL 138 +#define EC_F_EC_POINT_ADD 112 +#define EC_F_EC_POINT_CMP 113 +#define EC_F_EC_POINT_COPY 114 +#define EC_F_EC_POINT_DBL 115 +#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 +#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 +#define EC_F_EC_POINT_IS_AT_INFINITY 118 +#define EC_F_EC_POINT_IS_ON_CURVE 119 +#define EC_F_EC_POINT_MAKE_AFFINE 120 +#define EC_F_EC_POINT_NEW 121 +#define EC_F_EC_POINT_OCT2POINT 122 +#define EC_F_EC_POINT_POINT2OCT 123 +#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 +#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 +#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 +#define EC_F_EC_POINT_SET_TO_INFINITY 127 +#define EC_F_GFP_MONT_GROUP_SET_CURVE_GFP 135 + +/* Reason codes. */ +#define EC_R_BUFFER_TOO_SMALL 100 +#define EC_R_INCOMPATIBLE_OBJECTS 101 +#define EC_R_INVALID_ARGUMENT 112 +#define EC_R_INVALID_COMPRESSED_POINT 110 +#define EC_R_INVALID_COMPRESSION_BIT 109 +#define EC_R_INVALID_ENCODING 102 +#define EC_R_INVALID_FIELD 103 +#define EC_R_INVALID_FORM 104 +#define EC_R_NOT_INITIALIZED 111 +#define EC_R_NO_SUCH_EXTRA_DATA 105 +#define EC_R_POINT_AT_INFINITY 106 +#define EC_R_POINT_IS_NOT_ON_CURVE 107 +#define EC_R_SLOT_FULL 108 +#define EC_R_UNDEFINED_GENERATOR 113 +#define EC_R_UNKNOWN_ORDER 114 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/libcrypto/ec/ec_cvt.c b/src/lib/libcrypto/ec/ec_cvt.c new file mode 100644 index 0000000000..45b0ec33a0 --- /dev/null +++ b/src/lib/libcrypto/ec/ec_cvt.c @@ -0,0 +1,80 @@ +/* crypto/ec/ec_cvt.c */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "ec_lcl.h" + + +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + const EC_METHOD *meth; + EC_GROUP *ret; + + /* Finally, this will use EC_GFp_nist_method if 'p' is a special + * prime with optimized modular arithmetics (for NIST curves) + */ + meth = EC_GFp_mont_method(); + + ret = EC_GROUP_new(meth); + if (ret == NULL) + return NULL; + + if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) + { + EC_GROUP_clear_free(ret); + return NULL; + } + + return ret; + } diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c new file mode 100644 index 0000000000..394cdc021f --- /dev/null +++ b/src/lib/libcrypto/ec/ec_err.c @@ -0,0 +1,151 @@ +/* crypto/ec/ec_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 OPENSSL_NO_ERR +static ERR_STRING_DATA EC_str_functs[]= + { +{ERR_PACK(0,EC_F_COMPUTE_WNAF,0), "COMPUTE_WNAF"}, +{ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_DECODE,0), "ec_GFp_mont_field_decode"}, +{ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_ENCODE,0), "ec_GFp_mont_field_encode"}, +{ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_MUL,0), "ec_GFp_mont_field_mul"}, +{ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_SQR,0), "ec_GFp_mont_field_sqr"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP,0), "ec_GFp_simple_group_set_curve_GFp"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR,0), "ec_GFp_simple_group_set_generator"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_MAKE_AFFINE,0), "ec_GFp_simple_make_affine"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_OCT2POINT,0), "ec_GFp_simple_oct2point"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT2OCT,0), "ec_GFp_simple_point2oct"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE,0), "ec_GFp_simple_points_make_affine"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP,0), "ec_GFp_simple_point_get_affine_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP,0), "ec_GFp_simple_point_set_affine_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP,0), "ec_GFp_simple_set_compressed_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_GROUP_COPY,0), "EC_GROUP_copy"}, +{ERR_PACK(0,EC_F_EC_GROUP_GET0_GENERATOR,0), "EC_GROUP_get0_generator"}, +{ERR_PACK(0,EC_F_EC_GROUP_GET_COFACTOR,0), "EC_GROUP_get_cofactor"}, +{ERR_PACK(0,EC_F_EC_GROUP_GET_CURVE_GFP,0), "EC_GROUP_get_curve_GFp"}, +{ERR_PACK(0,EC_F_EC_GROUP_GET_EXTRA_DATA,0), "EC_GROUP_get_extra_data"}, +{ERR_PACK(0,EC_F_EC_GROUP_GET_ORDER,0), "EC_GROUP_get_order"}, +{ERR_PACK(0,EC_F_EC_GROUP_NEW,0), "EC_GROUP_new"}, +{ERR_PACK(0,EC_F_EC_GROUP_PRECOMPUTE_MULT,0), "EC_GROUP_precompute_mult"}, +{ERR_PACK(0,EC_F_EC_GROUP_SET_CURVE_GFP,0), "EC_GROUP_set_curve_GFp"}, +{ERR_PACK(0,EC_F_EC_GROUP_SET_EXTRA_DATA,0), "EC_GROUP_set_extra_data"}, +{ERR_PACK(0,EC_F_EC_GROUP_SET_GENERATOR,0), "EC_GROUP_set_generator"}, +{ERR_PACK(0,EC_F_EC_POINTS_MAKE_AFFINE,0), "EC_POINTs_make_affine"}, +{ERR_PACK(0,EC_F_EC_POINTS_MUL,0), "EC_POINTs_mul"}, +{ERR_PACK(0,EC_F_EC_POINT_ADD,0), "EC_POINT_add"}, +{ERR_PACK(0,EC_F_EC_POINT_CMP,0), "EC_POINT_cmp"}, +{ERR_PACK(0,EC_F_EC_POINT_COPY,0), "EC_POINT_copy"}, +{ERR_PACK(0,EC_F_EC_POINT_DBL,0), "EC_POINT_dbl"}, +{ERR_PACK(0,EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,0), "EC_POINT_get_affine_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,0), "EC_POINT_get_Jprojective_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_POINT_IS_AT_INFINITY,0), "EC_POINT_is_at_infinity"}, +{ERR_PACK(0,EC_F_EC_POINT_IS_ON_CURVE,0), "EC_POINT_is_on_curve"}, +{ERR_PACK(0,EC_F_EC_POINT_MAKE_AFFINE,0), "EC_POINT_make_affine"}, +{ERR_PACK(0,EC_F_EC_POINT_NEW,0), "EC_POINT_new"}, +{ERR_PACK(0,EC_F_EC_POINT_OCT2POINT,0), "EC_POINT_oct2point"}, +{ERR_PACK(0,EC_F_EC_POINT_POINT2OCT,0), "EC_POINT_point2oct"}, +{ERR_PACK(0,EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,0), "EC_POINT_set_affine_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,0), "EC_POINT_set_compressed_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,0), "EC_POINT_set_Jprojective_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_POINT_SET_TO_INFINITY,0), "EC_POINT_set_to_infinity"}, +{ERR_PACK(0,EC_F_GFP_MONT_GROUP_SET_CURVE_GFP,0), "GFP_MONT_GROUP_SET_CURVE_GFP"}, +{0,NULL} + }; + +static ERR_STRING_DATA EC_str_reasons[]= + { +{EC_R_BUFFER_TOO_SMALL ,"buffer too small"}, +{EC_R_INCOMPATIBLE_OBJECTS ,"incompatible objects"}, +{EC_R_INVALID_ARGUMENT ,"invalid argument"}, +{EC_R_INVALID_COMPRESSED_POINT ,"invalid compressed point"}, +{EC_R_INVALID_COMPRESSION_BIT ,"invalid compression bit"}, +{EC_R_INVALID_ENCODING ,"invalid encoding"}, +{EC_R_INVALID_FIELD ,"invalid field"}, +{EC_R_INVALID_FORM ,"invalid form"}, +{EC_R_NOT_INITIALIZED ,"not initialized"}, +{EC_R_NO_SUCH_EXTRA_DATA ,"no such extra data"}, +{EC_R_POINT_AT_INFINITY ,"point at infinity"}, +{EC_R_POINT_IS_NOT_ON_CURVE ,"point is not on curve"}, +{EC_R_SLOT_FULL ,"slot full"}, +{EC_R_UNDEFINED_GENERATOR ,"undefined generator"}, +{EC_R_UNKNOWN_ORDER ,"unknown order"}, +{0,NULL} + }; + +#endif + +void ERR_load_EC_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(ERR_LIB_EC,EC_str_functs); + ERR_load_strings(ERR_LIB_EC,EC_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/ec/ec_lcl.h b/src/lib/libcrypto/ec/ec_lcl.h new file mode 100644 index 0000000000..cc4cf27755 --- /dev/null +++ b/src/lib/libcrypto/ec/ec_lcl.h @@ -0,0 +1,277 @@ +/* crypto/ec/ec_lcl.h */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 + + +/* Structure details are not part of the exported interface, + * so all this may change in future versions. */ + +struct ec_method_st { + /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */ + int (*group_init)(EC_GROUP *); + void (*group_finish)(EC_GROUP *); + void (*group_clear_finish)(EC_GROUP *); + int (*group_copy)(EC_GROUP *, const EC_GROUP *); + + /* used by EC_GROUP_set_curve_GFp and EC_GROUP_get_curve_GFp: */ + int (*group_set_curve_GFp)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); + int (*group_get_curve_GFp)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); + + /* used by EC_GROUP_set_generator, EC_GROUP_get0_generator, + * EC_GROUP_get_order, EC_GROUP_get_cofactor: + */ + int (*group_set_generator)(EC_GROUP *, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); + EC_POINT *(*group_get0_generator)(const EC_GROUP *); + int (*group_get_order)(const EC_GROUP *, BIGNUM *order, BN_CTX *); + int (*group_get_cofactor)(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *); + + /* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, EC_POINT_copy: */ + int (*point_init)(EC_POINT *); + void (*point_finish)(EC_POINT *); + void (*point_clear_finish)(EC_POINT *); + int (*point_copy)(EC_POINT *, const EC_POINT *); + + /* used by EC_POINT_set_to_infinity, + * EC_POINT_set_Jprojective_coordinates_GFp, EC_POINT_get_Jprojective_coordinates_GFp, + * EC_POINT_set_affine_coordinates_GFp, EC_POINT_get_affine_coordinates_GFp, + * EC_POINT_set_compressed_coordinates_GFp: + */ + int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *); + int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); + int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); + int (*point_set_affine_coordinates_GFp)(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, BN_CTX *); + int (*point_get_affine_coordinates_GFp)(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); + int (*point_set_compressed_coordinates_GFp)(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, BN_CTX *); + + /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ + size_t (*point2oct)(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); + int (*oct2point)(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); + + /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */ + int (*add)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); + int (*dbl)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); + int (*invert)(const EC_GROUP *, EC_POINT *, BN_CTX *); + + /* used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: */ + int (*is_at_infinity)(const EC_GROUP *, const EC_POINT *); + int (*is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *); + int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *); + + /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */ + int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *); + int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); + + + /* internal functions */ + + /* 'field_mul' and 'field_sqr' can be used by 'add' and 'dbl' so that + * the same implementations of point operations can be used with different + * optimized implementations of expensive field operations: */ + int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + + int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */ + int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. from Montgomery */ + int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *); +} /* EC_METHOD */; + + +struct ec_group_st { + const EC_METHOD *meth; + + void *extra_data; + void *(*extra_data_dup_func)(void *); + void (*extra_data_free_func)(void *); + void (*extra_data_clear_free_func)(void *); + + /* All members except 'meth' and 'extra_data...' are handled by + * the method functions, even if they appear generic */ + + BIGNUM field; /* Field specification. + * For curves over GF(p), this is the modulus. */ + + BIGNUM a, b; /* Curve coefficients. + * (Here the assumption is that BIGNUMs can be used + * or abused for all kinds of fields, not just GF(p).) + * For characteristic > 3, the curve is defined + * by a Weierstrass equation of the form + * y^2 = x^3 + a*x + b. + */ + int a_is_minus3; /* enable optimized point arithmetics for special case */ + + EC_POINT *generator; /* optional */ + BIGNUM order, cofactor; + + void *field_data1; /* method-specific (e.g., Montgomery structure) */ + void *field_data2; /* method-specific */ +} /* EC_GROUP */; + + +/* Basically a 'mixin' for extra data, but available for EC_GROUPs only + * (with visibility limited to 'package' level for now). + * We use the function pointers as index for retrieval; this obviates + * global ex_data-style index tables. + * (Currently, we have one slot only, but is is possible to extend this + * if necessary.) */ +int EC_GROUP_set_extra_data(EC_GROUP *, void *extra_data, void *(*extra_data_dup_func)(void *), + void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)); +void *EC_GROUP_get_extra_data(const EC_GROUP *, void *(*extra_data_dup_func)(void *), + void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)); +void EC_GROUP_free_extra_data(EC_GROUP *); +void EC_GROUP_clear_free_extra_data(EC_GROUP *); + + + +struct ec_point_st { + const EC_METHOD *meth; + + /* All members except 'meth' are handled by the method functions, + * even if they appear generic */ + + BIGNUM X; + BIGNUM Y; + BIGNUM Z; /* Jacobian projective coordinates: + * (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ + int Z_is_one; /* enable optimized point arithmetics for special case */ +} /* EC_POINT */; + + + +/* method functions in ecp_smpl.c */ +int ec_GFp_simple_group_init(EC_GROUP *); +void ec_GFp_simple_group_finish(EC_GROUP *); +void ec_GFp_simple_group_clear_finish(EC_GROUP *); +int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_set_generator(EC_GROUP *, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); +EC_POINT *ec_GFp_simple_group_get0_generator(const EC_GROUP *); +int ec_GFp_simple_group_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *); +int ec_GFp_simple_group_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *); +int ec_GFp_simple_point_init(EC_POINT *); +void ec_GFp_simple_point_finish(EC_POINT *); +void ec_GFp_simple_point_clear_finish(EC_POINT *); +int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); +int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, BN_CTX *); +int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); +int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, BN_CTX *); +size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); +int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); +int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); +int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); +int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *); +int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); +int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + + +/* method functions in ecp_mont.c */ +int ec_GFp_mont_group_init(EC_GROUP *); +int ec_GFp_mont_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +void ec_GFp_mont_group_finish(EC_GROUP *); +void ec_GFp_mont_group_clear_finish(EC_GROUP *); +int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); +int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); +int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); +int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); + + +/* method functions in ecp_recp.c */ +int ec_GFp_recp_group_init(EC_GROUP *); +int ec_GFp_recp_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +void ec_GFp_recp_group_finish(EC_GROUP *); +void ec_GFp_recp_group_clear_finish(EC_GROUP *); +int ec_GFp_recp_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_recp_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_recp_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + + +/* method functions in ecp_nist.c */ +int ec_GFp_nist_group_init(EC_GROUP *); +int ec_GFp_nist_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +void ec_GFp_nist_group_finish(EC_GROUP *); +void ec_GFp_nist_group_clear_finish(EC_GROUP *); +int ec_GFp_nist_group_copy(EC_GROUP *, const EC_GROUP *); +int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c new file mode 100644 index 0000000000..e0d78d67fb --- /dev/null +++ b/src/lib/libcrypto/ec/ec_lib.c @@ -0,0 +1,646 @@ +/* crypto/ec/ec_lib.c */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "ec_lcl.h" + +static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; + + +/* functions for EC_GROUP objects */ + +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) + { + EC_GROUP *ret; + + if (meth == NULL) + { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (meth->group_init == 0) + { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) + { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->meth = meth; + + ret->extra_data = NULL; + ret->extra_data_dup_func = 0; + ret->extra_data_free_func = 0; + ret->extra_data_clear_free_func = 0; + + if (!meth->group_init(ret)) + { + OPENSSL_free(ret); + return NULL; + } + + return ret; + } + + +void EC_GROUP_free(EC_GROUP *group) + { + if (group->meth->group_finish != 0) + group->meth->group_finish(group); + + EC_GROUP_free_extra_data(group); + + OPENSSL_free(group); + } + + +void EC_GROUP_clear_free(EC_GROUP *group) + { + if (group->meth->group_clear_finish != 0) + group->meth->group_clear_finish(group); + else if (group->meth != NULL && group->meth->group_finish != 0) + group->meth->group_finish(group); + + EC_GROUP_clear_free_extra_data(group); + + memset(group, 0, sizeof *group); + OPENSSL_free(group); + } + + +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) + { + if (dest->meth->group_copy == 0) + { + ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (dest->meth != src->meth) + { + ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) + return 1; + + EC_GROUP_clear_free_extra_data(dest); + if (src->extra_data_dup_func) + { + if (src->extra_data != NULL) + { + dest->extra_data = src->extra_data_dup_func(src->extra_data); + if (dest->extra_data == NULL) + return 0; + } + + dest->extra_data_dup_func = src->extra_data_dup_func; + dest->extra_data_free_func = src->extra_data_free_func; + dest->extra_data_clear_free_func = src->extra_data_clear_free_func; + } + + return dest->meth->group_copy(dest, src); + } + + +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) + { + return group->meth; + } + + +int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + if (group->meth->group_set_curve_GFp == 0) + { + ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_set_curve_GFp(group, p, a, b, ctx); + } + + +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) + { + if (group->meth->group_get_curve_GFp == 0) + { + ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_curve_GFp(group, p, a, b, ctx); + } + + +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) + { + if (group->meth->group_set_generator == 0) + { + ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_set_generator(group, generator, order, cofactor); + } + + +EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) + { + if (group->meth->group_get0_generator == 0) + { + ECerr(EC_F_EC_GROUP_GET0_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get0_generator(group); + } + + +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) + { + if (group->meth->group_get_order == 0) + { + ECerr(EC_F_EC_GROUP_GET_ORDER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_order(group, order, ctx); + } + + +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) + { + if (group->meth->group_get_cofactor == 0) + { + ECerr(EC_F_EC_GROUP_GET_COFACTOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_cofactor(group, cofactor, ctx); + } + + +/* this has 'package' visibility */ +int EC_GROUP_set_extra_data(EC_GROUP *group, void *extra_data, void *(*extra_data_dup_func)(void *), + void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)) + { + if ((group->extra_data != NULL) + || (group->extra_data_dup_func != 0) + || (group->extra_data_free_func != 0) + || (group->extra_data_clear_free_func != 0)) + { + ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL); + return 0; + } + + group->extra_data = extra_data; + group->extra_data_dup_func = extra_data_dup_func; + group->extra_data_free_func = extra_data_free_func; + group->extra_data_clear_free_func = extra_data_clear_free_func; + return 1; + } + + +/* this has 'package' visibility */ +void *EC_GROUP_get_extra_data(const EC_GROUP *group, void *(*extra_data_dup_func)(void *), + void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)) + { + if ((group->extra_data_dup_func != extra_data_dup_func) + || (group->extra_data_free_func != extra_data_free_func) + || (group->extra_data_clear_free_func != extra_data_clear_free_func)) + { + ECerr(EC_F_EC_GROUP_GET_EXTRA_DATA, EC_R_NO_SUCH_EXTRA_DATA); + return NULL; + } + + return group->extra_data; + } + + +/* this has 'package' visibility */ +void EC_GROUP_free_extra_data(EC_GROUP *group) + { + if (group->extra_data_free_func) + group->extra_data_free_func(group->extra_data); + group->extra_data = NULL; + group->extra_data_dup_func = 0; + group->extra_data_free_func = 0; + group->extra_data_clear_free_func = 0; + } + + +/* this has 'package' visibility */ +void EC_GROUP_clear_free_extra_data(EC_GROUP *group) + { + if (group->extra_data_clear_free_func) + group->extra_data_clear_free_func(group->extra_data); + else if (group->extra_data_free_func) + group->extra_data_free_func(group->extra_data); + group->extra_data = NULL; + group->extra_data_dup_func = 0; + group->extra_data_free_func = 0; + group->extra_data_clear_free_func = 0; + } + + + +/* functions for EC_POINT objects */ + +EC_POINT *EC_POINT_new(const EC_GROUP *group) + { + EC_POINT *ret; + + if (group == NULL) + { + ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (group->meth->point_init == 0) + { + ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) + { + ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->meth = group->meth; + + if (!ret->meth->point_init(ret)) + { + OPENSSL_free(ret); + return NULL; + } + + return ret; + } + + +void EC_POINT_free(EC_POINT *point) + { + if (point->meth->point_finish != 0) + point->meth->point_finish(point); + OPENSSL_free(point); + } + + +void EC_POINT_clear_free(EC_POINT *point) + { + if (point->meth->point_clear_finish != 0) + point->meth->point_clear_finish(point); + else if (point->meth != NULL && point->meth->point_finish != 0) + point->meth->point_finish(point); + memset(point, 0, sizeof *point); + OPENSSL_free(point); + } + + +int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) + { + if (dest->meth->point_copy == 0) + { + ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (dest->meth != src->meth) + { + ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (dest == src) + return 1; + return dest->meth->point_copy(dest, src); + } + + +const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) + { + return point->meth; + } + + +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) + { + if (group->meth->point_set_to_infinity == 0) + { + ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_to_infinity(group, point); + } + + +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) + { + if (group->meth->point_set_Jprojective_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); + } + + +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) + { + if (group->meth->point_get_Jprojective_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); + } + + +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) + { + if (group->meth->point_set_affine_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_affine_coordinates_GFp(group, point, x, y, ctx); + } + + +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) + { + if (group->meth->point_get_affine_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_affine_coordinates_GFp(group, point, x, y, ctx); + } + + +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, int y_bit, BN_CTX *ctx) + { + if (group->meth->point_set_compressed_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx); + } + + +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) + { + if (group->meth->point2oct == 0) + { + ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point2oct(group, point, form, buf, len, ctx); + } + + +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, BN_CTX *ctx) + { + if (group->meth->oct2point == 0) + { + ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->oct2point(group, point, buf, len, ctx); + } + + +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) + { + if (group->meth->add == 0) + { + ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth)) + { + ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->add(group, r, a, b, ctx); + } + + +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) + { + if (group->meth->dbl == 0) + { + ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if ((group->meth != r->meth) || (r->meth != a->meth)) + { + ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->dbl(group, r, a, ctx); + } + + +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) + { + if (group->meth->dbl == 0) + { + ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != a->meth) + { + ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->invert(group, a, ctx); + } + + +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) + { + if (group->meth->is_at_infinity == 0) + { + ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->is_at_infinity(group, point); + } + + +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) + { + if (group->meth->is_on_curve == 0) + { + ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->is_on_curve(group, point, ctx); + } + + +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) + { + if (group->meth->point_cmp == 0) + { + ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if ((group->meth != a->meth) || (a->meth != b->meth)) + { + ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_cmp(group, a, b, ctx); + } + + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) + { + if (group->meth->make_affine == 0) + { + ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->make_affine(group, point, ctx); + } + + +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) + { + size_t i; + + if (group->meth->points_make_affine == 0) + { + ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + for (i = 0; i < num; i++) + { + if (group->meth != points[i]->meth) + { + ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + return group->meth->points_make_affine(group, num, points, ctx); + } diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c new file mode 100644 index 0000000000..603ba31b81 --- /dev/null +++ b/src/lib/libcrypto/ec/ec_mult.c @@ -0,0 +1,473 @@ +/* crypto/ec/ec_mult.c */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "ec_lcl.h" + + +/* TODO: optional precomputation of multiples of the generator */ + + + +/* + * wNAF-based interleaving multi-exponentation method + * () + */ + + +/* Determine the width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. + * This is an array r[] of values that are either zero or odd with an + * absolute value less than 2^w satisfying + * scalar = \sum_j r[j]*2^j + * where at most one of any w+1 consecutive digits is non-zero. + */ +static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len, BN_CTX *ctx) + { + BIGNUM *c; + int ok = 0; + signed char *r = NULL; + int sign = 1; + int bit, next_bit, mask; + size_t len = 0, j; + + BN_CTX_start(ctx); + c = BN_CTX_get(ctx); + if (c == NULL) goto err; + + if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */ + { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + bit = 1 << w; /* at most 128 */ + next_bit = bit << 1; /* at most 256 */ + mask = next_bit - 1; /* at most 255 */ + + if (!BN_copy(c, scalar)) goto err; + if (c->neg) + { + sign = -1; + c->neg = 0; + } + + len = BN_num_bits(c) + 1; /* wNAF may be one digit longer than binary representation */ + r = OPENSSL_malloc(len); + if (r == NULL) goto err; + + j = 0; + while (!BN_is_zero(c)) + { + int u = 0; + + if (BN_is_odd(c)) + { + if (c->d == NULL || c->top == 0) + { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + u = c->d[0] & mask; + if (u & bit) + { + u -= next_bit; + /* u < 0 */ + if (!BN_add_word(c, -u)) goto err; + } + else + { + /* u > 0 */ + if (!BN_sub_word(c, u)) goto err; + } + + if (u <= -bit || u >= bit || !(u & 1) || c->neg) + { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + r[j++] = sign * u; + + if (BN_is_odd(c)) + { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!BN_rshift1(c, c)) goto err; + } + + if (j > len) + { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + len = j; + ok = 1; + + err: + BN_CTX_end(ctx); + if (!ok) + { + OPENSSL_free(r); + r = NULL; + } + if (ok) + *ret_len = len; + return r; + } + + +/* TODO: table should be optimised for the wNAF-based implementation, + * sometimes smaller windows will give better performance + * (thus the boundaries should be increased) + */ +#define EC_window_bits_for_scalar_size(b) \ + ((b) >= 2000 ? 6 : \ + (b) >= 800 ? 5 : \ + (b) >= 300 ? 4 : \ + (b) >= 70 ? 3 : \ + (b) >= 20 ? 2 : \ + 1) + +/* Compute + * \sum scalars[i]*points[i], + * also including + * scalar*generator + * in the addition if scalar != NULL + */ +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + EC_POINT *generator = NULL; + EC_POINT *tmp = NULL; + size_t totalnum; + size_t i, j; + int k; + int r_is_inverted = 0; + int r_is_at_infinity = 1; + size_t *wsize = NULL; /* individual window sizes */ + signed char **wNAF = NULL; /* individual wNAFs */ + size_t *wNAF_len = NULL; + size_t max_len = 0; + size_t num_val; + EC_POINT **val = NULL; /* precomputation */ + EC_POINT **v; + EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */ + int ret = 0; + + if (scalar != NULL) + { + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) + { + ECerr(EC_F_EC_POINTS_MUL, EC_R_UNDEFINED_GENERATOR); + return 0; + } + } + + for (i = 0; i < num; i++) + { + if (group->meth != points[i]->meth) + { + ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + + totalnum = num + (scalar != NULL); + + wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]); + wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]); + wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); + if (wNAF != NULL) + { + wNAF[0] = NULL; /* preliminary pivot */ + } + if (wsize == NULL || wNAF_len == NULL || wNAF == NULL) goto err; + + /* num_val := total number of points to precompute */ + num_val = 0; + for (i = 0; i < totalnum; i++) + { + size_t bits; + + bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); + wsize[i] = EC_window_bits_for_scalar_size(bits); + num_val += 1u << (wsize[i] - 1); + } + + /* all precomputed points go into a single array 'val', + * 'val_sub[i]' is a pointer to the subarray for the i-th point */ + val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); + if (val == NULL) goto err; + val[num_val] = NULL; /* pivot element */ + + val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]); + if (val_sub == NULL) goto err; + + /* allocate points for precomputation */ + v = val; + for (i = 0; i < totalnum; i++) + { + val_sub[i] = v; + for (j = 0; j < (1u << (wsize[i] - 1)); j++) + { + *v = EC_POINT_new(group); + if (*v == NULL) goto err; + v++; + } + } + if (!(v == val + num_val)) + { + ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + } + + tmp = EC_POINT_new(group); + if (tmp == NULL) goto err; + + /* prepare precomputed values: + * val_sub[i][0] := points[i] + * val_sub[i][1] := 3 * points[i] + * val_sub[i][2] := 5 * points[i] + * ... + */ + for (i = 0; i < totalnum; i++) + { + if (i < num) + { + if (!EC_POINT_copy(val_sub[i][0], points[i])) goto err; + } + else + { + if (!EC_POINT_copy(val_sub[i][0], generator)) goto err; + } + + if (wsize[i] > 1) + { + if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) goto err; + for (j = 1; j < (1u << (wsize[i] - 1)); j++) + { + if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err; + } + } + + wNAF[i + 1] = NULL; /* make sure we always have a pivot */ + wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i], ctx); + if (wNAF[i] == NULL) goto err; + if (wNAF_len[i] > max_len) + max_len = wNAF_len[i]; + } + +#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */ + if (!EC_POINTs_make_affine(group, num_val, val, ctx)) goto err; +#endif + + r_is_at_infinity = 1; + + for (k = max_len - 1; k >= 0; k--) + { + if (!r_is_at_infinity) + { + if (!EC_POINT_dbl(group, r, r, ctx)) goto err; + } + + for (i = 0; i < totalnum; i++) + { + if (wNAF_len[i] > (size_t)k) + { + int digit = wNAF[i][k]; + int is_neg; + + if (digit) + { + is_neg = digit < 0; + + if (is_neg) + digit = -digit; + + if (is_neg != r_is_inverted) + { + if (!r_is_at_infinity) + { + if (!EC_POINT_invert(group, r, ctx)) goto err; + } + r_is_inverted = !r_is_inverted; + } + + /* digit > 0 */ + + if (r_is_at_infinity) + { + if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) goto err; + r_is_at_infinity = 0; + } + else + { + if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) goto err; + } + } + } + } + } + + if (r_is_at_infinity) + { + if (!EC_POINT_set_to_infinity(group, r)) goto err; + } + else + { + if (r_is_inverted) + if (!EC_POINT_invert(group, r, ctx)) goto err; + } + + ret = 1; + + err: + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (tmp != NULL) + EC_POINT_free(tmp); + if (wsize != NULL) + OPENSSL_free(wsize); + if (wNAF_len != NULL) + OPENSSL_free(wNAF_len); + if (wNAF != NULL) + { + signed char **w; + + for (w = wNAF; *w != NULL; w++) + OPENSSL_free(*w); + + OPENSSL_free(wNAF); + } + if (val != NULL) + { + for (v = val; *v != NULL; v++) + EC_POINT_clear_free(*v); + + OPENSSL_free(val); + } + if (val_sub != NULL) + { + OPENSSL_free(val_sub); + } + return ret; + } + + +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) + { + const EC_POINT *points[1]; + const BIGNUM *scalars[1]; + + points[0] = point; + scalars[0] = p_scalar; + + return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx); + } + + +int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) + { + const EC_POINT *generator; + BN_CTX *new_ctx = NULL; + BIGNUM *order; + int ret = 0; + + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) + { + ECerr(EC_F_EC_GROUP_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); + return 0; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + order = BN_CTX_get(ctx); + if (order == NULL) goto err; + + if (!EC_GROUP_get_order(group, order, ctx)) return 0; + if (BN_is_zero(order)) + { + ECerr(EC_F_EC_GROUP_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); + goto err; + } + + /* TODO */ + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } diff --git a/src/lib/libcrypto/ec/ecp_mont.c b/src/lib/libcrypto/ec/ecp_mont.c new file mode 100644 index 0000000000..7b30d4c38a --- /dev/null +++ b/src/lib/libcrypto/ec/ecp_mont.c @@ -0,0 +1,304 @@ +/* crypto/ec/ecp_mont.c */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "ec_lcl.h" + + +const EC_METHOD *EC_GFp_mont_method(void) + { + static const EC_METHOD ret = { + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_clear_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve_GFp, + ec_GFp_simple_group_get_curve_GFp, + ec_GFp_simple_group_set_generator, + ec_GFp_simple_group_get0_generator, + ec_GFp_simple_group_get_order, + ec_GFp_simple_group_get_cofactor, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + ec_GFp_simple_set_compressed_coordinates_GFp, + ec_GFp_simple_point2oct, + ec_GFp_simple_oct2point, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ec_GFp_mont_field_mul, + ec_GFp_mont_field_sqr, + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + ec_GFp_mont_field_set_to_one }; + + return &ret; + } + + +int ec_GFp_mont_group_init(EC_GROUP *group) + { + int ok; + + ok = ec_GFp_simple_group_init(group); + group->field_data1 = NULL; + group->field_data2 = NULL; + return ok; + } + + +int ec_GFp_mont_group_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + BN_MONT_CTX *mont = NULL; + BIGNUM *one = NULL; + int ret = 0; + + if (group->field_data1 != NULL) + { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + } + if (group->field_data2 != NULL) + { + BN_free(group->field_data2); + group->field_data2 = NULL; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + mont = BN_MONT_CTX_new(); + if (mont == NULL) goto err; + if (!BN_MONT_CTX_set(mont, p, ctx)) + { + ECerr(EC_F_GFP_MONT_GROUP_SET_CURVE_GFP, ERR_R_BN_LIB); + goto err; + } + one = BN_new(); + if (one == NULL) goto err; + if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err; + + group->field_data1 = mont; + mont = NULL; + group->field_data2 = one; + one = NULL; + + ret = ec_GFp_simple_group_set_curve_GFp(group, p, a, b, ctx); + + if (!ret) + { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + BN_free(group->field_data2); + group->field_data2 = NULL; + } + + err: + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (mont != NULL) + BN_MONT_CTX_free(mont); + return ret; + } + + +void ec_GFp_mont_group_finish(EC_GROUP *group) + { + if (group->field_data1 != NULL) + { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + } + if (group->field_data2 != NULL) + { + BN_free(group->field_data2); + group->field_data2 = NULL; + } + ec_GFp_simple_group_finish(group); + } + + +void ec_GFp_mont_group_clear_finish(EC_GROUP *group) + { + if (group->field_data1 != NULL) + { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + } + if (group->field_data2 != NULL) + { + BN_clear_free(group->field_data2); + group->field_data2 = NULL; + } + ec_GFp_simple_group_clear_finish(group); + } + + +int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) + { + if (dest->field_data1 != NULL) + { + BN_MONT_CTX_free(dest->field_data1); + dest->field_data1 = NULL; + } + if (dest->field_data2 != NULL) + { + BN_clear_free(dest->field_data2); + dest->field_data2 = NULL; + } + + if (!ec_GFp_simple_group_copy(dest, src)) return 0; + + if (src->field_data1 != NULL) + { + dest->field_data1 = BN_MONT_CTX_new(); + if (dest->field_data1 == NULL) return 0; + if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) goto err; + } + if (src->field_data2 != NULL) + { + dest->field_data2 = BN_dup(src->field_data2); + if (dest->field_data2 == NULL) goto err; + } + + return 1; + + err: + if (dest->field_data1 != NULL) + { + BN_MONT_CTX_free(dest->field_data1); + dest->field_data1 = NULL; + } + return 0; + } + + +int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + if (group->field_data1 == NULL) + { + ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); + } + + +int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) + { + if (group->field_data1 == NULL) + { + ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); + } + + +int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) + { + if (group->field_data1 == NULL) + { + ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); + } + + +int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) + { + if (group->field_data1 == NULL) + { + ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_from_montgomery(r, a, group->field_data1, ctx); + } + + +int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx) + { + if (group->field_data2 == NULL) + { + ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); + return 0; + } + + if (!BN_copy(r, group->field_data2)) return 0; + return 1; + } diff --git a/src/lib/libcrypto/ec/ecp_nist.c b/src/lib/libcrypto/ec/ecp_nist.c new file mode 100644 index 0000000000..ed07748675 --- /dev/null +++ b/src/lib/libcrypto/ec/ecp_nist.c @@ -0,0 +1,134 @@ +/* crypto/ec/ecp_nist.c */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "ec_lcl.h" + +#if 0 +const EC_METHOD *EC_GFp_nist_method(void) + { + static const EC_METHOD ret = { + ec_GFp_nist_group_init, + ec_GFp_nist_group_finish, + ec_GFp_nist_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nist_group_set_curve_GFp, + ec_GFp_simple_group_get_curve_GFp, + ec_GFp_simple_group_set_generator, + ec_GFp_simple_group_get0_generator, + ec_GFp_simple_group_get_order, + ec_GFp_simple_group_get_cofactor, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + ec_GFp_simple_set_compressed_coordinates_GFp, + ec_GFp_simple_point2oct, + ec_GFp_simple_oct2point, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_encode */, + 0 /* field_decode */, + 0 /* field_set_to_one */ }; + + return &ret; + } +#endif + + +int ec_GFp_nist_group_init(EC_GROUP *group) + { + int ok; + + ok = ec_GFp_simple_group_init(group); + group->field_data1 = NULL; + return ok; + } + + +int ec_GFp_nist_group_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +/* TODO */ + + +void ec_GFp_nist_group_finish(EC_GROUP *group); +/* TODO */ + + +void ec_GFp_nist_group_clear_finish(EC_GROUP *group); +/* TODO */ + + +int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); +/* TODO */ + + +int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +/* TODO */ + + +int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +/* TODO */ diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c new file mode 100644 index 0000000000..4666a052bf --- /dev/null +++ b/src/lib/libcrypto/ec/ecp_smpl.c @@ -0,0 +1,1717 @@ +/* crypto/ec/ecp_smpl.c */ +/* Includes code written by Lenka Fibikova + * for the OpenSSL project. */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "ec_lcl.h" + + +const EC_METHOD *EC_GFp_simple_method(void) + { + static const EC_METHOD ret = { + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve_GFp, + ec_GFp_simple_group_get_curve_GFp, + ec_GFp_simple_group_set_generator, + ec_GFp_simple_group_get0_generator, + ec_GFp_simple_group_get_order, + ec_GFp_simple_group_get_cofactor, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + ec_GFp_simple_set_compressed_coordinates_GFp, + ec_GFp_simple_point2oct, + ec_GFp_simple_oct2point, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + ec_GFp_simple_is_at_infinity, + ec_GFp_simple_is_on_curve, + ec_GFp_simple_cmp, + ec_GFp_simple_make_affine, + ec_GFp_simple_points_make_affine, + ec_GFp_simple_field_mul, + ec_GFp_simple_field_sqr, + 0 /* field_encode */, + 0 /* field_decode */, + 0 /* field_set_to_one */ }; + + return &ret; + } + + +int ec_GFp_simple_group_init(EC_GROUP *group) + { + BN_init(&group->field); + BN_init(&group->a); + BN_init(&group->b); + group->a_is_minus3 = 0; + group->generator = NULL; + BN_init(&group->order); + BN_init(&group->cofactor); + return 1; + } + + +void ec_GFp_simple_group_finish(EC_GROUP *group) + { + BN_free(&group->field); + BN_free(&group->a); + BN_free(&group->b); + if (group->generator != NULL) + EC_POINT_free(group->generator); + BN_free(&group->order); + BN_free(&group->cofactor); + } + + +void ec_GFp_simple_group_clear_finish(EC_GROUP *group) + { + BN_clear_free(&group->field); + BN_clear_free(&group->a); + BN_clear_free(&group->b); + if (group->generator != NULL) + { + EC_POINT_clear_free(group->generator); + group->generator = NULL; + } + BN_clear_free(&group->order); + BN_clear_free(&group->cofactor); + } + + +int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) + { + if (!BN_copy(&dest->field, &src->field)) return 0; + if (!BN_copy(&dest->a, &src->a)) return 0; + if (!BN_copy(&dest->b, &src->b)) return 0; + + dest->a_is_minus3 = src->a_is_minus3; + + if (src->generator != NULL) + { + if (dest->generator == NULL) + { + dest->generator = EC_POINT_new(dest); + if (dest->generator == NULL) return 0; + } + if (!EC_POINT_copy(dest->generator, src->generator)) return 0; + } + else + { + /* src->generator == NULL */ + if (dest->generator != NULL) + { + EC_POINT_clear_free(dest->generator); + dest->generator = NULL; + } + } + + if (!BN_copy(&dest->order, &src->order)) return 0; + if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0; + + return 1; + } + + +int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group, + const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *tmp_a; + + /* p must be a prime > 3 */ + if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP, EC_R_INVALID_FIELD); + return 0; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + tmp_a = BN_CTX_get(ctx); + if (tmp_a == NULL) goto err; + + /* group->field */ + if (!BN_copy(&group->field, p)) goto err; + group->field.neg = 0; + + /* group->a */ + if (!BN_nnmod(tmp_a, a, p, ctx)) goto err; + if (group->meth->field_encode) + { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; } + else + if (!BN_copy(&group->a, tmp_a)) goto err; + + /* group->b */ + if (!BN_nnmod(&group->b, b, p, ctx)) goto err; + if (group->meth->field_encode) + if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err; + + /* group->a_is_minus3 */ + if (!BN_add_word(tmp_a, 3)) goto err; + group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) + { + int ret = 0; + BN_CTX *new_ctx = NULL; + + if (p != NULL) + { + if (!BN_copy(p, &group->field)) return 0; + } + + if (a != NULL || b != NULL) + { + if (group->meth->field_decode) + { + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + if (a != NULL) + { + if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err; + } + if (b != NULL) + { + if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err; + } + } + else + { + if (a != NULL) + { + if (!BN_copy(a, &group->a)) goto err; + } + if (b != NULL) + { + if (!BN_copy(b, &group->b)) goto err; + } + } + } + + ret = 1; + + err: + if (new_ctx) + BN_CTX_free(new_ctx); + return ret; + } + + + +int ec_GFp_simple_group_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor) + { + if (generator == NULL) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); + return 0 ; + } + + if (group->generator == NULL) + { + group->generator = EC_POINT_new(group); + if (group->generator == NULL) return 0; + } + if (!EC_POINT_copy(group->generator, generator)) return 0; + + if (order != NULL) + { if (!BN_copy(&group->order, order)) return 0; } + else + { if (!BN_zero(&group->order)) return 0; } + + if (cofactor != NULL) + { if (!BN_copy(&group->cofactor, cofactor)) return 0; } + else + { if (!BN_zero(&group->cofactor)) return 0; } + + return 1; + } + + +EC_POINT *ec_GFp_simple_group_get0_generator(const EC_GROUP *group) + { + return group->generator; + } + + +int ec_GFp_simple_group_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) + { + if (!BN_copy(order, &group->order)) + return 0; + + return !BN_is_zero(&group->order); + } + + +int ec_GFp_simple_group_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) + { + if (!BN_copy(cofactor, &group->cofactor)) + return 0; + + return !BN_is_zero(&group->cofactor); + } + + +int ec_GFp_simple_point_init(EC_POINT *point) + { + BN_init(&point->X); + BN_init(&point->Y); + BN_init(&point->Z); + point->Z_is_one = 0; + + return 1; + } + + +void ec_GFp_simple_point_finish(EC_POINT *point) + { + BN_free(&point->X); + BN_free(&point->Y); + BN_free(&point->Z); + } + + +void ec_GFp_simple_point_clear_finish(EC_POINT *point) + { + BN_clear_free(&point->X); + BN_clear_free(&point->Y); + BN_clear_free(&point->Z); + point->Z_is_one = 0; + } + + +int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) + { + if (!BN_copy(&dest->X, &src->X)) return 0; + if (!BN_copy(&dest->Y, &src->Y)) return 0; + if (!BN_copy(&dest->Z, &src->Z)) return 0; + dest->Z_is_one = src->Z_is_one; + + return 1; + } + + +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) + { + point->Z_is_one = 0; + return (BN_zero(&point->Z)); + } + + +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + if (x != NULL) + { + if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err; + if (group->meth->field_encode) + { + if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err; + } + } + + if (y != NULL) + { + if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err; + if (group->meth->field_encode) + { + if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err; + } + } + + if (z != NULL) + { + int Z_is_one; + + if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err; + Z_is_one = BN_is_one(&point->Z); + if (group->meth->field_encode) + { + if (Z_is_one && (group->meth->field_set_to_one != 0)) + { + if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err; + } + else + { + if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err; + } + } + point->Z_is_one = Z_is_one; + } + + ret = 1; + + err: + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (group->meth->field_decode != 0) + { + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + if (x != NULL) + { + if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err; + } + if (y != NULL) + { + if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err; + } + if (z != NULL) + { + if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err; + } + } + else + { + if (x != NULL) + { + if (!BN_copy(x, &point->X)) goto err; + } + if (y != NULL) + { + if (!BN_copy(y, &point->Y)) goto err; + } + if (z != NULL) + { + if (!BN_copy(z, &point->Z)) goto err; + } + } + + ret = 1; + + err: + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) + { + if (x == NULL || y == NULL) + { + /* unlike for projective coordinates, we do not tolerate this */ + ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx); + } + + +int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + BIGNUM *X, *Y, *Z, *Z_1, *Z_2, *Z_3; + const BIGNUM *X_, *Y_, *Z_; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_POINT_AT_INFINITY); + return 0; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + X = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + Z = BN_CTX_get(ctx); + Z_1 = BN_CTX_get(ctx); + Z_2 = BN_CTX_get(ctx); + Z_3 = BN_CTX_get(ctx); + if (Z_3 == NULL) goto err; + + /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ + + if (group->meth->field_decode) + { + if (!group->meth->field_decode(group, X, &point->X, ctx)) goto err; + if (!group->meth->field_decode(group, Y, &point->Y, ctx)) goto err; + if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err; + X_ = X; Y_ = Y; Z_ = Z; + } + else + { + X_ = &point->X; + Y_ = &point->Y; + Z_ = &point->Z; + } + + if (BN_is_one(Z_)) + { + if (x != NULL) + { + if (!BN_copy(x, X_)) goto err; + } + if (y != NULL) + { + if (!BN_copy(y, Y_)) goto err; + } + } + else + { + if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_BN_LIB); + goto err; + } + + if (group->meth->field_encode == 0) + { + /* field_sqr works on standard representation */ + if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err; + } + else + { + if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err; + } + + if (x != NULL) + { + if (group->meth->field_encode == 0) + { + /* field_mul works on standard representation */ + if (!group->meth->field_mul(group, x, X_, Z_2, ctx)) goto err; + } + else + { + if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err; + } + } + + if (y != NULL) + { + if (group->meth->field_encode == 0) + { + /* field_mul works on standard representation */ + if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err; + if (!group->meth->field_mul(group, y, Y_, Z_3, ctx)) goto err; + + } + else + { + if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err; + if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err; + } + } + } + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x_, int y_bit, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *x, *y; + int ret = 0; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + y_bit = (y_bit != 0); + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; + + /* Recover y. We have a Weierstrass equation + * y^2 = x^3 + a*x + b, + * so y is one of the square roots of x^3 + a*x + b. + */ + + /* tmp1 := x^3 */ + if (!BN_nnmod(x, x_, &group->field,ctx)) goto err; + if (group->meth->field_decode == 0) + { + /* field_{sqr,mul} work on standard representation */ + if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err; + if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err; + } + else + { + if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err; + if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err; + } + + /* tmp1 := tmp1 + a*x */ + if (group->a_is_minus3) + { + if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err; + if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err; + if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err; + } + else + { + if (group->meth->field_decode) + { + if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err; + if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err; + } + else + { + /* field_mul works on standard representation */ + if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err; + } + + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; + } + + /* tmp1 := tmp1 + b */ + if (group->meth->field_decode) + { + if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err; + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; + } + else + { + if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err; + } + + if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) + { + unsigned long err = ERR_peek_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) + { + (void)ERR_get_error(); + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSED_POINT); + } + else + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, ERR_R_BN_LIB); + goto err; + } + /* If tmp1 is not a square (i.e. there is no point on the curve with + * our x), then y now is a nonsense value too */ + + if (y_bit != BN_is_odd(y)) + { + if (BN_is_zero(y)) + { + int kron; + + kron = BN_kronecker(x, &group->field, ctx); + if (kron == -2) goto err; + + if (kron == 1) + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSION_BIT); + else + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSED_POINT); + goto err; + } + if (!BN_usub(y, &group->field, y)) goto err; + } + if (y_bit != BN_is_odd(y)) + { + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) + { + size_t ret; + BN_CTX *new_ctx = NULL; + int used_ctx = 0; + BIGNUM *x, *y; + size_t field_len, i, skip; + + if ((form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); + goto err; + } + + if (EC_POINT_is_at_infinity(group, point)) + { + /* encodes to a single 0 octet */ + if (buf != NULL) + { + if (len < 1) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + buf[0] = 0; + } + return 1; + } + + + /* ret := required output buffer length */ + field_len = BN_num_bytes(&group->field); + ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; + + /* if 'buf' is NULL, just return required length */ + if (buf != NULL) + { + if (len < ret) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + goto err; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + used_ctx = 1; + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + + if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y)) + buf[0] = form + 1; + else + buf[0] = form; + + i = 1; + + skip = field_len - BN_num_bytes(x); + if (skip > field_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) + { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(x, buf + i); + i += skip; + if (i != 1 + field_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) + { + skip = field_len - BN_num_bytes(y); + if (skip > field_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) + { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(y, buf + i); + i += skip; + } + + if (i != ret) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (used_ctx) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + + err: + if (used_ctx) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return 0; + } + + +int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, BN_CTX *ctx) + { + point_conversion_form_t form; + int y_bit; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + size_t field_len, enc_len; + int ret = 0; + + if (len == 0) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1; + if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (form == 0) + { + if (len != 1) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + return EC_POINT_set_to_infinity(group, point); + } + + field_len = BN_num_bytes(&group->field); + enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; + + if (len != enc_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; + + if (!BN_bin2bn(buf + 1, field_len, x)) goto err; + if (BN_ucmp(x, &group->field) >= 0) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + + if (form == POINT_CONVERSION_COMPRESSED) + { + if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err; + } + else + { + if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; + if (BN_ucmp(y, &group->field) >= 0) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + if (form == POINT_CONVERSION_HYBRID) + { + if (y_bit != BN_is_odd(y)) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + } + + if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */ + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) + { + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; + int ret = 0; + + if (a == b) + return EC_POINT_dbl(group, r, a, ctx); + if (EC_POINT_is_at_infinity(group, a)) + return EC_POINT_copy(r, b); + if (EC_POINT_is_at_infinity(group, b)) + return EC_POINT_copy(r, a); + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + n4 = BN_CTX_get(ctx); + n5 = BN_CTX_get(ctx); + n6 = BN_CTX_get(ctx); + if (n6 == NULL) goto end; + + /* Note that in this function we must not read components of 'a' or 'b' + * once we have written the corresponding components of 'r'. + * ('r' might be one of 'a' or 'b'.) + */ + + /* n1, n2 */ + if (b->Z_is_one) + { + if (!BN_copy(n1, &a->X)) goto end; + if (!BN_copy(n2, &a->Y)) goto end; + /* n1 = X_a */ + /* n2 = Y_a */ + } + else + { + if (!field_sqr(group, n0, &b->Z, ctx)) goto end; + if (!field_mul(group, n1, &a->X, n0, ctx)) goto end; + /* n1 = X_a * Z_b^2 */ + + if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end; + if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end; + /* n2 = Y_a * Z_b^3 */ + } + + /* n3, n4 */ + if (a->Z_is_one) + { + if (!BN_copy(n3, &b->X)) goto end; + if (!BN_copy(n4, &b->Y)) goto end; + /* n3 = X_b */ + /* n4 = Y_b */ + } + else + { + if (!field_sqr(group, n0, &a->Z, ctx)) goto end; + if (!field_mul(group, n3, &b->X, n0, ctx)) goto end; + /* n3 = X_b * Z_a^2 */ + + if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end; + if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end; + /* n4 = Y_b * Z_a^3 */ + } + + /* n5, n6 */ + if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end; + if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end; + /* n5 = n1 - n3 */ + /* n6 = n2 - n4 */ + + if (BN_is_zero(n5)) + { + if (BN_is_zero(n6)) + { + /* a is the same point as b */ + BN_CTX_end(ctx); + ret = EC_POINT_dbl(group, r, a, ctx); + ctx = NULL; + goto end; + } + else + { + /* a is the inverse of b */ + if (!BN_zero(&r->Z)) goto end; + r->Z_is_one = 0; + ret = 1; + goto end; + } + } + + /* 'n7', 'n8' */ + if (!BN_mod_add_quick(n1, n1, n3, p)) goto end; + if (!BN_mod_add_quick(n2, n2, n4, p)) goto end; + /* 'n7' = n1 + n3 */ + /* 'n8' = n2 + n4 */ + + /* Z_r */ + if (a->Z_is_one && b->Z_is_one) + { + if (!BN_copy(&r->Z, n5)) goto end; + } + else + { + if (a->Z_is_one) + { if (!BN_copy(n0, &b->Z)) goto end; } + else if (b->Z_is_one) + { if (!BN_copy(n0, &a->Z)) goto end; } + else + { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; } + if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end; + } + r->Z_is_one = 0; + /* Z_r = Z_a * Z_b * n5 */ + + /* X_r */ + if (!field_sqr(group, n0, n6, ctx)) goto end; + if (!field_sqr(group, n4, n5, ctx)) goto end; + if (!field_mul(group, n3, n1, n4, ctx)) goto end; + if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end; + /* X_r = n6^2 - n5^2 * 'n7' */ + + /* 'n9' */ + if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end; + if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end; + /* n9 = n5^2 * 'n7' - 2 * X_r */ + + /* Y_r */ + if (!field_mul(group, n0, n0, n6, ctx)) goto end; + if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */ + if (!field_mul(group, n1, n2, n5, ctx)) goto end; + if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end; + if (BN_is_odd(n0)) + if (!BN_add(n0, n0, p)) goto end; + /* now 0 <= n0 < 2*p, and n0 is even */ + if (!BN_rshift1(&r->Y, n0)) goto end; + /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ + + ret = 1; + + end: + if (ctx) /* otherwise we already called BN_CTX_end */ + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) + { + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, a)) + { + if (!BN_zero(&r->Z)) return 0; + r->Z_is_one = 0; + return 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + if (n3 == NULL) goto err; + + /* Note that in this function we must not read components of 'a' + * once we have written the corresponding components of 'r'. + * ('r' might the same as 'a'.) + */ + + /* n1 */ + if (a->Z_is_one) + { + if (!field_sqr(group, n0, &a->X, ctx)) goto err; + if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; + if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; + if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err; + /* n1 = 3 * X_a^2 + a_curve */ + } + else if (group->a_is_minus3) + { + if (!field_sqr(group, n1, &a->Z, ctx)) goto err; + if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err; + if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err; + if (!field_mul(group, n1, n0, n2, ctx)) goto err; + if (!BN_mod_lshift1_quick(n0, n1, p)) goto err; + if (!BN_mod_add_quick(n1, n0, n1, p)) goto err; + /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) + * = 3 * X_a^2 - 3 * Z_a^4 */ + } + else + { + if (!field_sqr(group, n0, &a->X, ctx)) goto err; + if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; + if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; + if (!field_sqr(group, n1, &a->Z, ctx)) goto err; + if (!field_sqr(group, n1, n1, ctx)) goto err; + if (!field_mul(group, n1, n1, &group->a, ctx)) goto err; + if (!BN_mod_add_quick(n1, n1, n0, p)) goto err; + /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ + } + + /* Z_r */ + if (a->Z_is_one) + { + if (!BN_copy(n0, &a->Y)) goto err; + } + else + { + if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err; + } + if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err; + r->Z_is_one = 0; + /* Z_r = 2 * Y_a * Z_a */ + + /* n2 */ + if (!field_sqr(group, n3, &a->Y, ctx)) goto err; + if (!field_mul(group, n2, &a->X, n3, ctx)) goto err; + if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err; + /* n2 = 4 * X_a * Y_a^2 */ + + /* X_r */ + if (!BN_mod_lshift1_quick(n0, n2, p)) goto err; + if (!field_sqr(group, &r->X, n1, ctx)) goto err; + if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err; + /* X_r = n1^2 - 2 * n2 */ + + /* n3 */ + if (!field_sqr(group, n0, n3, ctx)) goto err; + if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err; + /* n3 = 8 * Y_a^4 */ + + /* Y_r */ + if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err; + if (!field_mul(group, n0, n1, n0, ctx)) goto err; + if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err; + /* Y_r = n1 * (n2 - X_r) - n3 */ + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) + { + if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) + /* point is its own inverse */ + return 1; + + return BN_usub(&point->Y, &group->field, &point->Y); + } + + +int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) + { + return BN_is_zero(&point->Z); + } + + +int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) + { + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, point)) + return 1; + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + rh = BN_CTX_get(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + Z4 = BN_CTX_get(ctx); + Z6 = BN_CTX_get(ctx); + if (Z6 == NULL) goto err; + + /* We have a curve defined by a Weierstrass equation + * y^2 = x^3 + a*x + b. + * The point to consider is given in Jacobian projective coordinates + * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). + * Substituting this and multiplying by Z^6 transforms the above equation into + * Y^2 = X^3 + a*X*Z^4 + b*Z^6. + * To test this, we add up the right-hand side in 'rh'. + */ + + /* rh := X^3 */ + if (!field_sqr(group, rh, &point->X, ctx)) goto err; + if (!field_mul(group, rh, rh, &point->X, ctx)) goto err; + + if (!point->Z_is_one) + { + if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err; + if (!field_sqr(group, Z4, tmp1, ctx)) goto err; + if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err; + + /* rh := rh + a*X*Z^4 */ + if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err; + if (group->a_is_minus3) + { + if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err; + if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err; + if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err; + } + else + { + if (!field_mul(group, tmp2, tmp1, &group->a, ctx)) goto err; + if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err; + } + + /* rh := rh + b*Z^6 */ + if (!field_mul(group, tmp1, &group->b, Z6, ctx)) goto err; + if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err; + } + else + { + /* point->Z_is_one */ + + /* rh := rh + a*X */ + if (group->a_is_minus3) + { + if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err; + if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err; + if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err; + } + else + { + if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err; + if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err; + } + + /* rh := rh + b */ + if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err; + } + + /* 'lh' := Y^2 */ + if (!field_sqr(group, tmp1, &point->Y, ctx)) goto err; + + ret = (0 == BN_cmp(tmp1, rh)); + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) + { + /* return values: + * -1 error + * 0 equal (in affine coordinates) + * 1 not equal + */ + + int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); + int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *Za23, *Zb23; + const BIGNUM *tmp1_, *tmp2_; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, a)) + { + return EC_POINT_is_at_infinity(group, b) ? 0 : 1; + } + + if (a->Z_is_one && b->Z_is_one) + { + return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + Za23 = BN_CTX_get(ctx); + Zb23 = BN_CTX_get(ctx); + if (Zb23 == NULL) goto end; + + /* We have to decide whether + * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), + * or equivalently, whether + * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). + */ + + if (!b->Z_is_one) + { + if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end; + if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end; + tmp1_ = tmp1; + } + else + tmp1_ = &a->X; + if (!a->Z_is_one) + { + if (!field_sqr(group, Za23, &a->Z, ctx)) goto end; + if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end; + tmp2_ = tmp2; + } + else + tmp2_ = &b->X; + + /* compare X_a*Z_b^2 with X_b*Z_a^2 */ + if (BN_cmp(tmp1_, tmp2_) != 0) + { + ret = 1; /* points differ */ + goto end; + } + + + if (!b->Z_is_one) + { + if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end; + if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end; + /* tmp1_ = tmp1 */ + } + else + tmp1_ = &a->Y; + if (!a->Z_is_one) + { + if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end; + if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end; + /* tmp2_ = tmp2 */ + } + else + tmp2_ = &b->Y; + + /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ + if (BN_cmp(tmp1_, tmp2_) != 0) + { + ret = 1; /* points differ */ + goto end; + } + + /* points are equal */ + ret = 0; + + end: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + int ret = 0; + + if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) + return 1; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + if (!point->Z_is_one) + { + ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR); + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + BIGNUM *tmp0, *tmp1; + size_t pow2 = 0; + BIGNUM **heap = NULL; + size_t i; + int ret = 0; + + if (num == 0) + return 1; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + tmp0 = BN_CTX_get(ctx); + tmp1 = BN_CTX_get(ctx); + if (tmp0 == NULL || tmp1 == NULL) goto err; + + /* Before converting the individual points, compute inverses of all Z values. + * Modular inversion is rather slow, but luckily we can do with a single + * explicit inversion, plus about 3 multiplications per input value. + */ + + pow2 = 1; + while (num > pow2) + pow2 <<= 1; + /* Now pow2 is the smallest power of 2 satifsying pow2 >= num. + * We need twice that. */ + pow2 <<= 1; + + heap = OPENSSL_malloc(pow2 * sizeof heap[0]); + if (heap == NULL) goto err; + + /* The array is used as a binary tree, exactly as in heapsort: + * + * heap[1] + * heap[2] heap[3] + * heap[4] heap[5] heap[6] heap[7] + * heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15] + * + * We put the Z's in the last line; + * then we set each other node to the product of its two child-nodes (where + * empty or 0 entries are treated as ones); + * then we invert heap[1]; + * then we invert each other node by replacing it by the product of its + * parent (after inversion) and its sibling (before inversion). + */ + heap[0] = NULL; + for (i = pow2/2 - 1; i > 0; i--) + heap[i] = NULL; + for (i = 0; i < num; i++) + heap[pow2/2 + i] = &points[i]->Z; + for (i = pow2/2 + num; i < pow2; i++) + heap[i] = NULL; + + /* set each node to the product of its children */ + for (i = pow2/2 - 1; i > 0; i--) + { + heap[i] = BN_new(); + if (heap[i] == NULL) goto err; + + if (heap[2*i] != NULL) + { + if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1])) + { + if (!BN_copy(heap[i], heap[2*i])) goto err; + } + else + { + if (BN_is_zero(heap[2*i])) + { + if (!BN_copy(heap[i], heap[2*i + 1])) goto err; + } + else + { + if (!group->meth->field_mul(group, heap[i], + heap[2*i], heap[2*i + 1], ctx)) goto err; + } + } + } + } + + /* invert heap[1] */ + if (!BN_is_zero(heap[1])) + { + if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); + goto err; + } + } + if (group->meth->field_encode != 0) + { + /* in the Montgomery case, we just turned R*H (representing H) + * into 1/(R*H), but we need R*(1/H) (representing 1/H); + * i.e. we have need to multiply by the Montgomery factor twice */ + if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err; + if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err; + } + + /* set other heap[i]'s to their inverses */ + for (i = 2; i < pow2/2 + num; i += 2) + { + /* i is even */ + if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1])) + { + if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err; + if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err; + if (!BN_copy(heap[i], tmp0)) goto err; + if (!BN_copy(heap[i + 1], tmp1)) goto err; + } + else + { + if (!BN_copy(heap[i], heap[i/2])) goto err; + } + } + + /* we have replaced all non-zero Z's by their inverses, now fix up all the points */ + for (i = 0; i < num; i++) + { + EC_POINT *p = points[i]; + + if (!BN_is_zero(&p->Z)) + { + /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ + + if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err; + if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err; + + if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err; + if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err; + + if (group->meth->field_set_to_one != 0) + { + if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err; + } + else + { + if (!BN_one(&p->Z)) goto err; + } + p->Z_is_one = 1; + } + } + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (heap != NULL) + { + /* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */ + for (i = pow2/2 - 1; i > 0; i--) + { + if (heap[i] != NULL) + BN_clear_free(heap[i]); + } + OPENSSL_free(heap); + } + return ret; + } + + +int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) + { + return BN_mod_mul(r, a, b, &group->field, ctx); + } + + +int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) + { + return BN_mod_sqr(r, a, &group->field, ctx); + } diff --git a/src/lib/libcrypto/engine/README b/src/lib/libcrypto/engine/README new file mode 100644 index 0000000000..96595e6f35 --- /dev/null +++ b/src/lib/libcrypto/engine/README @@ -0,0 +1,278 @@ +NOTES, THOUGHTS, and EVERYTHING +------------------------------- + +(1) Concurrency and locking ... I made a change to the ENGINE_free code + because I spotted a potential hold-up in proceedings (doing too + much inside a lock including calling a callback), there may be + other bits like this. What do the speed/optimisation freaks think + of this aspect of the code and design? There's lots of locking for + manipulation functions and I need that to keep things nice and + solid, but this manipulation is mostly (de)initialisation, I would + think that most run-time locking is purely in the ENGINE_init and + ENGINE_finish calls that might be made when getting handles for + RSA (and friends') structures. These would be mostly reference + count operations as the functional references should always be 1 + or greater at run-time to prevent init/deinit thrashing. + +(2) nCipher support, via the HWCryptoHook API, is now in the code. + Apparently this hasn't been tested too much yet, but it looks + good. :-) Atalla support has been added too, but shares a lot in + common with Ben's original hooks in bn_exp.c (although it has been + ENGINE-ified, and error handling wrapped around it) and it's also + had some low-volume testing, so it should be usable. + +(3) Of more concern, we need to work out (a) how to put together usable + RAND_METHODs for units that just have one "get n or less random + bytes" function, (b) we also need to determine how to hook the code + in crypto/rand/ to use the ENGINE defaults in a way similar to what + has been done in crypto/rsa/, crypto/dsa/, etc. + +(4) ENGINE should really grow to encompass more than 3 public key + algorithms and randomness gathering. The structure/data level of + the engine code is hidden from code outside the crypto/engine/ + directory so change shouldn't be too viral. More important though + is how things should evolve ... this needs thought and discussion. + + +-----------------------------------==*==----------------------------------- + +More notes 2000-08-01 +--------------------- + +Geoff Thorpe, who designed the engine part, wrote a pretty good description +of the thoughts he had when he built it, good enough to include verbatim here +(with his permission) -- Richard Levitte + + +Date: Tue, 1 Aug 2000 16:54:08 +0100 (BST) +From: Geoff Thorpe +Subject: Re: The thoughts to merge BRANCH_engine into the main trunk are + emerging + +Hi there, + +I'm going to try and do some justice to this, but I'm a little short on +time and the there is an endless amount that could be discussed on this +subject. sigh ... please bear with me :-) + +> The changes in BRANCH_engine dig deep into the core of OpenSSL, for example +> into the RSA and RAND routines, adding a level of indirection which is needed +> to keep the abstraction, as far as I understand. It would be a good thing if +> those who do play with those things took a look at the changes that have been +> done in the branch and say out loud how much (or hopefully little) we've made +> fools of ourselves. + +The point here is that the code that has emerged in the BRANCH_engine +branch was based on some initial requirements of mine that I went in and +addressed, and Richard has picked up the ball and run with it too. It +would be really useful to get some review of the approach we've taken, but +first I think I need to describe as best I can the reasons behind what has +been done so far, in particular what issues we have tried to address when +doing this, and what issues we have intentionally (or necessarily) tried +to avoid. + +methods, engines, and evps +-------------------------- + +There has been some dicussion, particularly with Steve, about where this +ENGINE stuff might fit into the conceptual picture as/when we start to +abstract algorithms a little bit to make the library more extensible. In +particular, it would desirable to have algorithms (symmetric, hash, pkc, +etc) abstracted in some way that allows them to be just objects sitting in +a list (or database) ... it'll just happen that the "DSA" object doesn't +support encryption whereas the "RSA" object does. This requires a lot of +consideration to begin to know how to tackle it; in particular how +encapsulated should these things be? If the objects also understand their +own ASN1 encodings and what-not, then it would for example be possible to +add support for elliptic-curve DSA in as a new algorithm and automatically +have ECC-DSA certificates supported in SSL applications. Possible, but not +easy. :-) + +Whatever, it seems that the way to go (if I've grok'd Steve's comments on +this in the past) is to amalgamate these things in EVP as is already done +(I think) for ciphers or hashes (Steve, please correct/elaborate). I +certainly think something should be done in this direction because right +now we have different source directories, types, functions, and methods +for each algorithm - even when conceptually they are very much different +feathers of the same bird. (This is certainly all true for the public-key +stuff, and may be partially true for the other parts.) + +ENGINE was *not* conceived as a way of solving this, far from it. Nor was +it conceived as a way of replacing the various "***_METHOD"s. It was +conceived as an abstraction of a sort of "virtual crypto device". If we +lived in a world where "EVP_ALGO"s (or something like them) encapsulated +particular algorithms like RSA,DSA,MD5,RC4,etc, and "***_METHOD"s +encapsulated interfaces to algorithms (eg. some algo's might support a +PKC_METHOD, a HASH_METHOD, or a CIPHER_METHOD, who knows?), then I would +think that ENGINE would encapsulate an implementation of arbitrarily many +of those algorithms - perhaps as alternatives to existing algorithms +and/or perhaps as new previously unimplemented algorithms. An ENGINE could +be used to contain an alternative software implementation, a wrapper for a +hardware acceleration and/or key-management unit, a comms-wrapper for +distributing cryptographic operations to remote machines, or any other +"devices" your imagination can dream up. + +However, what has been done in the ENGINE branch so far is nothing more +than starting to get our toes wet. I had a couple of self-imposed +requirements when putting the initial abstraction together, and I may have +already posed these in one form or another on the list, but briefly; + + (i) only bother with public key algorithms for now, and maybe RAND too + (motivated by the need to get hardware support going and the fact + this was a comparitively easy subset to address to begin with). + + (ii) don't change (if at all possible) the existing crypto code, ie. the + implementations, the way the ***_METHODs work, etc. + + (iii) ensure that if no function from the ENGINE code is ever called then + things work the way they always did, and there is no memory + allocation (otherwise the failure to cleanup would be a problem - + this is part of the reason no STACKs were used, the other part of + the reason being I found them inappropriate). + + (iv) ensure that all the built-in crypto was encapsulated by one of + these "ENGINE"s and that this engine was automatically selected as + the default. + + (v) provide the minimum hooking possible in the existing crypto code + so that global functions (eg. RSA_public_encrypt) do not need any + extra parameter, yet will use whatever the current default ENGINE + for that RSA key is, and that the default can be set "per-key" + and globally (new keys will assume the global default, and keys + without their own default will be operated on using the global + default). NB: Try and make (v) conflict as little as possible with + (ii). :-) + + (vi) wrap the ENGINE code up in duct tape so you can't even see the + corners. Ie. expose no structures at all, just black-box pointers. + + (v) maintain internally a list of ENGINEs on which a calling + application can iterate, interrogate, etc. Allow a calling + application to hook in new ENGINEs, remove ENGINEs from the list, + and enforce uniqueness within the global list of each ENGINE's + "unique id". + + (vi) keep reference counts for everything - eg. this includes storing a + reference inside each RSA structure to the ENGINE that it uses. + This is freed when the RSA structure is destroyed, or has its + ENGINE explicitly changed. The net effect needs to be that at any + time, it is deterministic to know whether an ENGINE is in use or + can be safely removed (or unloaded in the case of the other type + of reference) without invalidating function pointers that may or + may not be used indavertently in the future. This was actually + one of the biggest problems to overcome in the existing OpenSSL + code - implementations had always been assumed to be ever-present, + so there was no trivial way to get round this. + + (vii) distinguish between structural references and functional + references. + +A *little* detail +----------------- + +While my mind is on it; I'll illustrate the bit in item (vii). This idea +turned out to be very handy - the ENGINEs themselves need to be operated +on and manipulated simply as objects without necessarily trying to +"enable" them for use. Eg. most host machines will not have the necessary +hardware or software to support all the engines one might compile into +OpenSSL, yet it needs to be possible to iterate across the ENGINEs, +querying their names, properties, etc - all happening in a thread-safe +manner that uses reference counts (if you imagine two threads iterating +through a list and one thread removing the ENGINE the other is currently +looking at - you can see the gotcha waiting to happen). For all of this, +*structural references* are used and operate much like the other reference +counts in OpenSSL. + +The other kind of reference count is for *functional* references - these +indicate a reference on which the caller can actually assume the +particular ENGINE to be initialised and usable to perform the operations +it implements. Any increment or decrement of the functional reference +count automatically invokes a corresponding change in the structural +reference count, as it is fairly obvious that a functional reference is a +restricted case of a structural reference. So struct_ref >= funct_ref at +all times. NB: functional references are usually obtained by a call to +ENGINE_init(), but can also be created implicitly by calls that require a +new functional reference to be created, eg. ENGINE_set_default(). Either +way the only time the underlying ENGINE's "init" function is really called +is when the (functional) reference count increases to 1, similarly the +underlying "finish" handler is only called as the count goes down to 0. +The effect of this, for example, is that if you set the default ENGINE for +RSA operations to be "cswift", then its functional reference count will +already be at least 1 so the CryptoSwift shared-library and the card will +stay loaded and initialised until such time as all RSA keys using the +cswift ENGINE are changed or destroyed and the default ENGINE for RSA +operations has been changed. This prevents repeated thrashing of init and +finish handling if the count keeps getting down as far as zero. + +Otherwise, the way the ENGINE code has been put together I think pretty +much reflects the above points. The reason for the ENGINE structure having +individual RSA_METHOD, DSA_METHOD, etc pointers is simply that it was the +easiest way to go about things for now, to hook it all into the raw +RSA,DSA,etc code, and I was trying to the keep the structure invisible +anyway so that the way this is internally managed could be easily changed +later on when we start to work out what's to be done about these other +abstractions. + +Down the line, if some EVP-based technique emerges for adequately +encapsulating algorithms and all their various bits and pieces, then I can +imagine that "ENGINE" would turn into a reference-counting database of +these EVP things, of which the default "openssl" ENGINE would be the +library's own object database of pre-built software implemented algorithms +(and such). It would also be cool to see the idea of "METHOD"s detached +from the algorithms themselves ... so RSA, DSA, ElGamal, etc can all +expose essentially the same METHOD (aka interface), which would include +any querying/flagging stuff to identify what the algorithm can/can't do, +its name, and other stuff like max/min block sizes, key sizes, etc. This +would result in ENGINE similarly detaching its internal database of +algorithm implementations from the function definitions that return +interfaces to them. I think ... + +As for DSOs etc. Well the DSO code is pretty handy (but could be made much +more so) for loading vendor's driver-libraries and talking to them in some +generic way, but right now there's still big problems associated with +actually putting OpenSSL code (ie. new ENGINEs, or anything else for that +matter) in dynamically loadable libraries. These problems won't go away in +a hurry so I don't think we should expect to have any kind of +shared-library extensions any time soon - but solving the problems is a +good thing to aim for, and would as a side-effect probably help make +OpenSSL more usable as a shared-library itself (looking at the things +needed to do this will show you why). + +One of the problems is that if you look at any of the ENGINE +implementations, eg. hw_cswift.c or hw_ncipher.c, you'll see how it needs +a variety of functionality and definitions from various areas of OpenSSL, +including crypto/bn/, crypto/err/, crypto/ itself (locking for example), +crypto/dso/, crypto/engine/, crypto/rsa, etc etc etc. So if similar code +were to be suctioned off into shared libraries, the shared libraries would +either have to duplicate all the definitions and code and avoid loader +conflicts, or OpenSSL would have to somehow expose all that functionality +to the shared-library. If this isn't a big enough problem, the issue of +binary compatibility will be - anyone writing Apache modules can tell you +that (Ralf? Ben? :-). However, I don't think OpenSSL would need to be +quite so forgiving as Apache should be, so OpenSSL could simply tell its +version to the DSO and leave the DSO with the problem of deciding whether +to proceed or bail out for fear of binary incompatibilities. + +Certainly one thing that would go a long way to addressing this is to +embark on a bit of an opaqueness mission. I've set the ENGINE code up with +this in mind - it's so draconian that even to declare your own ENGINE, you +have to get the engine code to create the underlying ENGINE structure, and +then feed in the new ENGINE's function/method pointers through various +"set" functions. The more of the code that takes on such a black-box +approach, the more of the code that will be (a) easy to expose to shared +libraries that need it, and (b) easy to expose to applications wanting to +use OpenSSL itself as a shared-library. From my own explorations in +OpenSSL, the biggest leviathan I've seen that is a problem in this respect +is the BIGNUM code. Trying to "expose" the bignum code through any kind of +organised "METHODs", let alone do all the necessary bignum operations +solely through functions rather than direct access to the structures and +macros, will be a massive pain in the "r"s. + +Anyway, I'm done for now - hope it was readable. Thoughts? + +Cheers, +Geoff + + +-----------------------------------==*==----------------------------------- + diff --git a/src/lib/libcrypto/engine/eng_all.c b/src/lib/libcrypto/engine/eng_all.c new file mode 100644 index 0000000000..a35b3db9e8 --- /dev/null +++ b/src/lib/libcrypto/engine/eng_all.c @@ -0,0 +1,118 @@ +/* crypto/engine/eng_all.c -*- mode: C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2001 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 +#include "eng_int.h" + +#ifdef __OpenBSD__ +static int openbsd_default_loaded = 0; +#endif + +void ENGINE_load_builtin_engines(void) + { + /* There's no longer any need for an "openssl" ENGINE unless, one day, + * it is the *only* way for standard builtin implementations to be be + * accessed (ie. it would be possible to statically link binaries with + * *no* builtin implementations). */ +#if 0 + ENGINE_load_openssl(); +#endif + ENGINE_load_dynamic(); +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_CSWIFT + ENGINE_load_cswift(); +#endif +#ifndef OPENSSL_NO_HW_NCIPHER + ENGINE_load_chil(); +#endif +#ifndef OPENSSL_NO_HW_ATALLA + ENGINE_load_atalla(); +#endif +#ifndef OPENSSL_NO_HW_NURON + ENGINE_load_nuron(); +#endif +#ifndef OPENSSL_NO_HW_UBSEC + ENGINE_load_ubsec(); +#endif +#ifndef OPENSSL_NO_HW_AEP + ENGINE_load_aep(); +#endif +#ifndef OPENSSL_NO_HW_SUREWARE + ENGINE_load_sureware(); +#endif +#ifdef OPENSSL_OPENBSD_DEV_CRYPTO + ENGINE_load_openbsd_dev_crypto(); +#endif +#ifdef __OpenBSD__ + ENGINE_load_cryptodev(); +#endif +#endif + } + +#ifdef __OpenBSD__ +void ENGINE_setup_openbsd(void) { + if (!openbsd_default_loaded) { + ENGINE_load_cryptodev(); + ENGINE_register_all_complete(); + } + openbsd_default_loaded=1; +} +#endif + + diff --git a/src/lib/libcrypto/engine/eng_cnf.c b/src/lib/libcrypto/engine/eng_cnf.c new file mode 100644 index 0000000000..8c0ae8a1ad --- /dev/null +++ b/src/lib/libcrypto/engine/eng_cnf.c @@ -0,0 +1,242 @@ +/* eng_cnf.c */ +/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include "cryptlib.h" +#include +#include + +/* #define ENGINE_CONF_DEBUG */ + +/* ENGINE config module */ + +static char *skip_dot(char *name) + { + char *p; + p = strchr(name, '.'); + if (p) + return p + 1; + return name; + } + +static STACK_OF(ENGINE) *initialized_engines = NULL; + +static int int_engine_init(ENGINE *e) + { + if (!ENGINE_init(e)) + return 0; + if (!initialized_engines) + initialized_engines = sk_ENGINE_new_null(); + if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e)) + { + ENGINE_finish(e); + return 0; + } + return 1; + } + + +int int_engine_configure(char *name, char *value, const CONF *cnf) + { + int i; + int ret = 0; + long do_init = -1; + STACK_OF(CONF_VALUE) *ecmds; + CONF_VALUE *ecmd; + char *ctrlname, *ctrlvalue; + ENGINE *e = NULL; + name = skip_dot(name); +#ifdef ENGINE_CONF_DEBUG + fprintf(stderr, "Configuring engine %s\n", name); +#endif + /* Value is a section containing ENGINE commands */ + ecmds = NCONF_get_section(cnf, value); + + if (!ecmds) + { + ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR); + return 0; + } + + for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) + { + ecmd = sk_CONF_VALUE_value(ecmds, i); + ctrlname = skip_dot(ecmd->name); + ctrlvalue = ecmd->value; +#ifdef ENGINE_CONF_DEBUG + fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue); +#endif + + /* First handle some special pseudo ctrls */ + + /* Override engine name to use */ + if (!strcmp(ctrlname, "engine_id")) + name = ctrlvalue; + /* Load a dynamic ENGINE */ + else if (!strcmp(ctrlname, "dynamic_path")) + { + e = ENGINE_by_id("dynamic"); + if (!e) + goto err; + if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0)) + goto err; + if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0)) + goto err; + if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) + goto err; + } + /* ... add other pseudos here ... */ + else + { + /* At this point we need an ENGINE structural reference + * if we don't already have one. + */ + if (!e) + { + e = ENGINE_by_id(name); + if (!e) + return 0; + } + /* Allow "EMPTY" to mean no value: this allows a valid + * "value" to be passed to ctrls of type NO_INPUT + */ + if (!strcmp(ctrlvalue, "EMPTY")) + ctrlvalue = NULL; + else if (!strcmp(ctrlname, "init")) + { + if (!NCONF_get_number_e(cnf, value, "init", &do_init)) + goto err; + if (do_init == 1) + { + if (!int_engine_init(e)) + goto err; + } + else if (do_init != 0) + { + ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_INVALID_INIT_VALUE); + goto err; + } + } + else if (!strcmp(ctrlname, "default_algorithms")) + { + if (!ENGINE_set_default_string(e, ctrlvalue)) + goto err; + } + else if (!ENGINE_ctrl_cmd_string(e, + ctrlname, ctrlvalue, 0)) + return 0; + } + + + + } + if (e && (do_init == -1) && !int_engine_init(e)) + goto err; + ret = 1; + err: + if (e) + ENGINE_free(e); + return ret; + } + + +static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf) + { + STACK_OF(CONF_VALUE) *elist; + CONF_VALUE *cval; + int i; +#ifdef ENGINE_CONF_DEBUG + fprintf(stderr, "Called engine module: name %s, value %s\n", + CONF_imodule_get_name(md), CONF_imodule_get_value(md)); +#endif + /* Value is a section containing ENGINEs to configure */ + elist = NCONF_get_section(cnf, CONF_imodule_get_value(md)); + + if (!elist) + { + ENGINEerr(ENGINE_F_ENGINE_MODULE_INIT, ENGINE_R_ENGINES_SECTION_ERROR); + return 0; + } + + for (i = 0; i < sk_CONF_VALUE_num(elist); i++) + { + cval = sk_CONF_VALUE_value(elist, i); + if (!int_engine_configure(cval->name, cval->value, cnf)) + return 0; + } + + return 1; + } + +static void int_engine_module_finish(CONF_IMODULE *md) + { + ENGINE *e; + while ((e = sk_ENGINE_pop(initialized_engines))) + ENGINE_finish(e); + sk_ENGINE_free(initialized_engines); + initialized_engines = NULL; + } + + +void ENGINE_add_conf_module(void) + { + CONF_module_add("engines", + int_engine_module_init, + int_engine_module_finish); + } diff --git a/src/lib/libcrypto/engine/eng_ctrl.c b/src/lib/libcrypto/engine/eng_ctrl.c new file mode 100644 index 0000000000..ad3858395b --- /dev/null +++ b/src/lib/libcrypto/engine/eng_ctrl.c @@ -0,0 +1,387 @@ +/* crypto/engine/eng_ctrl.c */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 "eng_int.h" +#include + +/* When querying a ENGINE-specific control command's 'description', this string + * is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL. */ +static const char *int_no_description = ""; + +/* These internal functions handle 'CMD'-related control commands when the + * ENGINE in question has asked us to take care of it (ie. the ENGINE did not + * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag. */ + +static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn) + { + if((defn->cmd_num == 0) || (defn->cmd_name == NULL)) + return 1; + return 0; + } + +static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s) + { + int idx = 0; + while(!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0)) + { + idx++; + defn++; + } + if(int_ctrl_cmd_is_null(defn)) + /* The given name wasn't found */ + return -1; + return idx; + } + +static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num) + { + int idx = 0; + /* NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So + * our searches don't need to take any longer than necessary. */ + while(!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num)) + { + idx++; + defn++; + } + if(defn->cmd_num == num) + return idx; + /* The given cmd_num wasn't found */ + return -1; + } + +static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int idx; + char *s = (char *)p; + /* Take care of the easy one first (eg. it requires no searches) */ + if(cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE) + { + if((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns)) + return 0; + return e->cmd_defns->cmd_num; + } + /* One or two commands require that "p" be a valid string buffer */ + if((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) || + (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) || + (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD)) + { + if(s == NULL) + { + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, + ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + } + /* Now handle cmd_name -> cmd_num conversion */ + if(cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) + { + if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_name( + e->cmd_defns, s)) < 0)) + { + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, + ENGINE_R_INVALID_CMD_NAME); + return -1; + } + return e->cmd_defns[idx].cmd_num; + } + /* For the rest of the commands, the 'long' argument must specify a + * valie command number - so we need to conduct a search. */ + if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_num(e->cmd_defns, + (unsigned int)i)) < 0)) + { + ENGINEerr(ENGINE_F_INT_CTRL_HELPER, + ENGINE_R_INVALID_CMD_NUMBER); + return -1; + } + /* Now the logic splits depending on command type */ + switch(cmd) + { + case ENGINE_CTRL_GET_NEXT_CMD_TYPE: + idx++; + if(int_ctrl_cmd_is_null(e->cmd_defns + idx)) + /* end-of-list */ + return 0; + else + return e->cmd_defns[idx].cmd_num; + case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD: + return strlen(e->cmd_defns[idx].cmd_name); + case ENGINE_CTRL_GET_NAME_FROM_CMD: + return sprintf(s, "%s", e->cmd_defns[idx].cmd_name); + case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD: + if(e->cmd_defns[idx].cmd_desc) + return strlen(e->cmd_defns[idx].cmd_desc); + return strlen(int_no_description); + case ENGINE_CTRL_GET_DESC_FROM_CMD: + if(e->cmd_defns[idx].cmd_desc) + return sprintf(s, "%s", e->cmd_defns[idx].cmd_desc); + return sprintf(s, "%s", int_no_description); + case ENGINE_CTRL_GET_CMD_FLAGS: + return e->cmd_defns[idx].cmd_flags; + } + /* Shouldn't really be here ... */ + ENGINEerr(ENGINE_F_INT_CTRL_HELPER,ENGINE_R_INTERNAL_LIST_ERROR); + return -1; + } + +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int ctrl_exists, ref_exists; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + ref_exists = ((e->struct_ref > 0) ? 1 : 0); + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + ctrl_exists = ((e->ctrl == NULL) ? 0 : 1); + if(!ref_exists) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_REFERENCE); + return 0; + } + /* Intercept any "root-level" commands before trying to hand them on to + * ctrl() handlers. */ + switch(cmd) + { + case ENGINE_CTRL_HAS_CTRL_FUNCTION: + return ctrl_exists; + case ENGINE_CTRL_GET_FIRST_CMD_TYPE: + case ENGINE_CTRL_GET_NEXT_CMD_TYPE: + case ENGINE_CTRL_GET_CMD_FROM_NAME: + case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD: + case ENGINE_CTRL_GET_NAME_FROM_CMD: + case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD: + case ENGINE_CTRL_GET_DESC_FROM_CMD: + case ENGINE_CTRL_GET_CMD_FLAGS: + if(ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL)) + return int_ctrl_helper(e,cmd,i,p,f); + if(!ctrl_exists) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION); + /* For these cmd-related functions, failure is indicated + * by a -1 return value (because 0 is used as a valid + * return in some places). */ + return -1; + } + default: + break; + } + /* Anything else requires a ctrl() handler to exist. */ + if(!ctrl_exists) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION); + return 0; + } + return e->ctrl(e, cmd, i, p, f); + } + +int ENGINE_cmd_is_executable(ENGINE *e, int cmd) + { + int flags; + if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0) + { + ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE, + ENGINE_R_INVALID_CMD_NUMBER); + return 0; + } + if(!(flags & ENGINE_CMD_FLAG_NO_INPUT) && + !(flags & ENGINE_CMD_FLAG_NUMERIC) && + !(flags & ENGINE_CMD_FLAG_STRING)) + return 0; + return 1; + } + +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f)(), int cmd_optional) + { + int num; + + if((e == NULL) || (cmd_name == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e, + ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) <= 0)) + { + /* If the command didn't *have* to be supported, we fake + * success. This allows certain settings to be specified for + * multiple ENGINEs and only require a change of ENGINE id + * (without having to selectively apply settings). Eg. changing + * from a hardware device back to the regular software ENGINE + * without editing the config file, etc. */ + if(cmd_optional) + { + ERR_clear_error(); + return 1; + } + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, + ENGINE_R_INVALID_CMD_NAME); + return 0; + } + /* Force the result of the control command to 0 or 1, for the reasons + * mentioned before. */ + if (ENGINE_ctrl(e, num, i, p, f)) + return 1; + return 0; + } + +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional) + { + int num, flags; + long l; + char *ptr; + if((e == NULL) || (cmd_name == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e, + ENGINE_CTRL_GET_CMD_FROM_NAME, + 0, (void *)cmd_name, NULL)) <= 0)) + { + /* If the command didn't *have* to be supported, we fake + * success. This allows certain settings to be specified for + * multiple ENGINEs and only require a change of ENGINE id + * (without having to selectively apply settings). Eg. changing + * from a hardware device back to the regular software ENGINE + * without editing the config file, etc. */ + if(cmd_optional) + { + ERR_clear_error(); + return 1; + } + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_INVALID_CMD_NAME); + return 0; + } + if(!ENGINE_cmd_is_executable(e, num)) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_CMD_NOT_EXECUTABLE); + return 0; + } + if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL)) < 0) + { + /* Shouldn't happen, given that ENGINE_cmd_is_executable() + * returned success. */ + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + /* If the command takes no input, there must be no input. And vice + * versa. */ + if(flags & ENGINE_CMD_FLAG_NO_INPUT) + { + if(arg != NULL) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_COMMAND_TAKES_NO_INPUT); + return 0; + } + /* We deliberately force the result of ENGINE_ctrl() to 0 or 1 + * rather than returning it as "return data". This is to ensure + * usage of these commands is consistent across applications and + * that certain applications don't understand it one way, and + * others another. */ + if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL)) + return 1; + return 0; + } + /* So, we require input */ + if(arg == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_COMMAND_TAKES_INPUT); + return 0; + } + /* If it takes string input, that's easy */ + if(flags & ENGINE_CMD_FLAG_STRING) + { + /* Same explanation as above */ + if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL)) + return 1; + return 0; + } + /* If it doesn't take numeric either, then it is unsupported for use in + * a config-setting situation, which is what this function is for. This + * should never happen though, because ENGINE_cmd_is_executable() was + * used. */ + if(!(flags & ENGINE_CMD_FLAG_NUMERIC)) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + l = strtol(arg, &ptr, 10); + if((arg == ptr) || (*ptr != '\0')) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER); + return 0; + } + /* Force the result of the control command to 0 or 1, for the reasons + * mentioned before. */ + if(ENGINE_ctrl(e, num, l, NULL, NULL)) + return 1; + return 0; + } diff --git a/src/lib/libcrypto/engine/eng_dyn.c b/src/lib/libcrypto/engine/eng_dyn.c new file mode 100644 index 0000000000..4fefcc0cae --- /dev/null +++ b/src/lib/libcrypto/engine/eng_dyn.c @@ -0,0 +1,446 @@ +/* crypto/engine/eng_dyn.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 +#include "cryptlib.h" +#include "eng_int.h" +#include +#include + +/* Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE loader + * should implement the hook-up functions with the following prototypes. */ + +/* Our ENGINE handlers */ +static int dynamic_init(ENGINE *e); +static int dynamic_finish(ENGINE *e); +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); +/* Predeclare our context type */ +typedef struct st_dynamic_data_ctx dynamic_data_ctx; +/* The implementation for the important control command */ +static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx); + +#define DYNAMIC_CMD_SO_PATH ENGINE_CMD_BASE +#define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1) +#define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2) +#define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3) +#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 4) + +/* The constants used when creating the ENGINE */ +static const char *engine_dynamic_id = "dynamic"; +static const char *engine_dynamic_name = "Dynamic engine loading support"; +static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = { + {DYNAMIC_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the new ENGINE shared library", + ENGINE_CMD_FLAG_STRING}, + {DYNAMIC_CMD_NO_VCHECK, + "NO_VCHECK", + "Specifies to continue even if version checking fails (boolean)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_ID, + "ID", + "Specifies an ENGINE id name for loading", + ENGINE_CMD_FLAG_STRING}, + {DYNAMIC_CMD_LIST_ADD, + "LIST_ADD", + "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_LOAD, + "LOAD", + "Load up the ENGINE specified by other settings", + ENGINE_CMD_FLAG_NO_INPUT}, + {0, NULL, NULL, 0} + }; +static const ENGINE_CMD_DEFN dynamic_cmd_defns_empty[] = { + {0, NULL, NULL, 0} + }; + +/* Loading code stores state inside the ENGINE structure via the "ex_data" + * element. We load all our state into a single structure and use that as a + * single context in the "ex_data" stack. */ +struct st_dynamic_data_ctx + { + /* The DSO object we load that supplies the ENGINE code */ + DSO *dynamic_dso; + /* The function pointer to the version checking shared library function */ + dynamic_v_check_fn v_check; + /* The function pointer to the engine-binding shared library function */ + dynamic_bind_engine bind_engine; + /* The default name/path for loading the shared library */ + const char *DYNAMIC_LIBNAME; + /* Whether to continue loading on a version check failure */ + int no_vcheck; + /* If non-NULL, stipulates the 'id' of the ENGINE to be loaded */ + const char *engine_id; + /* If non-zero, a successfully loaded ENGINE should be added to the internal + * ENGINE list. If 2, the add must succeed or the entire load should fail. */ + int list_add_value; + /* The symbol name for the version checking function */ + const char *DYNAMIC_F1; + /* The symbol name for the "initialise ENGINE structure" function */ + const char *DYNAMIC_F2; + }; + +/* This is the "ex_data" index we obtain and reserve for use with our context + * structure. */ +static int dynamic_ex_data_idx = -1; + +/* Because our ex_data element may or may not get allocated depending on whether + * a "first-use" occurs before the ENGINE is freed, we have a memory leak + * problem to solve. We can't declare a "new" handler for the ex_data as we + * don't want a dynamic_data_ctx in *all* ENGINE structures of all types (this + * is a bug in the design of CRYPTO_EX_DATA). As such, we just declare a "free" + * handler and that will get called if an ENGINE is being destroyed and there + * was an ex_data element corresponding to our context type. */ +static void dynamic_data_ctx_free_func(void *parent, void *ptr, + CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) + { + if(ptr) + { + dynamic_data_ctx *ctx = (dynamic_data_ctx *)ptr; + if(ctx->dynamic_dso) + DSO_free(ctx->dynamic_dso); + OPENSSL_free(ctx); + } + } + +/* Construct the per-ENGINE context. We create it blindly and then use a lock to + * check for a race - if so, all but one of the threads "racing" will have + * wasted their time. The alternative involves creating everything inside the + * lock which is far worse. */ +static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) + { + dynamic_data_ctx *c; + c = OPENSSL_malloc(sizeof(dynamic_data_ctx)); + if(!ctx) + { + ENGINEerr(ENGINE_F_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); + return 0; + } + memset(c, 0, sizeof(dynamic_data_ctx)); + c->dynamic_dso = NULL; + c->v_check = NULL; + c->bind_engine = NULL; + c->DYNAMIC_LIBNAME = NULL; + c->no_vcheck = 0; + c->engine_id = NULL; + c->list_add_value = 0; + c->DYNAMIC_F1 = "v_check"; + c->DYNAMIC_F2 = "bind_engine"; + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, + dynamic_ex_data_idx)) == NULL) + { + /* Good, we're the first */ + ENGINE_set_ex_data(e, dynamic_ex_data_idx, c); + *ctx = c; + c = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + /* If we lost the race to set the context, c is non-NULL and *ctx is the + * context of the thread that won. */ + if(c) + OPENSSL_free(c); + return 1; + } + +/* This function retrieves the context structure from an ENGINE's "ex_data", or + * if it doesn't exist yet, sets it up. */ +static dynamic_data_ctx *dynamic_get_data_ctx(ENGINE *e) + { + dynamic_data_ctx *ctx; + if(dynamic_ex_data_idx < 0) + { + /* Create and register the ENGINE ex_data, and associate our + * "free" function with it to ensure any allocated contexts get + * freed when an ENGINE goes underground. */ + int new_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, + dynamic_data_ctx_free_func); + if(new_idx == -1) + { + ENGINEerr(ENGINE_F_DYNAMIC_GET_DATA_CTX,ENGINE_R_NO_INDEX); + return NULL; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + /* Avoid a race by checking again inside this lock */ + if(dynamic_ex_data_idx < 0) + { + /* Good, someone didn't beat us to it */ + dynamic_ex_data_idx = new_idx; + new_idx = -1; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + /* In theory we could "give back" the index here if + * (new_idx>-1), but it's not possible and wouldn't gain us much + * if it were. */ + } + ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx); + /* Check if the context needs to be created */ + if((ctx == NULL) && !dynamic_set_data_ctx(e, &ctx)) + /* "set_data" will set errors if necessary */ + return NULL; + return ctx; + } + +static ENGINE *engine_dynamic(void) + { + ENGINE *ret = ENGINE_new(); + if(!ret) + return NULL; + if(!ENGINE_set_id(ret, engine_dynamic_id) || + !ENGINE_set_name(ret, engine_dynamic_name) || + !ENGINE_set_init_function(ret, dynamic_init) || + !ENGINE_set_finish_function(ret, dynamic_finish) || + !ENGINE_set_ctrl_function(ret, dynamic_ctrl) || + !ENGINE_set_flags(ret, ENGINE_FLAGS_BY_ID_COPY) || + !ENGINE_set_cmd_defns(ret, dynamic_cmd_defns)) + { + ENGINE_free(ret); + return NULL; + } + return ret; + } + +void ENGINE_load_dynamic(void) + { + ENGINE *toadd = engine_dynamic(); + if(!toadd) return; + ENGINE_add(toadd); + /* If the "add" worked, it gets a structural reference. So either way, + * we release our just-created reference. */ + ENGINE_free(toadd); + /* If the "add" didn't work, it was probably a conflict because it was + * already added (eg. someone calling ENGINE_load_blah then calling + * ENGINE_load_builtin_engines() perhaps). */ + ERR_clear_error(); + } + +static int dynamic_init(ENGINE *e) + { + /* We always return failure - the "dyanamic" engine itself can't be used + * for anything. */ + return 0; + } + +static int dynamic_finish(ENGINE *e) + { + /* This should never be called on account of "dynamic_init" always + * failing. */ + return 0; + } + +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); + int initialised; + + if(!ctx) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL,ENGINE_R_NOT_LOADED); + return 0; + } + initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1); + /* All our control commands require the ENGINE to be uninitialised */ + if(initialised) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ENGINE_R_ALREADY_LOADED); + return 0; + } + switch(cmd) + { + case DYNAMIC_CMD_SO_PATH: + /* a NULL 'p' or a string of zero-length is the same thing */ + if(p && (strlen((const char *)p) < 1)) + p = NULL; + ctx->DYNAMIC_LIBNAME = (const char *)p; + return 1; + case DYNAMIC_CMD_NO_VCHECK: + ctx->no_vcheck = ((i == 0) ? 0 : 1); + return 1; + case DYNAMIC_CMD_ID: + /* a NULL 'p' or a string of zero-length is the same thing */ + if(p && (strlen((const char *)p) < 1)) + p = NULL; + ctx->engine_id = (const char *)p; + return 1; + case DYNAMIC_CMD_LIST_ADD: + if((i < 0) || (i > 2)) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ENGINE_R_INVALID_ARGUMENT); + return 0; + } + ctx->list_add_value = (int)i; + return 1; + case DYNAMIC_CMD_LOAD: + return dynamic_load(e, ctx); + default: + break; + } + ENGINEerr(ENGINE_F_DYNAMIC_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; + } + +static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) + { + ENGINE cpy; + dynamic_fns fns; + + if(!ctx->DYNAMIC_LIBNAME || ((ctx->dynamic_dso = DSO_load(NULL, + ctx->DYNAMIC_LIBNAME, NULL, 0)) == NULL)) + { + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, + ENGINE_R_DSO_NOT_FOUND); + return 0; + } + /* We have to find a bind function otherwise it'll always end badly */ + if(!(ctx->bind_engine = (dynamic_bind_engine)DSO_bind_func( + ctx->dynamic_dso, ctx->DYNAMIC_F2))) + { + ctx->bind_engine = NULL; + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, + ENGINE_R_DSO_FAILURE); + return 0; + } + /* Do we perform version checking? */ + if(!ctx->no_vcheck) + { + unsigned long vcheck_res = 0; + /* Now we try to find a version checking function and decide how + * to cope with failure if/when it fails. */ + ctx->v_check = (dynamic_v_check_fn)DSO_bind_func( + ctx->dynamic_dso, ctx->DYNAMIC_F1); + if(ctx->v_check) + vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION); + /* We fail if the version checker veto'd the load *or* if it is + * deferring to us (by returning its version) and we think it is + * too old. */ + if(vcheck_res < OSSL_DYNAMIC_OLDEST) + { + /* Fail */ + ctx->bind_engine = NULL; + ctx->v_check = NULL; + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, + ENGINE_R_VERSION_INCOMPATIBILITY); + return 0; + } + } + /* First binary copy the ENGINE structure so that we can roll back if + * the hand-over fails */ + memcpy(&cpy, e, sizeof(ENGINE)); + /* Provide the ERR, "ex_data", memory, and locking callbacks so the + * loaded library uses our state rather than its own. FIXME: As noted in + * engine.h, much of this would be simplified if each area of code + * provided its own "summary" structure of all related callbacks. It + * would also increase opaqueness. */ + fns.err_fns = ERR_get_implementation(); + fns.ex_data_fns = CRYPTO_get_ex_data_implementation(); + CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb, + &fns.mem_fns.realloc_cb, + &fns.mem_fns.free_cb); + fns.lock_fns.lock_locking_cb = CRYPTO_get_locking_callback(); + fns.lock_fns.lock_add_lock_cb = CRYPTO_get_add_lock_callback(); + fns.lock_fns.dynlock_create_cb = CRYPTO_get_dynlock_create_callback(); + fns.lock_fns.dynlock_lock_cb = CRYPTO_get_dynlock_lock_callback(); + fns.lock_fns.dynlock_destroy_cb = CRYPTO_get_dynlock_destroy_callback(); + /* Now that we've loaded the dynamic engine, make sure no "dynamic" + * ENGINE elements will show through. */ + engine_set_all_null(e); + + /* Try to bind the ENGINE onto our own ENGINE structure */ + if(!ctx->bind_engine(e, ctx->engine_id, &fns)) + { + ctx->bind_engine = NULL; + ctx->v_check = NULL; + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; + ENGINEerr(ENGINE_F_DYNAMIC_LOAD,ENGINE_R_INIT_FAILED); + /* Copy the original ENGINE structure back */ + memcpy(e, &cpy, sizeof(ENGINE)); + return 0; + } + /* Do we try to add this ENGINE to the internal list too? */ + if(ctx->list_add_value > 0) + { + if(!ENGINE_add(e)) + { + /* Do we tolerate this or fail? */ + if(ctx->list_add_value > 1) + { + /* Fail - NB: By this time, it's too late to + * rollback, and trying to do so allows the + * bind_engine() code to have created leaks. We + * just have to fail where we are, after the + * ENGINE has changed. */ + ENGINEerr(ENGINE_F_DYNAMIC_LOAD, + ENGINE_R_CONFLICTING_ENGINE_ID); + return 0; + } + /* Tolerate */ + ERR_clear_error(); + } + } + return 1; + } diff --git a/src/lib/libcrypto/engine/eng_err.c b/src/lib/libcrypto/engine/eng_err.c new file mode 100644 index 0000000000..f6c5630395 --- /dev/null +++ b/src/lib/libcrypto/engine/eng_err.c @@ -0,0 +1,165 @@ +/* crypto/engine/eng_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 OPENSSL_NO_ERR +static ERR_STRING_DATA ENGINE_str_functs[]= + { +{ERR_PACK(0,ENGINE_F_DYNAMIC_CTRL,0), "DYNAMIC_CTRL"}, +{ERR_PACK(0,ENGINE_F_DYNAMIC_GET_DATA_CTX,0), "DYNAMIC_GET_DATA_CTX"}, +{ERR_PACK(0,ENGINE_F_DYNAMIC_LOAD,0), "DYNAMIC_LOAD"}, +{ERR_PACK(0,ENGINE_F_ENGINE_ADD,0), "ENGINE_add"}, +{ERR_PACK(0,ENGINE_F_ENGINE_BY_ID,0), "ENGINE_by_id"}, +{ERR_PACK(0,ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,0), "ENGINE_cmd_is_executable"}, +{ERR_PACK(0,ENGINE_F_ENGINE_CTRL,0), "ENGINE_ctrl"}, +{ERR_PACK(0,ENGINE_F_ENGINE_CTRL_CMD,0), "ENGINE_ctrl_cmd"}, +{ERR_PACK(0,ENGINE_F_ENGINE_CTRL_CMD_STRING,0), "ENGINE_ctrl_cmd_string"}, +{ERR_PACK(0,ENGINE_F_ENGINE_FINISH,0), "ENGINE_finish"}, +{ERR_PACK(0,ENGINE_F_ENGINE_FREE,0), "ENGINE_free"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_CIPHER,0), "ENGINE_get_cipher"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_DEFAULT_TYPE,0), "ENGINE_GET_DEFAULT_TYPE"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_DIGEST,0), "ENGINE_get_digest"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_NEXT,0), "ENGINE_get_next"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_PREV,0), "ENGINE_get_prev"}, +{ERR_PACK(0,ENGINE_F_ENGINE_INIT,0), "ENGINE_init"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LIST_ADD,0), "ENGINE_LIST_ADD"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LIST_REMOVE,0), "ENGINE_LIST_REMOVE"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,0), "ENGINE_load_private_key"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,0), "ENGINE_load_public_key"}, +{ERR_PACK(0,ENGINE_F_ENGINE_MODULE_INIT,0), "ENGINE_MODULE_INIT"}, +{ERR_PACK(0,ENGINE_F_ENGINE_NEW,0), "ENGINE_new"}, +{ERR_PACK(0,ENGINE_F_ENGINE_REMOVE,0), "ENGINE_remove"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_DEFAULT_STRING,0), "ENGINE_set_default_string"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_DEFAULT_TYPE,0), "ENGINE_SET_DEFAULT_TYPE"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_ID,0), "ENGINE_set_id"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_NAME,0), "ENGINE_set_name"}, +{ERR_PACK(0,ENGINE_F_ENGINE_TABLE_REGISTER,0), "ENGINE_TABLE_REGISTER"}, +{ERR_PACK(0,ENGINE_F_ENGINE_UNLOAD_KEY,0), "ENGINE_UNLOAD_KEY"}, +{ERR_PACK(0,ENGINE_F_INT_CTRL_HELPER,0), "INT_CTRL_HELPER"}, +{ERR_PACK(0,ENGINE_F_INT_ENGINE_CONFIGURE,0), "INT_ENGINE_CONFIGURE"}, +{ERR_PACK(0,ENGINE_F_LOG_MESSAGE,0), "LOG_MESSAGE"}, +{ERR_PACK(0,ENGINE_F_SET_DATA_CTX,0), "SET_DATA_CTX"}, +{0,NULL} + }; + +static ERR_STRING_DATA ENGINE_str_reasons[]= + { +{ENGINE_R_ALREADY_LOADED ,"already loaded"}, +{ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER ,"argument is not a number"}, +{ENGINE_R_CMD_NOT_EXECUTABLE ,"cmd not executable"}, +{ENGINE_R_COMMAND_TAKES_INPUT ,"command takes input"}, +{ENGINE_R_COMMAND_TAKES_NO_INPUT ,"command takes no input"}, +{ENGINE_R_CONFLICTING_ENGINE_ID ,"conflicting engine id"}, +{ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"}, +{ENGINE_R_DH_NOT_IMPLEMENTED ,"dh not implemented"}, +{ENGINE_R_DSA_NOT_IMPLEMENTED ,"dsa not implemented"}, +{ENGINE_R_DSO_FAILURE ,"DSO failure"}, +{ENGINE_R_DSO_NOT_FOUND ,"dso not found"}, +{ENGINE_R_ENGINES_SECTION_ERROR ,"engines section error"}, +{ENGINE_R_ENGINE_IS_NOT_IN_LIST ,"engine is not in the list"}, +{ENGINE_R_ENGINE_SECTION_ERROR ,"engine section error"}, +{ENGINE_R_FAILED_LOADING_PRIVATE_KEY ,"failed loading private key"}, +{ENGINE_R_FAILED_LOADING_PUBLIC_KEY ,"failed loading public key"}, +{ENGINE_R_FINISH_FAILED ,"finish failed"}, +{ENGINE_R_GET_HANDLE_FAILED ,"could not obtain hardware handle"}, +{ENGINE_R_ID_OR_NAME_MISSING ,"'id' or 'name' missing"}, +{ENGINE_R_INIT_FAILED ,"init failed"}, +{ENGINE_R_INTERNAL_LIST_ERROR ,"internal list error"}, +{ENGINE_R_INVALID_ARGUMENT ,"invalid argument"}, +{ENGINE_R_INVALID_CMD_NAME ,"invalid cmd name"}, +{ENGINE_R_INVALID_CMD_NUMBER ,"invalid cmd number"}, +{ENGINE_R_INVALID_INIT_VALUE ,"invalid init value"}, +{ENGINE_R_INVALID_STRING ,"invalid string"}, +{ENGINE_R_NOT_INITIALISED ,"not initialised"}, +{ENGINE_R_NOT_LOADED ,"not loaded"}, +{ENGINE_R_NO_CONTROL_FUNCTION ,"no control function"}, +{ENGINE_R_NO_INDEX ,"no index"}, +{ENGINE_R_NO_LOAD_FUNCTION ,"no load function"}, +{ENGINE_R_NO_REFERENCE ,"no reference"}, +{ENGINE_R_NO_SUCH_ENGINE ,"no such engine"}, +{ENGINE_R_NO_UNLOAD_FUNCTION ,"no unload function"}, +{ENGINE_R_PROVIDE_PARAMETERS ,"provide parameters"}, +{ENGINE_R_RSA_NOT_IMPLEMENTED ,"rsa not implemented"}, +{ENGINE_R_UNIMPLEMENTED_CIPHER ,"unimplemented cipher"}, +{ENGINE_R_UNIMPLEMENTED_DIGEST ,"unimplemented digest"}, +{ENGINE_R_VERSION_INCOMPATIBILITY ,"version incompatibility"}, +{0,NULL} + }; + +#endif + +void ERR_load_ENGINE_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(ERR_LIB_ENGINE,ENGINE_str_functs); + ERR_load_strings(ERR_LIB_ENGINE,ENGINE_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/engine/eng_fat.c b/src/lib/libcrypto/engine/eng_fat.c new file mode 100644 index 0000000000..af918b1499 --- /dev/null +++ b/src/lib/libcrypto/engine/eng_fat.c @@ -0,0 +1,148 @@ +/* crypto/engine/eng_fat.c */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 "eng_int.h" +#include +#include + +int ENGINE_set_default(ENGINE *e, unsigned int flags) + { + if((flags & ENGINE_METHOD_CIPHERS) && !ENGINE_set_default_ciphers(e)) + return 0; + if((flags & ENGINE_METHOD_DIGESTS) && !ENGINE_set_default_digests(e)) + return 0; +#ifndef OPENSSL_NO_RSA + if((flags & ENGINE_METHOD_RSA) & !ENGINE_set_default_RSA(e)) + return 0; +#endif +#ifndef OPENSSL_NO_DSA + if((flags & ENGINE_METHOD_DSA) & !ENGINE_set_default_DSA(e)) + return 0; +#endif +#ifndef OPENSSL_NO_DH + if((flags & ENGINE_METHOD_DH) & !ENGINE_set_default_DH(e)) + return 0; +#endif + if((flags & ENGINE_METHOD_RAND) & !ENGINE_set_default_RAND(e)) + return 0; + return 1; + } + +/* Set default algorithms using a string */ + +int int_def_cb(const char *alg, int len, void *arg) + { + unsigned int *pflags = arg; + if (!strncmp(alg, "ALL", len)) + *pflags |= ENGINE_METHOD_ALL; + else if (!strncmp(alg, "RSA", len)) + *pflags |= ENGINE_METHOD_RSA; + else if (!strncmp(alg, "DSA", len)) + *pflags |= ENGINE_METHOD_DSA; + else if (!strncmp(alg, "DH", len)) + *pflags |= ENGINE_METHOD_DH; + else if (!strncmp(alg, "RAND", len)) + *pflags |= ENGINE_METHOD_RAND; + else if (!strncmp(alg, "CIPHERS", len)) + *pflags |= ENGINE_METHOD_CIPHERS; + else if (!strncmp(alg, "DIGESTS", len)) + *pflags |= ENGINE_METHOD_DIGESTS; + else + return 0; + return 1; + } + + +int ENGINE_set_default_string(ENGINE *e, const char *list) + { + unsigned int flags = 0; + if (!CONF_parse_list(list, ',', 1, int_def_cb, &flags)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_STRING, + ENGINE_R_INVALID_STRING); + ERR_add_error_data(2, "str=",list); + return 0; + } + return ENGINE_set_default(e, flags); + } + +int ENGINE_register_complete(ENGINE *e) + { + ENGINE_register_ciphers(e); + ENGINE_register_digests(e); +#ifndef OPENSSL_NO_RSA + ENGINE_register_RSA(e); +#endif +#ifndef OPENSSL_NO_DSA + ENGINE_register_DSA(e); +#endif +#ifndef OPENSSL_NO_DH + ENGINE_register_DH(e); +#endif + ENGINE_register_RAND(e); + return 1; + } + +int ENGINE_register_all_complete(void) + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) { + ENGINE_register_complete(e); + } + return 1; + } diff --git a/src/lib/libcrypto/engine/eng_init.c b/src/lib/libcrypto/engine/eng_init.c new file mode 100644 index 0000000000..cc9396e863 --- /dev/null +++ b/src/lib/libcrypto/engine/eng_init.c @@ -0,0 +1,158 @@ +/* crypto/engine/eng_init.c */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 "eng_int.h" +#include + +/* Initialise a engine type for use (or up its functional reference count + * if it's already in use). This version is only used internally. */ +int engine_unlocked_init(ENGINE *e) + { + int to_return = 1; + + if((e->funct_ref == 0) && e->init) + /* This is the first functional reference and the engine + * requires initialisation so we do it now. */ + to_return = e->init(e); + if(to_return) + { + /* OK, we return a functional reference which is also a + * structural reference. */ + e->struct_ref++; + e->funct_ref++; + engine_ref_debug(e, 0, 1) + engine_ref_debug(e, 1, 1) + } + return to_return; + } + +/* Free a functional reference to a engine type. This version is only used + * internally. */ +int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) + { + int to_return = 1; + + /* Reduce the functional reference count here so if it's the terminating + * case, we can release the lock safely and call the finish() handler + * without risk of a race. We get a race if we leave the count until + * after and something else is calling "finish" at the same time - + * there's a chance that both threads will together take the count from + * 2 to 0 without either calling finish(). */ + e->funct_ref--; + engine_ref_debug(e, 1, -1); + if((e->funct_ref == 0) && e->finish) + { + if(unlock_for_handlers) + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + to_return = e->finish(e); + if(unlock_for_handlers) + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(!to_return) + return 0; + } +#ifdef REF_CHECK + if(e->funct_ref < 0) + { + fprintf(stderr,"ENGINE_finish, bad functional reference count\n"); + abort(); + } +#endif + /* Release the structural reference too */ + if(!engine_free_util(e, 0)) + { + ENGINEerr(ENGINE_F_ENGINE_FINISH,ENGINE_R_FINISH_FAILED); + return 0; + } + return to_return; + } + +/* The API (locked) version of "init" */ +int ENGINE_init(ENGINE *e) + { + int ret; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_INIT,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + ret = engine_unlocked_init(e); + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } + +/* The API (locked) version of "finish" */ +int ENGINE_finish(ENGINE *e) + { + int to_return = 1; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_FINISH,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + to_return = engine_unlocked_finish(e, 1); + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + if(!to_return) + { + ENGINEerr(ENGINE_F_ENGINE_FINISH,ENGINE_R_FINISH_FAILED); + return 0; + } + return to_return; + } + diff --git a/src/lib/libcrypto/engine/eng_int.h b/src/lib/libcrypto/engine/eng_int.h new file mode 100644 index 0000000000..38335f99cd --- /dev/null +++ b/src/lib/libcrypto/engine/eng_int.h @@ -0,0 +1,185 @@ +/* crypto/engine/eng_int.h */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2001 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). + * + */ + +#ifndef HEADER_ENGINE_INT_H +#define HEADER_ENGINE_INT_H + +/* Take public definitions from engine.h */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* If we compile with this symbol defined, then both reference counts in the + * ENGINE structure will be monitored with a line of output on stderr for each + * change. This prints the engine's pointer address (truncated to unsigned int), + * "struct" or "funct" to indicate the reference type, the before and after + * reference count, and the file:line-number pair. The "engine_ref_debug" + * statements must come *after* the change. */ +#ifdef ENGINE_REF_COUNT_DEBUG + +#define engine_ref_debug(e, isfunct, diff) \ + fprintf(stderr, "engine: %08x %s from %d to %d (%s:%d)\n", \ + (unsigned int)(e), (isfunct ? "funct" : "struct"), \ + ((isfunct) ? ((e)->funct_ref - (diff)) : ((e)->struct_ref - (diff))), \ + ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \ + (__FILE__), (__LINE__)); + +#else + +#define engine_ref_debug(e, isfunct, diff) + +#endif + +/* Any code that will need cleanup operations should use these functions to + * register callbacks. ENGINE_cleanup() will call all registered callbacks in + * order. NB: both the "add" functions assume CRYPTO_LOCK_ENGINE to already be + * held (in "write" mode). */ +typedef void (ENGINE_CLEANUP_CB)(void); +typedef struct st_engine_cleanup_item + { + ENGINE_CLEANUP_CB *cb; + } ENGINE_CLEANUP_ITEM; +DECLARE_STACK_OF(ENGINE_CLEANUP_ITEM) +void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb); +void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb); + +/* We need stacks of ENGINEs for use in eng_table.c */ +DECLARE_STACK_OF(ENGINE) + +/* If this symbol is defined then engine_table_select(), the function that is + * used by RSA, DSA (etc) code to select registered ENGINEs, cache defaults and + * functional references (etc), will display debugging summaries to stderr. */ +/* #define ENGINE_TABLE_DEBUG */ + +/* This represents an implementation table. Dependent code should instantiate it + * as a (ENGINE_TABLE *) pointer value set initially to NULL. */ +typedef struct st_engine_table ENGINE_TABLE; +int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, + ENGINE *e, const int *nids, int num_nids, int setdefault); +void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e); +void engine_table_cleanup(ENGINE_TABLE **table); +#ifndef ENGINE_TABLE_DEBUG +ENGINE *engine_table_select(ENGINE_TABLE **table, int nid); +#else +ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l); +#define engine_table_select(t,n) engine_table_select_tmp(t,n,__FILE__,__LINE__) +#endif + +/* Internal versions of API functions that have control over locking. These are + * used between C files when functionality needs to be shared but the caller may + * already be controlling of the CRYPTO_LOCK_ENGINE lock. */ +int engine_unlocked_init(ENGINE *e); +int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers); +int engine_free_util(ENGINE *e, int locked); + +/* This function will reset all "set"able values in an ENGINE to NULL. This + * won't touch reference counts or ex_data, but is equivalent to calling all the + * ENGINE_set_***() functions with a NULL value. */ +void engine_set_all_null(ENGINE *e); + +/* NB: Bitwise OR-able values for the "flags" variable in ENGINE are now exposed + * in engine.h. */ + +/* This is a structure for storing implementations of various crypto + * algorithms and functions. */ +struct engine_st + { + const char *id; + const char *name; + const RSA_METHOD *rsa_meth; + const DSA_METHOD *dsa_meth; + const DH_METHOD *dh_meth; + const RAND_METHOD *rand_meth; + /* Cipher handling is via this callback */ + ENGINE_CIPHERS_PTR ciphers; + /* Digest handling is via this callback */ + ENGINE_DIGESTS_PTR digests; + + + ENGINE_GEN_INT_FUNC_PTR destroy; + + ENGINE_GEN_INT_FUNC_PTR init; + ENGINE_GEN_INT_FUNC_PTR finish; + ENGINE_CTRL_FUNC_PTR ctrl; + ENGINE_LOAD_KEY_PTR load_privkey; + ENGINE_LOAD_KEY_PTR load_pubkey; + + const ENGINE_CMD_DEFN *cmd_defns; + int flags; + /* reference count on the structure itself */ + int struct_ref; + /* reference count on usability of the engine type. NB: This + * controls the loading and initialisation of any functionlity + * required by this engine, whereas the previous count is + * simply to cope with (de)allocation of this structure. Hence, + * running_ref <= struct_ref at all times. */ + int funct_ref; + /* A place to store per-ENGINE data */ + CRYPTO_EX_DATA ex_data; + /* Used to maintain the linked-list of engines. */ + struct engine_st *prev; + struct engine_st *next; + }; + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_ENGINE_INT_H */ diff --git a/src/lib/libcrypto/engine/eng_lib.c b/src/lib/libcrypto/engine/eng_lib.c new file mode 100644 index 0000000000..a66d0f08af --- /dev/null +++ b/src/lib/libcrypto/engine/eng_lib.c @@ -0,0 +1,321 @@ +/* crypto/engine/eng_lib.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 "eng_int.h" +#include /* FIXME: This shouldn't be needed */ +#include + +/* The "new"/"free" stuff first */ + +ENGINE *ENGINE_new(void) + { + ENGINE *ret; + + ret = (ENGINE *)OPENSSL_malloc(sizeof(ENGINE)); + if(ret == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(ENGINE)); + ret->struct_ref = 1; + engine_ref_debug(ret, 0, 1) + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data); + return ret; + } + +/* Placed here (close proximity to ENGINE_new) so that modifications to the + * elements of the ENGINE structure are more likely to be caught and changed + * here. */ +void engine_set_all_null(ENGINE *e) + { + e->id = NULL; + e->name = NULL; + e->rsa_meth = NULL; + e->dsa_meth = NULL; + e->dh_meth = NULL; + e->rand_meth = NULL; + e->ciphers = NULL; + e->digests = NULL; + e->destroy = NULL; + e->init = NULL; + e->finish = NULL; + e->ctrl = NULL; + e->load_privkey = NULL; + e->load_pubkey = NULL; + e->cmd_defns = NULL; + e->flags = 0; + } + +int engine_free_util(ENGINE *e, int locked) + { + int i; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_FREE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(locked) + i = CRYPTO_add(&e->struct_ref,-1,CRYPTO_LOCK_ENGINE); + else + i = --e->struct_ref; + engine_ref_debug(e, 0, -1) + if (i > 0) return 1; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"ENGINE_free, bad structural reference count\n"); + abort(); + } +#endif + /* Give the ENGINE a chance to do any structural cleanup corresponding + * to allocation it did in its constructor (eg. unload error strings) */ + if(e->destroy) + e->destroy(e); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data); + OPENSSL_free(e); + return 1; + } + +int ENGINE_free(ENGINE *e) + { + return engine_free_util(e, 1); + } + +/* Cleanup stuff */ + +/* ENGINE_cleanup() is coded such that anything that does work that will need + * cleanup can register a "cleanup" callback here. That way we don't get linker + * bloat by referring to all *possible* cleanups, but any linker bloat into code + * "X" will cause X's cleanup function to end up here. */ +static STACK_OF(ENGINE_CLEANUP_ITEM) *cleanup_stack = NULL; +static int int_cleanup_check(int create) + { + if(cleanup_stack) return 1; + if(!create) return 0; + cleanup_stack = sk_ENGINE_CLEANUP_ITEM_new_null(); + return (cleanup_stack ? 1 : 0); + } +static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb) + { + ENGINE_CLEANUP_ITEM *item = OPENSSL_malloc(sizeof( + ENGINE_CLEANUP_ITEM)); + if(!item) return NULL; + item->cb = cb; + return item; + } +void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb) + { + ENGINE_CLEANUP_ITEM *item; + if(!int_cleanup_check(1)) return; + item = int_cleanup_item(cb); + if(item) + sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0); + } +void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb) + { + ENGINE_CLEANUP_ITEM *item; + if(!int_cleanup_check(1)) return; + item = int_cleanup_item(cb); + if(item) + sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item); + } +/* The API function that performs all cleanup */ +static void engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM *item) + { + (*(item->cb))(); + OPENSSL_free(item); + } +void ENGINE_cleanup(void) + { + if(int_cleanup_check(0)) + { + sk_ENGINE_CLEANUP_ITEM_pop_free(cleanup_stack, + engine_cleanup_cb_free); + cleanup_stack = NULL; + } + /* FIXME: This should be handled (somehow) through RAND, eg. by it + * registering a cleanup callback. */ + RAND_set_rand_method(NULL); + } + +/* Now the "ex_data" support */ + +int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, argl, argp, + new_func, dup_func, free_func); + } + +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg) + { + return(CRYPTO_set_ex_data(&e->ex_data, idx, arg)); + } + +void *ENGINE_get_ex_data(const ENGINE *e, int idx) + { + return(CRYPTO_get_ex_data(&e->ex_data, idx)); + } + +/* Functions to get/set an ENGINE's elements - mainly to avoid exposing the + * ENGINE structure itself. */ + +int ENGINE_set_id(ENGINE *e, const char *id) + { + if(id == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_SET_ID, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->id = id; + return 1; + } + +int ENGINE_set_name(ENGINE *e, const char *name) + { + if(name == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_SET_NAME, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->name = name; + return 1; + } + +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f) + { + e->destroy = destroy_f; + return 1; + } + +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f) + { + e->init = init_f; + return 1; + } + +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f) + { + e->finish = finish_f; + return 1; + } + +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f) + { + e->ctrl = ctrl_f; + return 1; + } + +int ENGINE_set_flags(ENGINE *e, int flags) + { + e->flags = flags; + return 1; + } + +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns) + { + e->cmd_defns = defns; + return 1; + } + +const char *ENGINE_get_id(const ENGINE *e) + { + return e->id; + } + +const char *ENGINE_get_name(const ENGINE *e) + { + return e->name; + } + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e) + { + return e->destroy; + } + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e) + { + return e->init; + } + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e) + { + return e->finish; + } + +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e) + { + return e->ctrl; + } + +int ENGINE_get_flags(const ENGINE *e) + { + return e->flags; + } + +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e) + { + return e->cmd_defns; + } diff --git a/src/lib/libcrypto/engine/eng_list.c b/src/lib/libcrypto/engine/eng_list.c new file mode 100644 index 0000000000..ce48d2255a --- /dev/null +++ b/src/lib/libcrypto/engine/eng_list.c @@ -0,0 +1,383 @@ +/* crypto/engine/eng_list.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 "eng_int.h" +#include + +/* The linked-list of pointers to engine types. engine_list_head + * incorporates an implicit structural reference but engine_list_tail + * does not - the latter is a computational niceity and only points + * to something that is already pointed to by its predecessor in the + * list (or engine_list_head itself). In the same way, the use of the + * "prev" pointer in each ENGINE is to save excessive list iteration, + * it doesn't correspond to an extra structural reference. Hence, + * engine_list_head, and each non-null "next" pointer account for + * the list itself assuming exactly 1 structural reference on each + * list member. */ +static ENGINE *engine_list_head = NULL; +static ENGINE *engine_list_tail = NULL; + +/* This cleanup function is only needed internally. If it should be called, we + * register it with the "ENGINE_cleanup()" stack to be called during cleanup. */ + +static void engine_list_cleanup(void) + { + ENGINE *iterator = engine_list_head; + + while(iterator != NULL) + { + ENGINE_remove(iterator); + iterator = engine_list_head; + } + return; + } + +/* These static functions starting with a lower case "engine_" always + * take place when CRYPTO_LOCK_ENGINE has been locked up. */ +static int engine_list_add(ENGINE *e) + { + int conflict = 0; + ENGINE *iterator = NULL; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + iterator = engine_list_head; + while(iterator && !conflict) + { + conflict = (strcmp(iterator->id, e->id) == 0); + iterator = iterator->next; + } + if(conflict) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ENGINE_R_CONFLICTING_ENGINE_ID); + return 0; + } + if(engine_list_head == NULL) + { + /* We are adding to an empty list. */ + if(engine_list_tail) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_head = e; + e->prev = NULL; + /* The first time the list allocates, we should register the + * cleanup. */ + engine_cleanup_add_last(engine_list_cleanup); + } + else + { + /* We are adding to the tail of an existing list. */ + if((engine_list_tail == NULL) || + (engine_list_tail->next != NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_tail->next = e; + e->prev = engine_list_tail; + } + /* Having the engine in the list assumes a structural + * reference. */ + e->struct_ref++; + engine_ref_debug(e, 0, 1) + /* However it came to be, e is the last item in the list. */ + engine_list_tail = e; + e->next = NULL; + return 1; + } + +static int engine_list_remove(ENGINE *e) + { + ENGINE *iterator; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + /* We need to check that e is in our linked list! */ + iterator = engine_list_head; + while(iterator && (iterator != e)) + iterator = iterator->next; + if(iterator == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, + ENGINE_R_ENGINE_IS_NOT_IN_LIST); + return 0; + } + /* un-link e from the chain. */ + if(e->next) + e->next->prev = e->prev; + if(e->prev) + e->prev->next = e->next; + /* Correct our head/tail if necessary. */ + if(engine_list_head == e) + engine_list_head = e->next; + if(engine_list_tail == e) + engine_list_tail = e->prev; + engine_free_util(e, 0); + return 1; + } + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void) + { + ENGINE *ret; + + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + ret = engine_list_head; + if(ret) + { + ret->struct_ref++; + engine_ref_debug(ret, 0, 1) + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } + +ENGINE *ENGINE_get_last(void) + { + ENGINE *ret; + + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + ret = engine_list_tail; + if(ret) + { + ret->struct_ref++; + engine_ref_debug(ret, 0, 1) + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } + +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e) + { + ENGINE *ret = NULL; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + ret = e->next; + if(ret) + { + /* Return a valid structural refernce to the next ENGINE */ + ret->struct_ref++; + engine_ref_debug(ret, 0, 1) + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + /* Release the structural reference to the previous ENGINE */ + ENGINE_free(e); + return ret; + } + +ENGINE *ENGINE_get_prev(ENGINE *e) + { + ENGINE *ret = NULL; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_PREV, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + ret = e->prev; + if(ret) + { + /* Return a valid structural reference to the next ENGINE */ + ret->struct_ref++; + engine_ref_debug(ret, 0, 1) + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + /* Release the structural reference to the previous ENGINE */ + ENGINE_free(e); + return ret; + } + +/* Add another "ENGINE" type into the list. */ +int ENGINE_add(ENGINE *e) + { + int to_return = 1; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_ADD, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if((e->id == NULL) || (e->name == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_ADD, + ENGINE_R_ID_OR_NAME_MISSING); + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(!engine_list_add(e)) + { + ENGINEerr(ENGINE_F_ENGINE_ADD, + ENGINE_R_INTERNAL_LIST_ERROR); + to_return = 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return to_return; + } + +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e) + { + int to_return = 1; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_REMOVE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(!engine_list_remove(e)) + { + ENGINEerr(ENGINE_F_ENGINE_REMOVE, + ENGINE_R_INTERNAL_LIST_ERROR); + to_return = 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return to_return; + } + +static void engine_cpy(ENGINE *dest, const ENGINE *src) + { + dest->id = src->id; + dest->name = src->name; +#ifndef OPENSSL_NO_RSA + dest->rsa_meth = src->rsa_meth; +#endif +#ifndef OPENSSL_NO_DSA + dest->dsa_meth = src->dsa_meth; +#endif +#ifndef OPENSSL_NO_DH + dest->dh_meth = src->dh_meth; +#endif + dest->rand_meth = src->rand_meth; + dest->ciphers = src->ciphers; + dest->digests = src->digests; + dest->destroy = src->destroy; + dest->init = src->init; + dest->finish = src->finish; + dest->ctrl = src->ctrl; + dest->load_privkey = src->load_privkey; + dest->load_pubkey = src->load_pubkey; + dest->cmd_defns = src->cmd_defns; + dest->flags = src->flags; + } + +ENGINE *ENGINE_by_id(const char *id) + { + ENGINE *iterator; + if(id == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_BY_ID, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + iterator = engine_list_head; + while(iterator && (strcmp(id, iterator->id) != 0)) + iterator = iterator->next; + if(iterator) + { + /* We need to return a structural reference. If this is an + * ENGINE type that returns copies, make a duplicate - otherwise + * increment the existing ENGINE's reference count. */ + if(iterator->flags & ENGINE_FLAGS_BY_ID_COPY) + { + ENGINE *cp = ENGINE_new(); + if(!cp) + iterator = NULL; + else + { + engine_cpy(cp, iterator); + iterator = cp; + } + } + else + { + iterator->struct_ref++; + engine_ref_debug(iterator, 0, 1) + } + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + if(iterator == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_BY_ID, + ENGINE_R_NO_SUCH_ENGINE); + ERR_add_error_data(2, "id=", id); + } + return iterator; + } diff --git a/src/lib/libcrypto/engine/eng_openssl.c b/src/lib/libcrypto/engine/eng_openssl.c new file mode 100644 index 0000000000..e9d976f46b --- /dev/null +++ b/src/lib/libcrypto/engine/eng_openssl.c @@ -0,0 +1,347 @@ +/* crypto/engine/eng_openssl.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 +#include "cryptlib.h" +#include +#include +#include + +/* This testing gunk is implemented (and explained) lower down. It also assumes + * the application explicitly calls "ENGINE_load_openssl()" because this is no + * longer automatic in ENGINE_load_builtin_engines(). */ +#define TEST_ENG_OPENSSL_RC4 +#define TEST_ENG_OPENSSL_PKEY +/* #define TEST_ENG_OPENSSL_RC4_OTHERS */ +#define TEST_ENG_OPENSSL_RC4_P_INIT +/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */ +#define TEST_ENG_OPENSSL_SHA +/* #define TEST_ENG_OPENSSL_SHA_OTHERS */ +/* #define TEST_ENG_OPENSSL_SHA_P_INIT */ +/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */ +/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */ + +#ifdef TEST_ENG_OPENSSL_RC4 +static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +#endif +#ifdef TEST_ENG_OPENSSL_SHA +static int openssl_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +#endif + +#ifdef TEST_ENG_OPENSSL_PKEY +static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +#endif + +/* The constants used when creating the ENGINE */ +static const char *engine_openssl_id = "openssl"; +static const char *engine_openssl_name = "Software engine support"; + +/* This internal function is used by ENGINE_openssl() and possibly by the + * "dynamic" ENGINE support too */ +static int bind_helper(ENGINE *e) + { + if(!ENGINE_set_id(e, engine_openssl_id) + || !ENGINE_set_name(e, engine_openssl_name) +#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS +#ifndef OPENSSL_NO_RSA + || !ENGINE_set_RSA(e, RSA_get_default_method()) +#endif +#ifndef OPENSSL_NO_DSA + || !ENGINE_set_DSA(e, DSA_get_default_method()) +#endif +#ifndef OPENSSL_NO_DH + || !ENGINE_set_DH(e, DH_get_default_method()) +#endif + || !ENGINE_set_RAND(e, RAND_SSLeay()) +#ifdef TEST_ENG_OPENSSL_RC4 + || !ENGINE_set_ciphers(e, openssl_ciphers) +#endif +#ifdef TEST_ENG_OPENSSL_SHA + || !ENGINE_set_digests(e, openssl_digests) +#endif +#endif +#ifdef TEST_ENG_OPENSSL_PKEY + || !ENGINE_set_load_privkey_function(e, openssl_load_privkey) +#endif + ) + return 0; + /* If we add errors to this ENGINE, ensure the error handling is setup here */ + /* openssl_load_error_strings(); */ + return 1; + } + +static ENGINE *engine_openssl(void) + { + ENGINE *ret = ENGINE_new(); + if(!ret) + return NULL; + if(!bind_helper(ret)) + { + ENGINE_free(ret); + return NULL; + } + return ret; + } + +void ENGINE_load_openssl(void) + { + ENGINE *toadd = engine_openssl(); + if(!toadd) return; + ENGINE_add(toadd); + /* If the "add" worked, it gets a structural reference. So either way, + * we release our just-created reference. */ + ENGINE_free(toadd); + ERR_clear_error(); + } + +/* This stuff is needed if this ENGINE is being compiled into a self-contained + * shared-library. */ +#ifdef ENGINE_DYNAMIC_SUPPORT +static int bind_fn(ENGINE *e, const char *id) + { + if(id && (strcmp(id, engine_openssl_id) != 0)) + return 0; + if(!bind_helper(e)) + return 0; + return 1; + } +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +#ifdef TEST_ENG_OPENSSL_RC4 +/* This section of code compiles an "alternative implementation" of two modes of + * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4" + * should under normal circumstances go via this support rather than the default + * EVP support. There are other symbols to tweak the testing; + * TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time + * we're asked for a cipher we don't support (should not happen). + * TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time + * the "init_key" handler is called. + * TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler. + */ +#include +#include +#define TEST_RC4_KEY_SIZE 16 +static int test_cipher_nids[] = {NID_rc4,NID_rc4_40}; +static int test_cipher_nids_number = 2; +typedef struct { + unsigned char key[TEST_RC4_KEY_SIZE]; + RC4_KEY ks; + } TEST_RC4_KEY; +#define test(ctx) ((TEST_RC4_KEY *)(ctx)->cipher_data) +static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { +#ifdef TEST_ENG_OPENSSL_RC4_P_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n"); +#endif + memcpy(&test(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx)); + RC4_set_key(&test(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx), + test(ctx)->key); + return 1; + } +static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) + { +#ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n"); +#endif + RC4(&test(ctx)->ks,inl,in,out); + return 1; + } +static const EVP_CIPHER test_r4_cipher= + { + NID_rc4, + 1,TEST_RC4_KEY_SIZE,0, + EVP_CIPH_VARIABLE_LENGTH, + test_rc4_init_key, + test_rc4_cipher, + NULL, + sizeof(TEST_RC4_KEY), + NULL, + NULL, + NULL + }; +static const EVP_CIPHER test_r4_40_cipher= + { + NID_rc4_40, + 1,5 /* 40 bit */,0, + EVP_CIPH_VARIABLE_LENGTH, + test_rc4_init_key, + test_rc4_cipher, + NULL, + sizeof(TEST_RC4_KEY), + NULL, + NULL, + NULL + }; +static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if(!cipher) + { + /* We are returning a list of supported nids */ + *nids = test_cipher_nids; + return test_cipher_nids_number; + } + /* We are being asked for a specific cipher */ + if(nid == NID_rc4) + *cipher = &test_r4_cipher; + else if(nid == NID_rc4_40) + *cipher = &test_r4_40_cipher; + else + { +#ifdef TEST_ENG_OPENSSL_RC4_OTHERS + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for " + "nid %d\n", nid); +#endif + *cipher = NULL; + return 0; + } + return 1; + } +#endif + +#ifdef TEST_ENG_OPENSSL_SHA +/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */ +#include +#include +static int test_digest_nids[] = {NID_sha1}; +static int test_digest_nids_number = 1; +static int test_sha1_init(EVP_MD_CTX *ctx) + { +#ifdef TEST_ENG_OPENSSL_SHA_P_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n"); +#endif + return SHA1_Init(ctx->md_data); + } +static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { +#ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n"); +#endif + return SHA1_Update(ctx->md_data,data,count); + } +static int test_sha1_final(EVP_MD_CTX *ctx,unsigned char *md) + { +#ifdef TEST_ENG_OPENSSL_SHA_P_FINAL + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n"); +#endif + return SHA1_Final(md,ctx->md_data); + } +static const EVP_MD test_sha_md= + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + 0, + test_sha1_init, + test_sha1_update, + test_sha1_final, + NULL, + NULL, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof(EVP_MD *)+sizeof(SHA_CTX), + }; +static int openssl_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if(!digest) + { + /* We are returning a list of supported nids */ + *nids = test_digest_nids; + return test_digest_nids_number; + } + /* We are being asked for a specific digest */ + if(nid == NID_sha1) + *digest = &test_sha_md; + else + { +#ifdef TEST_ENG_OPENSSL_SHA_OTHERS + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for " + "nid %d\n", nid); +#endif + *digest = NULL; + return 0; + } + return 1; + } +#endif + +#ifdef TEST_ENG_OPENSSL_PKEY +static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, + UI_METHOD *ui_method, void *callback_data) + { + BIO *in; + EVP_PKEY *key; + fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", key_id); + in = BIO_new_file(key_id, "r"); + if (!in) + return NULL; + key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL); + BIO_free(in); + return key; + } +#endif diff --git a/src/lib/libcrypto/engine/eng_pkey.c b/src/lib/libcrypto/engine/eng_pkey.c new file mode 100644 index 0000000000..8c69171511 --- /dev/null +++ b/src/lib/libcrypto/engine/eng_pkey.c @@ -0,0 +1,157 @@ +/* crypto/engine/eng_pkey.c */ +/* ==================================================================== + * Copyright (c) 1999-2001 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 "eng_int.h" +#include + +/* Basic get/set stuff */ + +int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f) + { + e->load_privkey = loadpriv_f; + return 1; + } + +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f) + { + e->load_pubkey = loadpub_f; + return 1; + } + +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e) + { + return e->load_privkey; + } + +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e) + { + return e->load_pubkey; + } + +/* API functions to load public/private keys */ + +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(e->funct_ref == 0) + { + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_NOT_INITIALISED); + return 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + if (!e->load_privkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + pkey = e->load_privkey(e, key_id, ui_method, callback_data); + if (!pkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_FAILED_LOADING_PRIVATE_KEY); + return 0; + } + return pkey; + } + +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(e->funct_ref == 0) + { + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_NOT_INITIALISED); + return 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + if (!e->load_pubkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + pkey = e->load_pubkey(e, key_id, ui_method, callback_data); + if (!pkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_FAILED_LOADING_PUBLIC_KEY); + return 0; + } + return pkey; + } diff --git a/src/lib/libcrypto/engine/eng_table.c b/src/lib/libcrypto/engine/eng_table.c new file mode 100644 index 0000000000..c69a84a8bf --- /dev/null +++ b/src/lib/libcrypto/engine/eng_table.c @@ -0,0 +1,361 @@ +/* ==================================================================== + * Copyright (c) 2001 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 +#include "eng_int.h" + +/* This is the type of item in the 'implementation' table. Each 'nid' hashes to + * a (potentially NULL) ENGINE_PILE structure which contains a stack of ENGINE* + * pointers. These pointers aren't references, because they're inserted and + * removed during ENGINE creation and ENGINE destruction. They point to ENGINEs + * that *exist* (ie. have a structural reference count greater than zero) rather + * than ENGINEs that are *functional*. Each pointer in those stacks are to + * ENGINEs that implements the algorithm corresponding to each 'nid'. */ + +/* The type of the items in the table */ +typedef struct st_engine_pile + { + /* The 'nid' of the algorithm/mode this ENGINE_PILE structure represents + * */ + int nid; + /* A stack of ENGINE pointers for ENGINEs that support this + * algorithm/mode. In the event that 'funct' is NULL, the first entry in + * this stack that initialises will be set as 'funct' and assumed as the + * default for operations of this type. */ + STACK_OF(ENGINE) *sk; + /* The default ENGINE to perform this algorithm/mode. */ + ENGINE *funct; + /* This value optimises engine_table_select(). If it is called it sets + * this value to 1. Any changes to this ENGINE_PILE resets it to zero. + * As such, no ENGINE_init() thrashing is done unless ENGINEs + * continually register (and/or unregister). */ + int uptodate; + } ENGINE_PILE; + +/* The type of the hash table of ENGINE_PILE structures such that each are + * unique and keyed by the 'nid' value. */ +struct st_engine_table + { + LHASH piles; + }; /* ENGINE_TABLE */ + +/* This value stores global options controlling behaviour of (mostly) the + * engine_table_select() function. It's a bitmask of flag values of the form + * ENGINE_TABLE_FLAG_*** (as defined in engine.h) and is controlled by the + * ENGINE_[get|set]_table_flags() function. */ +static unsigned int table_flags = 0; + +/* API function manipulating 'table_flags' */ +unsigned int ENGINE_get_table_flags(void) + { + return table_flags; + } +void ENGINE_set_table_flags(unsigned int flags) + { + table_flags = flags; + } + +/* Internal functions for the "piles" hash table */ +static unsigned long engine_pile_hash(const ENGINE_PILE *c) + { + return c->nid; + } +static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b) + { + return a->nid - b->nid; + } +static IMPLEMENT_LHASH_HASH_FN(engine_pile_hash, const ENGINE_PILE *) +static IMPLEMENT_LHASH_COMP_FN(engine_pile_cmp, const ENGINE_PILE *) +static int int_table_check(ENGINE_TABLE **t, int create) + { + LHASH *lh; + if(*t) + return 1; + if(!create) + return 0; + if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash), + LHASH_COMP_FN(engine_pile_cmp))) == NULL) + return 0; + *t = (ENGINE_TABLE *)lh; + return 1; + } + +/* Privately exposed (via eng_int.h) functions for adding and/or removing + * ENGINEs from the implementation table */ +int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, + ENGINE *e, const int *nids, int num_nids, int setdefault) + { + int ret = 0, added = 0; + ENGINE_PILE tmplate, *fnd; + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(!(*table)) + added = 1; + if(!int_table_check(table, 1)) + goto end; + if(added) + /* The cleanup callback needs to be added */ + engine_cleanup_add_first(cleanup); + while(num_nids--) + { + tmplate.nid = *nids; + fnd = lh_retrieve(&(*table)->piles, &tmplate); + if(!fnd) + { + fnd = OPENSSL_malloc(sizeof(ENGINE_PILE)); + if(!fnd) + goto end; + fnd->uptodate = 1; + fnd->nid = *nids; + fnd->sk = sk_ENGINE_new_null(); + if(!fnd->sk) + { + OPENSSL_free(fnd); + goto end; + } + fnd->funct= NULL; + lh_insert(&(*table)->piles, fnd); + } + /* A registration shouldn't add duplciate entries */ + sk_ENGINE_delete_ptr(fnd->sk, e); + /* if 'setdefault', this ENGINE goes to the head of the list */ + if(!sk_ENGINE_push(fnd->sk, e)) + goto end; + /* "touch" this ENGINE_PILE */ + fnd->uptodate = 0; + if(setdefault) + { + if(!engine_unlocked_init(e)) + { + ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER, + ENGINE_R_INIT_FAILED); + goto end; + } + if(fnd->funct) + engine_unlocked_finish(fnd->funct, 0); + fnd->funct = e; + } + nids++; + } + ret = 1; +end: + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } +static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e) + { + int n; + /* Iterate the 'c->sk' stack removing any occurance of 'e' */ + while((n = sk_ENGINE_find(pile->sk, e)) >= 0) + { + sk_ENGINE_delete(pile->sk, n); + /* "touch" this ENGINE_CIPHER */ + pile->uptodate = 0; + } + if(pile->funct == e) + { + engine_unlocked_finish(e, 0); + pile->funct = NULL; + } + } +static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb,ENGINE_PILE *,ENGINE *) +void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e) + { + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(int_table_check(table, 0)) + lh_doall_arg(&(*table)->piles, + LHASH_DOALL_ARG_FN(int_unregister_cb), e); + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + } + +static void int_cleanup_cb(ENGINE_PILE *p) + { + sk_ENGINE_free(p->sk); + if(p->funct) + engine_unlocked_finish(p->funct, 0); + OPENSSL_free(p); + } +static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb,ENGINE_PILE *) +void engine_table_cleanup(ENGINE_TABLE **table) + { + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(*table) + { + lh_doall(&(*table)->piles, LHASH_DOALL_FN(int_cleanup_cb)); + lh_free(&(*table)->piles); + *table = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given cipher 'nid' */ +#ifndef ENGINE_TABLE_DEBUG +ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) +#else +ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l) +#endif + { + ENGINE *ret = NULL; + ENGINE_PILE tmplate, *fnd=NULL; + int initres, loop = 0; + + /* If 'engine_ciphers' is NULL, then it's absolutely *sure* that no + * ENGINEs have registered any implementations! */ + if(!(*table)) + { +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no " + "registered for anything!\n", f, l, nid); +#endif + return NULL; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + /* Check again inside the lock otherwise we could race against cleanup + * operations. But don't worry about a fprintf(stderr). */ + if(!int_table_check(table, 0)) + goto end; + tmplate.nid = nid; + fnd = lh_retrieve(&(*table)->piles, &tmplate); + if(!fnd) + goto end; + if(fnd->funct && engine_unlocked_init(fnd->funct)) + { +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using " + "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id); +#endif + ret = fnd->funct; + goto end; + } + if(fnd->uptodate) + { + ret = fnd->funct; + goto end; + } +trynext: + ret = sk_ENGINE_value(fnd->sk, loop++); + if(!ret) + { +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no " + "registered implementations would initialise\n", + f, l, nid); +#endif + goto end; + } +#if 0 + /* Don't need to get a reference if we hold the lock. If the locking has + * to change in future, that would be different ... */ + ret->struct_ref++; engine_ref_debug(ret, 0, 1) +#endif + /* Try and initialise the ENGINE if it's already functional *or* if the + * ENGINE_TABLE_FLAG_NOINIT flag is not set. */ + if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT)) + initres = engine_unlocked_init(ret); + else + initres = 0; +#if 0 + /* Release the structural reference */ + ret->struct_ref--; engine_ref_debug(ret, 0, -1); +#endif + if(initres) + { + /* If we didn't have a default (functional reference) for this + * 'nid' (or we had one but for whatever reason we're now + * initialising a different one), use this opportunity to set + * 'funct'. */ + if((fnd->funct != ret) && engine_unlocked_init(ret)) + { + /* If there was a previous default we release it. */ + if(fnd->funct) + engine_unlocked_finish(fnd->funct, 0); + /* We got an extra functional reference for the + * per-'nid' default */ + fnd->funct = ret; +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, " + "setting default to '%s'\n", f, l, nid, ret->id); +#endif + } +#ifdef ENGINE_TABLE_DEBUG + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using " + "newly initialised '%s'\n", f, l, nid, ret->id); +#endif + goto end; + } + goto trynext; +end: + /* Whatever happened - we should "untouch" our uptodate file seeing as + * we have tried our best to find a functional reference for 'nid'. If + * it failed, it is unlikely to succeed again until some future + * registrations (or unregistrations) have taken place that affect that + * 'nid'. */ + if(fnd) + fnd->uptodate = 1; +#ifdef ENGINE_TABLE_DEBUG + if(ret) + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " + "ENGINE '%s'\n", f, l, nid, ret->id); + else + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " + "'no matching ENGINE'\n", f, l, nid); +#endif + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + /* Whatever happened, any failed init()s are not failures in this + * context, so clear our error state. */ + ERR_clear_error(); + return ret; + } diff --git a/src/lib/libcrypto/engine/engine.h b/src/lib/libcrypto/engine/engine.h new file mode 100644 index 0000000000..2983f47034 --- /dev/null +++ b/src/lib/libcrypto/engine/engine.h @@ -0,0 +1,398 @@ +/* openssl/engine.h */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * 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). + * + */ + +#ifndef HEADER_ENGINE_H +#define HEADER_ENGINE_H + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* These flags are used to control combinations of algorithm (methods) + * by bitwise "OR"ing. */ +#define ENGINE_METHOD_RSA (unsigned int)0x0001 +#define ENGINE_METHOD_DSA (unsigned int)0x0002 +#define ENGINE_METHOD_DH (unsigned int)0x0004 +#define ENGINE_METHOD_RAND (unsigned int)0x0008 +#define ENGINE_METHOD_BN_MOD_EXP (unsigned int)0x0010 +#define ENGINE_METHOD_BN_MOD_EXP_CRT (unsigned int)0x0020 +/* Obvious all-or-nothing cases. */ +#define ENGINE_METHOD_ALL (unsigned int)0xFFFF +#define ENGINE_METHOD_NONE (unsigned int)0x0000 + +/* These flags are used to tell the ctrl function what should be done. + * All command numbers are shared between all engines, even if some don't + * make sense to some engines. In such a case, they do nothing but return + * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */ +#define ENGINE_CTRL_SET_LOGSTREAM 1 +#define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +/* Flags specific to the nCipher "chil" engine */ +#define ENGINE_CTRL_CHIL_SET_FORKCHECK 100 + /* Depending on the value of the (long)i argument, this sets or + * unsets the SimpleForkCheck flag in the CHIL API to enable or + * disable checking and workarounds for applications that fork(). + */ +#define ENGINE_CTRL_CHIL_NO_LOCKING 101 + /* This prevents the initialisation function from providing mutex + * callbacks to the nCipher library. */ + +/* As we're missing a BIGNUM_METHOD, we need a couple of locally + * defined function types that engines can implement. */ + +#ifndef HEADER_ENGINE_INT_H +/* mod_exp operation, calculates; r = a ^ p mod m + * NB: ctx can be NULL, but if supplied, the implementation may use + * it if it wishes. */ +typedef int (*BN_MOD_EXP)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +/* private key operation for RSA, provided seperately in case other + * RSA implementations wish to use it. */ +typedef int (*BN_MOD_EXP_CRT)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp, BN_CTX *ctx); + +/* Generic function pointer */ +typedef void (*ENGINE_GEN_FUNC_PTR)(); +/* Generic function pointer taking no arguments */ +typedef void (*ENGINE_GEN_INT_FUNC_PTR)(void); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR)(int cmd, long i, void *p, void (*f)()); + +/* The list of "engine" types is a static array of (const ENGINE*) + * pointers (not dynamic because static is fine for now and we otherwise + * have to hook an appropriate load/unload function in to initialise and + * cleanup). */ +typedef struct engine_st ENGINE; +#endif + +/* STRUCTURE functions ... all of these functions deal with pointers to + * ENGINE structures where the pointers have a "structural reference". + * This means that their reference is to allow access to the structure + * but it does not imply that the structure is functional. To simply + * increment or decrement the structural reference count, use ENGINE_new + * and ENGINE_free. NB: This is not required when iterating using + * ENGINE_get_next as it will automatically decrement the structural + * reference count of the "current" ENGINE and increment the structural + * reference count of the ENGINE it returns (unless it is NULL). */ + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void); +ENGINE *ENGINE_get_last(void); +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e); +ENGINE *ENGINE_get_prev(ENGINE *e); +/* Add another "ENGINE" type into the array. */ +int ENGINE_add(ENGINE *e); +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e); +/* Retrieve an engine from the list by its unique "id" value. */ +ENGINE *ENGINE_by_id(const char *id); + +/* These functions are useful for manufacturing new ENGINE + * structures. They don't address reference counting at all - + * one uses them to populate an ENGINE structure with personalised + * implementations of things prior to using it directly or adding + * it to the builtin ENGINE list in OpenSSL. These are also here + * so that the ENGINE structure doesn't have to be exposed and + * break binary compatibility! + * + * NB: I'm changing ENGINE_new to force the ENGINE structure to + * be allocated from within OpenSSL. See the comment for + * ENGINE_get_struct_size(). + */ +#if 0 +ENGINE *ENGINE_new(ENGINE *e); +#else +ENGINE *ENGINE_new(void); +#endif +int ENGINE_free(ENGINE *e); +int ENGINE_set_id(ENGINE *e, const char *id); +int ENGINE_set_name(ENGINE *e, const char *name); +int ENGINE_set_RSA(ENGINE *e, RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, DSA_METHOD *dsa_meth); +int ENGINE_set_DH(ENGINE *e, DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, RAND_METHOD *rand_meth); +int ENGINE_set_BN_mod_exp(ENGINE *e, BN_MOD_EXP bn_mod_exp); +int ENGINE_set_BN_mod_exp_crt(ENGINE *e, BN_MOD_EXP_CRT bn_mod_exp_crt); +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); + +/* These return values from within the ENGINE structure. These can + * be useful with functional references as well as structural + * references - it depends which you obtained. Using the result + * for functional purposes if you only obtained a structural + * reference may be problematic! */ +const char *ENGINE_get_id(ENGINE *e); +const char *ENGINE_get_name(ENGINE *e); +RSA_METHOD *ENGINE_get_RSA(ENGINE *e); +DSA_METHOD *ENGINE_get_DSA(ENGINE *e); +DH_METHOD *ENGINE_get_DH(ENGINE *e); +RAND_METHOD *ENGINE_get_RAND(ENGINE *e); +BN_MOD_EXP ENGINE_get_BN_mod_exp(ENGINE *e); +BN_MOD_EXP_CRT ENGINE_get_BN_mod_exp_crt(ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(ENGINE *e); + +/* ENGINE_new is normally passed a NULL in the first parameter because + * the calling code doesn't have access to the definition of the ENGINE + * structure (for good reason). However, if the caller wishes to use + * its own memory allocation or use a static array, the following call + * should be used to check the amount of memory the ENGINE structure + * will occupy. This will make the code more future-proof. + * + * NB: I'm "#if 0"-ing this out because it's better to force the use of + * internally allocated memory. See similar change in ENGINE_new(). + */ +#if 0 +int ENGINE_get_struct_size(void); +#endif + +/* FUNCTIONAL functions. These functions deal with ENGINE structures + * that have (or will) be initialised for use. Broadly speaking, the + * structural functions are useful for iterating the list of available + * engine types, creating new engine types, and other "list" operations. + * These functions actually deal with ENGINEs that are to be used. As + * such these functions can fail (if applicable) when particular + * engines are unavailable - eg. if a hardware accelerator is not + * attached or not functioning correctly. Each ENGINE has 2 reference + * counts; structural and functional. Every time a functional reference + * is obtained or released, a corresponding structural reference is + * automatically obtained or released too. */ + +/* Initialise a engine type for use (or up its reference count if it's + * already in use). This will fail if the engine is not currently + * operational and cannot initialise. */ +int ENGINE_init(ENGINE *e); +/* Free a functional reference to a engine type. This does not require + * a corresponding call to ENGINE_free as it also releases a structural + * reference. */ +int ENGINE_finish(ENGINE *e); +/* Send control parametrised commands to the engine. The possibilities + * to send down an integer, a pointer to data or a function pointer are + * provided. Any of the parameters may or may not be NULL, depending + * on the command number */ +/* WARNING: This is currently experimental and may change radically! */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); + +/* The following functions handle keys that are stored in some secondary + * location, handled by the engine. The storage may be on a card or + * whatever. */ +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + const char *passphrase); +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + const char *passphrase); + +/* This returns a pointer for the current ENGINE structure that + * is (by default) performing any RSA operations. The value returned + * is an incremented reference, so it should be free'd (ENGINE_finish) + * before it is discarded. */ +ENGINE *ENGINE_get_default_RSA(void); +/* Same for the other "methods" */ +ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_DH(void); +ENGINE *ENGINE_get_default_RAND(void); +ENGINE *ENGINE_get_default_BN_mod_exp(void); +ENGINE *ENGINE_get_default_BN_mod_exp_crt(void); + +/* This sets a new default ENGINE structure for performing RSA + * operations. If the result is non-zero (success) then the ENGINE + * structure will have had its reference count up'd so the caller + * should still free their own reference 'e'. */ +int ENGINE_set_default_RSA(ENGINE *e); +/* Same for the other "methods" */ +int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_DH(ENGINE *e); +int ENGINE_set_default_RAND(ENGINE *e); +int ENGINE_set_default_BN_mod_exp(ENGINE *e); +int ENGINE_set_default_BN_mod_exp_crt(ENGINE *e); + +/* The combination "set" - the flags are bitwise "OR"d from the + * ENGINE_METHOD_*** defines above. */ +int ENGINE_set_default(ENGINE *e, unsigned int flags); + +/* Obligatory error function. */ +void ERR_load_ENGINE_strings(void); + +/* + * Error codes for all engine functions. NB: We use "generic" + * function names instead of per-implementation ones because this + * levels the playing field for externally implemented bootstrapped + * support code. As the filename and line number is included, it's + * more important to indicate the type of function, so that + * bootstrapped code (that can't easily add its own errors in) can + * use the same error codes too. + */ + +/* 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 ENGINE functions. */ + +/* Function codes. */ +#define ENGINE_F_ATALLA_FINISH 135 +#define ENGINE_F_ATALLA_INIT 136 +#define ENGINE_F_ATALLA_MOD_EXP 137 +#define ENGINE_F_ATALLA_RSA_MOD_EXP 138 +#define ENGINE_F_CSWIFT_DSA_SIGN 133 +#define ENGINE_F_CSWIFT_DSA_VERIFY 134 +#define ENGINE_F_CSWIFT_FINISH 100 +#define ENGINE_F_CSWIFT_INIT 101 +#define ENGINE_F_CSWIFT_MOD_EXP 102 +#define ENGINE_F_CSWIFT_MOD_EXP_CRT 103 +#define ENGINE_F_CSWIFT_RSA_MOD_EXP 104 +#define ENGINE_F_ENGINE_ADD 105 +#define ENGINE_F_ENGINE_BY_ID 106 +#define ENGINE_F_ENGINE_CTRL 142 +#define ENGINE_F_ENGINE_FINISH 107 +#define ENGINE_F_ENGINE_FREE 108 +#define ENGINE_F_ENGINE_GET_BN_MOD_EXP 109 +#define ENGINE_F_ENGINE_GET_BN_MOD_EXP_CRT 110 +#define ENGINE_F_ENGINE_GET_CTRL_FUNCTION 144 +#define ENGINE_F_ENGINE_GET_DH 111 +#define ENGINE_F_ENGINE_GET_DSA 112 +#define ENGINE_F_ENGINE_GET_FINISH_FUNCTION 145 +#define ENGINE_F_ENGINE_GET_ID 113 +#define ENGINE_F_ENGINE_GET_INIT_FUNCTION 146 +#define ENGINE_F_ENGINE_GET_NAME 114 +#define ENGINE_F_ENGINE_GET_NEXT 115 +#define ENGINE_F_ENGINE_GET_PREV 116 +#define ENGINE_F_ENGINE_GET_RAND 117 +#define ENGINE_F_ENGINE_GET_RSA 118 +#define ENGINE_F_ENGINE_INIT 119 +#define ENGINE_F_ENGINE_LIST_ADD 120 +#define ENGINE_F_ENGINE_LIST_REMOVE 121 +#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 +#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +#define ENGINE_F_ENGINE_NEW 122 +#define ENGINE_F_ENGINE_REMOVE 123 +#define ENGINE_F_ENGINE_SET_BN_MOD_EXP 124 +#define ENGINE_F_ENGINE_SET_BN_MOD_EXP_CRT 125 +#define ENGINE_F_ENGINE_SET_CTRL_FUNCTION 147 +#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126 +#define ENGINE_F_ENGINE_SET_DH 127 +#define ENGINE_F_ENGINE_SET_DSA 128 +#define ENGINE_F_ENGINE_SET_FINISH_FUNCTION 148 +#define ENGINE_F_ENGINE_SET_ID 129 +#define ENGINE_F_ENGINE_SET_INIT_FUNCTION 149 +#define ENGINE_F_ENGINE_SET_NAME 130 +#define ENGINE_F_ENGINE_SET_RAND 131 +#define ENGINE_F_ENGINE_SET_RSA 132 +#define ENGINE_F_ENGINE_UNLOAD_KEY 152 +#define ENGINE_F_HWCRHK_CTRL 143 +#define ENGINE_F_HWCRHK_FINISH 135 +#define ENGINE_F_HWCRHK_GET_PASS 155 +#define ENGINE_F_HWCRHK_INIT 136 +#define ENGINE_F_HWCRHK_LOAD_PRIVKEY 153 +#define ENGINE_F_HWCRHK_LOAD_PUBKEY 154 +#define ENGINE_F_HWCRHK_MOD_EXP 137 +#define ENGINE_F_HWCRHK_MOD_EXP_CRT 138 +#define ENGINE_F_HWCRHK_RAND_BYTES 139 +#define ENGINE_F_HWCRHK_RSA_MOD_EXP 140 +#define ENGINE_F_LOG_MESSAGE 141 + +/* Reason codes. */ +#define ENGINE_R_ALREADY_LOADED 100 +#define ENGINE_R_BIO_WAS_FREED 121 +#define ENGINE_R_BN_CTX_FULL 101 +#define ENGINE_R_BN_EXPAND_FAIL 102 +#define ENGINE_R_CHIL_ERROR 123 +#define ENGINE_R_CONFLICTING_ENGINE_ID 103 +#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +#define ENGINE_R_DSO_FAILURE 104 +#define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 +#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 +#define ENGINE_R_FINISH_FAILED 106 +#define ENGINE_R_GET_HANDLE_FAILED 107 +#define ENGINE_R_ID_OR_NAME_MISSING 108 +#define ENGINE_R_INIT_FAILED 109 +#define ENGINE_R_INTERNAL_LIST_ERROR 110 +#define ENGINE_R_MISSING_KEY_COMPONENTS 111 +#define ENGINE_R_NOT_INITIALISED 117 +#define ENGINE_R_NOT_LOADED 112 +#define ENGINE_R_NO_CALLBACK 127 +#define ENGINE_R_NO_CONTROL_FUNCTION 120 +#define ENGINE_R_NO_KEY 124 +#define ENGINE_R_NO_LOAD_FUNCTION 125 +#define ENGINE_R_NO_REFERENCE 130 +#define ENGINE_R_NO_SUCH_ENGINE 116 +#define ENGINE_R_NO_UNLOAD_FUNCTION 126 +#define ENGINE_R_PROVIDE_PARAMETERS 113 +#define ENGINE_R_REQUEST_FAILED 114 +#define ENGINE_R_REQUEST_FALLBACK 118 +#define ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL 122 +#define ENGINE_R_UNIT_FAILURE 115 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/engine/tb_cipher.c b/src/lib/libcrypto/engine/tb_cipher.c new file mode 100644 index 0000000000..c5a50fc910 --- /dev/null +++ b/src/lib/libcrypto/engine/tb_cipher.c @@ -0,0 +1,145 @@ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "eng_int.h" + +/* If this symbol is defined then ENGINE_get_cipher_engine(), the function that + * is used by EVP to hook in cipher code and cache defaults (etc), will display + * brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_CIPHER_DEBUG */ + +static ENGINE_TABLE *cipher_table = NULL; + +void ENGINE_unregister_ciphers(ENGINE *e) + { + engine_table_unregister(&cipher_table, e); + } + +static void engine_unregister_all_ciphers(void) + { + engine_table_cleanup(&cipher_table); + } + +int ENGINE_register_ciphers(ENGINE *e) + { + if(e->ciphers) + { + const int *nids; + int num_nids = e->ciphers(e, NULL, &nids, 0); + if(num_nids > 0) + return engine_table_register(&cipher_table, + &engine_unregister_all_ciphers, e, nids, + num_nids, 0); + } + return 1; + } + +void ENGINE_register_all_ciphers() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_ciphers(e); + } + +int ENGINE_set_default_ciphers(ENGINE *e) + { + if(e->ciphers) + { + const int *nids; + int num_nids = e->ciphers(e, NULL, &nids, 0); + if(num_nids > 0) + return engine_table_register(&cipher_table, + &engine_unregister_all_ciphers, e, nids, + num_nids, 1); + } + return 1; + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given cipher 'nid' */ +ENGINE *ENGINE_get_cipher_engine(int nid) + { + return engine_table_select(&cipher_table, nid); + } + +/* Obtains a cipher implementation from an ENGINE functional reference */ +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid) + { + const EVP_CIPHER *ret; + ENGINE_CIPHERS_PTR fn = ENGINE_get_ciphers(e); + if(!fn || !fn(e, &ret, NULL, nid)) + { + ENGINEerr(ENGINE_F_ENGINE_GET_CIPHER, + ENGINE_R_UNIMPLEMENTED_CIPHER); + return NULL; + } + return ret; + } + +/* Gets the cipher callback from an ENGINE structure */ +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e) + { + return e->ciphers; + } + +/* Sets the cipher callback in an ENGINE structure */ +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f) + { + e->ciphers = f; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_dh.c b/src/lib/libcrypto/engine/tb_dh.c new file mode 100644 index 0000000000..c9347235ea --- /dev/null +++ b/src/lib/libcrypto/engine/tb_dh.c @@ -0,0 +1,120 @@ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_DH(), the function that is + * used by DH to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_DH_DEBUG */ + +static ENGINE_TABLE *dh_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_DH(ENGINE *e) + { + engine_table_unregister(&dh_table, e); + } + +static void engine_unregister_all_DH(void) + { + engine_table_cleanup(&dh_table); + } + +int ENGINE_register_DH(ENGINE *e) + { + if(e->dh_meth) + return engine_table_register(&dh_table, + &engine_unregister_all_DH, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_DH() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_DH(e); + } + +int ENGINE_set_default_DH(ENGINE *e) + { + if(e->dh_meth) + return engine_table_register(&dh_table, + &engine_unregister_all_DH, e, &dummy_nid, 1, 1); + return 1; + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). */ +ENGINE *ENGINE_get_default_DH(void) + { + return engine_table_select(&dh_table, dummy_nid); + } + +/* Obtains an DH implementation from an ENGINE functional reference */ +const DH_METHOD *ENGINE_get_DH(const ENGINE *e) + { + return e->dh_meth; + } + +/* Sets an DH implementation in an ENGINE structure */ +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth) + { + e->dh_meth = dh_meth; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_digest.c b/src/lib/libcrypto/engine/tb_digest.c new file mode 100644 index 0000000000..2c4dd6f796 --- /dev/null +++ b/src/lib/libcrypto/engine/tb_digest.c @@ -0,0 +1,145 @@ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "eng_int.h" + +/* If this symbol is defined then ENGINE_get_digest_engine(), the function that + * is used by EVP to hook in digest code and cache defaults (etc), will display + * brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_DIGEST_DEBUG */ + +static ENGINE_TABLE *digest_table = NULL; + +void ENGINE_unregister_digests(ENGINE *e) + { + engine_table_unregister(&digest_table, e); + } + +static void engine_unregister_all_digests(void) + { + engine_table_cleanup(&digest_table); + } + +int ENGINE_register_digests(ENGINE *e) + { + if(e->digests) + { + const int *nids; + int num_nids = e->digests(e, NULL, &nids, 0); + if(num_nids > 0) + return engine_table_register(&digest_table, + &engine_unregister_all_digests, e, nids, + num_nids, 0); + } + return 1; + } + +void ENGINE_register_all_digests() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_digests(e); + } + +int ENGINE_set_default_digests(ENGINE *e) + { + if(e->digests) + { + const int *nids; + int num_nids = e->digests(e, NULL, &nids, 0); + if(num_nids > 0) + return engine_table_register(&digest_table, + &engine_unregister_all_digests, e, nids, + num_nids, 1); + } + return 1; + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given digest 'nid' */ +ENGINE *ENGINE_get_digest_engine(int nid) + { + return engine_table_select(&digest_table, nid); + } + +/* Obtains a digest implementation from an ENGINE functional reference */ +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid) + { + const EVP_MD *ret; + ENGINE_DIGESTS_PTR fn = ENGINE_get_digests(e); + if(!fn || !fn(e, &ret, NULL, nid)) + { + ENGINEerr(ENGINE_F_ENGINE_GET_DIGEST, + ENGINE_R_UNIMPLEMENTED_DIGEST); + return NULL; + } + return ret; + } + +/* Gets the digest callback from an ENGINE structure */ +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e) + { + return e->digests; + } + +/* Sets the digest callback in an ENGINE structure */ +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f) + { + e->digests = f; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_dsa.c b/src/lib/libcrypto/engine/tb_dsa.c new file mode 100644 index 0000000000..e9209476b8 --- /dev/null +++ b/src/lib/libcrypto/engine/tb_dsa.c @@ -0,0 +1,120 @@ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_DSA(), the function that is + * used by DSA to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_DSA_DEBUG */ + +static ENGINE_TABLE *dsa_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_DSA(ENGINE *e) + { + engine_table_unregister(&dsa_table, e); + } + +static void engine_unregister_all_DSA(void) + { + engine_table_cleanup(&dsa_table); + } + +int ENGINE_register_DSA(ENGINE *e) + { + if(e->dsa_meth) + return engine_table_register(&dsa_table, + &engine_unregister_all_DSA, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_DSA() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_DSA(e); + } + +int ENGINE_set_default_DSA(ENGINE *e) + { + if(e->dsa_meth) + return engine_table_register(&dsa_table, + &engine_unregister_all_DSA, e, &dummy_nid, 1, 0); + return 1; + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). */ +ENGINE *ENGINE_get_default_DSA(void) + { + return engine_table_select(&dsa_table, dummy_nid); + } + +/* Obtains an DSA implementation from an ENGINE functional reference */ +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e) + { + return e->dsa_meth; + } + +/* Sets an DSA implementation in an ENGINE structure */ +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth) + { + e->dsa_meth = dsa_meth; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_rand.c b/src/lib/libcrypto/engine/tb_rand.c new file mode 100644 index 0000000000..0b1d031f1e --- /dev/null +++ b/src/lib/libcrypto/engine/tb_rand.c @@ -0,0 +1,120 @@ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_RAND(), the function that is + * used by RAND to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_RAND_DEBUG */ + +static ENGINE_TABLE *rand_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_RAND(ENGINE *e) + { + engine_table_unregister(&rand_table, e); + } + +static void engine_unregister_all_RAND(void) + { + engine_table_cleanup(&rand_table); + } + +int ENGINE_register_RAND(ENGINE *e) + { + if(e->rand_meth) + return engine_table_register(&rand_table, + &engine_unregister_all_RAND, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_RAND() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_RAND(e); + } + +int ENGINE_set_default_RAND(ENGINE *e) + { + if(e->rand_meth) + return engine_table_register(&rand_table, + &engine_unregister_all_RAND, e, &dummy_nid, 1, 1); + return 1; + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). */ +ENGINE *ENGINE_get_default_RAND(void) + { + return engine_table_select(&rand_table, dummy_nid); + } + +/* Obtains an RAND implementation from an ENGINE functional reference */ +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e) + { + return e->rand_meth; + } + +/* Sets an RAND implementation in an ENGINE structure */ +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth) + { + e->rand_meth = rand_meth; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_rsa.c b/src/lib/libcrypto/engine/tb_rsa.c new file mode 100644 index 0000000000..f84fea3968 --- /dev/null +++ b/src/lib/libcrypto/engine/tb_rsa.c @@ -0,0 +1,120 @@ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_RSA(), the function that is + * used by RSA to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_RSA_DEBUG */ + +static ENGINE_TABLE *rsa_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_RSA(ENGINE *e) + { + engine_table_unregister(&rsa_table, e); + } + +static void engine_unregister_all_RSA(void) + { + engine_table_cleanup(&rsa_table); + } + +int ENGINE_register_RSA(ENGINE *e) + { + if(e->rsa_meth) + return engine_table_register(&rsa_table, + &engine_unregister_all_RSA, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_RSA() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_RSA(e); + } + +int ENGINE_set_default_RSA(ENGINE *e) + { + if(e->rsa_meth) + return engine_table_register(&rsa_table, + &engine_unregister_all_RSA, e, &dummy_nid, 1, 1); + return 1; + } + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references). */ +ENGINE *ENGINE_get_default_RSA(void) + { + return engine_table_select(&rsa_table, dummy_nid); + } + +/* Obtains an RSA implementation from an ENGINE functional reference */ +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e) + { + return e->rsa_meth; + } + +/* Sets an RSA implementation in an ENGINE structure */ +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth) + { + e->rsa_meth = rsa_meth; + return 1; + } diff --git a/src/lib/libcrypto/err/openssl.ec b/src/lib/libcrypto/err/openssl.ec new file mode 100644 index 0000000000..c2a8acff0c --- /dev/null +++ b/src/lib/libcrypto/err/openssl.ec @@ -0,0 +1,71 @@ +L ERR NONE NONE +L CRYPTO crypto/crypto.h crypto/cpt_err.c +L BN crypto/bn/bn.h crypto/bn/bn_err.c +L RSA crypto/rsa/rsa.h crypto/rsa/rsa_err.c +L DSA crypto/dsa/dsa.h crypto/dsa/dsa_err.c +L DH crypto/dh/dh.h crypto/dh/dh_err.c +L EVP crypto/evp/evp.h crypto/evp/evp_err.c +L BUF crypto/buffer/buffer.h crypto/buffer/buf_err.c +L BIO crypto/bio/bio.h crypto/bio/bio_err.c +L OBJ crypto/objects/objects.h crypto/objects/obj_err.c +L PEM crypto/pem/pem.h crypto/pem/pem_err.c +L X509 crypto/x509/x509.h crypto/x509/x509_err.c +L NONE crypto/x509/x509_vfy.h NONE +L X509V3 crypto/x509v3/x509v3.h crypto/x509v3/v3err.c +#L METH crypto/meth/meth.h crypto/meth/meth_err.c +L ASN1 crypto/asn1/asn1.h crypto/asn1/asn1_err.c +L CONF crypto/conf/conf.h crypto/conf/conf_err.c +#L PROXY crypto/proxy/proxy.h crypto/proxy/proxy_err.c +L PKCS7 crypto/pkcs7/pkcs7.h crypto/pkcs7/pkcs7err.c +L PKCS12 crypto/pkcs12/pkcs12.h crypto/pkcs12/pk12err.c +L RSAREF rsaref/rsaref.h rsaref/rsar_err.c +L SSL ssl/ssl.h ssl/ssl_err.c +L COMP crypto/comp/comp.h crypto/comp/comp_err.c + + +F RSAREF_F_RSA_BN2BIN +F RSAREF_F_RSA_PRIVATE_DECRYPT +F RSAREF_F_RSA_PRIVATE_ENCRYPT +F RSAREF_F_RSA_PUBLIC_DECRYPT +F RSAREF_F_RSA_PUBLIC_ENCRYPT +#F SSL_F_CLIENT_CERTIFICATE + +R SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +R SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +R SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +R SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +R SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +R SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +R SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +R SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +R SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +R SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +R SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +R SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +R SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +R SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +R SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +R SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +R SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +R SSL_R_TLSV1_ALERT_EXPORT_RESTRICION 1060 +R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +R SSL_R_TLSV1_ALERT_USER_CANCLED 1090 +R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 + +R RSAREF_R_CONTENT_ENCODING 0x0400 +R RSAREF_R_DATA 0x0401 +R RSAREF_R_DIGEST_ALGORITHM 0x0402 +R RSAREF_R_ENCODING 0x0403 +R RSAREF_R_KEY 0x0404 +R RSAREF_R_KEY_ENCODING 0x0405 +R RSAREF_R_LEN 0x0406 +R RSAREF_R_MODULUS_LEN 0x0407 +R RSAREF_R_NEED_RANDOM 0x0408 +R RSAREF_R_PRIVATE_KEY 0x0409 +R RSAREF_R_PUBLIC_KEY 0x040a +R RSAREF_R_SIGNATURE 0x040b +R RSAREF_R_SIGNATURE_ENCODING 0x040c +R RSAREF_R_ENCRYPTION_ALGORITHM 0x040d + diff --git a/src/lib/libcrypto/evp/e_aes.c b/src/lib/libcrypto/evp/e_aes.c new file mode 100644 index 0000000000..9d03a9602f --- /dev/null +++ b/src/lib/libcrypto/evp/e_aes.c @@ -0,0 +1,99 @@ +/* ==================================================================== + * Copyright (c) 2001 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. + * ==================================================================== + * + */ + +#ifndef OPENSSL_NO_AES +#include +#include +#include +#include +#include +#include "evp_locl.h" + +static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +typedef struct + { + AES_KEY ks; + } EVP_AES_KEY; + +#define data(ctx) EVP_C_DATA(EVP_AES_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(aes_128, ks, AES, EVP_AES_KEY, + NID_aes_128, 16, 16, 16, 128, + 0, aes_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) +IMPLEMENT_BLOCK_CIPHER(aes_192, ks, AES, EVP_AES_KEY, + NID_aes_192, 16, 24, 16, 128, + 0, aes_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) +IMPLEMENT_BLOCK_CIPHER(aes_256, ks, AES, EVP_AES_KEY, + NID_aes_256, 16, 32, 16, 128, + 0, aes_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) + +static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) { + + if (enc) + AES_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data); + else + AES_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data); + + return 1; +} + +#endif diff --git a/src/lib/libcrypto/evp/e_bf.c b/src/lib/libcrypto/evp/e_bf.c new file mode 100644 index 0000000000..72047f64da --- /dev/null +++ b/src/lib/libcrypto/evp/e_bf.c @@ -0,0 +1,80 @@ +/* crypto/evp/e_bf.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 NO_BF +#include +#include "cryptlib.h" +#include +#include "evp_locl.h" +#include + +static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +IMPLEMENT_BLOCK_CIPHER(bf, bf_ks, BF, bf_ks, NID_bf, 8, 16, 8, + 0, bf_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + BF_set_key(&(ctx->c.bf_ks),EVP_CIPHER_CTX_key_length(ctx),key); + return 1; + } + +#endif diff --git a/src/lib/libcrypto/evp/e_cast.c b/src/lib/libcrypto/evp/e_cast.c new file mode 100644 index 0000000000..e5af7fb4ed --- /dev/null +++ b/src/lib/libcrypto/evp/e_cast.c @@ -0,0 +1,82 @@ +/* crypto/evp/e_cast.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 NO_CAST + +#include +#include "cryptlib.h" +#include +#include +#include "evp_locl.h" + +static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); + +IMPLEMENT_BLOCK_CIPHER(cast5, cast_ks, CAST, cast_ks, + NID_cast5, 8, EVP_CAST5_KEY_SIZE, 8, + EVP_CIPH_VARIABLE_LENGTH, cast_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + CAST_set_key(&(ctx->c.cast_ks),EVP_CIPHER_CTX_key_length(ctx),key); + return 1; + } + +#endif diff --git a/src/lib/libcrypto/evp/e_des.c b/src/lib/libcrypto/evp/e_des.c new file mode 100644 index 0000000000..f4e998b81c --- /dev/null +++ b/src/lib/libcrypto/evp/e_des.c @@ -0,0 +1,118 @@ +/* crypto/evp/e_des.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 NO_DES +#include +#include "cryptlib.h" +#include +#include +#include "evp_locl.h" + +static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + +/* Because of various casts and different names can't use IMPLEMENT_BLOCK_CIPHER */ + +static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + BLOCK_CIPHER_ecb_loop() + des_ecb_encrypt((des_cblock *)(in + i), (des_cblock *)(out + i), ctx->c.des_ks, ctx->encrypt); + return 1; +} + +static int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + des_ofb64_encrypt(in, out, (long)inl, ctx->c.des_ks, (des_cblock *)ctx->iv, &ctx->num); + return 1; +} + +static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + des_ncbc_encrypt(in, out, (long)inl, ctx->c.des_ks, + (des_cblock *)ctx->iv, ctx->encrypt); + return 1; +} + +static int des_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + des_cfb64_encrypt(in, out, (long)inl, ctx->c.des_ks, + (des_cblock *)ctx->iv, &ctx->num, ctx->encrypt); + return 1; +} + +BLOCK_CIPHER_defs(des, des_ks, NID_des, 8, 8, 8, + 0, des_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) + + +static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + des_cblock *deskey = (des_cblock *)key; + + des_set_key_unchecked(deskey,ctx->c.des_ks); + return 1; + } + +#endif diff --git a/src/lib/libcrypto/evp/e_des3.c b/src/lib/libcrypto/evp/e_des3.c new file mode 100644 index 0000000000..a9aba4ae70 --- /dev/null +++ b/src/lib/libcrypto/evp/e_des3.c @@ -0,0 +1,165 @@ +/* crypto/evp/e_des3.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 NO_DES +#include +#include "cryptlib.h" +#include +#include +#include "evp_locl.h" + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); + +/* Because of various casts and different args can't use IMPLEMENT_BLOCK_CIPHER */ + +static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + BLOCK_CIPHER_ecb_loop() + des_ecb3_encrypt((des_cblock *)(in + i), (des_cblock *)(out + i), + ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, + ctx->encrypt); + return 1; +} + +static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + des_ede3_ofb64_encrypt(in, out, (long)inl, + ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, + (des_cblock *)ctx->iv, &ctx->num); + return 1; +} + +static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + des_ede3_cbc_encrypt(in, out, (long)inl, + ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, + (des_cblock *)ctx->iv, ctx->encrypt); + return 1; +} + +static int des_ede_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + des_ede3_cfb64_encrypt(in, out, (long)inl, + ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, + (des_cblock *)ctx->iv, &ctx->num, ctx->encrypt); + return 1; +} + +#define NID_des_ede_ecb NID_des_ede + +BLOCK_CIPHER_defs(des_ede, des_ede, NID_des_ede, 8, 16, 8, + 0, des_ede_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) + +#define NID_des_ede3_ecb NID_des_ede3 +#define des_ede3_cfb_cipher des_ede_cfb_cipher +#define des_ede3_ofb_cipher des_ede_ofb_cipher +#define des_ede3_cbc_cipher des_ede_cbc_cipher +#define des_ede3_ecb_cipher des_ede_ecb_cipher + +BLOCK_CIPHER_defs(des_ede3, des_ede, NID_des_ede3, 8, 24, 8, + 0, des_ede3_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL) + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + des_cblock *deskey = (des_cblock *)key; + + des_set_key_unchecked(&deskey[0],ctx->c.des_ede.ks1); + des_set_key_unchecked(&deskey[1],ctx->c.des_ede.ks2); + memcpy( (char *)ctx->c.des_ede.ks3, + (char *)ctx->c.des_ede.ks1, + sizeof(ctx->c.des_ede.ks1)); + return 1; + } + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + des_cblock *deskey = (des_cblock *)key; + + des_set_key_unchecked(&deskey[0],ctx->c.des_ede.ks1); + des_set_key_unchecked(&deskey[1],ctx->c.des_ede.ks2); + des_set_key_unchecked(&deskey[2],ctx->c.des_ede.ks3); + + return 1; + } + +EVP_CIPHER *EVP_des_ede(void) +{ + return &des_ede_ecb; +} + +EVP_CIPHER *EVP_des_ede3(void) +{ + return &des_ede3_ecb; +} +#endif diff --git a/src/lib/libcrypto/evp/e_idea.c b/src/lib/libcrypto/evp/e_idea.c new file mode 100644 index 0000000000..8d3c88deb7 --- /dev/null +++ b/src/lib/libcrypto/evp/e_idea.c @@ -0,0 +1,112 @@ +/* crypto/evp/e_idea.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 NO_IDEA + +#include +#include "cryptlib.h" +#include +#include +#include "evp_locl.h" + +static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); + +/* NB idea_ecb_encrypt doesn't take an 'encrypt' argument so we treat it as a special + * case + */ + +static int idea_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +{ + BLOCK_CIPHER_ecb_loop() + idea_ecb_encrypt(in + i, out + i, &ctx->c.idea_ks); + return 1; +} + +/* Can't use IMPLEMENT_BLOCK_CIPHER because idea_ecb_encrypt is different */ + +BLOCK_CIPHER_func_cbc(idea, idea, idea_ks) +BLOCK_CIPHER_func_ofb(idea, idea, idea_ks) +BLOCK_CIPHER_func_cfb(idea, idea, idea_ks) + +BLOCK_CIPHER_defs(idea, idea_ks, NID_idea, 8, 16, 8, + 0, idea_init_key, NULL, + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + if(!enc) { + if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) enc = 1; + else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) enc = 1; + } + if (enc) idea_set_encrypt_key(key,&(ctx->c.idea_ks)); + else + { + IDEA_KEY_SCHEDULE tmp; + + idea_set_encrypt_key(key,&tmp); + idea_set_decrypt_key(&tmp,&(ctx->c.idea_ks)); + memset((unsigned char *)&tmp,0, + sizeof(IDEA_KEY_SCHEDULE)); + } + return 1; + } + +#endif diff --git a/src/lib/libcrypto/evp/e_rc2.c b/src/lib/libcrypto/evp/e_rc2.c new file mode 100644 index 0000000000..3955c3ef84 --- /dev/null +++ b/src/lib/libcrypto/evp/e_rc2.c @@ -0,0 +1,222 @@ +/* crypto/evp/e_rc2.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 NO_RC2 + +#include +#include "cryptlib.h" +#include +#include +#include "evp_locl.h" + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); +static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx); +static int rc2_magic_to_meth(int i); +static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +IMPLEMENT_BLOCK_CIPHER(rc2, rc2.ks, RC2, rc2, NID_rc2, + 8, + EVP_RC2_KEY_SIZE, 8, + EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + rc2_init_key, NULL, + rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, + rc2_ctrl) + +#define RC2_40_MAGIC 0xa0 +#define RC2_64_MAGIC 0x78 +#define RC2_128_MAGIC 0x3a + +static EVP_CIPHER r2_64_cbc_cipher= + { + NID_rc2_64_cbc, + 8,8 /* 64 bit */,8, + EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + rc2_init_key, + rc2_cbc_cipher, + NULL, + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)), + rc2_set_asn1_type_and_iv, + rc2_get_asn1_type_and_iv, + rc2_ctrl, + NULL + }; + +static EVP_CIPHER r2_40_cbc_cipher= + { + NID_rc2_40_cbc, + 8,5 /* 40 bit */,8, + EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, + rc2_init_key, + rc2_cbc_cipher, + NULL, + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)), + rc2_set_asn1_type_and_iv, + rc2_get_asn1_type_and_iv, + rc2_ctrl, + NULL + }; + +EVP_CIPHER *EVP_rc2_64_cbc(void) + { + return(&r2_64_cbc_cipher); + } + +EVP_CIPHER *EVP_rc2_40_cbc(void) + { + return(&r2_40_cbc_cipher); + } + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + RC2_set_key(&(ctx->c.rc2.ks),EVP_CIPHER_CTX_key_length(ctx), + key,ctx->c.rc2.key_bits); + return 1; + } + +static int rc2_meth_to_magic(EVP_CIPHER_CTX *e) + { + int i; + + EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i); + if (i == 128) return(RC2_128_MAGIC); + else if (i == 64) return(RC2_64_MAGIC); + else if (i == 40) return(RC2_40_MAGIC); + else return(0); + } + +static int rc2_magic_to_meth(int i) + { + if (i == RC2_128_MAGIC) return 128; + else if (i == RC2_64_MAGIC) return 64; + else if (i == RC2_40_MAGIC) return 40; + else + { + EVPerr(EVP_F_RC2_MAGIC_TO_METH,EVP_R_UNSUPPORTED_KEY_SIZE); + return(0); + } + } + +static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) + { + long num=0; + int i=0,l; + int key_bits; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + if (type != NULL) + { + l=EVP_CIPHER_CTX_iv_length(c); + i=ASN1_TYPE_get_int_octetstring(type,&num,iv,l); + if (i != l) + return(-1); + key_bits =rc2_magic_to_meth((int)num); + if (!key_bits) + return(-1); + if(i > 0) EVP_CipherInit(c, NULL, NULL, iv, -1); + EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL); + EVP_CIPHER_CTX_set_key_length(c, key_bits / 8); + } + return(i); + } + +static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) + { + long num; + int i=0,j; + + if (type != NULL) + { + num=rc2_meth_to_magic(c); + j=EVP_CIPHER_CTX_iv_length(c); + i=ASN1_TYPE_set_int_octetstring(type,num,c->oiv,j); + } + return(i); + } + +static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) + { + switch(type) { + + case EVP_CTRL_INIT: + c->c.rc2.key_bits = EVP_CIPHER_CTX_key_length(c) * 8; + return 1; + + case EVP_CTRL_GET_RC2_KEY_BITS: + *(int *)ptr = c->c.rc2.key_bits; + return 1; + + + case EVP_CTRL_SET_RC2_KEY_BITS: + if(arg > 0) { + c->c.rc2.key_bits = arg; + return 1; + } + return 0; + + default: + return -1; + } + } + +#endif diff --git a/src/lib/libcrypto/evp/evp_locl.h b/src/lib/libcrypto/evp/evp_locl.h new file mode 100644 index 0000000000..ce49d5b7d8 --- /dev/null +++ b/src/lib/libcrypto/evp/evp_locl.h @@ -0,0 +1,168 @@ +/* evp_locl.h */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * 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). + * + */ + +/* Macros to code block cipher wrappers */ + +/* Wrapper functions for each cipher mode */ + +#define BLOCK_CIPHER_ecb_loop() \ + unsigned int i; \ + if(inl < 8) return 1;\ + inl -= 8; \ + for(i=0; i <= inl; i+=8) \ + +#define BLOCK_CIPHER_func_ecb(cname, cprefix, kname) \ +static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ +{\ + BLOCK_CIPHER_ecb_loop() \ + cprefix##_ecb_encrypt(in + i, out + i, &ctx->c.kname, ctx->encrypt);\ + return 1;\ +} + +#define BLOCK_CIPHER_func_ofb(cname, cprefix, kname) \ +static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ +{\ + cprefix##_ofb64_encrypt(in, out, (long)inl, &ctx->c.kname, ctx->iv, &ctx->num);\ + return 1;\ +} + +#define BLOCK_CIPHER_func_cbc(cname, cprefix, kname) \ +static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ +{\ + cprefix##_cbc_encrypt(in, out, (long)inl, &ctx->c.kname, ctx->iv, ctx->encrypt);\ + return 1;\ +} + +#define BLOCK_CIPHER_func_cfb(cname, cprefix, kname) \ +static int cname##_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ +{\ + cprefix##_cfb64_encrypt(in, out, (long)inl, &ctx->c.kname, ctx->iv, &ctx->num, ctx->encrypt);\ + return 1;\ +} + +#define BLOCK_CIPHER_all_funcs(cname, cprefix, kname) \ + BLOCK_CIPHER_func_cbc(cname, cprefix, kname) \ + BLOCK_CIPHER_func_cfb(cname, cprefix, kname) \ + BLOCK_CIPHER_func_ecb(cname, cprefix, kname) \ + BLOCK_CIPHER_func_ofb(cname, cprefix, kname) + +#define BLOCK_CIPHER_defs(cname, kstruct, \ + nid, block_size, key_len, iv_len, flags,\ + init_key, cleanup, set_asn1, get_asn1, ctrl)\ +static EVP_CIPHER cname##_cbc = {\ + nid##_cbc, block_size, key_len, iv_len, \ + flags | EVP_CIPH_CBC_MODE,\ + init_key,\ + cname##_cbc_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl, \ + NULL \ +};\ +EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\ +static EVP_CIPHER cname##_cfb = {\ + nid##_cfb64, 1, key_len, iv_len, \ + flags | EVP_CIPH_CFB_MODE,\ + init_key,\ + cname##_cfb_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl,\ + NULL \ +};\ +EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\ +static EVP_CIPHER cname##_ofb = {\ + nid##_ofb64, 1, key_len, iv_len, \ + flags | EVP_CIPH_OFB_MODE,\ + init_key,\ + cname##_ofb_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl,\ + NULL \ +};\ +EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\ +static EVP_CIPHER cname##_ecb = {\ + nid##_ecb, block_size, key_len, iv_len, \ + flags | EVP_CIPH_ECB_MODE,\ + init_key,\ + cname##_ecb_cipher,\ + cleanup,\ + sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\ + sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\ + set_asn1, get_asn1,\ + ctrl,\ + NULL \ +};\ +EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; } + + + +#define IMPLEMENT_BLOCK_CIPHER(cname, kname, cprefix, kstruct, \ + nid, block_size, key_len, iv_len, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) \ + BLOCK_CIPHER_all_funcs(cname, cprefix, kname) \ + BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, flags,\ + init_key, cleanup, set_asn1, get_asn1, ctrl) + diff --git a/src/lib/libcrypto/evp/evp_pbe.c b/src/lib/libcrypto/evp/evp_pbe.c new file mode 100644 index 0000000000..353c3ad667 --- /dev/null +++ b/src/lib/libcrypto/evp/evp_pbe.c @@ -0,0 +1,134 @@ +/* evp_pbe.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 +#include +#include "cryptlib.h" + +/* Password based encryption (PBE) functions */ + +static STACK *pbe_algs; + +/* Setup a cipher context from a PBE algorithm */ + +typedef struct { +int pbe_nid; +EVP_CIPHER *cipher; +EVP_MD *md; +EVP_PBE_KEYGEN *keygen; +} EVP_PBE_CTL; + +int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) +{ + + EVP_PBE_CTL *pbetmp, pbelu; + int i; + pbelu.pbe_nid = OBJ_obj2nid(pbe_obj); + if (pbelu.pbe_nid != NID_undef) i = sk_find(pbe_algs, (char *)&pbelu); + else i = -1; + + if (i == -1) { + char obj_tmp[80]; + EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_PBE_ALGORITHM); + if (!pbe_obj) strcpy (obj_tmp, "NULL"); + else i2t_ASN1_OBJECT(obj_tmp, 80, pbe_obj); + ERR_add_error_data(2, "TYPE=", obj_tmp); + return 0; + } + if (passlen == -1) passlen = strlen(pass); + pbetmp = (EVP_PBE_CTL *)sk_value (pbe_algs, i); + i = (*pbetmp->keygen)(ctx, pass, passlen, param, pbetmp->cipher, + pbetmp->md, en_de); + if (!i) { + EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_KEYGEN_FAILURE); + return 0; + } + return 1; +} + +static int pbe_cmp (EVP_PBE_CTL **pbe1, EVP_PBE_CTL **pbe2) +{ + return ((*pbe1)->pbe_nid - (*pbe2)->pbe_nid); +} + +/* Add a PBE algorithm */ + +int EVP_PBE_alg_add (int nid, EVP_CIPHER *cipher, EVP_MD *md, + EVP_PBE_KEYGEN *keygen) +{ + EVP_PBE_CTL *pbe_tmp; + if (!pbe_algs) pbe_algs = sk_new (pbe_cmp); + if (!(pbe_tmp = (EVP_PBE_CTL*) Malloc (sizeof(EVP_PBE_CTL)))) { + EVPerr(EVP_F_EVP_PBE_ALG_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + pbe_tmp->pbe_nid = nid; + pbe_tmp->cipher = cipher; + pbe_tmp->md = md; + pbe_tmp->keygen = keygen; + sk_push (pbe_algs, (char *)pbe_tmp); + return 1; +} + +void EVP_PBE_cleanup(void) +{ + sk_pop_free(pbe_algs, FreeFunc); + pbe_algs = NULL; +} diff --git a/src/lib/libcrypto/evp/evp_pkey.c b/src/lib/libcrypto/evp/evp_pkey.c new file mode 100644 index 0000000000..421e452db1 --- /dev/null +++ b/src/lib/libcrypto/evp/evp_pkey.c @@ -0,0 +1,298 @@ +/* evp_pkey.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 +#include "cryptlib.h" +#include +#include + +/* Extract a private key from a PKCS8 structure */ + +EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8) +{ + EVP_PKEY *pkey; +#ifndef NO_RSA + RSA *rsa; +#endif +#ifndef NO_DSA + DSA *dsa; + ASN1_INTEGER *dsapriv; + STACK *ndsa; + BN_CTX *ctx; + int plen; +#endif + X509_ALGOR *a; + unsigned char *p; + int pkeylen; + char obj_tmp[80]; + + switch (p8->broken) { + case PKCS8_OK: + p = p8->pkey->value.octet_string->data; + pkeylen = p8->pkey->value.octet_string->length; + break; + + case PKCS8_NO_OCTET: + p = p8->pkey->value.sequence->data; + pkeylen = p8->pkey->value.sequence->length; + break; + + default: + EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); + return NULL; + break; + } + if (!(pkey = EVP_PKEY_new())) { + EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); + return NULL; + } + a = p8->pkeyalg; + switch (OBJ_obj2nid(a->algorithm)) + { +#ifndef NO_RSA + case NID_rsaEncryption: + if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pkeylen))) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + return NULL; + } + EVP_PKEY_assign_RSA (pkey, rsa); + break; +#endif +#ifndef NO_DSA + case NID_dsa: + /* PKCS#8 DSA is weird: you just get a private key integer + * and parameters in the AlgorithmIdentifier the pubkey must + * be recalculated. + */ + + /* Check for broken Netscape Database DSA PKCS#8, UGH! */ + if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { + if(!(ndsa = ASN1_seq_unpack(p, pkeylen, + (char *(*)())d2i_ASN1_INTEGER, + ASN1_STRING_free))) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + return NULL; + } + if(sk_num(ndsa) != 2 ) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + sk_pop_free(ndsa, ASN1_STRING_free); + return NULL; + } + dsapriv = (ASN1_INTEGER *) sk_pop(ndsa); + sk_pop_free(ndsa, ASN1_STRING_free); + } else if (!(dsapriv=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + return NULL; + } + /* Retrieve parameters */ + if (a->parameter->type != V_ASN1_SEQUENCE) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_NO_DSA_PARAMETERS); + return NULL; + } + p = a->parameter->value.sequence->data; + plen = a->parameter->value.sequence->length; + if (!(dsa = d2i_DSAparams (NULL, &p, plen))) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + return NULL; + } + /* We have parameters now set private key */ + if (!(dsa->priv_key = ASN1_INTEGER_to_BN(dsapriv, NULL))) { + EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); + DSA_free (dsa); + return NULL; + } + /* Calculate public key (ouch!) */ + if (!(dsa->pub_key = BN_new())) { + EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); + DSA_free (dsa); + return NULL; + } + if (!(ctx = BN_CTX_new())) { + EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); + DSA_free (dsa); + return NULL; + } + + if (!BN_mod_exp(dsa->pub_key, dsa->g, + dsa->priv_key, dsa->p, ctx)) { + + EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); + BN_CTX_free (ctx); + DSA_free (dsa); + return NULL; + } + + EVP_PKEY_assign_DSA (pkey, dsa); + BN_CTX_free (ctx); + break; +#endif + default: + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); + if (!a->algorithm) strcpy (obj_tmp, "NULL"); + else i2t_ASN1_OBJECT(obj_tmp, 80, a->algorithm); + ERR_add_error_data(2, "TYPE=", obj_tmp); + EVP_PKEY_free (pkey); + return NULL; + } + return pkey; +} + +/* Turn a private key into a PKCS8 structure */ + +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) +{ + PKCS8_PRIV_KEY_INFO *p8; +#ifndef NO_DSA + ASN1_INTEGER *dpkey; + unsigned char *p, *q; + int len; +#endif + if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + return NULL; + } + ASN1_INTEGER_set (p8->version, 0); + if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + PKCS8_PRIV_KEY_INFO_free (p8); + return NULL; + } + switch (EVP_PKEY_type(pkey->type)) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + + p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption); + p8->pkeyalg->parameter->type = V_ASN1_NULL; + if (!ASN1_pack_string ((char *)pkey, i2d_PrivateKey, + &p8->pkey->value.octet_string)) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + PKCS8_PRIV_KEY_INFO_free (p8); + return NULL; + } + break; +#endif +#ifndef NO_DSA + case EVP_PKEY_DSA: + p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa); + + /* get paramaters and place in AlgorithmIdentifier */ + len = i2d_DSAparams (pkey->pkey.dsa, NULL); + if (!(p = Malloc(len))) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + PKCS8_PRIV_KEY_INFO_free (p8); + return NULL; + } + q = p; + i2d_DSAparams (pkey->pkey.dsa, &q); + p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; + p8->pkeyalg->parameter->value.sequence = ASN1_STRING_new(); + ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, len); + Free(p); + /* Get private key into an integer and pack */ + if (!(dpkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); + PKCS8_PRIV_KEY_INFO_free (p8); + return NULL; + } + + if (!ASN1_pack_string((char *)dpkey, i2d_ASN1_INTEGER, + &p8->pkey->value.octet_string)) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + ASN1_INTEGER_free (dpkey); + PKCS8_PRIV_KEY_INFO_free (p8); + return NULL; + } + ASN1_INTEGER_free (dpkey); + break; +#endif + default: + EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); + PKCS8_PRIV_KEY_INFO_free (p8); + return NULL; + } + p8->pkey->type = V_ASN1_OCTET_STRING; + RAND_seed (p8->pkey->value.octet_string->data, + p8->pkey->value.octet_string->length); + return p8; +} + +PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken) +{ + switch (broken) { + + case PKCS8_OK: + p8->broken = PKCS8_OK; + return p8; + break; + + case PKCS8_NO_OCTET: + p8->broken = PKCS8_NO_OCTET; + p8->pkey->type = V_ASN1_SEQUENCE; + return p8; + break; + + default: + EVPerr(EVP_F_EVP_PKCS8_SET_BROKEN,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); + return NULL; + break; + + } +} + + diff --git a/src/lib/libcrypto/evp/m_md4.c b/src/lib/libcrypto/evp/m_md4.c new file mode 100644 index 0000000000..6a24ceb86d --- /dev/null +++ b/src/lib/libcrypto/evp/m_md4.c @@ -0,0 +1,83 @@ +/* crypto/evp/m_md4.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 NO_MD4 +#include +#include "cryptlib.h" +#include +#include +#include + +static EVP_MD md4_md= + { + NID_md4, + 0, + MD4_DIGEST_LENGTH, + MD4_Init, + MD4_Update, + MD4_Final, + EVP_PKEY_RSA_method, + MD4_CBLOCK, + sizeof(EVP_MD *)+sizeof(MD4_CTX), + }; + +EVP_MD *EVP_md4(void) + { + return(&md4_md); + } +#endif diff --git a/src/lib/libcrypto/evp/p5_crpt.c b/src/lib/libcrypto/evp/p5_crpt.c new file mode 100644 index 0000000000..e3dae52d4d --- /dev/null +++ b/src/lib/libcrypto/evp/p5_crpt.c @@ -0,0 +1,146 @@ +/* p5_crpt.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 +#include +#include +#include "cryptlib.h" + +/* PKCS#5 v1.5 compatible PBE functions: see PKCS#5 v2.0 for more info. + */ + +void PKCS5_PBE_add(void) +{ +#ifndef NO_DES +# ifndef NO_MD5 +EVP_PBE_alg_add(NID_pbeWithMD5AndDES_CBC, EVP_des_cbc(), EVP_md5(), + PKCS5_PBE_keyivgen); +# endif +# ifndef NO_MD2 +EVP_PBE_alg_add(NID_pbeWithMD2AndDES_CBC, EVP_des_cbc(), EVP_md2(), + PKCS5_PBE_keyivgen); +# endif +# ifndef NO_SHA +EVP_PBE_alg_add(NID_pbeWithSHA1AndDES_CBC, EVP_des_cbc(), EVP_sha1(), + PKCS5_PBE_keyivgen); +# endif +#endif +#ifndef NO_RC2 +# ifndef NO_MD5 +EVP_PBE_alg_add(NID_pbeWithMD5AndRC2_CBC, EVP_rc2_64_cbc(), EVP_md5(), + PKCS5_PBE_keyivgen); +# endif +# ifndef NO_MD2 +EVP_PBE_alg_add(NID_pbeWithMD2AndRC2_CBC, EVP_rc2_64_cbc(), EVP_md2(), + PKCS5_PBE_keyivgen); +# endif +# ifndef NO_SHA +EVP_PBE_alg_add(NID_pbeWithSHA1AndRC2_CBC, EVP_rc2_64_cbc(), EVP_sha1(), + PKCS5_PBE_keyivgen); +# endif +#endif +#ifndef NO_HMAC +EVP_PBE_alg_add(NID_pbes2, NULL, NULL, PKCS5_v2_PBE_keyivgen); +#endif +} + +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md, + int en_de) +{ + EVP_MD_CTX ctx; + unsigned char md_tmp[EVP_MAX_MD_SIZE]; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + int i; + PBEPARAM *pbe; + int saltlen, iter; + unsigned char *salt, *pbuf; + + /* Extract useful info from parameter */ + pbuf = param->value.sequence->data; + if (!param || (param->type != V_ASN1_SEQUENCE) || + !(pbe = d2i_PBEPARAM (NULL, &pbuf, param->value.sequence->length))) { + EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) iter = 1; + else iter = ASN1_INTEGER_get (pbe->iter); + salt = pbe->salt->data; + saltlen = pbe->salt->length; + + EVP_DigestInit (&ctx, md); + EVP_DigestUpdate (&ctx, pass, passlen); + EVP_DigestUpdate (&ctx, salt, saltlen); + PBEPARAM_free(pbe); + EVP_DigestFinal (&ctx, md_tmp, NULL); + for (i = 1; i < iter; i++) { + EVP_DigestInit(&ctx, md); + EVP_DigestUpdate(&ctx, md_tmp, EVP_MD_size(md)); + EVP_DigestFinal (&ctx, md_tmp, NULL); + } + memcpy (key, md_tmp, EVP_CIPHER_key_length(cipher)); + memcpy (iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), + EVP_CIPHER_iv_length(cipher)); + EVP_CipherInit(cctx, cipher, key, iv, en_de); + memset(md_tmp, 0, EVP_MAX_MD_SIZE); + memset(key, 0, EVP_MAX_KEY_LENGTH); + memset(iv, 0, EVP_MAX_IV_LENGTH); + return 1; +} diff --git a/src/lib/libcrypto/evp/p5_crpt2.c b/src/lib/libcrypto/evp/p5_crpt2.c new file mode 100644 index 0000000000..27a2c518be --- /dev/null +++ b/src/lib/libcrypto/evp/p5_crpt2.c @@ -0,0 +1,247 @@ +/* p5_crpt2.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). + * + */ +#if !defined(NO_HMAC) && !defined(NO_SHA) +#include +#include +#include +#include +#include +#include "cryptlib.h" + +/* set this to print out info about the keygen algorithm */ +/* #define DEBUG_PKCS5V2 */ + +#ifdef DEBUG_PKCS5V2 + static void h__dump (const unsigned char *p, int len); +#endif + +/* This is an implementation of PKCS#5 v2.0 password based encryption key + * derivation function PBKDF2 using the only currently defined function HMAC + * with SHA1. Verified against test vectors posted by Peter Gutmann + * to the PKCS-TNG mailing list. + */ + +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out) +{ + unsigned char digtmp[SHA_DIGEST_LENGTH], *p, itmp[4]; + int cplen, j, k, tkeylen; + unsigned long i = 1; + HMAC_CTX hctx; + p = out; + tkeylen = keylen; + if(passlen == -1) passlen = strlen(pass); + while(tkeylen) { + if(tkeylen > SHA_DIGEST_LENGTH) cplen = SHA_DIGEST_LENGTH; + else cplen = tkeylen; + /* We are unlikely to ever use more than 256 blocks (5120 bits!) + * but just in case... + */ + itmp[0] = (unsigned char)((i >> 24) & 0xff); + itmp[1] = (unsigned char)((i >> 16) & 0xff); + itmp[2] = (unsigned char)((i >> 8) & 0xff); + itmp[3] = (unsigned char)(i & 0xff); + HMAC_Init(&hctx, pass, passlen, EVP_sha1()); + HMAC_Update(&hctx, salt, saltlen); + HMAC_Update(&hctx, itmp, 4); + HMAC_Final(&hctx, digtmp, NULL); + memcpy(p, digtmp, cplen); + for(j = 1; j < iter; j++) { + HMAC(EVP_sha1(), pass, passlen, + digtmp, SHA_DIGEST_LENGTH, digtmp, NULL); + for(k = 0; k < cplen; k++) p[k] ^= digtmp[k]; + } + tkeylen-= cplen; + i++; + p+= cplen; + } + HMAC_cleanup(&hctx); +#ifdef DEBUG_PKCS5V2 + fprintf(stderr, "Password:\n"); + h__dump (pass, passlen); + fprintf(stderr, "Salt:\n"); + h__dump (salt, saltlen); + fprintf(stderr, "Iteration count %d\n", iter); + fprintf(stderr, "Key:\n"); + h__dump (out, keylen); +#endif + return 1; +} + +#ifdef DO_TEST +main() +{ + unsigned char out[4]; + unsigned char salt[] = {0x12, 0x34, 0x56, 0x78}; + PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out); + fprintf(stderr, "Out %02X %02X %02X %02X\n", + out[0], out[1], out[2], out[3]); +} + +#endif + +/* Now the key derivation function itself. This is a bit evil because + * it has to check the ASN1 parameters are valid: and there are quite a + * few of them... + */ + +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *c, EVP_MD *md, + int en_de) +{ + unsigned char *pbuf, *salt, key[EVP_MAX_KEY_LENGTH]; + int saltlen, keylen, iter, plen; + PBE2PARAM *pbe2 = NULL; + const EVP_CIPHER *cipher; + PBKDF2PARAM *kdf = NULL; + + pbuf = param->value.sequence->data; + plen = param->value.sequence->length; + if(!param || (param->type != V_ASN1_SEQUENCE) || + !(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); + return 0; + } + + /* See if we recognise the key derivation function */ + + if(OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, + EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); + goto err; + } + + /* lets see if we recognise the encryption algorithm. + */ + + cipher = EVP_get_cipherbyname( + OBJ_nid2sn(OBJ_obj2nid(pbe2->encryption->algorithm))); + + if(!cipher) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, + EVP_R_UNSUPPORTED_CIPHER); + goto err; + } + + /* Fixup cipher based on AlgorithmIdentifier */ + EVP_CipherInit(ctx, cipher, NULL, NULL, en_de); + if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, + EVP_R_CIPHER_PARAMETER_ERROR); + goto err; + } + keylen = EVP_CIPHER_CTX_key_length(ctx); + + /* Now decode key derivation function */ + + pbuf = pbe2->keyfunc->parameter->value.sequence->data; + plen = pbe2->keyfunc->parameter->value.sequence->length; + if(!pbe2->keyfunc->parameter || + (pbe2->keyfunc->parameter->type != V_ASN1_SEQUENCE) || + !(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); + goto err; + } + + PBE2PARAM_free(pbe2); + pbe2 = NULL; + + /* Now check the parameters of the kdf */ + + if(kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != keylen)){ + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, + EVP_R_UNSUPPORTED_KEYLENGTH); + goto err; + } + + if(kdf->prf && (OBJ_obj2nid(kdf->prf->algorithm) != NID_hmacWithSHA1)) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); + goto err; + } + + if(kdf->salt->type != V_ASN1_OCTET_STRING) { + EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, + EVP_R_UNSUPPORTED_SALT_TYPE); + goto err; + } + + /* it seems that its all OK */ + salt = kdf->salt->value.octet_string->data; + saltlen = kdf->salt->value.octet_string->length; + iter = ASN1_INTEGER_get(kdf->iter); + PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, salt, saltlen, iter, keylen, key); + EVP_CipherInit(ctx, NULL, key, NULL, en_de); + memset(key, 0, keylen); + PBKDF2PARAM_free(kdf); + return 1; + + err: + PBE2PARAM_free(pbe2); + PBKDF2PARAM_free(kdf); + return 0; +} + +#ifdef DEBUG_PKCS5V2 +static void h__dump (const unsigned char *p, int len) +{ + for (; len --; p++) fprintf(stderr, "%02X ", *p); + fprintf(stderr, "\n"); +} +#endif +#endif diff --git a/src/lib/libcrypto/idea/idea.h b/src/lib/libcrypto/idea/idea.h new file mode 100644 index 0000000000..ae32f5692e --- /dev/null +++ b/src/lib/libcrypto/idea/idea.h @@ -0,0 +1,99 @@ +/* crypto/idea/idea.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_IDEA_H +#define HEADER_IDEA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_IDEA +#error IDEA is disabled. +#endif + +#define IDEA_ENCRYPT 1 +#define IDEA_DECRYPT 0 + +#include /* IDEA_INT */ +#define IDEA_BLOCK 8 +#define IDEA_KEY_LENGTH 16 + +typedef struct idea_key_st + { + IDEA_INT data[9][6]; + } IDEA_KEY_SCHEDULE; + +const char *idea_options(void); +void idea_ecb_encrypt(unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks); +void idea_set_encrypt_key(unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk); +void idea_cbc_encrypt(unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc); +void idea_cfb64_encrypt(unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num,int enc); +void idea_ofb64_encrypt(unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num); +void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/libcrypto/krb5/krb5_asn.c b/src/lib/libcrypto/krb5/krb5_asn.c new file mode 100644 index 0000000000..1fb741d2a0 --- /dev/null +++ b/src/lib/libcrypto/krb5/krb5_asn.c @@ -0,0 +1,167 @@ +/* krb5_asn.c */ +/* Written by Vern Staats for the OpenSSL project, +** using ocsp/{*.h,*asn*.c} as a starting point +*/ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include + + +ASN1_SEQUENCE(KRB5_ENCDATA) = { + ASN1_EXP(KRB5_ENCDATA, etype, ASN1_INTEGER, 0), + ASN1_EXP_OPT(KRB5_ENCDATA, kvno, ASN1_INTEGER, 1), + ASN1_EXP(KRB5_ENCDATA, cipher, ASN1_OCTET_STRING,2) +} ASN1_SEQUENCE_END(KRB5_ENCDATA) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_ENCDATA) + + +ASN1_SEQUENCE(KRB5_PRINCNAME) = { + ASN1_EXP(KRB5_PRINCNAME, nametype, ASN1_INTEGER, 0), + ASN1_EXP_SEQUENCE_OF(KRB5_PRINCNAME, namestring, ASN1_GENERALSTRING, 1) +} ASN1_SEQUENCE_END(KRB5_PRINCNAME) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_PRINCNAME) + + +/* [APPLICATION 1] = 0x61 */ +ASN1_SEQUENCE(KRB5_TKTBODY) = { + ASN1_EXP(KRB5_TKTBODY, tktvno, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_TKTBODY, realm, ASN1_GENERALSTRING, 1), + ASN1_EXP(KRB5_TKTBODY, sname, KRB5_PRINCNAME, 2), + ASN1_EXP(KRB5_TKTBODY, encdata, KRB5_ENCDATA, 3) +} ASN1_SEQUENCE_END(KRB5_TKTBODY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_TKTBODY) + + +ASN1_ITEM_TEMPLATE(KRB5_TICKET) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION, 1, + KRB5_TICKET, KRB5_TKTBODY) +ASN1_ITEM_TEMPLATE_END(KRB5_TICKET) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_TICKET) + + +/* [APPLICATION 14] = 0x6e */ +ASN1_SEQUENCE(KRB5_APREQBODY) = { + ASN1_EXP(KRB5_APREQBODY, pvno, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_APREQBODY, msgtype, ASN1_INTEGER, 1), + ASN1_EXP(KRB5_APREQBODY, apoptions, ASN1_BIT_STRING, 2), + ASN1_EXP(KRB5_APREQBODY, ticket, KRB5_TICKET, 3), + ASN1_EXP(KRB5_APREQBODY, authenticator, KRB5_ENCDATA, 4), +} ASN1_SEQUENCE_END(KRB5_APREQBODY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_APREQBODY) + +ASN1_ITEM_TEMPLATE(KRB5_APREQ) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION, 14, + KRB5_APREQ, KRB5_APREQBODY) +ASN1_ITEM_TEMPLATE_END(KRB5_APREQ) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_APREQ) + + +/* Authenticator stuff */ + +ASN1_SEQUENCE(KRB5_CHECKSUM) = { + ASN1_EXP(KRB5_CHECKSUM, ctype, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_CHECKSUM, checksum, ASN1_OCTET_STRING,1) +} ASN1_SEQUENCE_END(KRB5_CHECKSUM) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_CHECKSUM) + + +ASN1_SEQUENCE(KRB5_ENCKEY) = { + ASN1_EXP(KRB5_ENCKEY, ktype, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_ENCKEY, keyvalue, ASN1_OCTET_STRING,1) +} ASN1_SEQUENCE_END(KRB5_ENCKEY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_ENCKEY) + + +/* SEQ OF SEQ; see ASN1_EXP_SEQUENCE_OF_OPT() below */ +ASN1_SEQUENCE(KRB5_AUTHDATA) = { + ASN1_EXP(KRB5_AUTHDATA, adtype, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_AUTHDATA, addata, ASN1_OCTET_STRING,1) +} ASN1_SEQUENCE_END(KRB5_AUTHDATA) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_AUTHDATA) + + +/* [APPLICATION 2] = 0x62 */ +ASN1_SEQUENCE(KRB5_AUTHENTBODY) = { + ASN1_EXP(KRB5_AUTHENTBODY, avno, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_AUTHENTBODY, crealm, ASN1_GENERALSTRING, 1), + ASN1_EXP(KRB5_AUTHENTBODY, cname, KRB5_PRINCNAME, 2), + ASN1_EXP_OPT(KRB5_AUTHENTBODY, cksum, KRB5_CHECKSUM, 3), + ASN1_EXP(KRB5_AUTHENTBODY, cusec, ASN1_INTEGER, 4), + ASN1_EXP(KRB5_AUTHENTBODY, ctime, ASN1_GENERALIZEDTIME, 5), + ASN1_EXP_OPT(KRB5_AUTHENTBODY, subkey, KRB5_ENCKEY, 6), + ASN1_EXP_OPT(KRB5_AUTHENTBODY, seqnum, ASN1_INTEGER, 7), + ASN1_EXP_SEQUENCE_OF_OPT + (KRB5_AUTHENTBODY, authorization, KRB5_AUTHDATA, 8), +} ASN1_SEQUENCE_END(KRB5_AUTHENTBODY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_AUTHENTBODY) + +ASN1_ITEM_TEMPLATE(KRB5_AUTHENT) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION, 2, + KRB5_AUTHENT, KRB5_AUTHENTBODY) +ASN1_ITEM_TEMPLATE_END(KRB5_AUTHENT) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_AUTHENT) + diff --git a/src/lib/libcrypto/krb5/krb5_asn.h b/src/lib/libcrypto/krb5/krb5_asn.h new file mode 100644 index 0000000000..3329477b07 --- /dev/null +++ b/src/lib/libcrypto/krb5/krb5_asn.h @@ -0,0 +1,256 @@ +/* krb5_asn.h */ +/* Written by Vern Staats for the OpenSSL project, +** using ocsp/{*.h,*asn*.c} as a starting point +*/ + +/* ==================================================================== + * 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_KRB5_ASN_H +#define HEADER_KRB5_ASN_H + +/* +#include +*/ +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ASN.1 from Kerberos RFC 1510 +*/ + +/* EncryptedData ::= SEQUENCE { +** etype[0] INTEGER, -- EncryptionType +** kvno[1] INTEGER OPTIONAL, +** cipher[2] OCTET STRING -- ciphertext +** } +*/ +typedef struct krb5_encdata_st + { + ASN1_INTEGER *etype; + ASN1_INTEGER *kvno; + ASN1_OCTET_STRING *cipher; + } KRB5_ENCDATA; + +DECLARE_STACK_OF(KRB5_ENCDATA) + +/* PrincipalName ::= SEQUENCE { +** name-type[0] INTEGER, +** name-string[1] SEQUENCE OF GeneralString +** } +*/ +typedef struct krb5_princname_st + { + ASN1_INTEGER *nametype; + STACK_OF(ASN1_GENERALSTRING) *namestring; + } KRB5_PRINCNAME; + +DECLARE_STACK_OF(KRB5_PRINCNAME) + + +/* Ticket ::= [APPLICATION 1] SEQUENCE { +** tkt-vno[0] INTEGER, +** realm[1] Realm, +** sname[2] PrincipalName, +** enc-part[3] EncryptedData +** } +*/ +typedef struct krb5_tktbody_st + { + ASN1_INTEGER *tktvno; + ASN1_GENERALSTRING *realm; + KRB5_PRINCNAME *sname; + KRB5_ENCDATA *encdata; + } KRB5_TKTBODY; + +typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET; +DECLARE_STACK_OF(KRB5_TKTBODY) + + +/* AP-REQ ::= [APPLICATION 14] SEQUENCE { +** pvno[0] INTEGER, +** msg-type[1] INTEGER, +** ap-options[2] APOptions, +** ticket[3] Ticket, +** authenticator[4] EncryptedData +** } +** +** APOptions ::= BIT STRING { +** reserved(0), use-session-key(1), mutual-required(2) } +*/ +typedef struct krb5_ap_req_st + { + ASN1_INTEGER *pvno; + ASN1_INTEGER *msgtype; + ASN1_BIT_STRING *apoptions; + KRB5_TICKET *ticket; + KRB5_ENCDATA *authenticator; + } KRB5_APREQBODY; + +typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ; +DECLARE_STACK_OF(KRB5_APREQBODY) + + +/* Authenticator Stuff */ + + +/* Checksum ::= SEQUENCE { +** cksumtype[0] INTEGER, +** checksum[1] OCTET STRING +** } +*/ +typedef struct krb5_checksum_st + { + ASN1_INTEGER *ctype; + ASN1_OCTET_STRING *checksum; + } KRB5_CHECKSUM; + +DECLARE_STACK_OF(KRB5_CHECKSUM) + + +/* EncryptionKey ::= SEQUENCE { +** keytype[0] INTEGER, +** keyvalue[1] OCTET STRING +** } +*/ +typedef struct krb5_encryptionkey_st + { + ASN1_INTEGER *ktype; + ASN1_OCTET_STRING *keyvalue; + } KRB5_ENCKEY; + +DECLARE_STACK_OF(KRB5_ENCKEY) + + +/* AuthorizationData ::= SEQUENCE OF SEQUENCE { +** ad-type[0] INTEGER, +** ad-data[1] OCTET STRING +** } +*/ +typedef struct krb5_authorization_st + { + ASN1_INTEGER *adtype; + ASN1_OCTET_STRING *addata; + } KRB5_AUTHDATA; + +DECLARE_STACK_OF(KRB5_AUTHDATA) + + +/* -- Unencrypted authenticator +** Authenticator ::= [APPLICATION 2] SEQUENCE { +** authenticator-vno[0] INTEGER, +** crealm[1] Realm, +** cname[2] PrincipalName, +** cksum[3] Checksum OPTIONAL, +** cusec[4] INTEGER, +** ctime[5] KerberosTime, +** subkey[6] EncryptionKey OPTIONAL, +** seq-number[7] INTEGER OPTIONAL, +** authorization-data[8] AuthorizationData OPTIONAL +** } +*/ +typedef struct krb5_authenticator_st + { + ASN1_INTEGER *avno; + ASN1_GENERALSTRING *crealm; + KRB5_PRINCNAME *cname; + KRB5_CHECKSUM *cksum; + ASN1_INTEGER *cusec; + ASN1_GENERALIZEDTIME *ctime; + KRB5_ENCKEY *subkey; + ASN1_INTEGER *seqnum; + KRB5_AUTHDATA *authorization; + } KRB5_AUTHENTBODY; + +typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT; +DECLARE_STACK_OF(KRB5_AUTHENTBODY) + + +/* DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) = +** type *name##_new(void); +** void name##_free(type *a); +** DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) = +** DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) = +** type *d2i_##name(type **a, unsigned char **in, long len); +** int i2d_##name(type *a, unsigned char **out); +** DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it +*/ + +DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA) +DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME) +DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_TICKET) +DECLARE_ASN1_FUNCTIONS(KRB5_APREQ) + +DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM) +DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT) + + +/* 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. + */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/md32_common.h b/src/lib/libcrypto/md32_common.h new file mode 100644 index 0000000000..2b91f9eef2 --- /dev/null +++ b/src/lib/libcrypto/md32_common.h @@ -0,0 +1,594 @@ +/* crypto/md32_common.h */ +/* ==================================================================== + * 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). + * + */ + +/* + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at lest 32 bit wide, if it's wider, then + * HASH_LONG_LOG2 *has to* be defined along + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * HASH_LONG data[HASH_LBLOCK]; + * int num; + * ... + * } HASH_CTX; + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_HOST_ORDER + * name of "block" function treating *aligned* input message + * in host byte order, implemented externally. + * HASH_BLOCK_DATA_ORDER + * name of "block" function treating *unaligned* input message + * in original (data) byte order, implemented externally (it + * actually is optional if data and host are of the same + * "endianess"). + * + * Optional macros: + * + * B_ENDIAN or L_ENDIAN + * defines host byte-order. + * HASH_LONG_LOG2 + * defaults to 2 if not states otherwise. + * HASH_LBLOCK + * assumed to be HASH_CBLOCK/4 if not stated otherwise. + * HASH_BLOCK_DATA_ORDER_ALIGNED + * alternative "block" function capable of treating + * aligned input message in original (data) order, + * implemented externally. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_LONG_LOG2 MD5_LONG_LOG2 + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_LBLOCK MD5_LBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_HOST_ORDER md5_block_host_order + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + * + * + */ + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +#error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +#error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +#error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +#error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +#error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +#error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_HOST_ORDER +#error "HASH_BLOCK_HOST_ORDER must be defined!" +#endif + +#if 0 +/* + * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED + * isn't defined. + */ +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#ifndef HASH_LBLOCK +#define HASH_LBLOCK (HASH_CBLOCK/4) +#endif + +#ifndef HASH_LONG_LOG2 +#define HASH_LONG_LOG2 2 +#endif + +/* + * Engage compiler specific rotate intrinsic function if available. + */ +#undef ROTATE +#ifndef PEDANTIC +# if defined(_MSC_VER) +# define ROTATE(a,n) _lrotl(a,n) +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) + /* + * Some GNU C inline assembler templates. Note that these are + * rotates by *constant* number of bits! But that's exactly + * what we need here... + * + * + */ +# if defined(__i386) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm volatile ( \ + "roll %1,%0" \ + : "=r"(ret) \ + : "I"(n), "0"(a) \ + : "cc"); \ + ret; \ + }) +# elif defined(__powerpc) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm volatile ( \ + "rlwinm %0,%1,%2,0,31" \ + : "=r"(ret) \ + : "r"(a), "I"(n)); \ + ret; \ + }) +# endif +# endif + +/* + * Engage compiler specific "fetch in reverse byte order" + * intrinsic function if available. + */ +# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) + /* some GNU C inline assembler templates by */ +# if defined(__i386) && !defined(I386_ONLY) +# define BE_FETCH32(a) ({ register unsigned int l=(a);\ + asm volatile ( \ + "bswapl %0" \ + : "=r"(l) : "0"(l)); \ + l; \ + }) +# elif defined(__powerpc) +# define LE_FETCH32(a) ({ register unsigned int l; \ + asm volatile ( \ + "lwbrx %0,0,%1" \ + : "=r"(l) \ + : "r"(a)); \ + l; \ + }) + +# elif defined(__sparc) && defined(ULTRASPARC) +# define LE_FETCH32(a) ({ register unsigned int l; \ + asm volatile ( \ + "lda [%1]#ASI_PRIMARY_LITTLE,%0"\ + : "=r"(l) \ + : "r"(a)); \ + l; \ + }) +# endif +# endif +#endif /* PEDANTIC */ + +#if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */ +/* A nice byte order reversal from Wei Dai */ +#ifdef ROTATE +/* 5 instructions with rotate instruction, else 9 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \ + ) +#else +/* 6 instructions with rotate instruction, else 8 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \ + ROTATE(l,16) \ + ) +/* + * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... + * It's rewritten as above for two reasons: + * - RISCs aren't good at long constants and have to explicitely + * compose 'em with several (well, usually 2) instructions in a + * register before performing the actual operation and (as you + * already realized:-) having same constant should inspire the + * compiler to permanently allocate the only register for it; + * - most modern CPUs have two ALUs, but usually only one has + * circuitry for shifts:-( this minor tweak inspires compiler + * to schedule shift instructions in a better way... + * + * + */ +#endif +#endif + +#ifndef ROTATE +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* + * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED + * and HASH_BLOCK_HOST_ORDER ought to be the same if input data + * and host are of the same "endianess". It's possible to mask + * this with blank #define HASH_BLOCK_DATA_ORDER though... + * + * + */ +#if defined(B_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# ifndef HOST_FETCH32 +# ifdef LE_FETCH32 +# define HOST_FETCH32(p,l) LE_FETCH32(p) +# elif defined(REVERSE_FETCH32) +# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) +# endif +# endif +# endif +#elif defined(L_ENDIAN) +# if defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# elif defined(DATA_ORDER_IS_BIG_ENDIAN) +# ifndef HOST_FETCH32 +# ifdef BE_FETCH32 +# define HOST_FETCH32(p,l) BE_FETCH32(p) +# elif defined(REVERSE_FETCH32) +# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) +# endif +# endif +# endif +#endif + +#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ), \ + l) +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } } +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24), \ + l) +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } } +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) + +#endif + +/* + * Time for some action:-) + */ + +void HASH_UPDATE (HASH_CTX *c, const unsigned char *data, unsigned long len) + { + register HASH_LONG * p; + register unsigned long l; + int sw,sc,ew,ec; + + if (len==0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= HASH_CBLOCK) + { + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; swnum); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; sw < ew; sw++) + { + HOST_c2l(data,l); p[sw]=l; + } + if (ec) + { + HOST_c2l_p(data,l,ec); p[sw]=l; + } + } + return; + } + } + + sw=len/HASH_CBLOCK; + if (sw > 0) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + /* + * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined + * only if sizeof(HASH_LONG)==4. + */ + if ((((unsigned long)data)%4) == 0) + { + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } + else +#if !defined(HASH_BLOCK_DATA_ORDER) + while (sw--) + { + memcpy (p=c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); + data+=HASH_CBLOCK; + len-=HASH_CBLOCK; + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + { + HASH_BLOCK_DATA_ORDER(c,data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } +#endif + } + + if (len!=0) + { + p = c->data; + c->num = len; + ew=len>>2; /* words to copy */ + ec=len&0x03; + for (; ew; ew--,p++) + { + HOST_c2l(data,l); *p=l; + } + HOST_c2l_p(data,l,ec); + *p=l; + } + } + + +void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + if ((((unsigned long)data)%4) == 0) + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1); + else +#if !defined(HASH_BLOCK_DATA_ORDER) + { + memcpy (c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + HASH_BLOCK_DATA_ORDER (c,data,1); +#endif + } + + +void HASH_FINAL (unsigned char *md, HASH_CTX *c) + { + register HASH_LONG *p; + register unsigned long l; + register int i,j; + static const unsigned char end[4]={0x80,0x00,0x00,0x00}; + const unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + i=c->num>>2; + j=c->num&0x03; + +#if 0 + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + * Many thanks to Alex Tang for pickup this + * 'potential bug' */ +#ifdef PURIFY + if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */ +#endif + l=p[i]; +#else + l = (j==0) ? 0 : p[i]; +#endif + HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ + + if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ + { + if (iNh; + p[HASH_LBLOCK-1]=c->Nl; +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + p[HASH_LBLOCK-2]=c->Nl; + p[HASH_LBLOCK-1]=c->Nh; +#endif + HASH_BLOCK_HOST_ORDER (c,p,1); + + l=c->A; HOST_l2c(l,md); + l=c->B; HOST_l2c(l,md); + l=c->C; HOST_l2c(l,md); + l=c->D; HOST_l2c(l,md); + + c->num=0; + /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack + * but I'm not worried :-) + memset((void *)c,0,sizeof(HASH_CTX)); + */ + } diff --git a/src/lib/libcrypto/md4/md4.h b/src/lib/libcrypto/md4/md4.h new file mode 100644 index 0000000000..c794e186db --- /dev/null +++ b/src/lib/libcrypto/md4/md4.h @@ -0,0 +1,114 @@ +/* crypto/md4/md4.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_MD4_H +#define HEADER_MD4_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_MD4 +#error MD4 is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD4_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! MD4_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(WIN16) || defined(__LP32__) +#define MD4_LONG unsigned long +#elif defined(_CRAY) || defined(__ILP64__) +#define MD4_LONG unsigned long +#define MD4_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... + * + */ +#else +#define MD4_LONG unsigned int +#endif + +#define MD4_CBLOCK 64 +#define MD4_LBLOCK (MD4_CBLOCK/4) +#define MD4_DIGEST_LENGTH 16 + +typedef struct MD4state_st + { + MD4_LONG A,B,C,D; + MD4_LONG Nl,Nh; + MD4_LONG data[MD4_LBLOCK]; + int num; + } MD4_CTX; + +void MD4_Init(MD4_CTX *c); +void MD4_Update(MD4_CTX *c, const void *data, unsigned long len); +void MD4_Final(unsigned char *md, MD4_CTX *c); +unsigned char *MD4(const unsigned char *d, unsigned long n, unsigned char *md); +void MD4_Transform(MD4_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/libcrypto/md4/md4_dgst.c b/src/lib/libcrypto/md4/md4_dgst.c new file mode 100644 index 0000000000..81488ae2e2 --- /dev/null +++ b/src/lib/libcrypto/md4/md4_dgst.c @@ -0,0 +1,285 @@ +/* crypto/md4/md4_dgst.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 "md4_locl.h" +#include + +const char *MD4_version="MD4" OPENSSL_VERSION_PTEXT; + +/* Implemented from RFC1186 The MD4 Message-Digest Algorithm + */ + +#define INIT_DATA_A (unsigned long)0x67452301L +#define INIT_DATA_B (unsigned long)0xefcdab89L +#define INIT_DATA_C (unsigned long)0x98badcfeL +#define INIT_DATA_D (unsigned long)0x10325476L + +void MD4_Init(MD4_CTX *c) + { + c->A=INIT_DATA_A; + c->B=INIT_DATA_B; + c->C=INIT_DATA_C; + c->D=INIT_DATA_D; + c->Nl=0; + c->Nh=0; + c->num=0; + } + +#ifndef md4_block_host_order +void md4_block_host_order (MD4_CTX *c, const void *data, int num) + { + const MD4_LONG *X=data; + register unsigned long A,B,C,D; + /* + * In case you wonder why A-D are declared as long and not + * as MD4_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + * + * + */ + + A=c->A; + B=c->B; + C=c->C; + D=c->D; + + for (;num--;X+=HASH_LBLOCK) + { + /* Round 0 */ + R0(A,B,C,D,X[ 0], 3,0); + R0(D,A,B,C,X[ 1], 7,0); + R0(C,D,A,B,X[ 2],11,0); + R0(B,C,D,A,X[ 3],19,0); + R0(A,B,C,D,X[ 4], 3,0); + R0(D,A,B,C,X[ 5], 7,0); + R0(C,D,A,B,X[ 6],11,0); + R0(B,C,D,A,X[ 7],19,0); + R0(A,B,C,D,X[ 8], 3,0); + R0(D,A,B,C,X[ 9], 7,0); + R0(C,D,A,B,X[10],11,0); + R0(B,C,D,A,X[11],19,0); + R0(A,B,C,D,X[12], 3,0); + R0(D,A,B,C,X[13], 7,0); + R0(C,D,A,B,X[14],11,0); + R0(B,C,D,A,X[15],19,0); + /* Round 1 */ + R1(A,B,C,D,X[ 0], 3,0x5A827999L); + R1(D,A,B,C,X[ 4], 5,0x5A827999L); + R1(C,D,A,B,X[ 8], 9,0x5A827999L); + R1(B,C,D,A,X[12],13,0x5A827999L); + R1(A,B,C,D,X[ 1], 3,0x5A827999L); + R1(D,A,B,C,X[ 5], 5,0x5A827999L); + R1(C,D,A,B,X[ 9], 9,0x5A827999L); + R1(B,C,D,A,X[13],13,0x5A827999L); + R1(A,B,C,D,X[ 2], 3,0x5A827999L); + R1(D,A,B,C,X[ 6], 5,0x5A827999L); + R1(C,D,A,B,X[10], 9,0x5A827999L); + R1(B,C,D,A,X[14],13,0x5A827999L); + R1(A,B,C,D,X[ 3], 3,0x5A827999L); + R1(D,A,B,C,X[ 7], 5,0x5A827999L); + R1(C,D,A,B,X[11], 9,0x5A827999L); + R1(B,C,D,A,X[15],13,0x5A827999L); + /* Round 2 */ + R2(A,B,C,D,X[ 0], 3,0x6ED9EBA1); + R2(D,A,B,C,X[ 8], 9,0x6ED9EBA1); + R2(C,D,A,B,X[ 4],11,0x6ED9EBA1); + R2(B,C,D,A,X[12],15,0x6ED9EBA1); + R2(A,B,C,D,X[ 2], 3,0x6ED9EBA1); + R2(D,A,B,C,X[10], 9,0x6ED9EBA1); + R2(C,D,A,B,X[ 6],11,0x6ED9EBA1); + R2(B,C,D,A,X[14],15,0x6ED9EBA1); + R2(A,B,C,D,X[ 1], 3,0x6ED9EBA1); + R2(D,A,B,C,X[ 9], 9,0x6ED9EBA1); + R2(C,D,A,B,X[ 5],11,0x6ED9EBA1); + R2(B,C,D,A,X[13],15,0x6ED9EBA1); + R2(A,B,C,D,X[ 3], 3,0x6ED9EBA1); + R2(D,A,B,C,X[11], 9,0x6ED9EBA1); + R2(C,D,A,B,X[ 7],11,0x6ED9EBA1); + R2(B,C,D,A,X[15],15,0x6ED9EBA1); + + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; + } + } +#endif + +#ifndef md4_block_data_order +#ifdef X +#undef X +#endif +void md4_block_data_order (MD4_CTX *c, const void *data_, int num) + { + const unsigned char *data=data_; + register unsigned long A,B,C,D,l; + /* + * In case you wonder why A-D are declared as long and not + * as MD4_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + * + * + */ +#ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +# define X(i) XX##i +#else + MD4_LONG XX[MD4_LBLOCK]; +# define X(i) XX[i] +#endif + + A=c->A; + B=c->B; + C=c->C; + D=c->D; + + for (;num--;) + { + HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + /* Round 0 */ + R0(A,B,C,D,X( 0), 3,0); HOST_c2l(data,l); X( 2)=l; + R0(D,A,B,C,X( 1), 7,0); HOST_c2l(data,l); X( 3)=l; + R0(C,D,A,B,X( 2),11,0); HOST_c2l(data,l); X( 4)=l; + R0(B,C,D,A,X( 3),19,0); HOST_c2l(data,l); X( 5)=l; + R0(A,B,C,D,X( 4), 3,0); HOST_c2l(data,l); X( 6)=l; + R0(D,A,B,C,X( 5), 7,0); HOST_c2l(data,l); X( 7)=l; + R0(C,D,A,B,X( 6),11,0); HOST_c2l(data,l); X( 8)=l; + R0(B,C,D,A,X( 7),19,0); HOST_c2l(data,l); X( 9)=l; + R0(A,B,C,D,X( 8), 3,0); HOST_c2l(data,l); X(10)=l; + R0(D,A,B,C,X( 9), 7,0); HOST_c2l(data,l); X(11)=l; + R0(C,D,A,B,X(10),11,0); HOST_c2l(data,l); X(12)=l; + R0(B,C,D,A,X(11),19,0); HOST_c2l(data,l); X(13)=l; + R0(A,B,C,D,X(12), 3,0); HOST_c2l(data,l); X(14)=l; + R0(D,A,B,C,X(13), 7,0); HOST_c2l(data,l); X(15)=l; + R0(C,D,A,B,X(14),11,0); + R0(B,C,D,A,X(15),19,0); + /* Round 1 */ + R1(A,B,C,D,X( 0), 3,0x5A827999L); + R1(D,A,B,C,X( 4), 5,0x5A827999L); + R1(C,D,A,B,X( 8), 9,0x5A827999L); + R1(B,C,D,A,X(12),13,0x5A827999L); + R1(A,B,C,D,X( 1), 3,0x5A827999L); + R1(D,A,B,C,X( 5), 5,0x5A827999L); + R1(C,D,A,B,X( 9), 9,0x5A827999L); + R1(B,C,D,A,X(13),13,0x5A827999L); + R1(A,B,C,D,X( 2), 3,0x5A827999L); + R1(D,A,B,C,X( 6), 5,0x5A827999L); + R1(C,D,A,B,X(10), 9,0x5A827999L); + R1(B,C,D,A,X(14),13,0x5A827999L); + R1(A,B,C,D,X( 3), 3,0x5A827999L); + R1(D,A,B,C,X( 7), 5,0x5A827999L); + R1(C,D,A,B,X(11), 9,0x5A827999L); + R1(B,C,D,A,X(15),13,0x5A827999L); + /* Round 2 */ + R2(A,B,C,D,X( 0), 3,0x6ED9EBA1L); + R2(D,A,B,C,X( 8), 9,0x6ED9EBA1L); + R2(C,D,A,B,X( 4),11,0x6ED9EBA1L); + R2(B,C,D,A,X(12),15,0x6ED9EBA1L); + R2(A,B,C,D,X( 2), 3,0x6ED9EBA1L); + R2(D,A,B,C,X(10), 9,0x6ED9EBA1L); + R2(C,D,A,B,X( 6),11,0x6ED9EBA1L); + R2(B,C,D,A,X(14),15,0x6ED9EBA1L); + R2(A,B,C,D,X( 1), 3,0x6ED9EBA1L); + R2(D,A,B,C,X( 9), 9,0x6ED9EBA1L); + R2(C,D,A,B,X( 5),11,0x6ED9EBA1L); + R2(B,C,D,A,X(13),15,0x6ED9EBA1L); + R2(A,B,C,D,X( 3), 3,0x6ED9EBA1L); + R2(D,A,B,C,X(11), 9,0x6ED9EBA1L); + R2(C,D,A,B,X( 7),11,0x6ED9EBA1L); + R2(B,C,D,A,X(15),15,0x6ED9EBA1L); + + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; + } + } +#endif + +#ifdef undef +int printit(unsigned long *l) + { + int i,ii; + + for (i=0; i<2; i++) + { + for (ii=0; ii<8; ii++) + { + fprintf(stderr,"%08lx ",l[i*8+ii]); + } + fprintf(stderr,"\n"); + } + } +#endif diff --git a/src/lib/libcrypto/md4/md4_locl.h b/src/lib/libcrypto/md4/md4_locl.h new file mode 100644 index 0000000000..0a2b39018d --- /dev/null +++ b/src/lib/libcrypto/md4/md4_locl.h @@ -0,0 +1,154 @@ +/* crypto/md4/md4_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 +#include +#include +#include + +#ifndef MD4_LONG_LOG2 +#define MD4_LONG_LOG2 2 /* default to 32 bits */ +#endif + +void md4_block_host_order (MD4_CTX *c, const void *p,int num); +void md4_block_data_order (MD4_CTX *c, const void *p,int num); + +#if defined(__i386) || defined(_M_IX86) || defined(__INTEL__) +/* + * *_block_host_order is expected to handle aligned data while + * *_block_data_order - unaligned. As algorithm and host (x86) + * are in this case of the same "endianness" these two are + * otherwise indistinguishable. But normally you don't want to + * call the same function because unaligned access in places + * where alignment is expected is usually a "Bad Thing". Indeed, + * on RISCs you get punished with BUS ERROR signal or *severe* + * performance degradation. Intel CPUs are in turn perfectly + * capable of loading unaligned data without such drastic side + * effect. Yes, they say it's slower than aligned load, but no + * exception is generated and therefore performance degradation + * is *incomparable* with RISCs. What we should weight here is + * costs of unaligned access against costs of aligning data. + * According to my measurements allowing unaligned access results + * in ~9% performance improvement on Pentium II operating at + * 266MHz. I won't be surprised if the difference will be higher + * on faster systems:-) + * + * + */ +#define md4_block_data_order md4_block_host_order +#endif + +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG MD4_LONG +#define HASH_LONG_LOG2 MD4_LONG_LOG2 +#define HASH_CTX MD4_CTX +#define HASH_CBLOCK MD4_CBLOCK +#define HASH_LBLOCK MD4_LBLOCK +#define HASH_UPDATE MD4_Update +#define HASH_TRANSFORM MD4_Transform +#define HASH_FINAL MD4_Final +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; HOST_l2c(ll,(s)); \ + ll=(c)->B; HOST_l2c(ll,(s)); \ + ll=(c)->C; HOST_l2c(ll,(s)); \ + ll=(c)->D; HOST_l2c(ll,(s)); \ + } while (0) +#define HASH_BLOCK_HOST_ORDER md4_block_host_order +#if !defined(L_ENDIAN) || defined(md4_block_data_order) +#define HASH_BLOCK_DATA_ORDER md4_block_data_order +/* + * Little-endians (Intel and Alpha) feel better without this. + * It looks like memcpy does better job than generic + * md4_block_data_order on copying-n-aligning input data. + * But frankly speaking I didn't expect such result on Alpha. + * On the other hand I've got this with egcs-1.0.2 and if + * program is compiled with another (better?) compiler it + * might turn out other way around. + * + * + */ +#endif + +#include "md32_common.h" + +/* +#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x,y,z) (((x) & (y)) | ((x) & ((z))) | ((y) & ((z)))) +*/ + +/* As pointed out by Wei Dai , the above can be + * simplified to the code below. Wei attributes these optimizations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + */ +#define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define G(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define H(b,c,d) ((b) ^ (c) ^ (d)) + +#define R0(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+F((b),(c),(d))); \ + a=ROTATE(a,s); }; + +#define R1(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+G((b),(c),(d))); \ + a=ROTATE(a,s); };\ + +#define R2(a,b,c,d,k,s,t) { \ + a+=((k)+(t)+H((b),(c),(d))); \ + a=ROTATE(a,s); }; diff --git a/src/lib/libcrypto/md4/md4_one.c b/src/lib/libcrypto/md4/md4_one.c new file mode 100644 index 0000000000..87a995d38d --- /dev/null +++ b/src/lib/libcrypto/md4/md4_one.c @@ -0,0 +1,95 @@ +/* crypto/md4/md4_one.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 + +#ifdef CHARSET_EBCDIC +#include +#endif + +unsigned char *MD4(const unsigned char *d, unsigned long n, unsigned char *md) + { + MD4_CTX c; + static unsigned char m[MD4_DIGEST_LENGTH]; + + if (md == NULL) md=m; + MD4_Init(&c); +#ifndef CHARSET_EBCDIC + MD4_Update(&c,d,n); +#else + { + char temp[1024]; + unsigned long chunk; + + while (n > 0) + { + chunk = (n > sizeof(temp)) ? sizeof(temp) : n; + ebcdic2ascii(temp, d, chunk); + MD4_Update(&c,temp,chunk); + n -= chunk; + d += chunk; + } + } +#endif + MD4_Final(md,&c); + memset(&c,0,sizeof(c)); /* security consideration */ + return(md); + } + diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c new file mode 100644 index 0000000000..14770c0733 --- /dev/null +++ b/src/lib/libcrypto/mem_dbg.c @@ -0,0 +1,703 @@ +/* crypto/mem_dbg.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 +#include "cryptlib.h" + +static int mh_mode=CRYPTO_MEM_CHECK_OFF; +/* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE + * when the application asks for it (usually after library initialisation + * for which no book-keeping is desired). + * + * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library + * thinks that certain allocations should not be checked (e.g. the data + * structures used for memory checking). It is not suitable as an initial + * state: the library will unexpectedly enable memory checking when it + * executes one of those sections that want to disable checking + * temporarily. + * + * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever. + */ + +static unsigned long order = 0; /* number of memory requests */ +static LHASH *mh=NULL; /* hash-table of memory requests (address as key) */ + + +typedef struct app_mem_info_st +/* For application-defined information (static C-string `info') + * to be displayed in memory leak list. + * Each thread has its own stack. For applications, there is + * CRYPTO_push_info("...") to push an entry, + * CRYPTO_pop_info() to pop an entry, + * CRYPTO_remove_all_info() to pop all entries. + */ + { + unsigned long thread; + const char *file; + int line; + const char *info; + struct app_mem_info_st *next; /* tail of thread's stack */ + int references; + } APP_INFO; + +static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's + * that are at the top of their thread's stack + * (with `thread' as key) */ + +typedef struct mem_st +/* memory-block description */ + { + char *addr; + int num; + const char *file; + int line; + unsigned long thread; + unsigned long order; + time_t time; + APP_INFO *app_info; + } MEM; + +static long options = /* extra information to be recorded */ +#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL) + V_CRYPTO_MDEBUG_TIME | +#endif +#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL) + V_CRYPTO_MDEBUG_THREAD | +#endif + 0; + + +static unsigned long disabling_thread = 0; + +int CRYPTO_mem_ctrl(int mode) + { + int ret=mh_mode; + + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); + switch (mode) + { + /* for applications: */ + case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ + mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; + disabling_thread = 0; + break; + case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ + mh_mode = 0; + disabling_thread = 0; + break; + + /* switch off temporarily (for library-internal use): */ + case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ + if (mh_mode & CRYPTO_MEM_CHECK_ON) + { + mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE; + if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */ + { + /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while + * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if + * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release + * it because we block entry to this function). + * Give them a chance, first, and then claim the locks in + * appropriate order (long-time lock first). + */ + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); + /* Note that after we have waited for CRYPTO_LOCK_MALLOC2 + * and CRYPTO_LOCK_MALLOC, we'll still be in the right + * "case" and "if" branch because MemCheck_start and + * MemCheck_stop may never be used while there are multiple + * OpenSSL threads. */ + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); + disabling_thread=CRYPTO_thread_id(); + } + } + break; + case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ + if (mh_mode & CRYPTO_MEM_CHECK_ON) + { + mh_mode|=CRYPTO_MEM_CHECK_ENABLE; + if (disabling_thread != 0) + { + disabling_thread=0; + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + } + } + break; + + default: + break; + } + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); + return(ret); + } + +int CRYPTO_is_mem_check_on(void) + { + int ret = 0; + + if (mh_mode & CRYPTO_MEM_CHECK_ON) + { + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); + + ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) + && disabling_thread != CRYPTO_thread_id(); + + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); + } + return(ret); + } + + +void CRYPTO_dbg_set_options(long bits) + { + options = bits; + } + +long CRYPTO_dbg_get_options(void) + { + return options; + } + +static int mem_cmp(MEM *a, MEM *b) + { + return(a->addr - b->addr); + } + +static unsigned long mem_hash(MEM *a) + { + unsigned long ret; + + ret=(unsigned long)a->addr; + + ret=ret*17851+(ret>>14)*7+(ret>>4)*251; + return(ret); + } + +static int app_info_cmp(APP_INFO *a, APP_INFO *b) + { + return(a->thread != b->thread); + } + +static unsigned long app_info_hash(APP_INFO *a) + { + unsigned long ret; + + ret=(unsigned long)a->thread; + + ret=ret*17851+(ret>>14)*7+(ret>>4)*251; + return(ret); + } + +static APP_INFO *pop_info() + { + APP_INFO tmp; + APP_INFO *ret = NULL; + + if (amih != NULL) + { + tmp.thread=CRYPTO_thread_id(); + if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL) + { + APP_INFO *next=ret->next; + + if (next != NULL) + { + next->references++; + lh_insert(amih,(char *)next); + } +#ifdef LEVITTE_DEBUG + if (ret->thread != tmp.thread) + { + fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", + ret->thread, tmp.thread); + abort(); + } +#endif + if (--(ret->references) <= 0) + { + ret->next = NULL; + if (next != NULL) + next->references--; + Free(ret); + } + } + } + return(ret); + } + +int CRYPTO_push_info_(const char *info, const char *file, int line) + { + APP_INFO *ami, *amim; + int ret=0; + + if (is_MemCheck_on()) + { + MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + + if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL) + { + ret=0; + goto err; + } + if (amih == NULL) + { + if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL) + { + Free(ami); + ret=0; + goto err; + } + } + + ami->thread=CRYPTO_thread_id(); + ami->file=file; + ami->line=line; + ami->info=info; + ami->references=1; + ami->next=NULL; + + if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) + { +#ifdef LEVITTE_DEBUG + if (ami->thread != amim->thread) + { + fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", + amim->thread, ami->thread); + abort(); + } +#endif + ami->next=amim; + } + err: + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + } + + return(ret); + } + +int CRYPTO_pop_info(void) + { + int ret=0; + + if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ + { + MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + + ret=(pop_info() != NULL); + + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + } + return(ret); + } + +int CRYPTO_remove_all_info(void) + { + int ret=0; + + if (is_MemCheck_on()) /* _must_ be true */ + { + MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + + while(pop_info() != NULL) + ret++; + + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + } + return(ret); + } + + +static unsigned long break_order_num=0; +void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, + int before_p) + { + MEM *m,*mm; + APP_INFO tmp,*amim; + + switch(before_p & 127) + { + case 0: + break; + case 1: + if (addr == NULL) + break; + + if (is_MemCheck_on()) + { + MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL) + { + Free(addr); + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + return; + } + if (mh == NULL) + { + if ((mh=lh_new(mem_hash,mem_cmp)) == NULL) + { + Free(addr); + Free(m); + addr=NULL; + goto err; + } + } + + m->addr=addr; + m->file=file; + m->line=line; + m->num=num; + if (options & V_CRYPTO_MDEBUG_THREAD) + m->thread=CRYPTO_thread_id(); + else + m->thread=0; + + if (order == break_order_num) + { + /* BREAK HERE */ + m->order=order; + } + m->order=order++; +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n", + m->order, + (before_p & 128) ? '*' : '+', + m->addr, m->num); +#endif + if (options & V_CRYPTO_MDEBUG_TIME) + m->time=time(NULL); + else + m->time=0; + + tmp.thread=CRYPTO_thread_id(); + m->app_info=NULL; + if (amih != NULL + && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL) + { + m->app_info = amim; + amim->references++; + } + + if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL) + { + /* Not good, but don't sweat it */ + if (mm->app_info != NULL) + { + mm->app_info->references--; + } + Free(mm); + } + err: + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + } + break; + } + return; + } + +void CRYPTO_dbg_free(void *addr, int before_p) + { + MEM m,*mp; + + switch(before_p) + { + case 0: + if (addr == NULL) + break; + + if (is_MemCheck_on() && (mh != NULL)) + { + MemCheck_off(); + + m.addr=addr; + mp=(MEM *)lh_delete(mh,(char *)&m); + if (mp != NULL) + { +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n", + mp->order, mp->addr, mp->num); +#endif + if (mp->app_info != NULL) + { + mp->app_info->references--; + } + Free(mp); + } + + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + } + break; + case 1: + break; + } + } + +void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, + const char *file, int line, int before_p) + { + MEM m,*mp; + +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", + addr1, addr2, num, file, line, before_p); +#endif + + switch(before_p) + { + case 0: + break; + case 1: + if (addr2 == NULL) + break; + + if (addr1 == NULL) + { + CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p); + break; + } + + if (is_MemCheck_on()) + { + MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + + m.addr=addr1; + mp=(MEM *)lh_delete(mh,(char *)&m); + if (mp != NULL) + { +#ifdef LEVITTE_DEBUG + fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", + mp->order, + mp->addr, mp->num, + addr2, num); +#endif + mp->addr=addr2; + mp->num=num; + lh_insert(mh,(char *)mp); + } + + MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + } + break; + } + return; + } + + +typedef struct mem_leak_st + { + BIO *bio; + int chunks; + long bytes; + } MEM_LEAK; + +static void print_leak(MEM *m, MEM_LEAK *l) + { + char buf[1024]; + char *bufp = buf; + APP_INFO *amip; + int ami_cnt; + struct tm *lcl = NULL; + unsigned long ti; + + if(m->addr == (char *)l->bio) + return; + + if (options & V_CRYPTO_MDEBUG_TIME) + { + lcl = localtime(&m->time); + + sprintf(bufp, "[%02d:%02d:%02d] ", + lcl->tm_hour,lcl->tm_min,lcl->tm_sec); + bufp += strlen(bufp); + } + + sprintf(bufp, "%5lu file=%s, line=%d, ", + m->order,m->file,m->line); + bufp += strlen(bufp); + + if (options & V_CRYPTO_MDEBUG_THREAD) + { + sprintf(bufp, "thread=%lu, ", m->thread); + bufp += strlen(bufp); + } + + sprintf(bufp, "number=%d, address=%08lX\n", + m->num,(unsigned long)m->addr); + bufp += strlen(bufp); + + BIO_puts(l->bio,buf); + + l->chunks++; + l->bytes+=m->num; + + amip=m->app_info; + ami_cnt=0; + if (!amip) + return; + ti=amip->thread; + + do + { + int buf_len; + int info_len; + + ami_cnt++; + memset(buf,'>',ami_cnt); + sprintf(buf + ami_cnt, + " thread=%lu, file=%s, line=%d, info=\"", + amip->thread, amip->file, amip->line); + buf_len=strlen(buf); + info_len=strlen(amip->info); + if (128 - buf_len - 3 < info_len) + { + memcpy(buf + buf_len, amip->info, 128 - buf_len - 3); + buf_len = 128 - 3; + } + else + { + strcpy(buf + buf_len, amip->info); + buf_len = strlen(buf); + } + sprintf(buf + buf_len, "\"\n"); + + BIO_puts(l->bio,buf); + + amip = amip->next; + } + while(amip && amip->thread == ti); + +#ifdef LEVITTE_DEBUG + if (amip) + { + fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); + abort(); + } +#endif + } + +void CRYPTO_mem_leaks(BIO *b) + { + MEM_LEAK ml; + char buf[80]; + + if (mh == NULL) return; + ml.bio=b; + ml.bytes=0; + ml.chunks=0; + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); + lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml); + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + if (ml.chunks != 0) + { + sprintf(buf,"%ld bytes leaked in %d chunks\n", + ml.bytes,ml.chunks); + BIO_puts(b,buf); + } + +#if 0 + lh_stats_bio(mh,b); + lh_node_stats_bio(mh,b); + lh_node_usage_stats_bio(mh,b); +#endif + } + +union void_fn_to_char_u + { + char *char_p; + void (*fn_p)(); + }; + +static void cb_leak(MEM *m, char *cb) + { + union void_fn_to_char_u mem_callback; + + mem_callback.char_p=cb; + mem_callback.fn_p(m->order,m->file,m->line,m->num,m->addr); + } + +void CRYPTO_mem_leaks_cb(void (*cb)()) + { + union void_fn_to_char_u mem_cb; + + if (mh == NULL) return; + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); + mem_cb.fn_p=cb; + lh_doall_arg(mh,(void (*)())cb_leak,mem_cb.char_p); + mem_cb.char_p=NULL; + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + } + +#ifndef NO_FP_API +void CRYPTO_mem_leaks_fp(FILE *fp) + { + BIO *b; + + if (mh == NULL) return; + if ((b=BIO_new(BIO_s_file())) == NULL) + return; + BIO_set_fp(b,fp,BIO_NOCLOSE); + CRYPTO_mem_leaks(b); + BIO_free(b); + } +#endif + diff --git a/src/lib/libcrypto/o_time.c b/src/lib/libcrypto/o_time.c new file mode 100644 index 0000000000..1bc0297b36 --- /dev/null +++ b/src/lib/libcrypto/o_time.c @@ -0,0 +1,203 @@ +/* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include "o_time.h" + +#ifdef OPENSSL_SYS_VMS +# include +# include +# include +# include +# include +# include +#endif + +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) + { + struct tm *ts = NULL; + +#if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_OS2) && !defined(__CYGWIN32__) && (!defined(OPENSSL_SYS_VMS) || defined(gmtime_r)) && !defined(OPENSSL_SYS_MACOSX) + /* should return &data, but doesn't on some systems, + so we don't even look at the return value */ + gmtime_r(timer,result); + ts = result; +#elif !defined(OPENSSL_SYS_VMS) + ts = gmtime(timer); + memcpy(result, ts, sizeof(struct tm)); + ts = result; +#endif +#ifdef OPENSSL_SYS_VMS + if (ts == NULL) + { + static $DESCRIPTOR(tabnam,"LNM$DCL_LOGICAL"); + static $DESCRIPTOR(lognam,"SYS$TIMEZONE_DIFFERENTIAL"); + char logvalue[256]; + unsigned int reslen = 0; + struct { + short buflen; + short code; + void *bufaddr; + unsigned int *reslen; + } itemlist[] = { + { 0, LNM$_STRING, 0, 0 }, + { 0, 0, 0, 0 }, + }; + int status; + time_t t; + + /* Get the value for SYS$TIMEZONE_DIFFERENTIAL */ + itemlist[0].buflen = sizeof(logvalue); + itemlist[0].bufaddr = logvalue; + itemlist[0].reslen = &reslen; + status = sys$trnlnm(0, &tabnam, &lognam, 0, itemlist); + if (!(status & 1)) + return NULL; + logvalue[reslen] = '\0'; + + /* Get the numerical value of the equivalence string */ + status = atoi(logvalue); + + /* and use it to move time to GMT */ + t = *timer - status; + + /* then convert the result to the time structure */ +#ifndef OPENSSL_THREADS + ts=(struct tm *)localtime(&t); +#else + /* Since there was no gmtime_r() to do this stuff for us, + we have to do it the hard way. */ + { + /* The VMS epoch is the astronomical Smithsonian date, + if I remember correctly, which is November 17, 1858. + Furthermore, time is measure in thenths of microseconds + and stored in quadwords (64 bit integers). unix_epoch + below is January 1st 1970 expressed as a VMS time. The + following code was used to get this number: + + #include + #include + #include + #include + + main() + { + unsigned long systime[2]; + unsigned short epoch_values[7] = + { 1970, 1, 1, 0, 0, 0, 0 }; + + lib$cvt_vectim(epoch_values, systime); + + printf("%u %u", systime[0], systime[1]); + } + */ + unsigned long unix_epoch[2] = { 1273708544, 8164711 }; + unsigned long deltatime[2]; + unsigned long systime[2]; + struct vms_vectime + { + short year, month, day, hour, minute, second, + centi_second; + } time_values; + long operation; + + /* Turn the number of seconds since January 1st 1970 to + an internal delta time. + Note that lib$cvt_to_internal_time() will assume + that t is signed, and will therefore break on 32-bit + systems some time in 2038. + */ + operation = LIB$K_DELTA_SECONDS; + status = lib$cvt_to_internal_time(&operation, + &t, deltatime); + + /* Add the delta time with the Unix epoch and we have + the current UTC time in internal format */ + status = lib$add_times(unix_epoch, deltatime, systime); + + /* Turn the internal time into a time vector */ + status = sys$numtim(&time_values, systime); + + /* Fill in the struct tm with the result */ + result->tm_sec = time_values.second; + result->tm_min = time_values.minute; + result->tm_hour = time_values.hour; + result->tm_mday = time_values.day; + result->tm_mon = time_values.month - 1; + result->tm_year = time_values.year - 1900; + + operation = LIB$K_DAY_OF_WEEK; + status = lib$cvt_from_internal_time(&operation, + &result->tm_wday, systime); + result->tm_wday %= 7; + + operation = LIB$K_DAY_OF_YEAR; + status = lib$cvt_from_internal_time(&operation, + &result->tm_yday, systime); + result->tm_yday--; + + result->tm_isdst = 0; /* There's no way to know... */ + + ts = result; +#endif + } + } +#endif + return ts; + } diff --git a/src/lib/libcrypto/o_time.h b/src/lib/libcrypto/o_time.h new file mode 100644 index 0000000000..e66044626d --- /dev/null +++ b/src/lib/libcrypto/o_time.h @@ -0,0 +1,66 @@ +/* crypto/o_time.h -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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). + * + */ + +#ifndef HEADER_O_TIME_H +#define HEADER_O_TIME_H + +#include + +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); + +#endif diff --git a/src/lib/libcrypto/objects/o_names.c b/src/lib/libcrypto/objects/o_names.c new file mode 100644 index 0000000000..4da5e45b9c --- /dev/null +++ b/src/lib/libcrypto/objects/o_names.c @@ -0,0 +1,243 @@ +#include +#include +#include + +#include +#include + +/* I use the ex_data stuff to manage the identifiers for the obj_name_types + * that applications may define. I only really use the free function field. + */ +static LHASH *names_lh=NULL; +static int names_type_num=OBJ_NAME_TYPE_NUM; +static STACK *names_cmp=NULL; +static STACK *names_hash=NULL; +static STACK *names_free=NULL; + +static unsigned long obj_name_hash(OBJ_NAME *a); +static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); + +int OBJ_NAME_init(void) + { + if (names_lh != NULL) return(1); + MemCheck_off(); + names_lh=lh_new(obj_name_hash,obj_name_cmp); + MemCheck_on(); + return(names_lh != NULL); + } + +int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(), + void (*free_func)()) + { + int ret; + int i; + + if (names_free == NULL) + { + MemCheck_off(); + names_hash=sk_new_null(); + names_cmp=sk_new_null(); + names_free=sk_new_null(); + MemCheck_on(); + } + if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL)) + { + /* ERROR */ + return(0); + } + ret=names_type_num; + names_type_num++; + for (i=sk_num(names_free); itype-b->type; + if (ret == 0) + { + if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type)) + { + cmp=(int (*)())sk_value(names_cmp,a->type); + ret=cmp(a->name,b->name); + } + else + ret=strcmp(a->name,b->name); + } + return(ret); + } + +static unsigned long obj_name_hash(OBJ_NAME *a) + { + unsigned long ret; + unsigned long (*hash)(); + + if ((names_hash != NULL) && (sk_num(names_hash) > a->type)) + { + hash=(unsigned long (*)())sk_value(names_hash,a->type); + ret=hash(a->name); + } + else + { + ret=lh_strhash(a->name); + } + ret^=a->type; + return(ret); + } + +const char *OBJ_NAME_get(const char *name, int type) + { + OBJ_NAME on,*ret; + int num=0,alias; + + if (name == NULL) return(NULL); + if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL); + + alias=type&OBJ_NAME_ALIAS; + type&= ~OBJ_NAME_ALIAS; + + on.name=name; + on.type=type; + + for (;;) + { + ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on); + if (ret == NULL) return(NULL); + if ((ret->alias) && !alias) + { + if (++num > 10) return(NULL); + on.name=ret->data; + } + else + { + return(ret->data); + } + } + } + +int OBJ_NAME_add(const char *name, int type, const char *data) + { + void (*f)(); + OBJ_NAME *onp,*ret; + int alias; + + if ((names_lh == NULL) && !OBJ_NAME_init()) return(0); + + alias=type&OBJ_NAME_ALIAS; + type&= ~OBJ_NAME_ALIAS; + + onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME)); + if (onp == NULL) + { + /* ERROR */ + return(0); + } + + onp->name=name; + onp->alias=alias; + onp->type=type; + onp->data=data; + + ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp); + if (ret != NULL) + { + /* free things */ + if ((names_free != NULL) && (sk_num(names_free) > ret->type)) + { + f=(void (*)())sk_value(names_free,ret->type); + f(ret->name,ret->type,ret->data); + } + Free((char *)ret); + } + else + { + if (lh_error(names_lh)) + { + /* ERROR */ + return(0); + } + } + return(1); + } + +int OBJ_NAME_remove(const char *name, int type) + { + OBJ_NAME on,*ret; + void (*f)(); + + if (names_lh == NULL) return(0); + + type&= ~OBJ_NAME_ALIAS; + on.name=name; + on.type=type; + ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on); + if (ret != NULL) + { + /* free things */ + if ((names_free != NULL) && (sk_num(names_free) > type)) + { + f=(void (*)())sk_value(names_free,type); + f(ret->name,ret->type,ret->data); + } + Free((char *)ret); + return(1); + } + else + return(0); + } + +static int free_type; + +static void names_lh_free(OBJ_NAME *onp, int type) +{ + if(onp == NULL) + return; + + if ((free_type < 0) || (free_type == onp->type)) + { + OBJ_NAME_remove(onp->name,onp->type); + } + } + +void OBJ_NAME_cleanup(int type) + { + unsigned long down_load; + + if (names_lh == NULL) return; + + free_type=type; + down_load=names_lh->down_load; + names_lh->down_load=0; + + lh_doall(names_lh,names_lh_free); + if (type < 0) + { + lh_free(names_lh); + sk_free(names_hash); + sk_free(names_cmp); + sk_free(names_free); + names_lh=NULL; + names_hash=NULL; + names_cmp=NULL; + names_free=NULL; + } + else + names_lh->down_load=down_load; + } + diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num new file mode 100644 index 0000000000..d73a51370f --- /dev/null +++ b/src/lib/libcrypto/objects/obj_mac.num @@ -0,0 +1,392 @@ +undef 0 +rsadsi 1 +pkcs 2 +md2 3 +md5 4 +rc4 5 +rsaEncryption 6 +md2WithRSAEncryption 7 +md5WithRSAEncryption 8 +pbeWithMD2AndDES_CBC 9 +pbeWithMD5AndDES_CBC 10 +X500 11 +X509 12 +commonName 13 +countryName 14 +localityName 15 +stateOrProvinceName 16 +organizationName 17 +organizationalUnitName 18 +rsa 19 +pkcs7 20 +pkcs7_data 21 +pkcs7_signed 22 +pkcs7_enveloped 23 +pkcs7_signedAndEnveloped 24 +pkcs7_digest 25 +pkcs7_encrypted 26 +pkcs3 27 +dhKeyAgreement 28 +des_ecb 29 +des_cfb64 30 +des_cbc 31 +des_ede 32 +des_ede3 33 +idea_cbc 34 +idea_cfb64 35 +idea_ecb 36 +rc2_cbc 37 +rc2_ecb 38 +rc2_cfb64 39 +rc2_ofb64 40 +sha 41 +shaWithRSAEncryption 42 +des_ede_cbc 43 +des_ede3_cbc 44 +des_ofb64 45 +idea_ofb64 46 +pkcs9 47 +pkcs9_emailAddress 48 +pkcs9_unstructuredName 49 +pkcs9_contentType 50 +pkcs9_messageDigest 51 +pkcs9_signingTime 52 +pkcs9_countersignature 53 +pkcs9_challengePassword 54 +pkcs9_unstructuredAddress 55 +pkcs9_extCertAttributes 56 +netscape 57 +netscape_cert_extension 58 +netscape_data_type 59 +des_ede_cfb64 60 +des_ede3_cfb64 61 +des_ede_ofb64 62 +des_ede3_ofb64 63 +sha1 64 +sha1WithRSAEncryption 65 +dsaWithSHA 66 +dsa_2 67 +pbeWithSHA1AndRC2_CBC 68 +id_pbkdf2 69 +dsaWithSHA1_2 70 +netscape_cert_type 71 +netscape_base_url 72 +netscape_revocation_url 73 +netscape_ca_revocation_url 74 +netscape_renewal_url 75 +netscape_ca_policy_url 76 +netscape_ssl_server_name 77 +netscape_comment 78 +netscape_cert_sequence 79 +desx_cbc 80 +id_ce 81 +subject_key_identifier 82 +key_usage 83 +private_key_usage_period 84 +subject_alt_name 85 +issuer_alt_name 86 +basic_constraints 87 +crl_number 88 +certificate_policies 89 +authority_key_identifier 90 +bf_cbc 91 +bf_ecb 92 +bf_cfb64 93 +bf_ofb64 94 +mdc2 95 +mdc2WithRSA 96 +rc4_40 97 +rc2_40_cbc 98 +givenName 99 +surname 100 +initials 101 +uniqueIdentifier 102 +crl_distribution_points 103 +md5WithRSA 104 +serialNumber 105 +title 106 +description 107 +cast5_cbc 108 +cast5_ecb 109 +cast5_cfb64 110 +cast5_ofb64 111 +pbeWithMD5AndCast5_CBC 112 +dsaWithSHA1 113 +md5_sha1 114 +sha1WithRSA 115 +dsa 116 +ripemd160 117 +ripemd160WithRSA 119 +rc5_cbc 120 +rc5_ecb 121 +rc5_cfb64 122 +rc5_ofb64 123 +rle_compression 124 +zlib_compression 125 +ext_key_usage 126 +id_pkix 127 +id_kp 128 +server_auth 129 +client_auth 130 +code_sign 131 +email_protect 132 +time_stamp 133 +ms_code_ind 134 +ms_code_com 135 +ms_ctl_sign 136 +ms_sgc 137 +ms_efs 138 +ns_sgc 139 +delta_crl 140 +crl_reason 141 +invalidity_date 142 +sxnet 143 +pbe_WithSHA1And128BitRC4 144 +pbe_WithSHA1And40BitRC4 145 +pbe_WithSHA1And3_Key_TripleDES_CBC 146 +pbe_WithSHA1And2_Key_TripleDES_CBC 147 +pbe_WithSHA1And128BitRC2_CBC 148 +pbe_WithSHA1And40BitRC2_CBC 149 +keyBag 150 +pkcs8ShroudedKeyBag 151 +certBag 152 +crlBag 153 +secretBag 154 +safeContentsBag 155 +friendlyName 156 +localKeyID 157 +x509Certificate 158 +sdsiCertificate 159 +x509Crl 160 +pbes2 161 +pbmac1 162 +hmacWithSHA1 163 +id_qt_cps 164 +id_qt_unotice 165 +rc2_64_cbc 166 +SMIMECapabilities 167 +pbeWithMD2AndRC2_CBC 168 +pbeWithMD5AndRC2_CBC 169 +pbeWithSHA1AndDES_CBC 170 +ms_ext_req 171 +ext_req 172 +name 173 +dnQualifier 174 +id_pe 175 +id_ad 176 +info_access 177 +ad_OCSP 178 +ad_ca_issuers 179 +OCSP_sign 180 +iso 181 +member_body 182 +ISO_US 183 +X9_57 184 +X9cm 185 +pkcs1 186 +pkcs5 187 +SMIME 188 +id_smime_mod 189 +id_smime_ct 190 +id_smime_aa 191 +id_smime_alg 192 +id_smime_cd 193 +id_smime_spq 194 +id_smime_cti 195 +id_smime_mod_cms 196 +id_smime_mod_ess 197 +id_smime_mod_oid 198 +id_smime_mod_msg_v3 199 +id_smime_mod_ets_eSignature_88 200 +id_smime_mod_ets_eSignature_97 201 +id_smime_mod_ets_eSigPolicy_88 202 +id_smime_mod_ets_eSigPolicy_97 203 +id_smime_ct_receipt 204 +id_smime_ct_authData 205 +id_smime_ct_publishCert 206 +id_smime_ct_TSTInfo 207 +id_smime_ct_TDTInfo 208 +id_smime_ct_contentInfo 209 +id_smime_ct_DVCSRequestData 210 +id_smime_ct_DVCSResponseData 211 +id_smime_aa_receiptRequest 212 +id_smime_aa_securityLabel 213 +id_smime_aa_mlExpandHistory 214 +id_smime_aa_contentHint 215 +id_smime_aa_msgSigDigest 216 +id_smime_aa_encapContentType 217 +id_smime_aa_contentIdentifier 218 +id_smime_aa_macValue 219 +id_smime_aa_equivalentLabels 220 +id_smime_aa_contentReference 221 +id_smime_aa_encrypKeyPref 222 +id_smime_aa_signingCertificate 223 +id_smime_aa_smimeEncryptCerts 224 +id_smime_aa_timeStampToken 225 +id_smime_aa_ets_sigPolicyId 226 +id_smime_aa_ets_commitmentType 227 +id_smime_aa_ets_signerLocation 228 +id_smime_aa_ets_signerAttr 229 +id_smime_aa_ets_otherSigCert 230 +id_smime_aa_ets_contentTimestamp 231 +id_smime_aa_ets_CertificateRefs 232 +id_smime_aa_ets_RevocationRefs 233 +id_smime_aa_ets_certValues 234 +id_smime_aa_ets_revocationValues 235 +id_smime_aa_ets_escTimeStamp 236 +id_smime_aa_ets_certCRLTimestamp 237 +id_smime_aa_ets_archiveTimeStamp 238 +id_smime_aa_signatureType 239 +id_smime_aa_dvcs_dvc 240 +id_smime_alg_ESDHwith3DES 241 +id_smime_alg_ESDHwithRC2 242 +id_smime_alg_3DESwrap 243 +id_smime_alg_RC2wrap 244 +id_smime_alg_ESDH 245 +id_smime_alg_CMS3DESwrap 246 +id_smime_alg_CMSRC2wrap 247 +id_smime_cd_ldap 248 +id_smime_spq_ets_sqt_uri 249 +id_smime_spq_ets_sqt_unotice 250 +id_smime_cti_ets_proofOfOrigin 251 +id_smime_cti_ets_proofOfReceipt 252 +id_smime_cti_ets_proofOfDelivery 253 +id_smime_cti_ets_proofOfSender 254 +id_smime_cti_ets_proofOfApproval 255 +id_smime_cti_ets_proofOfCreation 256 +md4 257 +id_pkix_mod 258 +id_qt 259 +id_it 260 +id_pkip 261 +id_alg 262 +id_cmc 263 +id_on 264 +id_pda 265 +id_aca 266 +id_qcs 267 +id_cct 268 +id_pkix1_explicit_88 269 +id_pkix1_implicit_88 270 +id_pkix1_explicit_93 271 +id_pkix1_implicit_93 272 +id_mod_crmf 273 +id_mod_cmc 274 +id_mod_kea_profile_88 275 +id_mod_kea_profile_93 276 +id_mod_cmp 277 +id_mod_qualified_cert_88 278 +id_mod_qualified_cert_93 279 +id_mod_attribute_cert 280 +id_mod_timestamp_protocol 281 +id_mod_ocsp 282 +id_mod_dvcs 283 +id_mod_cmp2000 284 +biometricInfo 285 +qcStatements 286 +ac_auditEntity 287 +ac_targeting 288 +aaControls 289 +sbqp_ipAddrBlock 290 +sbqp_autonomousSysNum 291 +sbqp_routerIdentifier 292 +textNotice 293 +ipsecEndSystem 294 +ipsecTunnel 295 +ipsecUser 296 +dvcs 297 +id_it_caProtEncCert 298 +id_it_signKeyPairTypes 299 +id_it_encKeyPairTypes 300 +id_it_preferredSymmAlg 301 +id_it_caKeyUpdateInfo 302 +id_it_currentCRL 303 +id_it_unsupportedOIDs 304 +id_it_subscriptionRequest 305 +id_it_subscriptionResponse 306 +id_it_keyPairParamReq 307 +id_it_keyPairParamRep 308 +id_it_revPassphrase 309 +id_it_implicitConfirm 310 +id_it_confirmWaitTime 311 +id_it_origPKIMessage 312 +id_regCtrl 313 +id_regInfo 314 +id_regCtrl_regToken 315 +id_regCtrl_authenticator 316 +id_regCtrl_pkiPublicationInfo 317 +id_regCtrl_pkiArchiveOptions 318 +id_regCtrl_oldCertID 319 +id_regCtrl_protocolEncrKey 320 +id_regInfo_utf8Pairs 321 +id_regInfo_certReq 322 +id_alg_des40 323 +id_alg_noSignature 324 +id_alg_dh_sig_hmac_sha1 325 +id_alg_dh_pop 326 +id_cmc_statusInfo 327 +id_cmc_identification 328 +id_cmc_identityProof 329 +id_cmc_dataReturn 330 +id_cmc_transactionId 331 +id_cmc_senderNonce 332 +id_cmc_recipientNonce 333 +id_cmc_addExtensions 334 +id_cmc_encryptedPOP 335 +id_cmc_decryptedPOP 336 +id_cmc_lraPOPWitness 337 +id_cmc_getCert 338 +id_cmc_getCRL 339 +id_cmc_revokeRequest 340 +id_cmc_regInfo 341 +id_cmc_responseInfo 342 +id_cmc_queryPending 343 +id_cmc_popLinkRandom 344 +id_cmc_popLinkWitness 345 +id_cmc_confirmCertAcceptance 346 +id_on_personalData 347 +id_pda_dateOfBirth 348 +id_pda_placeOfBirth 349 +id_pda_pseudonym 350 +id_pda_gender 351 +id_pda_countryOfCitizenship 352 +id_pda_countryOfResidence 353 +id_aca_authenticationInfo 354 +id_aca_accessIdentity 355 +id_aca_chargingIdentity 356 +id_aca_group 357 +id_aca_role 358 +id_qcs_pkixQCSyntax_v1 359 +id_cct_crs 360 +id_cct_PKIData 361 +id_cct_PKIResponse 362 +ad_timeStamping 363 +ad_dvcs 364 +id_pkix_OCSP_basic 365 +id_pkix_OCSP_Nonce 366 +id_pkix_OCSP_CrlID 367 +id_pkix_OCSP_acceptableResponses 368 +id_pkix_OCSP_noCheck 369 +id_pkix_OCSP_archiveCutoff 370 +id_pkix_OCSP_serviceLocator 371 +id_pkix_OCSP_extendedStatus 372 +id_pkix_OCSP_valid 373 +id_pkix_OCSP_path 374 +id_pkix_OCSP_trustRoot 375 +algorithm 376 +rsaSignature 377 +X500algorithms 378 +org 379 +dod 380 +iana 381 +Directory 382 +Management 383 +Experimental 384 +Private 385 +Security 386 +SNMPv2 387 +Mail 388 +Enterprises 389 +dcObject 390 +domainComponent 391 +Domain 392 diff --git a/src/lib/libcrypto/objects/objects.README b/src/lib/libcrypto/objects/objects.README new file mode 100644 index 0000000000..4d745508d8 --- /dev/null +++ b/src/lib/libcrypto/objects/objects.README @@ -0,0 +1,44 @@ +objects.txt syntax +------------------ + +To cover all the naming hacks that were previously in objects.h needed some +kind of hacks in objects.txt. + +The basic syntax for adding an object is as follows: + + 1 2 3 4 : shortName : Long Name + + If the long name doesn't contain spaces, or no short name + exists, the long name is used as basis for the base name + in C. Otherwise, the short name is used. + + The base name (let's call it 'base') will then be used to + create the C macros SN_base, LN_base, NID_base and OBJ_base. + + Note that if the base name contains spaces, dashes or periods, + those will be converte to underscore. + +Then there are some extra commands: + + !Alias foo 1 2 3 4 + + This juts makes a name foo for an OID. The C macro + OBJ_foo will be created as a result. + + !Cname foo + + This makes sure that the name foo will be used as base name + in C. + + !module foo + 1 2 3 4 : shortName : Long Name + !global + + The !module command was meant to define a kind of modularity. + What it does is to make sure the module name is prepended + to the base name. !global turns this off. This construction + is not recursive. + +Lines starting with # are treated as comments, as well as any line starting +with ! and not matching the commands above. + diff --git a/src/lib/libcrypto/objects/objects.pl b/src/lib/libcrypto/objects/objects.pl new file mode 100644 index 0000000000..c956bbb841 --- /dev/null +++ b/src/lib/libcrypto/objects/objects.pl @@ -0,0 +1,224 @@ +#!/usr/local/bin/perl + +open (NUMIN,"$ARGV[1]") || die "Can't open number file $ARGV[1]"; +$max_nid=0; +$o=0; +while() + { + chop; + $o++; + s/#.*$//; + next if /^\s*$/; + ($Cname,$mynum) = split; + if (defined($nidn{$mynum})) + { die "$ARGV[1]:$o:There's already an object with NID ",$mynum," on line ",$order{$mynum},"\n"; } + $nid{$Cname} = $mynum; + $nidn{$mynum} = $Cname; + $order{$mynum} = $o; + $max_nid = $mynum if $mynum > $max_nid; + } +close NUMIN; + +open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]"; +$Cname=""; +$o=0; +while () + { + chop; + $o++; + if (/^!module\s+(.*)$/) + { + $module = $1."-"; + $module =~ s/\./_/g; + $module =~ s/-/_/g; + } + if (/^!global$/) + { $module = ""; } + if (/^!Cname\s+(.*)$/) + { $Cname = $1; } + if (/^!Alias\s+(.+?)\s+(.*)$/) + { + $Cname = $module.$1; + $myoid = $2; + $myoid = &process_oid($myoid); + $Cname =~ s/-/_/g; + $ordern{$o} = $Cname; + $order{$Cname} = $o; + $obj{$Cname} = $myoid; + $_ = ""; + $Cname = ""; + } + s/!.*$//; + s/#.*$//; + next if /^\s*$/; + ($myoid,$mysn,$myln) = split ':'; + $mysn =~ s/^\s*//; + $mysn =~ s/\s*$//; + $myln =~ s/^\s*//; + $myln =~ s/\s*$//; + $myoid =~ s/^\s*//; + $myoid =~ s/\s*$//; + if ($myoid ne "") + { + $myoid = &process_oid($myoid); + } + + if ($Cname eq "" && !($myln =~ / /)) + { + $Cname = $myln; + $Cname =~ s/\./_/g; + $Cname =~ s/-/_/g; + if ($Cname ne "" && defined($ln{$module.$Cname})) + { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + if ($Cname eq "") + { + $Cname = $mysn; + $Cname =~ s/-/_/g; + if ($Cname ne "" && defined($sn{$module.$Cname})) + { die "objects.txt:$o:There's already an object with short name ",$sn{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + if ($Cname eq "") + { + $Cname = $myln; + $Cname =~ s/-/_/g; + $Cname =~ s/\./_/g; + $Cname =~ s/ /_/g; + if ($Cname ne "" && defined($ln{$module.$Cname})) + { die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; } + } + $Cname =~ s/\./_/g; + $Cname =~ s/-/_/g; + $Cname = $module.$Cname; + $ordern{$o} = $Cname; + $order{$Cname} = $o; + $sn{$Cname} = $mysn; + $ln{$Cname} = $myln; + $obj{$Cname} = $myoid; + if (!defined($nid{$Cname})) + { + $max_nid++; + $nid{$Cname} = $max_nid; + $nidn{$max_nid} = $Cname; + } + $Cname=""; + } +close IN; + +open (NUMOUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]"; +foreach (sort { $a <=> $b } keys %nidn) + { + print NUMOUT $nidn{$_},"\t\t",$_,"\n"; + } +close NUMOUT; + +open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]"; +print OUT <<'EOF'; +/* lib/obj/obj_mac.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.] + */ + +/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the + * following command: + * perl objects.pl objects.txt obj_mac.num obj_mac.h + */ + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +EOF + +foreach (sort { $a <=> $b } keys %ordern) + { + $Cname=$ordern{$_}; + print OUT "#define SN_",$Cname,"\t\t\"",$sn{$Cname},"\"\n" if $sn{$Cname} ne ""; + print OUT "#define LN_",$Cname,"\t\t\"",$ln{$Cname},"\"\n" if $ln{$Cname} ne ""; + print OUT "#define NID_",$Cname,"\t\t",$nid{$Cname},"\n" if $nid{$Cname} ne ""; + print OUT "#define OBJ_",$Cname,"\t\t",$obj{$Cname},"\n" if $obj{$Cname} ne ""; + print OUT "\n"; + } + +close OUT; + +sub process_oid + { + local($oid)=@_; + local(@a,$oid_pref); + + @a = split(/\s+/,$myoid); + $pref_oid = ""; + $pref_sep = ""; + if (!($a[0] =~ /^[0-9]+$/)) + { + $a[0] =~ s/-/_/g; + $pref_oid = "OBJ_" . $a[0]; + $pref_sep = ","; + shift @a; + } + $oids = join('L,',@a) . "L"; + if ($oids ne "L") + { + $oids = $pref_oid . $pref_sep . $oids; + } + else + { + $oids = $pref_oid; + } + return($oids); + } diff --git a/src/lib/libcrypto/ocsp/ocsp.h b/src/lib/libcrypto/ocsp/ocsp.h new file mode 100644 index 0000000000..fab3c03182 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp.h @@ -0,0 +1,619 @@ +/* ocsp.h */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * 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_OCSP_H +#define HEADER_OCSP_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Various flags and values */ + +#define OCSP_DEFAULT_NONCE_LENGTH 16 + +#define OCSP_NOCERTS 0x1 +#define OCSP_NOINTERN 0x2 +#define OCSP_NOSIGS 0x4 +#define OCSP_NOCHAIN 0x8 +#define OCSP_NOVERIFY 0x10 +#define OCSP_NOEXPLICIT 0x20 +#define OCSP_NOCASIGN 0x40 +#define OCSP_NODELEGATED 0x80 +#define OCSP_NOCHECKS 0x100 +#define OCSP_TRUSTOTHER 0x200 +#define OCSP_RESPID_KEY 0x400 +#define OCSP_NOTIME 0x800 + +/* CertID ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier, + * issuerNameHash OCTET STRING, -- Hash of Issuer's DN + * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields) + * serialNumber CertificateSerialNumber } + */ +typedef struct ocsp_cert_id_st + { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *issuerNameHash; + ASN1_OCTET_STRING *issuerKeyHash; + ASN1_INTEGER *serialNumber; + } OCSP_CERTID; + +DECLARE_STACK_OF(OCSP_CERTID) + +/* Request ::= SEQUENCE { + * reqCert CertID, + * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_one_request_st + { + OCSP_CERTID *reqCert; + STACK_OF(X509_EXTENSION) *singleRequestExtensions; + } OCSP_ONEREQ; + +DECLARE_STACK_OF(OCSP_ONEREQ) +DECLARE_ASN1_SET_OF(OCSP_ONEREQ) + + +/* TBSRequest ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * requestorName [1] EXPLICIT GeneralName OPTIONAL, + * requestList SEQUENCE OF Request, + * requestExtensions [2] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_req_info_st + { + ASN1_INTEGER *version; + GENERAL_NAME *requestorName; + STACK_OF(OCSP_ONEREQ) *requestList; + STACK_OF(X509_EXTENSION) *requestExtensions; + } OCSP_REQINFO; + +/* Signature ::= SEQUENCE { + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ +typedef struct ocsp_signature_st + { + X509_ALGOR *signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; + } OCSP_SIGNATURE; + +/* OCSPRequest ::= SEQUENCE { + * tbsRequest TBSRequest, + * optionalSignature [0] EXPLICIT Signature OPTIONAL } + */ +typedef struct ocsp_request_st + { + OCSP_REQINFO *tbsRequest; + OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */ + } OCSP_REQUEST; + +/* OCSPResponseStatus ::= ENUMERATED { + * successful (0), --Response has valid confirmations + * malformedRequest (1), --Illegal confirmation request + * internalError (2), --Internal error in issuer + * tryLater (3), --Try again later + * --(4) is not used + * sigRequired (5), --Must sign the request + * unauthorized (6) --Request unauthorized + * } + */ +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 +#define OCSP_RESPONSE_STATUS_INTERNALERROR 2 +#define OCSP_RESPONSE_STATUS_TRYLATER 3 +#define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 +#define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 + +/* ResponseBytes ::= SEQUENCE { + * responseType OBJECT IDENTIFIER, + * response OCTET STRING } + */ +typedef struct ocsp_resp_bytes_st + { + ASN1_OBJECT *responseType; + ASN1_OCTET_STRING *response; + } OCSP_RESPBYTES; + +/* OCSPResponse ::= SEQUENCE { + * responseStatus OCSPResponseStatus, + * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + */ +typedef struct ocsp_response_st + { + ASN1_ENUMERATED *responseStatus; + OCSP_RESPBYTES *responseBytes; + } OCSP_RESPONSE; + +/* ResponderID ::= CHOICE { + * byName [1] Name, + * byKey [2] KeyHash } + */ +#define V_OCSP_RESPID_NAME 0 +#define V_OCSP_RESPID_KEY 1 +typedef struct ocsp_responder_id_st + { + int type; + union { + X509_NAME* byName; + ASN1_OCTET_STRING *byKey; + } value; + } OCSP_RESPID; +/* KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key + * --(excluding the tag and length fields) + */ + +/* RevokedInfo ::= SEQUENCE { + * revocationTime GeneralizedTime, + * revocationReason [0] EXPLICIT CRLReason OPTIONAL } + */ +typedef struct ocsp_revoked_info_st + { + ASN1_GENERALIZEDTIME *revocationTime; + ASN1_ENUMERATED *revocationReason; + } OCSP_REVOKEDINFO; + +/* CertStatus ::= CHOICE { + * good [0] IMPLICIT NULL, + * revoked [1] IMPLICIT RevokedInfo, + * unknown [2] IMPLICIT UnknownInfo } + */ +#define V_OCSP_CERTSTATUS_GOOD 0 +#define V_OCSP_CERTSTATUS_REVOKED 1 +#define V_OCSP_CERTSTATUS_UNKNOWN 2 +typedef struct ocsp_cert_status_st + { + int type; + union { + ASN1_NULL *good; + OCSP_REVOKEDINFO *revoked; + ASN1_NULL *unknown; + } value; + } OCSP_CERTSTATUS; + +/* SingleResponse ::= SEQUENCE { + * certID CertID, + * certStatus CertStatus, + * thisUpdate GeneralizedTime, + * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + * singleExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_single_response_st + { + OCSP_CERTID *certId; + OCSP_CERTSTATUS *certStatus; + ASN1_GENERALIZEDTIME *thisUpdate; + ASN1_GENERALIZEDTIME *nextUpdate; + STACK_OF(X509_EXTENSION) *singleExtensions; + } OCSP_SINGLERESP; + +DECLARE_STACK_OF(OCSP_SINGLERESP) +DECLARE_ASN1_SET_OF(OCSP_SINGLERESP) + +/* ResponseData ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * responderID ResponderID, + * producedAt GeneralizedTime, + * responses SEQUENCE OF SingleResponse, + * responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_response_data_st + { + ASN1_INTEGER *version; + OCSP_RESPID *responderId; + ASN1_GENERALIZEDTIME *producedAt; + STACK_OF(OCSP_SINGLERESP) *responses; + STACK_OF(X509_EXTENSION) *responseExtensions; + } OCSP_RESPDATA; + +/* BasicOCSPResponse ::= SEQUENCE { + * tbsResponseData ResponseData, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ + /* Note 1: + The value for "signature" is specified in the OCSP rfc2560 as follows: + "The value for the signature SHALL be computed on the hash of the DER + encoding ResponseData." This means that you must hash the DER-encoded + tbsResponseData, and then run it through a crypto-signing function, which + will (at least w/RSA) do a hash-'n'-private-encrypt operation. This seems + a bit odd, but that's the spec. Also note that the data structures do not + leave anywhere to independently specify the algorithm used for the initial + hash. So, we look at the signature-specification algorithm, and try to do + something intelligent. -- Kathy Weinhold, CertCo */ + /* Note 2: + It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open + for interpretation. I've done tests against another responder, and found + that it doesn't do the double hashing that the RFC seems to say one + should. Therefore, all relevant functions take a flag saying which + variant should be used. -- Richard Levitte, OpenSSL team and CeloCom */ +typedef struct ocsp_basic_response_st + { + OCSP_RESPDATA *tbsResponseData; + X509_ALGOR *signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; + } OCSP_BASICRESP; + +/* + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + */ +#define OCSP_REVOKED_STATUS_NOSTATUS -1 +#define OCSP_REVOKED_STATUS_UNSPECIFIED 0 +#define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1 +#define OCSP_REVOKED_STATUS_CACOMPROMISE 2 +#define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3 +#define OCSP_REVOKED_STATUS_SUPERSEDED 4 +#define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5 +#define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6 +#define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8 + +/* CrlID ::= SEQUENCE { + * crlUrl [0] EXPLICIT IA5String OPTIONAL, + * crlNum [1] EXPLICIT INTEGER OPTIONAL, + * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL } + */ +typedef struct ocsp_crl_id_st + { + ASN1_IA5STRING *crlUrl; + ASN1_INTEGER *crlNum; + ASN1_GENERALIZEDTIME *crlTime; + } OCSP_CRLID; + +/* ServiceLocator ::= SEQUENCE { + * issuer Name, + * locator AuthorityInfoAccessSyntax OPTIONAL } + */ +typedef struct ocsp_service_locator_st + { + X509_NAME* issuer; + STACK_OF(ACCESS_DESCRIPTION) *locator; + } OCSP_SERVICELOC; + +#define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" +#define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" + +#define d2i_OCSP_REQUEST_bio(bp,p) (OCSP_REQUEST*)ASN1_d2i_bio((char*(*)()) \ + OCSP_REQUEST_new,(char *(*)())d2i_OCSP_REQUEST, (bp),\ + (unsigned char **)(p)) + +#define d2i_OCSP_RESPONSE_bio(bp,p) (OCSP_RESPONSE*)ASN1_d2i_bio((char*(*)())\ + OCSP_REQUEST_new,(char *(*)())d2i_OCSP_RESPONSE, (bp),\ + (unsigned char **)(p)) + +#define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL) + +#define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\ + (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL) + +#define PEM_write_bio_OCSP_REQUEST(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\ + bp,(char *)o, NULL,NULL,0,NULL,NULL) + +#define PEM_write_bio_OCSP_RESPONSE(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\ + bp,(char *)o, NULL,NULL,0,NULL,NULL) + +#define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio(i2d_OCSP_RESPONSE,bp,\ + (unsigned char *)o) + +#define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio(i2d_OCSP_REQUEST,bp,\ + (unsigned char *)o) + +#define OCSP_REQUEST_sign(o,pkey,md) \ + ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\ + o->optionalSignature->signatureAlgorithm,NULL,\ + o->optionalSignature->signature,o->tbsRequest,pkey,md) + +#define OCSP_BASICRESP_sign(o,pkey,md,d) \ + ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),o->signatureAlgorithm,NULL,\ + o->signature,o->tbsResponseData,pkey,md) + +#define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\ + a->optionalSignature->signatureAlgorithm,\ + a->optionalSignature->signature,a->tbsRequest,r) + +#define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\ + a->signatureAlgorithm,a->signature,a->tbsResponseData,r) + +#define ASN1_BIT_STRING_digest(data,type,md,len) \ + ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len) + +#define OCSP_CERTID_dup(cid) (OCSP_CERTID*)ASN1_dup((int(*)())i2d_OCSP_CERTID,\ + (char *(*)())d2i_OCSP_CERTID,(char *)(cid)) + +#define OCSP_CERTSTATUS_dup(cs)\ + (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\ + (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs)) + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req); + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer); + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, + X509_NAME *issuerName, + ASN1_BIT_STRING* issuerKey, + ASN1_INTEGER *serialNumber); + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid); + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len); +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len); +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs); +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req); + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm); +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert); + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, + unsigned long flags); + +int OCSP_response_status(OCSP_RESPONSE *resp); +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); + +int OCSP_resp_count(OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx); +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last); +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, + ASN1_GENERALIZEDTIME *nextupd, + long sec, long maxsec); + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags); + +int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl); + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b); +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); + +int OCSP_request_onereq_count(OCSP_REQUEST *req); +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one); +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, + ASN1_INTEGER **pserial, OCSP_CERTID *cid); +int OCSP_request_is_signed(OCSP_REQUEST *req); +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, + OCSP_CERTID *cid, + int status, int reason, + ASN1_TIME *revtime, + ASN1_TIME *thisupd, ASN1_TIME *nextupd); +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert); +int OCSP_basic_sign(OCSP_BASICRESP *brsp, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); + +ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, int (*i2d)(), + char *data, STACK_OF(ASN1_OBJECT) *sk); + +X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim); + +X509_EXTENSION *OCSP_accept_responses_new(char **oids); + +X509_EXTENSION *OCSP_archive_cutoff_new(char* tim); + +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls); + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x); +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos); +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos); +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos); +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc); +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc); +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx); +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc); + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x); +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos); +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos); +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos); +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc); +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc); +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx); +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc); + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x); +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos); +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos); +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos); +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc); +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc); +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx); +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc); + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x); +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos); +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos); +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos); +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc); +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc); +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx); +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc); + +DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS) +DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPID) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES) +DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTID) +DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST) +DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE) +DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_CRLID) +DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC) + +char *OCSP_response_status_str(long s); +char *OCSP_cert_status_str(long s); +char *OCSP_crl_reason_str(long s); + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags); +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags); + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); + +/* 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. + */ +void ERR_load_OCSP_strings(void); + +/* Error codes for the OCSP functions. */ + +/* Function codes. */ +#define OCSP_F_ASN1_STRING_ENCODE 100 +#define OCSP_F_CERT_ID_NEW 101 +#define OCSP_F_D2I_OCSP_NONCE 102 +#define OCSP_F_OCSP_BASIC_ADD1_STATUS 103 +#define OCSP_F_OCSP_BASIC_SIGN 104 +#define OCSP_F_OCSP_BASIC_VERIFY 105 +#define OCSP_F_OCSP_CHECK_DELEGATED 106 +#define OCSP_F_OCSP_CHECK_IDS 107 +#define OCSP_F_OCSP_CHECK_ISSUER 108 +#define OCSP_F_OCSP_CHECK_VALIDITY 115 +#define OCSP_F_OCSP_MATCH_ISSUERID 109 +#define OCSP_F_OCSP_PARSE_URL 114 +#define OCSP_F_OCSP_REQUEST_SIGN 110 +#define OCSP_F_OCSP_REQUEST_VERIFY 116 +#define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111 +#define OCSP_F_OCSP_SENDREQ_BIO 112 +#define OCSP_F_REQUEST_VERIFY 113 + +/* Reason codes. */ +#define OCSP_R_BAD_DATA 100 +#define OCSP_R_CERTIFICATE_VERIFY_ERROR 101 +#define OCSP_R_DIGEST_ERR 102 +#define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122 +#define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123 +#define OCSP_R_ERROR_PARSING_URL 121 +#define OCSP_R_MISSING_OCSPSIGNING_USAGE 103 +#define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124 +#define OCSP_R_NOT_BASIC_RESPONSE 104 +#define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105 +#define OCSP_R_NO_CONTENT 106 +#define OCSP_R_NO_PUBLIC_KEY 107 +#define OCSP_R_NO_RESPONSE_DATA 108 +#define OCSP_R_NO_REVOKED_TIME 109 +#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110 +#define OCSP_R_REQUEST_NOT_SIGNED 128 +#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111 +#define OCSP_R_ROOT_CA_NOT_TRUSTED 112 +#define OCSP_R_SERVER_READ_ERROR 113 +#define OCSP_R_SERVER_RESPONSE_ERROR 114 +#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115 +#define OCSP_R_SERVER_WRITE_ERROR 116 +#define OCSP_R_SIGNATURE_FAILURE 117 +#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118 +#define OCSP_R_STATUS_EXPIRED 125 +#define OCSP_R_STATUS_NOT_YET_VALID 126 +#define OCSP_R_STATUS_TOO_OLD 127 +#define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119 +#define OCSP_R_UNKNOWN_NID 120 +#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/libcrypto/ocsp/ocsp_asn.c b/src/lib/libcrypto/ocsp/ocsp_asn.c new file mode 100644 index 0000000000..8c148cda6a --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_asn.c @@ -0,0 +1,182 @@ +/* ocsp_asn.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include + +ASN1_SEQUENCE(OCSP_SIGNATURE) = { + ASN1_SIMPLE(OCSP_SIGNATURE, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(OCSP_SIGNATURE, signature, ASN1_BIT_STRING), + ASN1_EXP_SEQUENCE_OF(OCSP_SIGNATURE, certs, X509, 0) +} ASN1_SEQUENCE_END(OCSP_SIGNATURE) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_SIGNATURE) + +ASN1_SEQUENCE(OCSP_CERTID) = { + ASN1_SIMPLE(OCSP_CERTID, hashAlgorithm, X509_ALGOR), + ASN1_SIMPLE(OCSP_CERTID, issuerNameHash, ASN1_OCTET_STRING), + ASN1_SIMPLE(OCSP_CERTID, issuerKeyHash, ASN1_OCTET_STRING), + ASN1_SIMPLE(OCSP_CERTID, serialNumber, ASN1_INTEGER) +} ASN1_SEQUENCE_END(OCSP_CERTID) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_CERTID) + +ASN1_SEQUENCE(OCSP_ONEREQ) = { + ASN1_SIMPLE(OCSP_ONEREQ, reqCert, OCSP_CERTID), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_ONEREQ, singleRequestExtensions, X509_EXTENSION, 0) +} ASN1_SEQUENCE_END(OCSP_ONEREQ) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_ONEREQ) + +ASN1_SEQUENCE(OCSP_REQINFO) = { + ASN1_EXP_OPT(OCSP_REQINFO, version, ASN1_INTEGER, 0), + ASN1_EXP_OPT(OCSP_REQINFO, requestorName, GENERAL_NAME, 1), + ASN1_SEQUENCE_OF(OCSP_REQINFO, requestList, OCSP_ONEREQ), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_REQINFO, requestExtensions, X509_EXTENSION, 2) +} ASN1_SEQUENCE_END(OCSP_REQINFO) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_REQINFO) + +ASN1_SEQUENCE(OCSP_REQUEST) = { + ASN1_SIMPLE(OCSP_REQUEST, tbsRequest, OCSP_REQINFO), + ASN1_EXP_OPT(OCSP_REQUEST, optionalSignature, OCSP_SIGNATURE, 0) +} ASN1_SEQUENCE_END(OCSP_REQUEST) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_REQUEST) + +/* OCSP_RESPONSE templates */ + +ASN1_SEQUENCE(OCSP_RESPBYTES) = { + ASN1_SIMPLE(OCSP_RESPBYTES, responseType, ASN1_OBJECT), + ASN1_SIMPLE(OCSP_RESPBYTES, response, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(OCSP_RESPBYTES) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPBYTES) + +ASN1_SEQUENCE(OCSP_RESPONSE) = { + ASN1_SIMPLE(OCSP_RESPONSE, responseStatus, ASN1_ENUMERATED), + ASN1_EXP_OPT(OCSP_RESPONSE, responseBytes, OCSP_RESPBYTES, 0) +} ASN1_SEQUENCE_END(OCSP_RESPONSE) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPONSE) + +ASN1_CHOICE(OCSP_RESPID) = { + ASN1_EXP(OCSP_RESPID, value.byName, X509_NAME, 1), + ASN1_IMP(OCSP_RESPID, value.byKey, ASN1_OCTET_STRING, 2) +} ASN1_CHOICE_END(OCSP_RESPID) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPID) + +ASN1_SEQUENCE(OCSP_REVOKEDINFO) = { + ASN1_SIMPLE(OCSP_REVOKEDINFO, revocationTime, ASN1_GENERALIZEDTIME), + ASN1_EXP_OPT(OCSP_REVOKEDINFO, revocationReason, ASN1_ENUMERATED, 0) +} ASN1_SEQUENCE_END(OCSP_REVOKEDINFO) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_REVOKEDINFO) + +ASN1_CHOICE(OCSP_CERTSTATUS) = { + ASN1_IMP(OCSP_CERTSTATUS, value.good, ASN1_NULL, 0), + ASN1_IMP(OCSP_CERTSTATUS, value.revoked, OCSP_REVOKEDINFO, 1), + ASN1_IMP(OCSP_CERTSTATUS, value.unknown, ASN1_NULL, 2) +} ASN1_CHOICE_END(OCSP_CERTSTATUS) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_CERTSTATUS) + +ASN1_SEQUENCE(OCSP_SINGLERESP) = { + ASN1_SIMPLE(OCSP_SINGLERESP, certId, OCSP_CERTID), + ASN1_SIMPLE(OCSP_SINGLERESP, certStatus, OCSP_CERTSTATUS), + ASN1_SIMPLE(OCSP_SINGLERESP, thisUpdate, ASN1_GENERALIZEDTIME), + ASN1_EXP_OPT(OCSP_SINGLERESP, nextUpdate, ASN1_GENERALIZEDTIME, 0), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_SINGLERESP, singleExtensions, X509_EXTENSION, 1) +} ASN1_SEQUENCE_END(OCSP_SINGLERESP) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_SINGLERESP) + +ASN1_SEQUENCE(OCSP_RESPDATA) = { + ASN1_EXP_OPT(OCSP_RESPDATA, version, ASN1_INTEGER, 0), + ASN1_SIMPLE(OCSP_RESPDATA, responderId, OCSP_RESPID), + ASN1_SIMPLE(OCSP_RESPDATA, producedAt, ASN1_GENERALIZEDTIME), + ASN1_SEQUENCE_OF(OCSP_RESPDATA, responses, OCSP_SINGLERESP), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_RESPDATA, responseExtensions, X509_EXTENSION, 1) +} ASN1_SEQUENCE_END(OCSP_RESPDATA) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_RESPDATA) + +ASN1_SEQUENCE(OCSP_BASICRESP) = { + ASN1_SIMPLE(OCSP_BASICRESP, tbsResponseData, OCSP_RESPDATA), + ASN1_SIMPLE(OCSP_BASICRESP, signatureAlgorithm, X509_ALGOR), + ASN1_SIMPLE(OCSP_BASICRESP, signature, ASN1_BIT_STRING), + ASN1_EXP_SEQUENCE_OF_OPT(OCSP_BASICRESP, certs, X509, 0) +} ASN1_SEQUENCE_END(OCSP_BASICRESP) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_BASICRESP) + +ASN1_SEQUENCE(OCSP_CRLID) = { + ASN1_EXP_OPT(OCSP_CRLID, crlUrl, ASN1_IA5STRING, 0), + ASN1_EXP_OPT(OCSP_CRLID, crlNum, ASN1_INTEGER, 1), + ASN1_EXP_OPT(OCSP_CRLID, crlTime, ASN1_GENERALIZEDTIME, 2) +} ASN1_SEQUENCE_END(OCSP_CRLID) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_CRLID) + +ASN1_SEQUENCE(OCSP_SERVICELOC) = { + ASN1_SIMPLE(OCSP_SERVICELOC, issuer, X509_NAME), + ASN1_SEQUENCE_OF_OPT(OCSP_SERVICELOC, locator, ACCESS_DESCRIPTION) +} ASN1_SEQUENCE_END(OCSP_SERVICELOC) + +IMPLEMENT_ASN1_FUNCTIONS(OCSP_SERVICELOC) diff --git a/src/lib/libcrypto/ocsp/ocsp_cl.c b/src/lib/libcrypto/ocsp/ocsp_cl.c new file mode 100644 index 0000000000..9b3e6dd8ca --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_cl.c @@ -0,0 +1,370 @@ +/* ocsp_cl.c */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * 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 +#include +#include + +/* Utility functions related to sending OCSP requests and extracting + * relevant information from the response. + */ + +/* Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ + * pointer: useful if we want to add extensions. + */ + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) + { + OCSP_ONEREQ *one = NULL; + + if (!(one = OCSP_ONEREQ_new())) goto err; + if (one->reqCert) OCSP_CERTID_free(one->reqCert); + one->reqCert = cid; + if (req && + !sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)) + goto err; + return one; +err: + OCSP_ONEREQ_free(one); + return NULL; + } + +/* Set requestorName from an X509_NAME structure */ + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm) + { + GENERAL_NAME *gen; + gen = GENERAL_NAME_new(); + if (!X509_NAME_set(&gen->d.directoryName, nm)) + { + GENERAL_NAME_free(gen); + return 0; + } + gen->type = GEN_DIRNAME; + if (req->tbsRequest->requestorName) + GENERAL_NAME_free(req->tbsRequest->requestorName); + req->tbsRequest->requestorName = gen; + return 1; + } + + +/* Add a certificate to an OCSP request */ + +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert) + { + OCSP_SIGNATURE *sig; + if (!req->optionalSignature) + req->optionalSignature = OCSP_SIGNATURE_new(); + sig = req->optionalSignature; + if (!sig) return 0; + if (!cert) return 1; + if (!sig->certs && !(sig->certs = sk_X509_new_null())) + return 0; + + if(!sk_X509_push(sig->certs, cert)) return 0; + CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + return 1; + } + +/* Sign an OCSP request set the requestorName to the subjec + * name of an optional signers certificate and include one + * or more optional certificates in the request. Behaves + * like PKCS7_sign(). + */ + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, + unsigned long flags) + { + int i; + OCSP_SIGNATURE *sig; + X509 *x; + + if (!OCSP_request_set1_name(req, X509_get_subject_name(signer))) + goto err; + + if (!(req->optionalSignature = sig = OCSP_SIGNATURE_new())) goto err; + if (!dgst) dgst = EVP_sha1(); + if (key) + { + if (!X509_check_private_key(signer, key)) + { + OCSPerr(OCSP_F_OCSP_REQUEST_SIGN, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + goto err; + } + if (!OCSP_REQUEST_sign(req, key, dgst)) goto err; + } + + if (!(flags & OCSP_NOCERTS)) + { + if(!OCSP_request_add1_cert(req, signer)) goto err; + for (i = 0; i < sk_X509_num(certs); i++) + { + x = sk_X509_value(certs, i); + if (!OCSP_request_add1_cert(req, x)) goto err; + } + } + + return 1; +err: + OCSP_SIGNATURE_free(req->optionalSignature); + req->optionalSignature = NULL; + return 0; + } + +/* Get response status */ + +int OCSP_response_status(OCSP_RESPONSE *resp) + { + return ASN1_ENUMERATED_get(resp->responseStatus); + } + +/* Extract basic response from OCSP_RESPONSE or NULL if + * no basic response present. + */ + + +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) + { + OCSP_RESPBYTES *rb; + rb = resp->responseBytes; + if (!rb) + { + OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NO_RESPONSE_DATA); + return NULL; + } + if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) + { + OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NOT_BASIC_RESPONSE); + return NULL; + } + + return ASN1_item_unpack(rb->response, ASN1_ITEM_rptr(OCSP_BASICRESP)); + } + +/* Return number of OCSP_SINGLERESP reponses present in + * a basic response. + */ + +int OCSP_resp_count(OCSP_BASICRESP *bs) + { + if (!bs) return -1; + return sk_OCSP_SINGLERESP_num(bs->tbsResponseData->responses); + } + +/* Extract an OCSP_SINGLERESP response with a given index */ + +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) + { + if (!bs) return NULL; + return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx); + } + +/* Look single response matching a given certificate ID */ + +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) + { + int i; + STACK_OF(OCSP_SINGLERESP) *sresp; + OCSP_SINGLERESP *single; + if (!bs) return -1; + if (last < 0) last = 0; + else last++; + sresp = bs->tbsResponseData->responses; + for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++) + { + single = sk_OCSP_SINGLERESP_value(sresp, i); + if (!OCSP_id_cmp(id, single->certId)) return i; + } + return -1; + } + +/* Extract status information from an OCSP_SINGLERESP structure. + * Note: the revtime and reason values are only set if the + * certificate status is revoked. Returns numerical value of + * status. + */ + +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd) + { + int ret; + OCSP_CERTSTATUS *cst; + if(!single) return -1; + cst = single->certStatus; + ret = cst->type; + if (ret == V_OCSP_CERTSTATUS_REVOKED) + { + OCSP_REVOKEDINFO *rev = cst->value.revoked; + if (revtime) *revtime = rev->revocationTime; + if (reason) + { + if(rev->revocationReason) + *reason = ASN1_ENUMERATED_get(rev->revocationReason); + else *reason = -1; + } + } + if(thisupd) *thisupd = single->thisUpdate; + if(nextupd) *nextupd = single->nextUpdate; + return ret; + } + +/* This function combines the previous ones: look up a certificate ID and + * if found extract status information. Return 0 is successful. + */ + +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd) + { + int i; + OCSP_SINGLERESP *single; + i = OCSP_resp_find(bs, id, -1); + /* Maybe check for multiple responses and give an error? */ + if(i < 0) return 0; + single = OCSP_resp_get0(bs, i); + i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd); + if(status) *status = i; + return 1; + } + +/* Check validity of thisUpdate and nextUpdate fields. It is possible that the request will + * take a few seconds to process and/or the time wont be totally accurate. Therefore to avoid + * rejecting otherwise valid time we allow the times to be within 'nsec' of the current time. + * Also to avoid accepting very old responses without a nextUpdate field an optional maxage + * parameter specifies the maximum age the thisUpdate field can be. + */ + +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec) + { + int ret = 1; + time_t t_now, t_tmp; + time(&t_now); + /* Check thisUpdate is valid and not more than nsec in the future */ + if (!ASN1_GENERALIZEDTIME_check(thisupd)) + { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_THISUPDATE_FIELD); + ret = 0; + } + else + { + t_tmp = t_now + nsec; + if (X509_cmp_time(thisupd, &t_tmp) > 0) + { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_NOT_YET_VALID); + ret = 0; + } + + /* If maxsec specified check thisUpdate is not more than maxsec in the past */ + if (maxsec >= 0) + { + t_tmp = t_now - maxsec; + if (X509_cmp_time(thisupd, &t_tmp) < 0) + { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_TOO_OLD); + ret = 0; + } + } + } + + + if (!nextupd) return ret; + + /* Check nextUpdate is valid and not more than nsec in the past */ + if (!ASN1_GENERALIZEDTIME_check(nextupd)) + { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD); + ret = 0; + } + else + { + t_tmp = t_now - nsec; + if (X509_cmp_time(nextupd, &t_tmp) < 0) + { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_EXPIRED); + ret = 0; + } + } + + /* Also don't allow nextUpdate to precede thisUpdate */ + if (ASN1_STRING_cmp(nextupd, thisupd) < 0) + { + OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE); + ret = 0; + } + + return ret; + } diff --git a/src/lib/libcrypto/ocsp/ocsp_err.c b/src/lib/libcrypto/ocsp/ocsp_err.c new file mode 100644 index 0000000000..4c4d8306f8 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_err.c @@ -0,0 +1,139 @@ +/* crypto/ocsp/ocsp_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 OPENSSL_NO_ERR +static ERR_STRING_DATA OCSP_str_functs[]= + { +{ERR_PACK(0,OCSP_F_ASN1_STRING_ENCODE,0), "ASN1_STRING_encode"}, +{ERR_PACK(0,OCSP_F_CERT_ID_NEW,0), "CERT_ID_NEW"}, +{ERR_PACK(0,OCSP_F_D2I_OCSP_NONCE,0), "D2I_OCSP_NONCE"}, +{ERR_PACK(0,OCSP_F_OCSP_BASIC_ADD1_STATUS,0), "OCSP_basic_add1_status"}, +{ERR_PACK(0,OCSP_F_OCSP_BASIC_SIGN,0), "OCSP_basic_sign"}, +{ERR_PACK(0,OCSP_F_OCSP_BASIC_VERIFY,0), "OCSP_basic_verify"}, +{ERR_PACK(0,OCSP_F_OCSP_CHECK_DELEGATED,0), "OCSP_CHECK_DELEGATED"}, +{ERR_PACK(0,OCSP_F_OCSP_CHECK_IDS,0), "OCSP_CHECK_IDS"}, +{ERR_PACK(0,OCSP_F_OCSP_CHECK_ISSUER,0), "OCSP_CHECK_ISSUER"}, +{ERR_PACK(0,OCSP_F_OCSP_CHECK_VALIDITY,0), "OCSP_check_validity"}, +{ERR_PACK(0,OCSP_F_OCSP_MATCH_ISSUERID,0), "OCSP_MATCH_ISSUERID"}, +{ERR_PACK(0,OCSP_F_OCSP_PARSE_URL,0), "OCSP_parse_url"}, +{ERR_PACK(0,OCSP_F_OCSP_REQUEST_SIGN,0), "OCSP_request_sign"}, +{ERR_PACK(0,OCSP_F_OCSP_REQUEST_VERIFY,0), "OCSP_request_verify"}, +{ERR_PACK(0,OCSP_F_OCSP_RESPONSE_GET1_BASIC,0), "OCSP_response_get1_basic"}, +{ERR_PACK(0,OCSP_F_OCSP_SENDREQ_BIO,0), "OCSP_sendreq_bio"}, +{ERR_PACK(0,OCSP_F_REQUEST_VERIFY,0), "REQUEST_VERIFY"}, +{0,NULL} + }; + +static ERR_STRING_DATA OCSP_str_reasons[]= + { +{OCSP_R_BAD_DATA ,"bad data"}, +{OCSP_R_CERTIFICATE_VERIFY_ERROR ,"certificate verify error"}, +{OCSP_R_DIGEST_ERR ,"digest err"}, +{OCSP_R_ERROR_IN_NEXTUPDATE_FIELD ,"error in nextupdate field"}, +{OCSP_R_ERROR_IN_THISUPDATE_FIELD ,"error in thisupdate field"}, +{OCSP_R_ERROR_PARSING_URL ,"error parsing url"}, +{OCSP_R_MISSING_OCSPSIGNING_USAGE ,"missing ocspsigning usage"}, +{OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE ,"nextupdate before thisupdate"}, +{OCSP_R_NOT_BASIC_RESPONSE ,"not basic response"}, +{OCSP_R_NO_CERTIFICATES_IN_CHAIN ,"no certificates in chain"}, +{OCSP_R_NO_CONTENT ,"no content"}, +{OCSP_R_NO_PUBLIC_KEY ,"no public key"}, +{OCSP_R_NO_RESPONSE_DATA ,"no response data"}, +{OCSP_R_NO_REVOKED_TIME ,"no revoked time"}, +{OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE,"private key does not match certificate"}, +{OCSP_R_REQUEST_NOT_SIGNED ,"request not signed"}, +{OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA,"response contains no revocation data"}, +{OCSP_R_ROOT_CA_NOT_TRUSTED ,"root ca not trusted"}, +{OCSP_R_SERVER_READ_ERROR ,"server read error"}, +{OCSP_R_SERVER_RESPONSE_ERROR ,"server response error"}, +{OCSP_R_SERVER_RESPONSE_PARSE_ERROR ,"server response parse error"}, +{OCSP_R_SERVER_WRITE_ERROR ,"server write error"}, +{OCSP_R_SIGNATURE_FAILURE ,"signature failure"}, +{OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND ,"signer certificate not found"}, +{OCSP_R_STATUS_EXPIRED ,"status expired"}, +{OCSP_R_STATUS_NOT_YET_VALID ,"status not yet valid"}, +{OCSP_R_STATUS_TOO_OLD ,"status too old"}, +{OCSP_R_UNKNOWN_MESSAGE_DIGEST ,"unknown message digest"}, +{OCSP_R_UNKNOWN_NID ,"unknown nid"}, +{OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE ,"unsupported requestorname type"}, +{0,NULL} + }; + +#endif + +void ERR_load_OCSP_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(ERR_LIB_OCSP,OCSP_str_functs); + ERR_load_strings(ERR_LIB_OCSP,OCSP_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/ocsp/ocsp_ext.c b/src/lib/libcrypto/ocsp/ocsp_ext.c new file mode 100644 index 0000000000..d6c8899f58 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_ext.c @@ -0,0 +1,528 @@ +/* ocsp_ext.c */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * 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 + +/* Standard wrapper functions for extensions */ + +/* OCSP request extensions */ + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x) + { + return(X509v3_get_ext_count(x->tbsRequest->requestExtensions)); + } + +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos) + { + return(X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions,nid,lastpos)); + } + +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos) + { + return(X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions,obj,lastpos)); + } + +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos) + { + return(X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions,crit,lastpos)); + } + +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc) + { + return(X509v3_get_ext(x->tbsRequest->requestExtensions,loc)); + } + +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc) + { + return(X509v3_delete_ext(x->tbsRequest->requestExtensions,loc)); + } + +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx) + { + return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx); + } + +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, + unsigned long flags) + { + return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value, crit, flags); + } + +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc) + { + return(X509v3_add_ext(&(x->tbsRequest->requestExtensions),ex,loc) != NULL); + } + +/* Single extensions */ + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x) + { + return(X509v3_get_ext_count(x->singleRequestExtensions)); + } + +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos) + { + return(X509v3_get_ext_by_NID(x->singleRequestExtensions,nid,lastpos)); + } + +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos) + { + return(X509v3_get_ext_by_OBJ(x->singleRequestExtensions,obj,lastpos)); + } + +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos) + { + return(X509v3_get_ext_by_critical(x->singleRequestExtensions,crit,lastpos)); + } + +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc) + { + return(X509v3_get_ext(x->singleRequestExtensions,loc)); + } + +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc) + { + return(X509v3_delete_ext(x->singleRequestExtensions,loc)); + } + +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx) + { + return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx); + } + +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags) + { + return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit, flags); + } + +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc) + { + return(X509v3_add_ext(&(x->singleRequestExtensions),ex,loc) != NULL); + } + +/* OCSP Basic response */ + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x) + { + return(X509v3_get_ext_count(x->tbsResponseData->responseExtensions)); + } + +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos) + { + return(X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions,nid,lastpos)); + } + +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos) + { + return(X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions,obj,lastpos)); + } + +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos) + { + return(X509v3_get_ext_by_critical(x->tbsResponseData->responseExtensions,crit,lastpos)); + } + +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc) + { + return(X509v3_get_ext(x->tbsResponseData->responseExtensions,loc)); + } + +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc) + { + return(X509v3_delete_ext(x->tbsResponseData->responseExtensions,loc)); + } + +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx) + { + return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid, crit, idx); + } + +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit, + unsigned long flags) + { + return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid, value, crit, flags); + } + +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc) + { + return(X509v3_add_ext(&(x->tbsResponseData->responseExtensions),ex,loc) != NULL); + } + +/* OCSP single response extensions */ + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x) + { + return(X509v3_get_ext_count(x->singleExtensions)); + } + +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos) + { + return(X509v3_get_ext_by_NID(x->singleExtensions,nid,lastpos)); + } + +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos) + { + return(X509v3_get_ext_by_OBJ(x->singleExtensions,obj,lastpos)); + } + +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos) + { + return(X509v3_get_ext_by_critical(x->singleExtensions,crit,lastpos)); + } + +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc) + { + return(X509v3_get_ext(x->singleExtensions,loc)); + } + +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc) + { + return(X509v3_delete_ext(x->singleExtensions,loc)); + } + +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx) + { + return X509V3_get_d2i(x->singleExtensions, nid, crit, idx); + } + +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit, + unsigned long flags) + { + return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags); + } + +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc) + { + return(X509v3_add_ext(&(x->singleExtensions),ex,loc) != NULL); + } + +/* also CRL Entry Extensions */ + +ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, int (*i2d)(), + char *data, STACK_OF(ASN1_OBJECT) *sk) + { + int i; + unsigned char *p, *b = NULL; + + if (data) + { + if ((i=i2d(data,NULL)) <= 0) goto err; + if (!(b=p=(unsigned char*)OPENSSL_malloc((unsigned int)i))) + goto err; + if (i2d(data, &p) <= 0) goto err; + } + else if (sk) + { + if ((i=i2d_ASN1_SET_OF_ASN1_OBJECT(sk,NULL,i2d,V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL,IS_SEQUENCE))<=0) goto err; + if (!(b=p=(unsigned char*)OPENSSL_malloc((unsigned int)i))) + goto err; + if (i2d_ASN1_SET_OF_ASN1_OBJECT(sk,&p,i2d,V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL,IS_SEQUENCE)<=0) goto err; + } + else + { + OCSPerr(OCSP_F_ASN1_STRING_ENCODE,OCSP_R_BAD_DATA); + goto err; + } + if (!s && !(s = ASN1_STRING_new())) goto err; + if (!(ASN1_STRING_set(s, b, i))) goto err; + OPENSSL_free(b); + return s; +err: + if (b) OPENSSL_free(b); + return NULL; + } + +/* Nonce handling functions */ + +/* Add a nonce to an extension stack. A nonce can be specificed or if NULL + * a random nonce will be generated. + */ + +static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len) + { + unsigned char *tmpval; + ASN1_OCTET_STRING os; + int ret = 0; + if (len <= 0) len = OCSP_DEFAULT_NONCE_LENGTH; + if (val) tmpval = val; + else + { + if (!(tmpval = OPENSSL_malloc(len))) goto err; + RAND_pseudo_bytes(tmpval, len); + } + os.data = tmpval; + os.length = len; + if(!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, + &os, 0, X509V3_ADD_REPLACE)) + goto err; + ret = 1; + err: + if(!val) OPENSSL_free(tmpval); + return ret; + } + + +/* Add nonce to an OCSP request */ + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) + { + return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len); + } + +/* Same as above but for a response */ + +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len) + { + return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val, len); + } + +/* Check nonce validity in a request and response. + * Return value reflects result: + * 1: nonces present and equal. + * 2: nonces both absent. + * 3: nonce present in response only. + * 0: nonces both present and not equal. + * -1: nonce in request only. + * + * For most responders clients can check return > 0. + * If responder doesn't handle nonces return != 0 may be + * necessary. return == 0 is always an error. + */ + +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) + { + /* + * Since we are only interested in the presence or absence of + * the nonce and comparing its value there is no need to use + * the X509V3 routines: this way we can avoid them allocating an + * ASN1_OCTET_STRING structure for the value which would be + * freed immediately anyway. + */ + + int req_idx, resp_idx; + X509_EXTENSION *req_ext, *resp_ext; + req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); + resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1); + /* Check both absent */ + if((req_idx < 0) && (resp_idx < 0)) + return 2; + /* Check in request only */ + if((req_idx >= 0) && (resp_idx < 0)) + return -1; + /* Check in response but not request */ + if((req_idx < 0) && (resp_idx >= 0)) + return 3; + /* Otherwise nonce in request and response so retrieve the extensions */ + req_ext = OCSP_REQUEST_get_ext(req, req_idx); + resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx); + if(ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value)) + return 0; + return 1; + } + +/* Copy the nonce value (if any) from an OCSP request to + * a response. + */ + +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req) + { + X509_EXTENSION *req_ext; + int req_idx; + /* Check for nonce in request */ + req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1); + /* If no nonce that's OK */ + if (req_idx < 0) return 2; + req_ext = OCSP_REQUEST_get_ext(req, req_idx); + return OCSP_BASICRESP_add_ext(resp, req_ext, -1); + } + +X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim) + { + X509_EXTENSION *x = NULL; + OCSP_CRLID *cid = NULL; + + if (!(cid = OCSP_CRLID_new())) goto err; + if (url) + { + if (!(cid->crlUrl = ASN1_IA5STRING_new())) goto err; + if (!(ASN1_STRING_set(cid->crlUrl, url, -1))) goto err; + } + if (n) + { + if (!(cid->crlNum = ASN1_INTEGER_new())) goto err; + if (!(ASN1_INTEGER_set(cid->crlNum, *n))) goto err; + } + if (tim) + { + if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new())) goto err; + if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim))) + goto err; + } + if (!(x = X509_EXTENSION_new())) goto err; + if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_CrlID))) goto err; + if (!(ASN1_STRING_encode(x->value,i2d_OCSP_CRLID,(char*)cid,NULL))) + goto err; + OCSP_CRLID_free(cid); + return x; +err: + if (x) X509_EXTENSION_free(x); + if (cid) OCSP_CRLID_free(cid); + return NULL; + } + +/* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */ +X509_EXTENSION *OCSP_accept_responses_new(char **oids) + { + int nid; + STACK_OF(ASN1_OBJECT) *sk = NULL; + ASN1_OBJECT *o = NULL; + X509_EXTENSION *x = NULL; + + if (!(sk = sk_ASN1_OBJECT_new_null())) goto err; + while (oids && *oids) + { + if ((nid=OBJ_txt2nid(*oids))!=NID_undef&&(o=OBJ_nid2obj(nid))) + sk_ASN1_OBJECT_push(sk, o); + oids++; + } + if (!(x = X509_EXTENSION_new())) goto err; + if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_acceptableResponses))) + goto err; + if (!(ASN1_STRING_encode(x->value,i2d_ASN1_OBJECT,NULL,sk))) + goto err; + sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); + return x; +err: + if (x) X509_EXTENSION_free(x); + if (sk) sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free); + return NULL; + } + +/* ArchiveCutoff ::= GeneralizedTime */ +X509_EXTENSION *OCSP_archive_cutoff_new(char* tim) + { + X509_EXTENSION *x=NULL; + ASN1_GENERALIZEDTIME *gt = NULL; + + if (!(gt = ASN1_GENERALIZEDTIME_new())) goto err; + if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim))) goto err; + if (!(x = X509_EXTENSION_new())) goto err; + if (!(x->object=OBJ_nid2obj(NID_id_pkix_OCSP_archiveCutoff)))goto err; + if (!(ASN1_STRING_encode(x->value,i2d_ASN1_GENERALIZEDTIME, + (char*)gt,NULL))) goto err; + ASN1_GENERALIZEDTIME_free(gt); + return x; +err: + if (gt) ASN1_GENERALIZEDTIME_free(gt); + if (x) X509_EXTENSION_free(x); + return NULL; + } + +/* per ACCESS_DESCRIPTION parameter are oids, of which there are currently + * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This + * method forces NID_ad_ocsp and uniformResourceLocator [6] IA5String. + */ +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls) + { + X509_EXTENSION *x = NULL; + ASN1_IA5STRING *ia5 = NULL; + OCSP_SERVICELOC *sloc = NULL; + ACCESS_DESCRIPTION *ad = NULL; + + if (!(sloc = OCSP_SERVICELOC_new())) goto err; + if (!(sloc->issuer = X509_NAME_dup(issuer))) goto err; + if (urls && *urls && !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null())) goto err; + while (urls && *urls) + { + if (!(ad = ACCESS_DESCRIPTION_new())) goto err; + if (!(ad->method=OBJ_nid2obj(NID_ad_OCSP))) goto err; + if (!(ad->location = GENERAL_NAME_new())) goto err; + if (!(ia5 = ASN1_IA5STRING_new())) goto err; + if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1)) goto err; + ad->location->type = GEN_URI; + ad->location->d.ia5 = ia5; + if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad)) goto err; + urls++; + } + if (!(x = X509_EXTENSION_new())) goto err; + if (!(x->object = OBJ_nid2obj(NID_id_pkix_OCSP_serviceLocator))) + goto err; + if (!(ASN1_STRING_encode(x->value, i2d_OCSP_SERVICELOC, + (char*)sloc, NULL))) goto err; + OCSP_SERVICELOC_free(sloc); + return x; +err: + if (x) X509_EXTENSION_free(x); + if (sloc) OCSP_SERVICELOC_free(sloc); + return NULL; + } + diff --git a/src/lib/libcrypto/ocsp/ocsp_ht.c b/src/lib/libcrypto/ocsp/ocsp_ht.c new file mode 100644 index 0000000000..b78cd37092 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_ht.c @@ -0,0 +1,164 @@ +/* ocsp_ht.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include +#include +#include +#include +#include +#include + +/* Quick and dirty HTTP OCSP request handler. + * Could make this a bit cleverer by adding + * support for non blocking BIOs and a few + * other refinements. + */ + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req) +{ + BIO *mem = NULL; + char tmpbuf[1024]; + OCSP_RESPONSE *resp = NULL; + char *p, *q, *r; + int len, retcode; + static char req_txt[] = +"POST %s HTTP/1.0\r\n\ +Content-Type: application/ocsp-request\r\n\ +Content-Length: %d\r\n\r\n"; + + len = i2d_OCSP_REQUEST(req, NULL); + if(BIO_printf(b, req_txt, path, len) < 0) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR); + goto err; + } + if(i2d_OCSP_REQUEST_bio(b, req) <= 0) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR); + goto err; + } + if(!(mem = BIO_new(BIO_s_mem()))) goto err; + /* Copy response to a memory BIO: socket bios can't do gets! */ + while ((len = BIO_read(b, tmpbuf, 1024))) { + if(len < 0) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_READ_ERROR); + goto err; + } + BIO_write(mem, tmpbuf, len); + } + if(BIO_gets(mem, tmpbuf, 512) <= 0) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + goto err; + } + /* Parse the HTTP response. This will look like this: + * "HTTP/1.0 200 OK". We need to obtain the numeric code and + * informational message. + */ + + /* Skip to first white space (passed protocol info) */ + for(p = tmpbuf; *p && !isspace((unsigned char)*p); p++) continue; + if(!*p) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + goto err; + } + /* Skip past white space to start of response code */ + while(*p && isspace((unsigned char)*p)) p++; + if(!*p) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + goto err; + } + /* Find end of response code: first whitespace after start of code */ + for(q = p; *q && !isspace((unsigned char)*q); q++) continue; + if(!*q) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + goto err; + } + /* Set end of response code and start of message */ + *q++ = 0; + /* Attempt to parse numeric code */ + retcode = strtoul(p, &r, 10); + if(*r) goto err; + /* Skip over any leading white space in message */ + while(*q && isspace((unsigned char)*q)) q++; + if(!*q) goto err; + /* Finally zap any trailing white space in message (include CRLF) */ + /* We know q has a non white space character so this is OK */ + for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0; + if(retcode != 200) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_ERROR); + ERR_add_error_data(4, "Code=", p, ",Reason=", q); + goto err; + } + /* Find blank line marking beginning of content */ + while(BIO_gets(mem, tmpbuf, 512) > 0) + { + for(p = tmpbuf; *p && isspace((unsigned char)*p); p++) continue; + if(!*p) break; + } + if(*p) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_NO_CONTENT); + goto err; + } + if(!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) { + OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,ERR_R_NESTED_ASN1_ERROR); + goto err; + } + err: + BIO_free(mem); + return resp; +} diff --git a/src/lib/libcrypto/ocsp/ocsp_lib.c b/src/lib/libcrypto/ocsp/ocsp_lib.c new file mode 100644 index 0000000000..3875af165c --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_lib.c @@ -0,0 +1,261 @@ +/* ocsp_lib.c */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * 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 +#include + +/* Convert a certificate and its issuer to an OCSP_CERTID */ + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer) +{ + X509_NAME *iname; + ASN1_INTEGER *serial; + ASN1_BIT_STRING *ikey; +#ifndef OPENSSL_NO_SHA1 + if(!dgst) dgst = EVP_sha1(); +#endif + if (subject) + { + iname = X509_get_issuer_name(subject); + serial = X509_get_serialNumber(subject); + } + else + { + iname = X509_get_subject_name(issuer); + serial = NULL; + } + ikey = X509_get0_pubkey_bitstr(issuer); + return OCSP_cert_id_new(dgst, iname, ikey, serial); +} + + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, + X509_NAME *issuerName, + ASN1_BIT_STRING* issuerKey, + ASN1_INTEGER *serialNumber) + { + int nid; + unsigned int i; + X509_ALGOR *alg; + OCSP_CERTID *cid = NULL; + unsigned char md[EVP_MAX_MD_SIZE]; + + if (!(cid = OCSP_CERTID_new())) goto err; + + alg = cid->hashAlgorithm; + if (alg->algorithm != NULL) ASN1_OBJECT_free(alg->algorithm); + if ((nid = EVP_MD_type(dgst)) == NID_undef) + { + OCSPerr(OCSP_F_CERT_ID_NEW,OCSP_R_UNKNOWN_NID); + goto err; + } + if (!(alg->algorithm=OBJ_nid2obj(nid))) goto err; + if ((alg->parameter=ASN1_TYPE_new()) == NULL) goto err; + alg->parameter->type=V_ASN1_NULL; + + if (!X509_NAME_digest(issuerName, dgst, md, &i)) goto digerr; + if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i))) goto err; + + /* Calculate the issuerKey hash, excluding tag and length */ + EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL); + + if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i))) goto err; + + if (serialNumber) + { + ASN1_INTEGER_free(cid->serialNumber); + if (!(cid->serialNumber = ASN1_INTEGER_dup(serialNumber))) goto err; + } + return cid; +digerr: + OCSPerr(OCSP_F_CERT_ID_NEW,OCSP_R_DIGEST_ERR); +err: + if (cid) OCSP_CERTID_free(cid); + return NULL; + } + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) + { + int ret; + ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm); + if (ret) return ret; + ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash); + if (ret) return ret; + return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash); + } + +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b) + { + int ret; + ret = OCSP_id_issuer_cmp(a, b); + if (ret) return ret; + return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber); + } + + +/* Parse a URL and split it up into host, port and path components and whether + * it is SSL. + */ + +int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl) + { + char *p, *buf; + + char *host, *port; + + /* dup the buffer since we are going to mess with it */ + buf = BUF_strdup(url); + if (!buf) goto mem_err; + + *phost = NULL; + *pport = NULL; + *ppath = NULL; + + /* Check for initial colon */ + p = strchr(buf, ':'); + + if (!p) goto parse_err; + + *(p++) = '\0'; + + if (!strcmp(buf, "http")) + { + *pssl = 0; + port = "80"; + } + else if (!strcmp(buf, "https")) + { + *pssl = 1; + port = "443"; + } + else + goto parse_err; + + /* Check for double slash */ + if ((p[0] != '/') || (p[1] != '/')) + goto parse_err; + + p += 2; + + host = p; + + /* Check for trailing part of path */ + + p = strchr(p, '/'); + + if (!p) + *ppath = BUF_strdup("/"); + else + { + *ppath = BUF_strdup(p); + /* Set start of path to 0 so hostname is valid */ + *p = '\0'; + } + + if (!*ppath) goto mem_err; + + /* Look for optional ':' for port number */ + if ((p = strchr(host, ':'))) + { + *p = 0; + port = p + 1; + } + else + { + /* Not found: set default port */ + if (*pssl) port = "443"; + else port = "80"; + } + + *pport = BUF_strdup(port); + if (!*pport) goto mem_err; + + *phost = BUF_strdup(host); + + if (!*phost) goto mem_err; + + OPENSSL_free(buf); + + return 1; + + mem_err: + OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE); + goto err; + + parse_err: + OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL); + + + err: + if (*ppath) OPENSSL_free(*ppath); + if (*pport) OPENSSL_free(*pport); + if (*phost) OPENSSL_free(*phost); + return 0; + + } diff --git a/src/lib/libcrypto/ocsp/ocsp_prn.c b/src/lib/libcrypto/ocsp/ocsp_prn.c new file mode 100644 index 0000000000..4b7bc28769 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_prn.c @@ -0,0 +1,291 @@ +/* ocsp_prn.c */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was originally part of ocsp.c and was transfered to Richard + Levitte from CertCo by Kathy Weinhold in mid-spring 2000 to be included + in OpenSSL or released as a patch kit. */ + +/* ==================================================================== + * 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 + +static int ocsp_certid_print(BIO *bp, OCSP_CERTID* a, int indent) + { + BIO_printf(bp, "%*sCertificate ID:\n", indent, ""); + indent += 2; + BIO_printf(bp, "%*sHash Algorithm: ", indent, ""); + i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm); + BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, ""); + i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING); + BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, ""); + i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING); + BIO_printf(bp, "\n%*sSerial Number: ", indent, ""); + i2a_ASN1_INTEGER(bp, a->serialNumber); + BIO_printf(bp, "\n"); + return 1; + } + +typedef struct + { + long t; + char *m; + } OCSP_TBLSTR; + +static char *table2string(long s, OCSP_TBLSTR *ts, int len) +{ + OCSP_TBLSTR *p; + for (p=ts; p < ts + len; p++) + if (p->t == s) + return p->m; + return "(UNKNOWN)"; +} + +char *OCSP_response_status_str(long s) + { + static OCSP_TBLSTR rstat_tbl[] = { + { OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" }, + { OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest" }, + { OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror" }, + { OCSP_RESPONSE_STATUS_TRYLATER, "trylater" }, + { OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired" }, + { OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized" } }; + return table2string(s, rstat_tbl, 6); + } + +char *OCSP_cert_status_str(long s) + { + static OCSP_TBLSTR cstat_tbl[] = { + { V_OCSP_CERTSTATUS_GOOD, "good" }, + { V_OCSP_CERTSTATUS_REVOKED, "revoked" }, + { V_OCSP_CERTSTATUS_UNKNOWN, "unknown" } }; + return table2string(s, cstat_tbl, 3); + } + +char *OCSP_crl_reason_str(long s) + { + OCSP_TBLSTR reason_tbl[] = { + { OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified" }, + { OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise" }, + { OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise" }, + { OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged" }, + { OCSP_REVOKED_STATUS_SUPERSEDED, "superseded" }, + { OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation" }, + { OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold" }, + { OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL" } }; + return table2string(s, reason_tbl, 8); + } + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* o, unsigned long flags) + { + int i; + long l; + OCSP_CERTID* cid = NULL; + OCSP_ONEREQ *one = NULL; + OCSP_REQINFO *inf = o->tbsRequest; + OCSP_SIGNATURE *sig = o->optionalSignature; + + if (BIO_write(bp,"OCSP Request Data:\n",19) <= 0) goto err; + l=ASN1_INTEGER_get(inf->version); + if (BIO_printf(bp," Version: %lu (0x%lx)",l+1,l) <= 0) goto err; + if (inf->requestorName != NULL) + { + if (BIO_write(bp,"\n Requestor Name: ",21) <= 0) + goto err; + GENERAL_NAME_print(bp, inf->requestorName); + } + if (BIO_write(bp,"\n Requestor List:\n",21) <= 0) goto err; + for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) + { + one = sk_OCSP_ONEREQ_value(inf->requestList, i); + cid = one->reqCert; + ocsp_certid_print(bp, cid, 8); + if (!X509V3_extensions_print(bp, + "Request Single Extensions", + one->singleRequestExtensions, flags, 8)) + goto err; + } + if (!X509V3_extensions_print(bp, "Request Extensions", + inf->requestExtensions, flags, 4)) + goto err; + if (sig) + { + X509_signature_print(bp, sig->signatureAlgorithm, sig->signature); + for (i=0; icerts); i++) + { + X509_print(bp, sk_X509_value(sig->certs,i)); + PEM_write_bio_X509(bp,sk_X509_value(sig->certs,i)); + } + } + return 1; +err: + return 0; + } + +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags) + { + int i, ret = 0; + long l; + unsigned char *p; + OCSP_CERTID *cid = NULL; + OCSP_BASICRESP *br = NULL; + OCSP_RESPID *rid = NULL; + OCSP_RESPDATA *rd = NULL; + OCSP_CERTSTATUS *cst = NULL; + OCSP_REVOKEDINFO *rev = NULL; + OCSP_SINGLERESP *single = NULL; + OCSP_RESPBYTES *rb = o->responseBytes; + + if (BIO_puts(bp,"OCSP Response Data:\n") <= 0) goto err; + l=ASN1_ENUMERATED_get(o->responseStatus); + if (BIO_printf(bp," OCSP Response Status: %s (0x%x)\n", + OCSP_response_status_str(l), l) <= 0) goto err; + if (rb == NULL) return 1; + if (BIO_puts(bp," Response Type: ") <= 0) + goto err; + if(i2a_ASN1_OBJECT(bp, rb->responseType) <= 0) + goto err; + if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) + { + BIO_puts(bp," (unknown response type)\n"); + return 1; + } + + p = ASN1_STRING_data(rb->response); + i = ASN1_STRING_length(rb->response); + if (!(br = OCSP_response_get1_basic(o))) goto err; + rd = br->tbsResponseData; + l=ASN1_INTEGER_get(rd->version); + if (BIO_printf(bp,"\n Version: %lu (0x%lx)\n", + l+1,l) <= 0) goto err; + if (BIO_puts(bp," Responder Id: ") <= 0) goto err; + + rid = rd->responderId; + switch (rid->type) + { + case V_OCSP_RESPID_NAME: + X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE); + break; + case V_OCSP_RESPID_KEY: + i2a_ASN1_STRING(bp, rid->value.byKey, V_ASN1_OCTET_STRING); + break; + } + + if (BIO_printf(bp,"\n Produced At: ")<=0) goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt)) goto err; + if (BIO_printf(bp,"\n Responses:\n") <= 0) goto err; + for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) + { + if (! sk_OCSP_SINGLERESP_value(rd->responses, i)) continue; + single = sk_OCSP_SINGLERESP_value(rd->responses, i); + cid = single->certId; + if(ocsp_certid_print(bp, cid, 4) <= 0) goto err; + cst = single->certStatus; + if (BIO_printf(bp," Cert Status: %s", + OCSP_cert_status_str(cst->type)) <= 0) + goto err; + if (cst->type == V_OCSP_CERTSTATUS_REVOKED) + { + rev = cst->value.revoked; + if (BIO_printf(bp, "\n Revocation Time: ") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, + rev->revocationTime)) + goto err; + if (rev->revocationReason) + { + l=ASN1_ENUMERATED_get(rev->revocationReason); + if (BIO_printf(bp, + "\n Revocation Reason: %s (0x%x)", + OCSP_crl_reason_str(l), l) <= 0) + goto err; + } + } + if (BIO_printf(bp,"\n This Update: ") <= 0) goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate)) + goto err; + if (single->nextUpdate) + { + if (BIO_printf(bp,"\n Next Update: ") <= 0)goto err; + if (!ASN1_GENERALIZEDTIME_print(bp,single->nextUpdate)) + goto err; + } + if (!BIO_write(bp,"\n",1)) goto err; + if (!X509V3_extensions_print(bp, + "Response Single Extensions", + single->singleExtensions, flags, 8)) + goto err; + if (!BIO_write(bp,"\n",1)) goto err; + } + if (!X509V3_extensions_print(bp, "Response Extensions", + rd->responseExtensions, flags, 4)) + if(X509_signature_print(bp, br->signatureAlgorithm, br->signature) <= 0) + goto err; + + for (i=0; icerts); i++) + { + X509_print(bp, sk_X509_value(br->certs,i)); + PEM_write_bio_X509(bp,sk_X509_value(br->certs,i)); + } + + ret = 1; +err: + OCSP_BASICRESP_free(br); + return ret; + } diff --git a/src/lib/libcrypto/ocsp/ocsp_srv.c b/src/lib/libcrypto/ocsp/ocsp_srv.c new file mode 100644 index 0000000000..fffa134e75 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_srv.c @@ -0,0 +1,264 @@ +/* ocsp_srv.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 +#include + +/* Utility functions related to sending OCSP responses and extracting + * relevant information from the request. + */ + +int OCSP_request_onereq_count(OCSP_REQUEST *req) + { + return sk_OCSP_ONEREQ_num(req->tbsRequest->requestList); + } + +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i) + { + return sk_OCSP_ONEREQ_value(req->tbsRequest->requestList, i); + } + +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one) + { + return one->reqCert; + } + +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, + ASN1_INTEGER **pserial, OCSP_CERTID *cid) + { + if (!cid) return 0; + if (pmd) *pmd = cid->hashAlgorithm->algorithm; + if(piNameHash) *piNameHash = cid->issuerNameHash; + if (pikeyHash) *pikeyHash = cid->issuerKeyHash; + if (pserial) *pserial = cid->serialNumber; + return 1; + } + +int OCSP_request_is_signed(OCSP_REQUEST *req) + { + if(req->optionalSignature) return 1; + return 0; + } + +/* Create an OCSP response and encode an optional basic response */ +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs) + { + OCSP_RESPONSE *rsp = NULL; + + if (!(rsp = OCSP_RESPONSE_new())) goto err; + if (!(ASN1_ENUMERATED_set(rsp->responseStatus, status))) goto err; + if (!bs) return rsp; + if (!(rsp->responseBytes = OCSP_RESPBYTES_new())) goto err; + rsp->responseBytes->responseType = OBJ_nid2obj(NID_id_pkix_OCSP_basic); + if (!ASN1_item_pack(bs, ASN1_ITEM_rptr(OCSP_BASICRESP), &rsp->responseBytes->response)) + goto err; + return rsp; +err: + if (rsp) OCSP_RESPONSE_free(rsp); + return NULL; + } + + +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, + OCSP_CERTID *cid, + int status, int reason, + ASN1_TIME *revtime, + ASN1_TIME *thisupd, ASN1_TIME *nextupd) + { + OCSP_SINGLERESP *single = NULL; + OCSP_CERTSTATUS *cs; + OCSP_REVOKEDINFO *ri; + + if(!rsp->tbsResponseData->responses && + !(rsp->tbsResponseData->responses = sk_OCSP_SINGLERESP_new_null())) + goto err; + + if (!(single = OCSP_SINGLERESP_new())) + goto err; + + + + if (!ASN1_TIME_to_generalizedtime(thisupd, &single->thisUpdate)) + goto err; + if (nextupd && + !ASN1_TIME_to_generalizedtime(nextupd, &single->nextUpdate)) + goto err; + + OCSP_CERTID_free(single->certId); + + if(!(single->certId = OCSP_CERTID_dup(cid))) + goto err; + + cs = single->certStatus; + switch(cs->type = status) + { + case V_OCSP_CERTSTATUS_REVOKED: + if (!revtime) + { + OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS,OCSP_R_NO_REVOKED_TIME); + goto err; + } + if (!(cs->value.revoked = ri = OCSP_REVOKEDINFO_new())) goto err; + if (!ASN1_TIME_to_generalizedtime(revtime, &ri->revocationTime)) + goto err; + if (reason != OCSP_REVOKED_STATUS_NOSTATUS) + { + if (!(ri->revocationReason = ASN1_ENUMERATED_new())) + goto err; + if (!(ASN1_ENUMERATED_set(ri->revocationReason, + reason))) + goto err; + } + break; + + case V_OCSP_CERTSTATUS_GOOD: + cs->value.good = ASN1_NULL_new(); + break; + + case V_OCSP_CERTSTATUS_UNKNOWN: + cs->value.unknown = ASN1_NULL_new(); + break; + + default: + goto err; + + } + if (!(sk_OCSP_SINGLERESP_push(rsp->tbsResponseData->responses, single))) + goto err; + return single; +err: + OCSP_SINGLERESP_free(single); + return NULL; + } + +/* Add a certificate to an OCSP request */ + +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert) + { + if (!resp->certs && !(resp->certs = sk_X509_new_null())) + return 0; + + if(!sk_X509_push(resp->certs, cert)) return 0; + CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); + return 1; + } + +int OCSP_basic_sign(OCSP_BASICRESP *brsp, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags) + { + int i; + OCSP_RESPID *rid; + + if (!X509_check_private_key(signer, key)) + { + OCSPerr(OCSP_F_OCSP_BASIC_SIGN, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + goto err; + } + + if(!(flags & OCSP_NOCERTS)) + { + if(!OCSP_basic_add1_cert(brsp, signer)) + goto err; + for (i = 0; i < sk_X509_num(certs); i++) + { + X509 *tmpcert = sk_X509_value(certs, i); + if(!OCSP_basic_add1_cert(brsp, tmpcert)) + goto err; + } + } + + rid = brsp->tbsResponseData->responderId; + if (flags & OCSP_RESPID_KEY) + { + unsigned char md[SHA_DIGEST_LENGTH]; + X509_pubkey_digest(signer, EVP_sha1(), md, NULL); + if (!(rid->value.byKey = ASN1_OCTET_STRING_new())) + goto err; + if (!(ASN1_OCTET_STRING_set(rid->value.byKey, md, SHA_DIGEST_LENGTH))) + goto err; + rid->type = V_OCSP_RESPID_KEY; + } + else + { + if (!X509_NAME_set(&rid->value.byName, + X509_get_subject_name(signer))) + goto err; + rid->type = V_OCSP_RESPID_NAME; + } + + if (!(flags & OCSP_NOTIME) && + !X509_gmtime_adj(brsp->tbsResponseData->producedAt, 0)) + goto err; + + /* Right now, I think that not doing double hashing is the right + thing. -- Richard Levitte */ + + if (!OCSP_BASICRESP_sign(brsp, key, dgst, 0)) goto err; + + return 1; +err: + return 0; + } diff --git a/src/lib/libcrypto/ocsp/ocsp_vfy.c b/src/lib/libcrypto/ocsp/ocsp_vfy.c new file mode 100644 index 0000000000..1f5fda7ca3 --- /dev/null +++ b/src/lib/libcrypto/ocsp/ocsp_vfy.c @@ -0,0 +1,444 @@ +/* ocsp_vfy.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include + +static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); +static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); +static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags); +static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret); +static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, STACK_OF(OCSP_SINGLERESP) *sresp); +static int ocsp_check_delegated(X509 *x, int flags); +static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); + +/* Verify a basic response message */ + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags) + { + X509 *signer, *x; + STACK_OF(X509) *chain = NULL; + X509_STORE_CTX ctx; + int i, ret = 0; + ret = ocsp_find_signer(&signer, bs, certs, st, flags); + if (!ret) + { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); + goto end; + } + if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) + flags |= OCSP_NOVERIFY; + if (!(flags & OCSP_NOSIGS)) + { + EVP_PKEY *skey; + skey = X509_get_pubkey(signer); + ret = OCSP_BASICRESP_verify(bs, skey, 0); + EVP_PKEY_free(skey); + if(ret <= 0) + { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE); + goto end; + } + } + if (!(flags & OCSP_NOVERIFY)) + { + int init_res; + if(flags & OCSP_NOCHAIN) + init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL); + else + init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs); + if(!init_res) + { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB); + goto end; + } + + X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); + ret = X509_verify_cert(&ctx); + chain = X509_STORE_CTX_get1_chain(&ctx); + X509_STORE_CTX_cleanup(&ctx); + if (ret <= 0) + { + i = X509_STORE_CTX_get_error(&ctx); + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(i)); + goto end; + } + if(flags & OCSP_NOCHECKS) + { + ret = 1; + goto end; + } + /* At this point we have a valid certificate chain + * need to verify it against the OCSP issuer criteria. + */ + ret = ocsp_check_issuer(bs, chain, flags); + + /* If fatal error or valid match then finish */ + if (ret != 0) goto end; + + /* Easy case: explicitly trusted. Get root CA and + * check for explicit trust + */ + if(flags & OCSP_NOEXPLICIT) goto end; + + x = sk_X509_value(chain, sk_X509_num(chain) - 1); + if(X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) + { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_ROOT_CA_NOT_TRUSTED); + goto end; + } + ret = 1; + } + + + + end: + if(chain) sk_X509_pop_free(chain, X509_free); + return ret; + } + + +static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags) + { + X509 *signer; + OCSP_RESPID *rid = bs->tbsResponseData->responderId; + if ((signer = ocsp_find_signer_sk(certs, rid))) + { + *psigner = signer; + return 2; + } + if(!(flags & OCSP_NOINTERN) && + (signer = ocsp_find_signer_sk(bs->certs, rid))) + { + *psigner = signer; + return 1; + } + /* Maybe lookup from store if by subject name */ + + *psigner = NULL; + return 0; + } + + +static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) + { + int i; + unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; + X509 *x; + + /* Easy if lookup by name */ + if (id->type == V_OCSP_RESPID_NAME) + return X509_find_by_subject(certs, id->value.byName); + + /* Lookup by key hash */ + + /* If key hash isn't SHA1 length then forget it */ + if (id->value.byKey->length != SHA_DIGEST_LENGTH) return NULL; + keyhash = id->value.byKey->data; + /* Calculate hash of each key and compare */ + for (i = 0; i < sk_X509_num(certs); i++) + { + x = sk_X509_value(certs, i); + X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); + if(!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) + return x; + } + return NULL; + } + + +static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags) + { + STACK_OF(OCSP_SINGLERESP) *sresp; + X509 *signer, *sca; + OCSP_CERTID *caid = NULL; + int i; + sresp = bs->tbsResponseData->responses; + + if (sk_X509_num(chain) <= 0) + { + OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN); + return -1; + } + + /* See if the issuer IDs match. */ + i = ocsp_check_ids(sresp, &caid); + + /* If ID mismatch or other error then return */ + if (i <= 0) return i; + + signer = sk_X509_value(chain, 0); + /* Check to see if OCSP responder CA matches request CA */ + if (sk_X509_num(chain) > 1) + { + sca = sk_X509_value(chain, 1); + i = ocsp_match_issuerid(sca, caid, sresp); + if (i < 0) return i; + if (i) + { + /* We have a match, if extensions OK then success */ + if (ocsp_check_delegated(signer, flags)) return 1; + return 0; + } + } + + /* Otherwise check if OCSP request signed directly by request CA */ + return ocsp_match_issuerid(signer, caid, sresp); + } + + +/* Check the issuer certificate IDs for equality. If there is a mismatch with the same + * algorithm then there's no point trying to match any certificates against the issuer. + * If the issuer IDs all match then we just need to check equality against one of them. + */ + +static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) + { + OCSP_CERTID *tmpid, *cid; + int i, idcount; + + idcount = sk_OCSP_SINGLERESP_num(sresp); + if (idcount <= 0) + { + OCSPerr(OCSP_F_OCSP_CHECK_IDS, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); + return -1; + } + + cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; + + *ret = NULL; + + for (i = 1; i < idcount; i++) + { + tmpid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; + /* Check to see if IDs match */ + if (OCSP_id_issuer_cmp(cid, tmpid)) + { + /* If algoritm mismatch let caller deal with it */ + if (OBJ_cmp(tmpid->hashAlgorithm->algorithm, + cid->hashAlgorithm->algorithm)) + return 2; + /* Else mismatch */ + return 0; + } + } + + /* All IDs match: only need to check one ID */ + *ret = cid; + return 1; + } + + +static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, + STACK_OF(OCSP_SINGLERESP) *sresp) + { + /* If only one ID to match then do it */ + if(cid) + { + const EVP_MD *dgst; + X509_NAME *iname; + int mdlen; + unsigned char md[EVP_MAX_MD_SIZE]; + if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) + { + OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, OCSP_R_UNKNOWN_MESSAGE_DIGEST); + return -1; + } + + mdlen = EVP_MD_size(dgst); + if ((cid->issuerNameHash->length != mdlen) || + (cid->issuerKeyHash->length != mdlen)) + return 0; + iname = X509_get_subject_name(cert); + if (!X509_NAME_digest(iname, dgst, md, NULL)) + return -1; + if (memcmp(md, cid->issuerNameHash->data, mdlen)) + return 0; + X509_pubkey_digest(cert, EVP_sha1(), md, NULL); + if (memcmp(md, cid->issuerKeyHash->data, mdlen)) + return 0; + + return 1; + + } + else + { + /* We have to match the whole lot */ + int i, ret; + OCSP_CERTID *tmpid; + for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) + { + tmpid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; + ret = ocsp_match_issuerid(cert, tmpid, NULL); + if (ret <= 0) return ret; + } + return 1; + } + + } + +static int ocsp_check_delegated(X509 *x, int flags) + { + X509_check_purpose(x, -1, 0); + if ((x->ex_flags & EXFLAG_XKUSAGE) && + (x->ex_xkusage & XKU_OCSP_SIGN)) + return 1; + OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE); + return 0; + } + +/* Verify an OCSP request. This is fortunately much easier than OCSP + * response verify. Just find the signers certificate and verify it + * against a given trust value. + */ + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags) + { + X509 *signer; + X509_NAME *nm; + GENERAL_NAME *gen; + int ret; + X509_STORE_CTX ctx; + if (!req->optionalSignature) + { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED); + return 0; + } + gen = req->tbsRequest->requestorName; + if (gen->type != GEN_DIRNAME) + { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); + return 0; + } + nm = gen->d.directoryName; + ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags); + if (ret <= 0) + { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); + return 0; + } + if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) + flags |= OCSP_NOVERIFY; + if (!(flags & OCSP_NOSIGS)) + { + EVP_PKEY *skey; + skey = X509_get_pubkey(signer); + ret = OCSP_REQUEST_verify(req, skey); + EVP_PKEY_free(skey); + if(ret <= 0) + { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE); + return 0; + } + } + if (!(flags & OCSP_NOVERIFY)) + { + int init_res; + if(flags & OCSP_NOCHAIN) + init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL); + else + init_res = X509_STORE_CTX_init(&ctx, store, signer, + req->optionalSignature->certs); + if(!init_res) + { + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,ERR_R_X509_LIB); + return 0; + } + + X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); + X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST); + ret = X509_verify_cert(&ctx); + X509_STORE_CTX_cleanup(&ctx); + if (ret <= 0) + { + ret = X509_STORE_CTX_get_error(&ctx); + OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(ret)); + return 0; + } + } + return 1; + } + +static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags) + { + X509 *signer; + if(!(flags & OCSP_NOINTERN)) + { + signer = X509_find_by_subject(req->optionalSignature->certs, nm); + *psigner = signer; + return 1; + } + + signer = X509_find_by_subject(certs, nm); + if (signer) + { + *psigner = signer; + return 2; + } + return 0; + } diff --git a/src/lib/libcrypto/opensslv.h b/src/lib/libcrypto/opensslv.h new file mode 100644 index 0000000000..b841347f05 --- /dev/null +++ b/src/lib/libcrypto/opensslv.h @@ -0,0 +1,21 @@ +#ifndef HEADER_OPENSSLV_H +#define HEADER_OPENSSLV_H + +/* Numeric release version identifier: + * MMNNFFRBB: major minor fix final beta/patch + * For example: + * 0.9.3-dev 0x00903000 + * 0.9.3beta1 0x00903001 + * 0.9.3beta2-dev 0x00903002 + * 0.9.3beta2 0x00903002 + * 0.9.3 0x00903100 + * 0.9.3a 0x00903101 + * 0.9.4 0x00904100 + * 1.2.3z 0x1020311a + * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) + */ +#define OPENSSL_VERSION_NUMBER 0x00904100L +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.4 09 Aug 1999" +#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT + +#endif /* HEADER_OPENSSLV_H */ diff --git a/src/lib/libcrypto/ossl_typ.h b/src/lib/libcrypto/ossl_typ.h new file mode 100644 index 0000000000..6bd42aee4d --- /dev/null +++ b/src/lib/libcrypto/ossl_typ.h @@ -0,0 +1,120 @@ +/* ==================================================================== + * Copyright (c) 1998-2001 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_OPENSSL_TYPES_H +#define HEADER_OPENSSL_TYPES_H + +#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 +#define ASN1_BOOLEAN int +#define ASN1_NULL int +#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; +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; +#endif + +#ifdef OPENSSL_SYS_WIN32 +#undef X509_NAME +#undef PKCS7_ISSUER_AND_SERIAL +#endif + +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct env_md_st EVP_MD; +typedef struct env_md_ctx_st EVP_MD_CTX; +typedef struct evp_pkey_st EVP_PKEY; + +typedef struct x509_st X509; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct X509_name_st X509_NAME; +typedef struct x509_store_st X509_STORE; +typedef struct x509_store_ctx_st X509_STORE_CTX; + +typedef struct engine_st ENGINE; + + /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */ +#define DECLARE_PKCS12_STACK_OF(type) /* Nothing */ +#define IMPLEMENT_PKCS12_STACK_OF(type) /* Nothing */ + +#endif /* def HEADER_OPENSSL_TYPES_H */ diff --git a/src/lib/libcrypto/pem/pem2.h b/src/lib/libcrypto/pem/pem2.h new file mode 100644 index 0000000000..4a016aacd2 --- /dev/null +++ b/src/lib/libcrypto/pem/pem2.h @@ -0,0 +1,60 @@ +/* ==================================================================== + * 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). + * + */ + +/* + * This header only exists to break a circular dependency between pem and err + * Ben 30 Jan 1999. + */ + +void ERR_load_PEM_strings(void); diff --git a/src/lib/libcrypto/pem/pem_oth.c b/src/lib/libcrypto/pem/pem_oth.c new file mode 100644 index 0000000000..8d9064ea7c --- /dev/null +++ b/src/lib/libcrypto/pem/pem_oth.c @@ -0,0 +1,85 @@ +/* crypto/pem/pem_oth.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 +#include +#include + +/* Handle 'other' PEMs: not private keys */ + +char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x, + pem_password_cb *cb, void *u) + { + unsigned char *p=NULL,*data=NULL; + long len; + char *ret=NULL; + + if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u)) + return NULL; + p = data; + ret=d2i(x,&p,len); + if (ret == NULL) + PEMerr(PEM_F_PEM_ASN1_READ_BIO,ERR_R_ASN1_LIB); + OPENSSL_free(data); + return(ret); + } diff --git a/src/lib/libcrypto/pem/pem_pk8.c b/src/lib/libcrypto/pem/pem_pk8.c new file mode 100644 index 0000000000..f44182ffb5 --- /dev/null +++ b/src/lib/libcrypto/pem/pem_pk8.c @@ -0,0 +1,243 @@ +/* crypto/pem/pem_pkey.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 +#include +#include +#include + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, + int nid, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); + +/* These functions write a private key in PKCS#8 format: it is a "drop in" + * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' + * is NULL then it uses the unencrypted private key form. The 'nid' versions + * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. + */ + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); +} + +static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + X509_SIG *p8; + PKCS8_PRIV_KEY_INFO *p8inf; + char buf[PEM_BUFSIZE]; + int ret; + if(!(p8inf = EVP_PKEY2PKCS8(x))) { + PEMerr(PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY, + PEM_R_ERROR_CONVERTING_PRIVATE_KEY); + return 0; + } + if(enc || (nid != -1)) { + if(!kstr) { + if(!cb) klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u); + else klen = cb(buf, PEM_BUFSIZE, 1, u); + if(klen <= 0) { + PEMerr(PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY, + PEM_R_READ_KEY); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return 0; + } + + kstr = buf; + } + p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); + if(kstr == buf) memset(buf, 0, klen); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if(isder) ret = i2d_PKCS8_bio(bp, p8); + else ret = PEM_write_bio_PKCS8(bp, p8); + X509_SIG_free(p8); + return ret; + } else { + if(isder) ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + else ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; + } +} + +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) +{ + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + X509_SIG *p8 = NULL; + int klen; + EVP_PKEY *ret; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_PKCS8_bio(bp, NULL); + if(!p8) return NULL; + if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u); + else klen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u); + if (klen <= 0) { + PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ); + X509_SIG_free(p8); + return NULL; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + if(!p8inf) return NULL; + ret = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if(!ret) return NULL; + if(x) { + if(*x) EVP_PKEY_free(*x); + *x = ret; + } + return ret; +} + +#ifndef OPENSSL_NO_FP_API + +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); +} + +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); +} + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cb, void *u) +{ + return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); +} + +static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + BIO *bp; + int ret; + if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { + PEMerr(PEM_F_PEM_F_DO_PK8KEY_FP,ERR_R_BUF_LIB); + return(0); + } + ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); + BIO_free(bp); + return ret; +} + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u) +{ + BIO *bp; + EVP_PKEY *ret; + if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { + PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_FP,ERR_R_BUF_LIB); + return NULL; + } + ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); + BIO_free(bp); + return ret; +} + +#endif + +IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG) +IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, + PKCS8_PRIV_KEY_INFO) diff --git a/src/lib/libcrypto/pem/pem_pkey.c b/src/lib/libcrypto/pem/pem_pkey.c new file mode 100644 index 0000000000..270892d72b --- /dev/null +++ b/src/lib/libcrypto/pem/pem_pkey.c @@ -0,0 +1,139 @@ +/* crypto/pem/pem_pkey.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 +#include +#include +#include + + +EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) + { + char *nm=NULL; + unsigned char *p=NULL,*data=NULL; + long len; + EVP_PKEY *ret=NULL; + + if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) + return NULL; + p = data; + + if (strcmp(nm,PEM_STRING_RSA) == 0) + ret=d2i_PrivateKey(EVP_PKEY_RSA,x,&p,len); + else if (strcmp(nm,PEM_STRING_DSA) == 0) + ret=d2i_PrivateKey(EVP_PKEY_DSA,x,&p,len); + else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); + ret = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else if (strcmp(nm,PEM_STRING_PKCS8) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf; + X509_SIG *p8; + int klen; + char psbuf[PEM_BUFSIZE]; + p8 = d2i_X509_SIG(NULL, &p, len); + if(!p8) goto p8err; + if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u); + else klen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u); + if (klen <= 0) { + PEMerr(PEM_F_PEM_ASN1_READ_BIO, + PEM_R_BAD_PASSWORD_READ); + goto err; + } + p8inf = PKCS8_decrypt(p8, psbuf, klen); + X509_SIG_free(p8); + if(!p8inf) goto p8err; + ret = EVP_PKCS82PKEY(p8inf); + if(x) { + if(*x) EVP_PKEY_free((EVP_PKEY *)*x); + *x = ret; + } + PKCS8_PRIV_KEY_INFO_free(p8inf); + } +p8err: + if (ret == NULL) + PEMerr(PEM_F_PEM_ASN1_READ_BIO,ERR_R_ASN1_LIB); +err: + OPENSSL_free(nm); + OPENSSL_free(data); + return(ret); + } + +#ifndef OPENSSL_NO_FP_API +EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u) + { + BIO *b; + EVP_PKEY *ret; + + if ((b=BIO_new(BIO_s_file())) == NULL) + { + PEMerr(PEM_F_PEM_ASN1_READ,ERR_R_BUF_LIB); + return(0); + } + BIO_set_fp(b,fp,BIO_NOCLOSE); + ret=PEM_read_bio_PrivateKey(b,x,cb,u); + BIO_free(b); + return(ret); + } +#endif diff --git a/src/lib/libcrypto/pem/pem_x509.c b/src/lib/libcrypto/pem/pem_x509.c new file mode 100644 index 0000000000..19f88d8d3a --- /dev/null +++ b/src/lib/libcrypto/pem/pem_x509.c @@ -0,0 +1,69 @@ +/* pem_x509.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#undef SSLEAY_MACROS +#include "cryptlib.h" +#include +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509) + diff --git a/src/lib/libcrypto/pem/pem_xaux.c b/src/lib/libcrypto/pem/pem_xaux.c new file mode 100644 index 0000000000..2f579b5421 --- /dev/null +++ b/src/lib/libcrypto/pem/pem_xaux.c @@ -0,0 +1,68 @@ +/* pem_xaux.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#undef SSLEAY_MACROS +#include "cryptlib.h" +#include +#include +#include +#include +#include + +IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX) diff --git a/src/lib/libcrypto/pkcs12/p12_add.c b/src/lib/libcrypto/pkcs12/p12_add.c new file mode 100644 index 0000000000..ae3d9de3b4 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_add.c @@ -0,0 +1,214 @@ +/* p12_add.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 + +/* Pack an object into an OCTET STRING and turn into a safebag */ + +PKCS12_SAFEBAG *PKCS12_pack_safebag (char *obj, int (*i2d)(), int nid1, + int nid2) +{ + PKCS12_BAGS *bag; + PKCS12_SAFEBAG *safebag; + if (!(bag = PKCS12_BAGS_new ())) { + PKCS12err(PKCS12_F_PKCS12_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); + return NULL; + } + bag->type = OBJ_nid2obj(nid1); + if (!ASN1_pack_string(obj, i2d, &bag->value.octet)) { + PKCS12err(PKCS12_F_PKCS12_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!(safebag = PKCS12_SAFEBAG_new ())) { + PKCS12err(PKCS12_F_PKCS12_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); + return NULL; + } + safebag->value.bag = bag; + safebag->type = OBJ_nid2obj(nid2); + return safebag; +} + +/* Turn PKCS8 object into a keybag */ + +PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG (PKCS8_PRIV_KEY_INFO *p8) +{ + PKCS12_SAFEBAG *bag; + if (!(bag = PKCS12_SAFEBAG_new())) { + PKCS12err(PKCS12_F_PKCS12_MAKE_KEYBAG,ERR_R_MALLOC_FAILURE); + return NULL; + } + bag->type = OBJ_nid2obj(NID_keyBag); + bag->value.keybag = p8; + return bag; +} + +/* Turn PKCS8 object into a shrouded keybag */ + +PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG (int pbe_nid, const char *pass, + int passlen, unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8) +{ + PKCS12_SAFEBAG *bag; + + /* Set up the safe bag */ + if (!(bag = PKCS12_SAFEBAG_new ())) { + PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE); + return NULL; + } + + bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag); + if (!(bag->value.shkeybag = + PKCS8_encrypt(pbe_nid, NULL, pass, passlen, salt, saltlen, iter, + p8))) { + PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE); + return NULL; + } + + return bag; +} + +/* Turn a stack of SAFEBAGS into a PKCS#7 data Contentinfo */ +PKCS7 *PKCS12_pack_p7data (STACK *sk) +{ + PKCS7 *p7; + if (!(p7 = PKCS7_new())) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + p7->type = OBJ_nid2obj(NID_pkcs7_data); + if (!(p7->d.data = ASN1_OCTET_STRING_new())) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!ASN1_seq_pack(sk, i2d_PKCS12_SAFEBAG, &p7->d.data->data, + &p7->d.data->length)) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, PKCS12_R_CANT_PACK_STRUCTURE); + return NULL; + } + return p7; +} + +/* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */ + +PKCS7 *PKCS12_pack_p7encdata (int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, STACK *bags) +{ + PKCS7 *p7; + X509_ALGOR *pbe; + if (!(p7 = PKCS7_new())) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + p7->type = OBJ_nid2obj(NID_pkcs7_encrypted); + if (!(p7->d.encrypted = PKCS7_ENCRYPT_new ())) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + ASN1_INTEGER_set (p7->d.encrypted->version, 0); + p7->d.encrypted->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); + if (!(pbe = PKCS5_pbe_set (pbe_nid, iter, salt, saltlen))) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); + return NULL; + } + X509_ALGOR_free(p7->d.encrypted->enc_data->algorithm); + p7->d.encrypted->enc_data->algorithm = pbe; + ASN1_OCTET_STRING_free(p7->d.encrypted->enc_data->enc_data); + if (!(p7->d.encrypted->enc_data->enc_data = + PKCS12_i2d_encrypt (pbe, i2d_PKCS12_SAFEBAG, pass, passlen, + (char *)bags, 1))) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, PKCS12_R_ENCRYPT_ERROR); + return NULL; + } + + return p7; +} + +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8inf) +{ + X509_SIG *p8; + X509_ALGOR *pbe; + + if (!(p8 = X509_SIG_new())) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if(pbe_nid == -1) pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen); + else pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen); + if(!pbe) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_MALLOC_FAILURE); + return NULL; + } + X509_ALGOR_free(p8->algor); + p8->algor = pbe; + ASN1_OCTET_STRING_free(p8->digest); + if (!(p8->digest = + PKCS12_i2d_encrypt (pbe, i2d_PKCS8_PRIV_KEY_INFO, pass, passlen, + (char *)p8inf, 0))) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, PKCS12_R_ENCRYPT_ERROR); + return NULL; + } + + return p8; +} diff --git a/src/lib/libcrypto/pkcs12/p12_asn.c b/src/lib/libcrypto/pkcs12/p12_asn.c new file mode 100644 index 0000000000..c327bdba03 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_asn.c @@ -0,0 +1,125 @@ +/* p12_asn.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 + +/* PKCS#12 ASN1 module */ + +ASN1_SEQUENCE(PKCS12) = { + ASN1_SIMPLE(PKCS12, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS12, authsafes, PKCS7), + ASN1_OPT(PKCS12, mac, PKCS12_MAC_DATA) +} ASN1_SEQUENCE_END(PKCS12) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12) + +ASN1_SEQUENCE(PKCS12_MAC_DATA) = { + ASN1_SIMPLE(PKCS12_MAC_DATA, dinfo, X509_SIG), + ASN1_SIMPLE(PKCS12_MAC_DATA, salt, ASN1_OCTET_STRING), + ASN1_OPT(PKCS12_MAC_DATA, iter, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PKCS12_MAC_DATA) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12_MAC_DATA) + +ASN1_ADB_TEMPLATE(bag_default) = ASN1_EXP(PKCS12_BAGS, value.other, ASN1_ANY, 0); + +ASN1_ADB(PKCS12_BAGS) = { + ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.x509cert, ASN1_OCTET_STRING, 0)), + ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.x509crl, ASN1_OCTET_STRING, 0)), + ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.sdsicert, ASN1_IA5STRING, 0)), +} ASN1_ADB_END(PKCS12_BAGS, 0, type, 0, &bag_default_tt, NULL); + +ASN1_SEQUENCE(PKCS12_BAGS) = { + ASN1_SIMPLE(PKCS12_BAGS, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(PKCS12_BAGS), +} ASN1_SEQUENCE_END(PKCS12_BAGS) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12_BAGS) + +ASN1_ADB_TEMPLATE(safebag_default) = ASN1_EXP(PKCS12_SAFEBAG, value.other, ASN1_ANY, 0); + +ASN1_ADB(PKCS12_SAFEBAG) = { + ADB_ENTRY(NID_keyBag, ASN1_EXP(PKCS12_SAFEBAG, value.keybag, PKCS8_PRIV_KEY_INFO, 0)), + ADB_ENTRY(NID_pkcs8ShroudedKeyBag, ASN1_EXP(PKCS12_SAFEBAG, value.keybag, X509_SIG, 0)), + ADB_ENTRY(NID_safeContentsBag, ASN1_EXP_SET_OF(PKCS12_SAFEBAG, value.safes, PKCS12_SAFEBAG, 0)), + ADB_ENTRY(NID_certBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)), + ADB_ENTRY(NID_crlBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)), + ADB_ENTRY(NID_secretBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)) +} ASN1_ADB_END(PKCS12_SAFEBAG, 0, type, 0, &safebag_default_tt, NULL); + +ASN1_SEQUENCE(PKCS12_SAFEBAG) = { + ASN1_SIMPLE(PKCS12_SAFEBAG, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(PKCS12_SAFEBAG), + ASN1_SET_OF_OPT(PKCS12_SAFEBAG, attrib, X509_ATTRIBUTE) +} ASN1_SEQUENCE_END(PKCS12_SAFEBAG) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS12_SAFEBAG) + +/* SEQUENCE OF SafeBag */ +ASN1_ITEM_TEMPLATE(PKCS12_SAFEBAGS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PKCS12_SAFEBAGS, PKCS12_SAFEBAG) +ASN1_ITEM_TEMPLATE_END(PKCS12_SAFEBAGS) + +/* Authsafes: SEQUENCE OF PKCS7 */ +ASN1_ITEM_TEMPLATE(PKCS12_AUTHSAFES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, PKCS12_AUTHSAFES, PKCS7) +ASN1_ITEM_TEMPLATE_END(PKCS12_AUTHSAFES) + diff --git a/src/lib/libcrypto/pkcs12/p12_attr.c b/src/lib/libcrypto/pkcs12/p12_attr.c new file mode 100644 index 0000000000..31c9782b77 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_attr.c @@ -0,0 +1,238 @@ +/* p12_attr.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 + +/* Add a local keyid to a safebag */ + +int PKCS12_add_localkeyid (PKCS12_SAFEBAG *bag, unsigned char *name, + int namelen) +{ + X509_ATTRIBUTE *attrib; + ASN1_BMPSTRING *oct; + ASN1_TYPE *keyid; + if (!(keyid = ASN1_TYPE_new ())) { + PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + keyid->type = V_ASN1_OCTET_STRING; + if (!(oct = ASN1_OCTET_STRING_new())) { + PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!ASN1_OCTET_STRING_set(oct, name, namelen)) { + PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + keyid->value.octet_string = oct; + if (!(attrib = X509_ATTRIBUTE_new ())) { + PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + attrib->object = OBJ_nid2obj(NID_localKeyID); + if (!(attrib->value.set = sk_ASN1_TYPE_new(NULL))) { + PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + sk_ASN1_TYPE_push (attrib->value.set,keyid); + attrib->set = 1; + if (!bag->attrib && !(bag->attrib = sk_X509_ATTRIBUTE_new (NULL))) { + PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + return 0; + } + sk_X509_ATTRIBUTE_push (bag->attrib, attrib); + return 1; +} + +/* Add key usage to PKCS#8 structure */ + +int PKCS8_add_keyusage (PKCS8_PRIV_KEY_INFO *p8, int usage) +{ + X509_ATTRIBUTE *attrib; + ASN1_BIT_STRING *bstr; + ASN1_TYPE *keyid; + unsigned char us_val; + us_val = (unsigned char) usage; + if (!(keyid = ASN1_TYPE_new ())) { + PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + return 0; + } + keyid->type = V_ASN1_BIT_STRING; + if (!(bstr = ASN1_BIT_STRING_new())) { + PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!ASN1_BIT_STRING_set(bstr, &us_val, 1)) { + PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + return 0; + } + keyid->value.bit_string = bstr; + if (!(attrib = X509_ATTRIBUTE_new ())) { + PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + return 0; + } + attrib->object = OBJ_nid2obj(NID_key_usage); + if (!(attrib->value.set = sk_ASN1_TYPE_new(NULL))) { + PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + return 0; + } + sk_ASN1_TYPE_push (attrib->value.set,keyid); + attrib->set = 1; + if (!p8->attributes + && !(p8->attributes = sk_X509_ATTRIBUTE_new (NULL))) { + PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + return 0; + } + sk_X509_ATTRIBUTE_push (p8->attributes, attrib); + return 1; +} + +/* Add a friendlyname to a safebag */ + +int PKCS12_add_friendlyname_asc (PKCS12_SAFEBAG *bag, const char *name, + int namelen) +{ + unsigned char *uniname; + int ret, unilen; + if (!asc2uni(name, &uniname, &unilen)) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC, + ERR_R_MALLOC_FAILURE); + return 0; + } + ret = PKCS12_add_friendlyname_uni (bag, uniname, unilen); + Free(uniname); + return ret; +} + + +int PKCS12_add_friendlyname_uni (PKCS12_SAFEBAG *bag, + const unsigned char *name, int namelen) +{ + X509_ATTRIBUTE *attrib; + ASN1_BMPSTRING *bmp; + ASN1_TYPE *fname; + /* Zap ending double null if included */ + if(!name[namelen - 1] && !name[namelen - 2]) namelen -= 2; + if (!(fname = ASN1_TYPE_new ())) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, + ERR_R_MALLOC_FAILURE); + return 0; + } + fname->type = V_ASN1_BMPSTRING; + if (!(bmp = ASN1_BMPSTRING_new())) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, + ERR_R_MALLOC_FAILURE); + return 0; + } + if (!(bmp->data = Malloc (namelen))) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, + ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy (bmp->data, name, namelen); + bmp->length = namelen; + fname->value.bmpstring = bmp; + if (!(attrib = X509_ATTRIBUTE_new ())) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, + ERR_R_MALLOC_FAILURE); + return 0; + } + attrib->object = OBJ_nid2obj(NID_friendlyName); + if (!(attrib->value.set = sk_ASN1_TYPE_new(NULL))) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME, + ERR_R_MALLOC_FAILURE); + return 0; + } + sk_ASN1_TYPE_push (attrib->value.set,fname); + attrib->set = 1; + if (!bag->attrib && !(bag->attrib = sk_X509_ATTRIBUTE_new (NULL))) { + PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, + ERR_R_MALLOC_FAILURE); + return 0; + } + sk_X509_ATTRIBUTE_push (bag->attrib, attrib); + return PKCS12_OK; +} + +ASN1_TYPE *PKCS12_get_attr_gen (STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid) +{ + X509_ATTRIBUTE *attrib; + int i; + if (!attrs) return NULL; + for (i = 0; i < sk_X509_ATTRIBUTE_num (attrs); i++) { + attrib = sk_X509_ATTRIBUTE_value (attrs, i); + if (OBJ_obj2nid (attrib->object) == attr_nid) { + if (sk_ASN1_TYPE_num (attrib->value.set)) + return sk_ASN1_TYPE_value(attrib->value.set, 0); + else return NULL; + } + } + return NULL; +} + +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag) +{ + ASN1_TYPE *atype; + if (!(atype = PKCS12_get_attr(bag, NID_friendlyName))) return NULL; + if (atype->type != V_ASN1_BMPSTRING) return NULL; + return uni2asc(atype->value.bmpstring->data, + atype->value.bmpstring->length); +} + diff --git a/src/lib/libcrypto/pkcs12/p12_crpt.c b/src/lib/libcrypto/pkcs12/p12_crpt.c new file mode 100644 index 0000000000..6de6f8128f --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_crpt.c @@ -0,0 +1,122 @@ +/* p12_crpt.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 + +/* PKCS#12 specific PBE functions */ + +void PKCS12_PBE_add(void) +{ +#ifndef NO_RC4 +EVP_PBE_alg_add(NID_pbe_WithSHA1And128BitRC4, EVP_rc4(), EVP_sha1(), + PKCS12_PBE_keyivgen); +EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC4, EVP_rc4_40(), EVP_sha1(), + PKCS12_PBE_keyivgen); +#endif +EVP_PBE_alg_add(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + EVP_des_ede3_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); +EVP_PBE_alg_add(NID_pbe_WithSHA1And2_Key_TripleDES_CBC, + EVP_des_ede_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); +#ifndef NO_RC2 +EVP_PBE_alg_add(NID_pbe_WithSHA1And128BitRC2_CBC, EVP_rc2_cbc(), + EVP_sha1(), PKCS12_PBE_keyivgen); +EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc(), + EVP_sha1(), PKCS12_PBE_keyivgen); +#endif +} + +int PKCS12_PBE_keyivgen (EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md, int en_de) +{ + PBEPARAM *pbe; + int saltlen, iter; + unsigned char *salt, *pbuf; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + + /* Extract useful info from parameter */ + pbuf = param->value.sequence->data; + if (!param || (param->type != V_ASN1_SEQUENCE) || + !(pbe = d2i_PBEPARAM (NULL, &pbuf, param->value.sequence->length))) { + EVPerr(PKCS12_F_PKCS12_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) iter = 1; + else iter = ASN1_INTEGER_get (pbe->iter); + salt = pbe->salt->data; + saltlen = pbe->salt->length; + if (!PKCS12_key_gen (pass, passlen, salt, saltlen, PKCS12_KEY_ID, + iter, EVP_CIPHER_key_length(cipher), key, md)) { + PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN,PKCS12_R_KEY_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + if (!PKCS12_key_gen (pass, passlen, salt, saltlen, PKCS12_IV_ID, + iter, EVP_CIPHER_iv_length(cipher), iv, md)) { + PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN,PKCS12_R_IV_GEN_ERROR); + PBEPARAM_free(pbe); + return 0; + } + PBEPARAM_free(pbe); + EVP_CipherInit(ctx, cipher, key, iv, en_de); + memset(key, 0, EVP_MAX_KEY_LENGTH); + memset(iv, 0, EVP_MAX_IV_LENGTH); + return 1; +} diff --git a/src/lib/libcrypto/pkcs12/p12_crt.c b/src/lib/libcrypto/pkcs12/p12_crt.c new file mode 100644 index 0000000000..56d88b0759 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_crt.c @@ -0,0 +1,159 @@ +/* p12_crt.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 + +PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, + STACK *ca, int nid_key, int nid_cert, int iter, int mac_iter, + int keytype) +{ + PKCS12 *p12; + STACK *bags, *safes; + PKCS12_SAFEBAG *bag; + PKCS8_PRIV_KEY_INFO *p8; + PKCS7 *authsafe; + X509 *tcert; + int i; + unsigned char keyid[EVP_MAX_MD_SIZE]; + unsigned int keyidlen; + + /* Set defaults */ + if(!nid_cert) nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC; + if(!nid_key) nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + if(!iter) iter = PKCS12_DEFAULT_ITER; + if(!mac_iter) mac_iter = 1; + + if(!pkey || !cert) { + PKCS12err(PKCS12_F_PKCS12_CREATE,PKCS12_R_INVALID_NULL_ARGUMENT); + return NULL; + } + + if(!(bags = sk_new (NULL))) { + PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* Add user certificate */ + if(!(bag = M_PKCS12_x5092certbag(cert))) return NULL; + if(name && !PKCS12_add_friendlyname(bag, name, -1)) return NULL; + X509_digest(cert, EVP_sha1(), keyid, &keyidlen); + if(!PKCS12_add_localkeyid(bag, keyid, keyidlen)) return NULL; + + if(!sk_push(bags, (char *)bag)) { + PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* Add all other certificates */ + if(ca) { + for(i = 0; i < sk_num(ca); i++) { + tcert = (X509 *)sk_value(ca, i); + if(!(bag = M_PKCS12_x5092certbag(tcert))) return NULL; + if(!sk_push(bags, (char *)bag)) { + PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); + return NULL; + } + } + } + + /* Turn certbags into encrypted authsafe */ + authsafe = PKCS12_pack_p7encdata (nid_cert, pass, -1, NULL, 0, + iter, bags); + sk_pop_free(bags, PKCS12_SAFEBAG_free); + + if (!authsafe) return NULL; + + if(!(safes = sk_new (NULL)) || !sk_push(safes, (char *)authsafe)) { + PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* Make a shrouded key bag */ + if(!(p8 = EVP_PKEY2PKCS8 (pkey))) return NULL; + if(keytype && !PKCS8_add_keyusage(p8, keytype)) return NULL; + bag = PKCS12_MAKE_SHKEYBAG (nid_key, pass, -1, NULL, 0, iter, p8); + if(!bag) return NULL; + PKCS8_PRIV_KEY_INFO_free(p8); + if (name && !PKCS12_add_friendlyname (bag, name, -1)) return NULL; + if(!PKCS12_add_localkeyid (bag, keyid, keyidlen)) return NULL; + if(!(bags = sk_new(NULL)) || !sk_push (bags, (char *)bag)) { + PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); + return NULL; + } + /* Turn it into unencrypted safe bag */ + if(!(authsafe = PKCS12_pack_p7data (bags))) return NULL; + sk_pop_free(bags, PKCS12_SAFEBAG_free); + if(!sk_push(safes, (char *)authsafe)) { + PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); + return NULL; + } + + if(!(p12 = PKCS12_init (NID_pkcs7_data))) return NULL; + + if(!M_PKCS12_pack_authsafes (p12, safes)) return NULL; + + sk_pop_free(safes, PKCS7_free); + + if(!PKCS12_set_mac (p12, pass, -1, NULL, 0, mac_iter, NULL)) + return NULL; + + return p12; + +} diff --git a/src/lib/libcrypto/pkcs12/p12_decr.c b/src/lib/libcrypto/pkcs12/p12_decr.c new file mode 100644 index 0000000000..d3d288e187 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_decr.c @@ -0,0 +1,185 @@ +/* p12_decr.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 + +/* Define this to dump decrypted output to files called DERnnn */ +/*#define DEBUG_DECRYPT*/ + + +/* Encrypt/Decrypt a buffer based on password and algor, result in a + * Malloc'ed buffer + */ + +unsigned char * PKCS12_pbe_crypt (X509_ALGOR *algor, const char *pass, + int passlen, unsigned char *in, int inlen, unsigned char **data, + int *datalen, int en_de) +{ + unsigned char *out; + int outlen, i; + EVP_CIPHER_CTX ctx; + + /* Decrypt data */ + if (!EVP_PBE_CipherInit (algor->algorithm, pass, passlen, + algor->parameter, &ctx, en_de)) { + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR); + return NULL; + } + + if(!(out = Malloc (inlen + EVP_CIPHER_CTX_block_size(&ctx)))) { + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,ERR_R_MALLOC_FAILURE); + return NULL; + } + + EVP_CipherUpdate (&ctx, out, &i, in, inlen); + outlen = i; + if(!EVP_CipherFinal (&ctx, out + i, &i)) { + Free (out); + PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,PKCS12_R_PKCS12_CIPHERFINAL_ERROR); + return NULL; + } + outlen += i; + if (datalen) *datalen = outlen; + if (data) *data = out; + return out; + +} + +/* Decrypt an OCTET STRING and decode ASN1 structure + * if seq & 1 'obj' is a stack of structures to be encoded + * if seq & 2 zero buffer after use + * as a sequence. + */ + +char * PKCS12_decrypt_d2i (X509_ALGOR *algor, char * (*d2i)(), + void (*free_func)(), const char *pass, int passlen, + ASN1_OCTET_STRING *oct, int seq) +{ + unsigned char *out, *p; + char *ret; + int outlen; + + if (!PKCS12_pbe_crypt (algor, pass, passlen, oct->data, oct->length, + &out, &outlen, 0)) { + PKCS12err(PKCS12_F_PKCS12_DECRYPT_D2I,PKCS12_R_PKCS12_PBE_CRYPT_ERROR); + return NULL; + } + p = out; +#ifdef DEBUG_DECRYPT + { + FILE *op; + + char fname[30]; + static int fnm = 1; + sprintf(fname, "DER%d", fnm++); + op = fopen(fname, "wb"); + fwrite (p, 1, outlen, op); + fclose(op); + } +#endif + if (seq & 1) ret = (char *) d2i_ASN1_SET(NULL, &p, outlen, d2i, + free_func, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); + else ret = d2i(NULL, &p, outlen); + if (seq & 2) memset(out, 0, outlen); + if(!ret) PKCS12err(PKCS12_F_PKCS12_DECRYPT_D2I,PKCS12_R_DECODE_ERROR); + Free (out); + return ret; +} + +/* Encode ASN1 structure and encrypt, return OCTET STRING + * if 'seq' is non-zero 'obj' is a stack of structures to be encoded + * as a sequence + */ + +ASN1_OCTET_STRING *PKCS12_i2d_encrypt (X509_ALGOR *algor, int (*i2d)(), + const char *pass, int passlen, + char *obj, int seq) +{ + ASN1_OCTET_STRING *oct; + unsigned char *in, *p; + int inlen; + if (!(oct = ASN1_OCTET_STRING_new ())) { + PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,ERR_R_MALLOC_FAILURE); + return NULL; + } + if (seq) inlen = i2d_ASN1_SET((STACK *)obj, NULL, i2d, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); + else inlen = i2d (obj, NULL); + if (!inlen) { + PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,PKCS12_R_ENCODE_ERROR); + return NULL; + } + if (!(in = Malloc (inlen))) { + PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,ERR_R_MALLOC_FAILURE); + return NULL; + } + p = in; + if (seq) i2d_ASN1_SET((STACK *)obj, &p, i2d, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); + else i2d (obj, &p); + if (!PKCS12_pbe_crypt (algor, pass, passlen, in, inlen, &oct->data, + &oct->length, 1)) { + PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,PKCS12_R_ENCRYPT_ERROR); + Free(in); + return NULL; + } + Free (in); + return oct; +} diff --git a/src/lib/libcrypto/pkcs12/p12_init.c b/src/lib/libcrypto/pkcs12/p12_init.c new file mode 100644 index 0000000000..dc6ab41db8 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_init.c @@ -0,0 +1,98 @@ +/* p12_init.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 + +/* Initialise a PKCS12 structure to take data */ + +PKCS12 *PKCS12_init (int mode) +{ + PKCS12 *pkcs12; + if (!(pkcs12 = PKCS12_new())) { + PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); + return NULL; + } + if (!(pkcs12->version = ASN1_INTEGER_new ())) { + PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); + return NULL; + } + ASN1_INTEGER_set (pkcs12->version, 3); + if (!(pkcs12->authsafes = PKCS7_new())) { + PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); + return NULL; + } + pkcs12->authsafes->type = OBJ_nid2obj(mode); + switch (mode) { + case NID_pkcs7_data: + if (!(pkcs12->authsafes->d.data = + ASN1_OCTET_STRING_new())) { + PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); + return NULL; + } + break; + default: + PKCS12err(PKCS12_F_PKCS12_INIT,PKCS12_R_UNSUPPORTED_PKCS12_MODE); + PKCS12_free(pkcs12); + return NULL; + break; + } + + return pkcs12; +} diff --git a/src/lib/libcrypto/pkcs12/p12_key.c b/src/lib/libcrypto/pkcs12/p12_key.c new file mode 100644 index 0000000000..25d8cdae57 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_key.c @@ -0,0 +1,182 @@ +/* p12_key.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 + + +/* Uncomment out this line to get debugging info about key generation */ +/*#define DEBUG_KEYGEN*/ +#ifdef DEBUG_KEYGEN +#include +extern BIO *bio_err; +void h__dump (unsigned char *p, int len); +#endif + +/* PKCS12 compatible key/IV generation */ +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +int PKCS12_key_gen_asc (const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, unsigned char *out, + const EVP_MD *md_type) +{ + int ret; + unsigned char *unipass; + int uniplen; + if (!asc2uni (pass, &unipass, &uniplen)) { + PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE); + return 0; + } + ret = PKCS12_key_gen_uni (unipass, uniplen, salt, saltlen, + id, iter, n, out, md_type); + memset(unipass, 0, uniplen); /* Clear password from memory */ + Free(unipass); + return ret; +} + +int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, unsigned char *out, + const EVP_MD *md_type) +{ + unsigned char *B, *D, *I, *p, *Ai; + int Slen, Plen, Ilen; + int i, j, u, v; + BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */ + EVP_MD_CTX ctx; +#ifdef DEBUG_KEYGEN + unsigned char *tmpout = out; + int tmpn = n; + BIO_printf (bio_err, "KEYGEN DEBUG\n"); + BIO_printf (bio_err, "ID %d, ITER %d\n", id, iter); + BIO_printf (bio_err, "Password (length %d):\n", passlen); + h__dump (pass, passlen); + BIO_printf (bio_err, "Salt (length %d):\n", saltlen); + h__dump (salt, saltlen); + BIO_printf (bio_err, "ID %d, ITER %d\n\n", id, iter); +#endif + v = EVP_MD_block_size (md_type); + u = EVP_MD_size (md_type); + D = Malloc (v); + Ai = Malloc (u); + B = Malloc (v + 1); + Slen = v * ((saltlen+v-1)/v); + Plen = v * ((passlen+v-1)/v); + Ilen = Slen + Plen; + I = Malloc (Ilen); + Ij = BN_new(); + Bpl1 = BN_new(); + if (!D || !Ai || !B || !I || !Ij || !Bpl1) { + PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_MALLOC_FAILURE); + return 0; + } + for (i = 0; i < v; i++) D[i] = id; + p = I; + for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen]; + for (i = 0; i < Plen; i++) *p++ = pass[i % passlen]; + for (;;) { + EVP_DigestInit (&ctx, md_type); + EVP_DigestUpdate (&ctx, D, v); + EVP_DigestUpdate (&ctx, I, Ilen); + EVP_DigestFinal (&ctx, Ai, NULL); + for (j = 1; j < iter; j++) { + EVP_DigestInit (&ctx, md_type); + EVP_DigestUpdate (&ctx, Ai, u); + EVP_DigestFinal (&ctx, Ai, NULL); + } + memcpy (out, Ai, min (n, u)); + if (u >= n) { + Free (Ai); + Free (B); + Free (D); + Free (I); + BN_free (Ij); + BN_free (Bpl1); +#ifdef DEBUG_KEYGEN + BIO_printf (bio_err, "Output KEY (length %d)\n", tmpn); + h__dump (tmpout, tmpn); +#endif + return 1; + } + n -= u; + out += u; + for (j = 0; j < v; j++) B[j] = Ai[j % u]; + /* Work out B + 1 first then can use B as tmp space */ + BN_bin2bn (B, v, Bpl1); + BN_add_word (Bpl1, 1); + for (j = 0; j < Ilen ; j+=v) { + BN_bin2bn (I + j, v, Ij); + BN_add (Ij, Ij, Bpl1); + BN_bn2bin (Ij, B); + /* If more than 2^(v*8) - 1 cut off MSB */ + if (BN_num_bytes (Ij) > v) { + BN_bn2bin (Ij, B); + memcpy (I + j, B + 1, v); + } else BN_bn2bin (Ij, I + j); + } + } +} +#ifdef DEBUG_KEYGEN +void h__dump (unsigned char *p, int len) +{ + for (; len --; p++) BIO_printf (bio_err, "%02X", *p); + BIO_printf (bio_err, "\n"); +} +#endif diff --git a/src/lib/libcrypto/pkcs12/p12_kiss.c b/src/lib/libcrypto/pkcs12/p12_kiss.c new file mode 100644 index 0000000000..767e1303da --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_kiss.c @@ -0,0 +1,238 @@ +/* p12_kiss.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 + +/* Simplified PKCS#12 routines */ + +static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca); +static int parse_bags( STACK *bags, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca, ASN1_OCTET_STRING **keyid, char *keymatch); +static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca, ASN1_OCTET_STRING **keyid, char *keymatch); +/* Parse and decrypt a PKCS#12 structure returning user key, user cert + * and other (CA) certs. Note either ca should be NULL, *ca should be NULL, + * or it should point to a valid STACK structure. pkey and cert can be + * passed unitialised. + */ + +int PKCS12_parse (PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK **ca) +{ + +/* Check for NULL PKCS12 structure */ + +if(!p12) { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER); + return 0; +} + +/* Allocate stack for ca certificates if needed */ +if ((ca != NULL) && (*ca == NULL)) { + if (!(*ca = sk_new(NULL))) { + PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE); + return 0; + } +} + +if(pkey) *pkey = NULL; +if(cert) *cert = NULL; + +/* Check the mac */ + +if (!PKCS12_verify_mac (p12, pass, -1)) { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE); + goto err; +} + +if (!parse_pk12 (p12, pass, -1, pkey, cert, ca)) { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR); + goto err; +} + +return 1; + +err: + +if (pkey && *pkey) EVP_PKEY_free (*pkey); +if (cert && *cert) X509_free (*cert); +if (ca) sk_pop_free (*ca, X509_free); +return 0; + +} + +/* Parse the outer PKCS#12 structure */ + +static int parse_pk12 (PKCS12 *p12, const char *pass, int passlen, + EVP_PKEY **pkey, X509 **cert, STACK **ca) +{ + STACK *asafes, *bags; + int i, bagnid; + PKCS7 *p7; + ASN1_OCTET_STRING *keyid = NULL; + char keymatch = 0; + if (!( asafes = M_PKCS12_unpack_authsafes (p12))) return 0; + for (i = 0; i < sk_num (asafes); i++) { + p7 = (PKCS7 *) sk_value (asafes, i); + bagnid = OBJ_obj2nid (p7->type); + if (bagnid == NID_pkcs7_data) { + bags = M_PKCS12_unpack_p7data (p7); + } else if (bagnid == NID_pkcs7_encrypted) { + bags = M_PKCS12_unpack_p7encdata (p7, pass, passlen); + } else continue; + if (!bags) { + sk_pop_free (asafes, PKCS7_free); + return 0; + } + if (!parse_bags (bags, pass, passlen, pkey, cert, ca, + &keyid, &keymatch)) { + sk_pop_free (bags, PKCS12_SAFEBAG_free); + sk_pop_free (asafes, PKCS7_free); + return 0; + } + sk_pop_free (bags, PKCS12_SAFEBAG_free); + } + sk_pop_free (asafes, PKCS7_free); + if (keyid) ASN1_OCTET_STRING_free (keyid); + return 1; +} + + +static int parse_bags (STACK *bags, const char *pass, int passlen, + EVP_PKEY **pkey, X509 **cert, STACK **ca, + ASN1_OCTET_STRING **keyid, char *keymatch) +{ + int i; + for (i = 0; i < sk_num (bags); i++) { + if (!parse_bag ((PKCS12_SAFEBAG *)sk_value (bags, i), + pass, passlen, pkey, cert, ca, keyid, + keymatch)) return 0; + } + return 1; +} + +#define MATCH_KEY 0x1 +#define MATCH_CERT 0x2 +#define MATCH_ALL 0x3 + +static int parse_bag (PKCS12_SAFEBAG *bag, const char *pass, int passlen, + EVP_PKEY **pkey, X509 **cert, STACK **ca, + ASN1_OCTET_STRING **keyid, + char *keymatch) +{ + PKCS8_PRIV_KEY_INFO *p8; + X509 *x509; + ASN1_OCTET_STRING *lkey = NULL; + ASN1_TYPE *attrib; + + + if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) + lkey = attrib->value.octet_string; + + /* Check for any local key id matching (if needed) */ + if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) { + if (*keyid) { + if (ASN1_OCTET_STRING_cmp (*keyid, lkey)) lkey = NULL; + } else { + if (!(*keyid = ASN1_OCTET_STRING_dup (lkey))) { + PKCS12err(PKCS12_F_PARSE_BAGS,ERR_R_MALLOC_FAILURE); + return 0; + } + } + } + + switch (M_PKCS12_bag_type(bag)) + { + case NID_keyBag: + if (!lkey || !pkey) return 1; + if (!(*pkey = EVP_PKCS82PKEY (bag->value.keybag))) return 0; + *keymatch |= MATCH_KEY; + break; + + case NID_pkcs8ShroudedKeyBag: + if (!lkey || !pkey) return 1; + if (!(p8 = M_PKCS12_decrypt_skey (bag, pass, passlen))) + return 0; + *pkey = EVP_PKCS82PKEY (p8); + PKCS8_PRIV_KEY_INFO_free (p8); + if (!(*pkey)) return 0; + *keymatch |= MATCH_KEY; + break; + + case NID_certBag: + if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) + return 1; + if (!(x509 = M_PKCS12_certbag2x509(bag))) return 0; + if (lkey) { + *keymatch |= MATCH_CERT; + if (cert) *cert = x509; + } else if (ca) sk_push (*ca, (char *)x509); + break; + + case NID_safeContentsBag: + return parse_bags(bag->value.safes, pass, passlen, + pkey, cert, ca, keyid, keymatch); + break; + + default: + return 1; + break; + } + return 1; +} + diff --git a/src/lib/libcrypto/pkcs12/p12_mutl.c b/src/lib/libcrypto/pkcs12/p12_mutl.c new file mode 100644 index 0000000000..bac558d6b9 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_mutl.c @@ -0,0 +1,170 @@ +/* p12_mutl.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). + * + */ + +#ifndef NO_HMAC +#include +#include "cryptlib.h" +#include +#include +#include + +/* Generate a MAC */ +int PKCS12_gen_mac (PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen) +{ + const EVP_MD *md_type; + HMAC_CTX hmac; + unsigned char key[PKCS12_MAC_KEY_LENGTH], *salt; + int saltlen, iter; + salt = p12->mac->salt->data; + saltlen = p12->mac->salt->length; + if (!p12->mac->iter) iter = 1; + else iter = ASN1_INTEGER_get (p12->mac->iter); + if(!(md_type = + EVP_get_digestbyobj (p12->mac->dinfo->algor->algorithm))) { + PKCS12err(PKCS12_F_PKCS12_GEN_MAC,PKCS12_R_UNKNOWN_DIGEST_ALGORITHM); + return 0; + } + if(!PKCS12_key_gen (pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter, + PKCS12_MAC_KEY_LENGTH, key, md_type)) { + PKCS12err(PKCS12_F_PKCS12_GEN_MAC,PKCS12_R_KEY_GEN_ERROR); + return 0; + } + HMAC_Init (&hmac, key, PKCS12_MAC_KEY_LENGTH, md_type); + HMAC_Update (&hmac, p12->authsafes->d.data->data, + p12->authsafes->d.data->length); + HMAC_Final (&hmac, mac, maclen); + return 1; +} + +/* Verify the mac */ +int PKCS12_verify_mac (PKCS12 *p12, const char *pass, int passlen) +{ + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + if(p12->mac == NULL) { + PKCS12err(PKCS12_F_VERIFY_MAC,PKCS12_R_MAC_ABSENT); + return 0; + } + if (!PKCS12_gen_mac (p12, pass, passlen, mac, &maclen)) { + PKCS12err(PKCS12_F_VERIFY_MAC,PKCS12_R_MAC_GENERATION_ERROR); + return 0; + } + if ((maclen != (unsigned int)p12->mac->dinfo->digest->length) + || memcmp (mac, p12->mac->dinfo->digest->data, maclen)) { + PKCS12err(PKCS12_F_VERIFY_MAC,PKCS12_R_MAC_VERIFY_ERROR); + return 0; + } + return 1; +} + +/* Set a mac */ + +int PKCS12_set_mac (PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, EVP_MD *md_type) +{ + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + + if (!md_type) md_type = EVP_sha1(); + if (PKCS12_setup_mac (p12, iter, salt, saltlen, md_type) == + PKCS12_ERROR) { + PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_SETUP_ERROR); + return 0; + } + if (!PKCS12_gen_mac (p12, pass, passlen, mac, &maclen)) { + PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_GENERATION_ERROR); + return 0; + } + if (!(ASN1_OCTET_STRING_set (p12->mac->dinfo->digest, mac, maclen))) { + PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_STRING_SET_ERROR); + return 0; + } + return 1; +} + +/* Set up a mac structure */ +int PKCS12_setup_mac (PKCS12 *p12, int iter, unsigned char *salt, int saltlen, + EVP_MD *md_type) +{ + if (!(p12->mac = PKCS12_MAC_DATA_new ())) return PKCS12_ERROR; + if (iter > 1) { + if(!(p12->mac->iter = ASN1_INTEGER_new())) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_INTEGER_set (p12->mac->iter, iter); + } + if (!saltlen) saltlen = PKCS12_SALT_LEN; + p12->mac->salt->length = saltlen; + if (!(p12->mac->salt->data = Malloc (saltlen))) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!salt) RAND_bytes (p12->mac->salt->data, saltlen); + else memcpy (p12->mac->salt->data, salt, saltlen); + p12->mac->dinfo->algor->algorithm = OBJ_nid2obj(EVP_MD_type(md_type)); + if (!(p12->mac->dinfo->algor->parameter = ASN1_TYPE_new())) { + PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); + return 0; + } + p12->mac->dinfo->algor->parameter->type = V_ASN1_NULL; + + return 1; +} +#endif diff --git a/src/lib/libcrypto/pkcs12/p12_npas.c b/src/lib/libcrypto/pkcs12/p12_npas.c new file mode 100644 index 0000000000..ee71707e2c --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_npas.c @@ -0,0 +1,212 @@ +/* p12_npas.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 +#include +#include +#include +#include + +/* PKCS#12 password change routine */ + +static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass); +static int newpass_bags(STACK *bags, char *oldpass, char *newpass); +static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass); +static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen); + +/* + * Change the password on a PKCS#12 structure. + */ + +int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass) +{ + +/* Check for NULL PKCS12 structure */ + +if(!p12) { + PKCS12err(PKCS12_F_PKCS12_NEWPASS,PKCS12_R_INVALID_NULL_PKCS12_POINTER); + return 0; +} + +/* Check the mac */ + +if (!PKCS12_verify_mac(p12, oldpass, -1)) { + PKCS12err(PKCS12_F_PKCS12_NEWPASS,PKCS12_R_MAC_VERIFY_FAILURE); + return 0; +} + +if (!newpass_p12(p12, oldpass, newpass)) { + PKCS12err(PKCS12_F_PKCS12_NEWPASS,PKCS12_R_PARSE_ERROR); + return 0; +} + +return 1; + +} + +/* Parse the outer PKCS#12 structure */ + +static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass) +{ + STACK *asafes, *newsafes, *bags; + int i, bagnid, pbe_nid, pbe_iter, pbe_saltlen; + PKCS7 *p7, *p7new; + ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + if (!(asafes = M_PKCS12_unpack_authsafes(p12))) return 0; + if(!(newsafes = sk_new(NULL))) return 0; + for (i = 0; i < sk_num (asafes); i++) { + p7 = (PKCS7 *) sk_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); + if (bagnid == NID_pkcs7_data) { + bags = M_PKCS12_unpack_p7data(p7); + } else if (bagnid == NID_pkcs7_encrypted) { + bags = M_PKCS12_unpack_p7encdata(p7, oldpass, -1); + alg_get(p7->d.encrypted->enc_data->algorithm, + &pbe_nid, &pbe_iter, &pbe_saltlen); + } else continue; + if (!bags) { + sk_pop_free(asafes, PKCS7_free); + return 0; + } + if (!newpass_bags(bags, oldpass, newpass)) { + sk_pop_free(bags, PKCS12_SAFEBAG_free); + sk_pop_free(asafes, PKCS7_free); + return 0; + } + /* Repack bag in same form with new password */ + if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); + else p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, + pbe_saltlen, pbe_iter, bags); + sk_pop_free(bags, PKCS12_SAFEBAG_free); + if(!p7new) { + sk_pop_free(asafes, PKCS7_free); + return 0; + } + sk_push(newsafes, (char *)p7new); + } + sk_pop_free(asafes, PKCS7_free); + + /* Repack safe: save old safe in case of error */ + + p12_data_tmp = p12->authsafes->d.data; + if(!(p12->authsafes->d.data = ASN1_OCTET_STRING_new())) goto saferr; + if(!M_PKCS12_pack_authsafes(p12, newsafes)) goto saferr; + + if(!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto saferr; + if(!(macnew = ASN1_OCTET_STRING_new())) goto saferr; + if(!ASN1_OCTET_STRING_set(macnew, mac, maclen)) goto saferr; + ASN1_OCTET_STRING_free(p12->mac->dinfo->digest); + p12->mac->dinfo->digest = macnew; + ASN1_OCTET_STRING_free(p12_data_tmp); + + return 1; + + saferr: + /* Restore old safe */ + ASN1_OCTET_STRING_free(p12->authsafes->d.data); + ASN1_OCTET_STRING_free(macnew); + p12->authsafes->d.data = p12_data_tmp; + return 0; + +} + + +static int newpass_bags(STACK *bags, char *oldpass, char *newpass) +{ + int i; + for (i = 0; i < sk_num(bags); i++) { + if (!newpass_bag((PKCS12_SAFEBAG *)sk_value(bags, i), + oldpass, newpass)) return 0; + } + return 1; +} + +/* Change password of safebag: only needs handle shrouded keybags */ + +static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass) +{ + PKCS8_PRIV_KEY_INFO *p8; + X509_SIG *p8new; + int p8_nid, p8_saltlen, p8_iter; + + if(M_PKCS12_bag_type(bag) != NID_pkcs8ShroudedKeyBag) return 1; + + if (!(p8 = M_PKCS12_decrypt_skey(bag, oldpass, -1))) return 0; + alg_get(bag->value.shkeybag->algor, &p8_nid, &p8_iter, &p8_saltlen); + if(!(p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, + p8_iter, p8))) return 0; + X509_SIG_free(bag->value.shkeybag); + bag->value.shkeybag = p8new; + return 1; +} + +static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen) +{ + PBEPARAM *pbe; + unsigned char *p; + p = alg->parameter->value.sequence->data; + pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length); + *pnid = OBJ_obj2nid(alg->algorithm); + *piter = ASN1_INTEGER_get(pbe->iter); + *psaltlen = pbe->salt->length; + PBEPARAM_free(pbe); + return 0; +} diff --git a/src/lib/libcrypto/pkcs12/p12_p8d.c b/src/lib/libcrypto/pkcs12/p12_p8d.c new file mode 100644 index 0000000000..3c6f377933 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_p8d.c @@ -0,0 +1,68 @@ +/* p12_p8d.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 + +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, int passlen) +{ + return PKCS12_item_decrypt_d2i(p8->algor, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass, + passlen, p8->digest, 1); +} + diff --git a/src/lib/libcrypto/pkcs12/p12_p8e.c b/src/lib/libcrypto/pkcs12/p12_p8e.c new file mode 100644 index 0000000000..3d47956652 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_p8e.c @@ -0,0 +1,97 @@ +/* p12_p8e.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 + +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8inf) +{ + X509_SIG *p8 = NULL; + X509_ALGOR *pbe; + + if (!(p8 = X509_SIG_new())) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if(pbe_nid == -1) pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen); + else pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen); + if(!pbe) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_ASN1_LIB); + goto err; + } + X509_ALGOR_free(p8->algor); + p8->algor = pbe; + M_ASN1_OCTET_STRING_free(p8->digest); + p8->digest = PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), + pass, passlen, p8inf, 1); + if(!p8->digest) { + PKCS12err(PKCS12_F_PKCS8_ENCRYPT, PKCS12_R_ENCRYPT_ERROR); + goto err; + } + + return p8; + + err: + X509_SIG_free(p8); + return NULL; +} diff --git a/src/lib/libcrypto/pkcs12/p12_utl.c b/src/lib/libcrypto/pkcs12/p12_utl.c new file mode 100644 index 0000000000..2adcbc95e1 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/p12_utl.c @@ -0,0 +1,118 @@ +/* p12_utl.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 + +/* Cheap and nasty Unicode stuff */ + +unsigned char *asc2uni (const char *asc, unsigned char **uni, int *unilen) +{ + int ulen, i; + unsigned char *unitmp; + ulen = strlen(asc)*2 + 2; + if (!(unitmp = Malloc (ulen))) return NULL; + for (i = 0; i < ulen; i+=2) { + unitmp[i] = 0; + unitmp[i + 1] = asc[i>>1]; + } + if (unilen) *unilen = ulen; + if (uni) *uni = unitmp; + return unitmp; +} + +char *uni2asc (unsigned char *uni, int unilen) +{ + int asclen, i; + char *asctmp; + asclen = unilen / 2; + /* If no terminating zero allow for one */ + if (uni[unilen - 1]) asclen++; + uni++; + if (!(asctmp = Malloc (asclen))) return NULL; + for (i = 0; i < unilen; i+=2) asctmp[i>>1] = uni[i]; + asctmp[asclen - 1] = 0; + return asctmp; +} + +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12) +{ + return ASN1_i2d_bio((int(*)())i2d_PKCS12, bp, (unsigned char *)p12); +} + +#ifndef NO_FP_API +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12) +{ + return ASN1_i2d_fp((int(*)())i2d_PKCS12, fp, (unsigned char *)p12); +} +#endif + +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) +{ + return (PKCS12 *)ASN1_d2i_bio((char *(*)())PKCS12_new, + (char *(*)())d2i_PKCS12, bp, (unsigned char **)p12); +} +#ifndef NO_FP_API +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) +{ + return (PKCS12 *)ASN1_d2i_fp((char *(*)())PKCS12_new, + (char *(*)())d2i_PKCS12, fp, (unsigned char **)(p12)); +} +#endif + diff --git a/src/lib/libcrypto/pkcs12/pk12err.c b/src/lib/libcrypto/pkcs12/pk12err.c new file mode 100644 index 0000000000..38d7be7675 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/pk12err.c @@ -0,0 +1,136 @@ +/* crypto/pkcs12/pk12err.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. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA PKCS12_str_functs[]= + { +{ERR_PACK(0,PKCS12_F_PARSE_BAGS,0), "PARSE_BAGS"}, +{ERR_PACK(0,PKCS12_F_PKCS12_ADD_FRIENDLYNAME,0), "PKCS12_ADD_FRIENDLYNAME"}, +{ERR_PACK(0,PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC,0), "PKCS12_add_friendlyname_asc"}, +{ERR_PACK(0,PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI,0), "PKCS12_add_friendlyname_uni"}, +{ERR_PACK(0,PKCS12_F_PKCS12_ADD_LOCALKEYID,0), "PKCS12_add_localkeyid"}, +{ERR_PACK(0,PKCS12_F_PKCS12_CREATE,0), "PKCS12_create"}, +{ERR_PACK(0,PKCS12_F_PKCS12_DECRYPT_D2I,0), "PKCS12_decrypt_d2i"}, +{ERR_PACK(0,PKCS12_F_PKCS12_GEN_MAC,0), "PKCS12_gen_mac"}, +{ERR_PACK(0,PKCS12_F_PKCS12_I2D_ENCRYPT,0), "PKCS12_i2d_encrypt"}, +{ERR_PACK(0,PKCS12_F_PKCS12_INIT,0), "PKCS12_init"}, +{ERR_PACK(0,PKCS12_F_PKCS12_KEY_GEN_ASC,0), "PKCS12_key_gen_asc"}, +{ERR_PACK(0,PKCS12_F_PKCS12_KEY_GEN_UNI,0), "PKCS12_key_gen_uni"}, +{ERR_PACK(0,PKCS12_F_PKCS12_MAKE_KEYBAG,0), "PKCS12_MAKE_KEYBAG"}, +{ERR_PACK(0,PKCS12_F_PKCS12_MAKE_SHKEYBAG,0), "PKCS12_MAKE_SHKEYBAG"}, +{ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7DATA,0), "PKCS12_pack_p7data"}, +{ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7ENCDATA,0), "PKCS12_pack_p7encdata"}, +{ERR_PACK(0,PKCS12_F_PKCS12_PACK_SAFEBAG,0), "PKCS12_pack_safebag"}, +{ERR_PACK(0,PKCS12_F_PKCS12_PARSE,0), "PKCS12_parse"}, +{ERR_PACK(0,PKCS12_F_PKCS12_PBE_CRYPT,0), "PKCS12_pbe_crypt"}, +{ERR_PACK(0,PKCS12_F_PKCS12_PBE_KEYIVGEN,0), "PKCS12_PBE_keyivgen"}, +{ERR_PACK(0,PKCS12_F_PKCS12_SETUP_MAC,0), "PKCS12_setup_mac"}, +{ERR_PACK(0,PKCS12_F_PKCS12_SET_MAC,0), "PKCS12_set_mac"}, +{ERR_PACK(0,PKCS12_F_PKCS8_ADD_KEYUSAGE,0), "PKCS8_add_keyusage"}, +{ERR_PACK(0,PKCS12_F_PKCS8_ENCRYPT,0), "PKCS8_encrypt"}, +{ERR_PACK(0,PKCS12_F_VERIFY_MAC,0), "VERIFY_MAC"}, +{0,NULL} + }; + +static ERR_STRING_DATA PKCS12_str_reasons[]= + { +{PKCS12_R_CANT_PACK_STRUCTURE ,"cant pack structure"}, +{PKCS12_R_DECODE_ERROR ,"decode error"}, +{PKCS12_R_ENCODE_ERROR ,"encode error"}, +{PKCS12_R_ENCRYPT_ERROR ,"encrypt error"}, +{PKCS12_R_INVALID_NULL_ARGUMENT ,"invalid null argument"}, +{PKCS12_R_INVALID_NULL_PKCS12_POINTER ,"invalid null pkcs12 pointer"}, +{PKCS12_R_IV_GEN_ERROR ,"iv gen error"}, +{PKCS12_R_KEY_GEN_ERROR ,"key gen error"}, +{PKCS12_R_MAC_ABSENT ,"mac absent"}, +{PKCS12_R_MAC_GENERATION_ERROR ,"mac generation error"}, +{PKCS12_R_MAC_SETUP_ERROR ,"mac setup error"}, +{PKCS12_R_MAC_STRING_SET_ERROR ,"mac string set error"}, +{PKCS12_R_MAC_VERIFY_ERROR ,"mac verify error"}, +{PKCS12_R_MAC_VERIFY_FAILURE ,"mac verify failure"}, +{PKCS12_R_PARSE_ERROR ,"parse error"}, +{PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR ,"pkcs12 algor cipherinit error"}, +{PKCS12_R_PKCS12_CIPHERFINAL_ERROR ,"pkcs12 cipherfinal error"}, +{PKCS12_R_PKCS12_PBE_CRYPT_ERROR ,"pkcs12 pbe crypt error"}, +{PKCS12_R_UNKNOWN_DIGEST_ALGORITHM ,"unknown digest algorithm"}, +{PKCS12_R_UNSUPPORTED_PKCS12_MODE ,"unsupported pkcs12 mode"}, +{0,NULL} + }; + +#endif + +void ERR_load_PKCS12_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_PKCS12,PKCS12_str_functs); + ERR_load_strings(ERR_LIB_PKCS12,PKCS12_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/pkcs12/pkcs12.h b/src/lib/libcrypto/pkcs12/pkcs12.h new file mode 100644 index 0000000000..4cfba5e6c6 --- /dev/null +++ b/src/lib/libcrypto/pkcs12/pkcs12.h @@ -0,0 +1,337 @@ +/* pkcs12.h */ +/* 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). + * + */ + +#ifndef HEADER_PKCS12_H +#define HEADER_PKCS12_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define PKCS12_KEY_ID 1 +#define PKCS12_IV_ID 2 +#define PKCS12_MAC_ID 3 + +/* Default iteration count */ +#ifndef PKCS12_DEFAULT_ITER +#define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER +#endif + +#define PKCS12_MAC_KEY_LENGTH 20 + +#define PKCS12_SALT_LEN 8 + +/* Uncomment out next line for unicode password and names, otherwise ASCII */ + +/*#define PBE_UNICODE*/ + +#ifdef PBE_UNICODE +#define PKCS12_key_gen PKCS12_key_gen_uni +#define PKCS12_add_friendlyname PKCS12_add_friendlyname_uni +#else +#define PKCS12_key_gen PKCS12_key_gen_asc +#define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc +#endif + +/* MS key usage constants */ + +#define KEY_EX 0x10 +#define KEY_SIG 0x80 + +typedef struct { +X509_SIG *dinfo; +ASN1_OCTET_STRING *salt; +ASN1_INTEGER *iter; /* defaults to 1 */ +} PKCS12_MAC_DATA; + +typedef struct { +ASN1_INTEGER *version; +PKCS12_MAC_DATA *mac; +PKCS7 *authsafes; +} PKCS12; + +typedef struct { +ASN1_OBJECT *type; +union { + struct pkcs12_bag_st *bag; /* secret, crl and certbag */ + struct pkcs8_priv_key_info_st *keybag; /* keybag */ + X509_SIG *shkeybag; /* shrouded key bag */ + STACK /* PKCS12_SAFEBAG */ *safes; + ASN1_TYPE *other; +}value; +STACK_OF(X509_ATTRIBUTE) *attrib; +ASN1_TYPE *rest; +} PKCS12_SAFEBAG; + +typedef struct pkcs12_bag_st { +ASN1_OBJECT *type; +union { + ASN1_OCTET_STRING *x509cert; + ASN1_OCTET_STRING *x509crl; + ASN1_OCTET_STRING *octet; + ASN1_IA5STRING *sdsicert; + ASN1_TYPE *other; /* Secret or other bag */ +}value; +} PKCS12_BAGS; + +#define PKCS12_ERROR 0 +#define PKCS12_OK 1 + +#define M_PKCS12_bag_type(bag) OBJ_obj2nid(bag->type) +#define M_PKCS12_cert_bag_type(bag) OBJ_obj2nid(bag->value.bag->type) +#define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type + +#define M_PKCS12_x5092certbag(x509) \ +PKCS12_pack_safebag ((char *)(x509), i2d_X509, NID_x509Certificate, NID_certBag) + +#define M_PKCS12_x509crl2certbag(crl) \ +PKCS12_pack_safebag ((char *)(crl), i2d_X509CRL, NID_x509Crl, NID_crlBag) + +#define M_PKCS12_certbag2x509(bg) \ +(X509 *) ASN1_unpack_string ((bg)->value.bag->value.octet, \ +(char *(*)())d2i_X509) + +#define M_PKCS12_certbag2x509crl(bg) \ +(X509CRL *) ASN1_unpack_string ((bg)->value.bag->value.octet, \ +(char *(*)())d2i_X509CRL) + +/*#define M_PKCS12_pkcs82rsa(p8) \ +(RSA *) ASN1_unpack_string ((p8)->pkey, (char *(*)())d2i_RSAPrivateKey)*/ + +#define M_PKCS12_unpack_p7data(p7) \ +ASN1_seq_unpack ((p7)->d.data->data, p7->d.data->length, \ + (char *(*)())d2i_PKCS12_SAFEBAG, PKCS12_SAFEBAG_free) + +#define M_PKCS12_pack_authsafes(p12, safes) \ +ASN1_seq_pack((safes), (int (*)())i2d_PKCS7,\ + &(p12)->authsafes->d.data->data, &(p12)->authsafes->d.data->length) + +#define M_PKCS12_unpack_authsafes(p12) \ +ASN1_seq_unpack((p12)->authsafes->d.data->data, \ + (p12)->authsafes->d.data->length, (char *(*)())d2i_PKCS7, \ + PKCS7_free) + +#define M_PKCS12_unpack_p7encdata(p7, pass, passlen) \ +(STACK *) PKCS12_decrypt_d2i ((p7)->d.encrypted->enc_data->algorithm,\ + (char *(*)())d2i_PKCS12_SAFEBAG, PKCS12_SAFEBAG_free, \ + (pass), (passlen), \ + (p7)->d.encrypted->enc_data->enc_data, 3) + +#define M_PKCS12_decrypt_skey(bag, pass, passlen) \ +(PKCS8_PRIV_KEY_INFO *) PKCS12_decrypt_d2i ((bag)->value.shkeybag->algor, \ +(char *(*)())d2i_PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free, \ + (pass), (passlen), \ + (bag)->value.shkeybag->digest, 2) + +#define M_PKCS8_decrypt(p8, pass, passlen) \ +(PKCS8_PRIV_KEY_INFO *) PKCS12_decrypt_d2i ((p8)->algor, \ +(char *(*)())d2i_PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free,\ + (pass), (passlen), (p8)->digest, 2) + +#define PKCS12_get_attr(bag, attr_nid) \ + PKCS12_get_attr_gen(bag->attrib, attr_nid) + +#define PKCS8_get_attr(p8, attr_nid) \ + PKCS12_get_attr_gen(p8->attributes, attr_nid) + +#define PKCS12_mac_present(p12) ((p12)->mac ? 1 : 0) + + +PKCS12_SAFEBAG *PKCS12_pack_safebag(char *obj, int (*i2d)(), int nid1, int nid2); +PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8); +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8); +PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass, + int passlen, unsigned char *salt, + int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8); +PKCS7 *PKCS12_pack_p7data(STACK *sk); +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + STACK *bags); +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen); +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name, + int namelen); +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage); +ASN1_TYPE *PKCS12_get_attr_gen(STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid); +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); +unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass, + int passlen, unsigned char *in, int inlen, + unsigned char **data, int *datalen, int en_de); +char *PKCS12_decrypt_d2i(X509_ALGOR *algor, char *(*d2i)(), + void (*free_func)(), const char *pass, int passlen, + ASN1_STRING *oct, int seq); +ASN1_STRING *PKCS12_i2d_encrypt(X509_ALGOR *algor, int (*i2d)(), + const char *pass, int passlen, char *obj, + int seq); +PKCS12 *PKCS12_init(int mode); +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type); +int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md_type, + int en_de); +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen); +int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); +int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + EVP_MD *md_type); +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, + int saltlen, EVP_MD *md_type); +unsigned char *asc2uni(const char *asc, unsigned char **uni, int *unilen); +char *uni2asc(unsigned char *uni, int unilen); +int i2d_PKCS12_BAGS(PKCS12_BAGS *a, unsigned char **pp); +PKCS12_BAGS *PKCS12_BAGS_new(void); +PKCS12_BAGS *d2i_PKCS12_BAGS(PKCS12_BAGS **a, unsigned char **pp, long length); +void PKCS12_BAGS_free(PKCS12_BAGS *a); +int i2d_PKCS12(PKCS12 *a, unsigned char **pp); +PKCS12 *d2i_PKCS12(PKCS12 **a, unsigned char **pp, long length); +PKCS12 *PKCS12_new(void); +void PKCS12_free(PKCS12 *a); +int i2d_PKCS12_MAC_DATA(PKCS12_MAC_DATA *a, unsigned char **pp); +PKCS12_MAC_DATA *PKCS12_MAC_DATA_new(void); +PKCS12_MAC_DATA *d2i_PKCS12_MAC_DATA(PKCS12_MAC_DATA **a, unsigned char **pp, + long length); +void PKCS12_MAC_DATA_free(PKCS12_MAC_DATA *a); +int i2d_PKCS12_SAFEBAG(PKCS12_SAFEBAG *a, unsigned char **pp); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_new(void); +PKCS12_SAFEBAG *d2i_PKCS12_SAFEBAG(PKCS12_SAFEBAG **a, unsigned char **pp, + long length); +void PKCS12_SAFEBAG_free(PKCS12_SAFEBAG *a); +void ERR_load_PKCS12_strings(void); +void PKCS12_PBE_add(void); +int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK **ca); +PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, + STACK *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype); +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); + +/* 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 PKCS12 functions. */ + +/* Function codes. */ +#define PKCS12_F_PARSE_BAGS 103 +#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME 100 +#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC 127 +#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI 102 +#define PKCS12_F_PKCS12_ADD_LOCALKEYID 104 +#define PKCS12_F_PKCS12_CREATE 105 +#define PKCS12_F_PKCS12_DECRYPT_D2I 106 +#define PKCS12_F_PKCS12_GEN_MAC 107 +#define PKCS12_F_PKCS12_I2D_ENCRYPT 108 +#define PKCS12_F_PKCS12_INIT 109 +#define PKCS12_F_PKCS12_KEY_GEN_ASC 110 +#define PKCS12_F_PKCS12_KEY_GEN_UNI 111 +#define PKCS12_F_PKCS12_MAKE_KEYBAG 112 +#define PKCS12_F_PKCS12_MAKE_SHKEYBAG 113 +#define PKCS12_F_PKCS12_PACK_P7DATA 114 +#define PKCS12_F_PKCS12_PACK_P7ENCDATA 115 +#define PKCS12_F_PKCS12_PACK_SAFEBAG 117 +#define PKCS12_F_PKCS12_PARSE 118 +#define PKCS12_F_PKCS12_PBE_CRYPT 119 +#define PKCS12_F_PKCS12_PBE_KEYIVGEN 120 +#define PKCS12_F_PKCS12_SETUP_MAC 122 +#define PKCS12_F_PKCS12_SET_MAC 123 +#define PKCS12_F_PKCS8_ADD_KEYUSAGE 124 +#define PKCS12_F_PKCS8_ENCRYPT 125 +#define PKCS12_F_VERIFY_MAC 126 + +/* Reason codes. */ +#define PKCS12_R_CANT_PACK_STRUCTURE 100 +#define PKCS12_R_DECODE_ERROR 101 +#define PKCS12_R_ENCODE_ERROR 102 +#define PKCS12_R_ENCRYPT_ERROR 103 +#define PKCS12_R_INVALID_NULL_ARGUMENT 104 +#define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105 +#define PKCS12_R_IV_GEN_ERROR 106 +#define PKCS12_R_KEY_GEN_ERROR 107 +#define PKCS12_R_MAC_ABSENT 108 +#define PKCS12_R_MAC_GENERATION_ERROR 109 +#define PKCS12_R_MAC_SETUP_ERROR 110 +#define PKCS12_R_MAC_STRING_SET_ERROR 111 +#define PKCS12_R_MAC_VERIFY_ERROR 112 +#define PKCS12_R_MAC_VERIFY_FAILURE 113 +#define PKCS12_R_PARSE_ERROR 114 +#define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115 +#define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116 +#define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117 +#define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118 +#define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/libcrypto/pkcs7/pk7_asn1.c b/src/lib/libcrypto/pkcs7/pk7_asn1.c new file mode 100644 index 0000000000..46f0fc9375 --- /dev/null +++ b/src/lib/libcrypto/pkcs7/pk7_asn1.c @@ -0,0 +1,213 @@ +/* pk7_asn.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 + +/* PKCS#7 ASN1 module */ + +/* This is the ANY DEFINED BY table for the top level PKCS#7 structure */ + +ASN1_ADB_TEMPLATE(p7default) = ASN1_EXP_OPT(PKCS7, d.other, ASN1_ANY, 0); + +ASN1_ADB(PKCS7) = { + ADB_ENTRY(NID_pkcs7_data, ASN1_EXP_OPT(PKCS7, d.data, ASN1_OCTET_STRING, 0)), + ADB_ENTRY(NID_pkcs7_signed, ASN1_EXP_OPT(PKCS7, d.sign, PKCS7_SIGNED, 0)), + ADB_ENTRY(NID_pkcs7_enveloped, ASN1_EXP_OPT(PKCS7, d.enveloped, PKCS7_ENVELOPE, 0)), + ADB_ENTRY(NID_pkcs7_signedAndEnveloped, ASN1_EXP_OPT(PKCS7, d.signed_and_enveloped, PKCS7_SIGN_ENVELOPE, 0)), + ADB_ENTRY(NID_pkcs7_digest, ASN1_EXP_OPT(PKCS7, d.digest, PKCS7_DIGEST, 0)), + ADB_ENTRY(NID_pkcs7_encrypted, ASN1_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0)) +} ASN1_ADB_END(PKCS7, 0, type, 0, &p7default_tt, NULL); + +ASN1_SEQUENCE(PKCS7) = { + ASN1_SIMPLE(PKCS7, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(PKCS7) +}ASN1_SEQUENCE_END(PKCS7) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7) +IMPLEMENT_ASN1_DUP_FUNCTION(PKCS7) + +ASN1_SEQUENCE(PKCS7_SIGNED) = { + ASN1_SIMPLE(PKCS7_SIGNED, version, ASN1_INTEGER), + ASN1_SET_OF(PKCS7_SIGNED, md_algs, X509_ALGOR), + ASN1_SIMPLE(PKCS7_SIGNED, contents, PKCS7), + ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNED, cert, X509, 0), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGNED, crl, X509_CRL, 1), + ASN1_SET_OF(PKCS7_SIGNED, signer_info, PKCS7_SIGNER_INFO) +} ASN1_SEQUENCE_END(PKCS7_SIGNED) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNED) + +/* Minor tweak to operation: free up EVP_PKEY */ +static int si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if(operation == ASN1_OP_FREE_POST) { + PKCS7_SIGNER_INFO *si = (PKCS7_SIGNER_INFO *)*pval; + EVP_PKEY_free(si->pkey); + } + return 1; +} + +ASN1_SEQUENCE_cb(PKCS7_SIGNER_INFO, si_cb) = { + ASN1_SIMPLE(PKCS7_SIGNER_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_alg, X509_ALGOR), + /* NB this should be a SET OF but we use a SEQUENCE OF so the + * original order * is retained when the structure is reencoded. + * Since the attributes are implicitly tagged this will not affect + * the encoding. + */ + ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNER_INFO, auth_attr, X509_ATTRIBUTE, 0), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_enc_alg, X509_ALGOR), + ASN1_SIMPLE(PKCS7_SIGNER_INFO, enc_digest, ASN1_OCTET_STRING), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGNER_INFO, unauth_attr, X509_ATTRIBUTE, 1) +} ASN1_SEQUENCE_END_cb(PKCS7_SIGNER_INFO, PKCS7_SIGNER_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) + +ASN1_SEQUENCE(PKCS7_ISSUER_AND_SERIAL) = { + ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, issuer, X509_NAME), + ASN1_SIMPLE(PKCS7_ISSUER_AND_SERIAL, serial, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PKCS7_ISSUER_AND_SERIAL) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) + +ASN1_SEQUENCE(PKCS7_ENVELOPE) = { + ASN1_SIMPLE(PKCS7_ENVELOPE, version, ASN1_INTEGER), + ASN1_SET_OF(PKCS7_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), + ASN1_SIMPLE(PKCS7_ENVELOPE, enc_data, PKCS7_ENC_CONTENT) +} ASN1_SEQUENCE_END(PKCS7_ENVELOPE) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENVELOPE) + +/* Minor tweak to operation: free up X509 */ +static int ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if(operation == ASN1_OP_FREE_POST) { + PKCS7_RECIP_INFO *ri = (PKCS7_RECIP_INFO *)*pval; + X509_free(ri->cert); + } + return 1; +} + +ASN1_SEQUENCE_cb(PKCS7_RECIP_INFO, ri_cb) = { + ASN1_SIMPLE(PKCS7_RECIP_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_RECIP_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), + ASN1_SIMPLE(PKCS7_RECIP_INFO, key_enc_algor, X509_ALGOR), + ASN1_SIMPLE(PKCS7_RECIP_INFO, enc_key, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END_cb(PKCS7_RECIP_INFO, PKCS7_RECIP_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) + +ASN1_SEQUENCE(PKCS7_ENC_CONTENT) = { + ASN1_SIMPLE(PKCS7_ENC_CONTENT, content_type, ASN1_OBJECT), + ASN1_SIMPLE(PKCS7_ENC_CONTENT, algorithm, X509_ALGOR), + ASN1_IMP_OPT(PKCS7_ENC_CONTENT, enc_data, ASN1_OCTET_STRING, 0) +} ASN1_SEQUENCE_END(PKCS7_ENC_CONTENT) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) + +ASN1_SEQUENCE(PKCS7_SIGN_ENVELOPE) = { + ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, version, ASN1_INTEGER), + ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), + ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, md_algs, X509_ALGOR), + ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, enc_data, PKCS7_ENC_CONTENT), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, cert, X509, 0), + ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, crl, X509_CRL, 1), + ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, signer_info, PKCS7_SIGNER_INFO) +} ASN1_SEQUENCE_END(PKCS7_SIGN_ENVELOPE) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) + +ASN1_SEQUENCE(PKCS7_ENCRYPT) = { + ASN1_SIMPLE(PKCS7_ENCRYPT, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_ENCRYPT, enc_data, PKCS7_ENC_CONTENT) +} ASN1_SEQUENCE_END(PKCS7_ENCRYPT) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENCRYPT) + +ASN1_SEQUENCE(PKCS7_DIGEST) = { + ASN1_SIMPLE(PKCS7_DIGEST, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS7_DIGEST, md, X509_ALGOR), + ASN1_SIMPLE(PKCS7_DIGEST, contents, PKCS7), + ASN1_SIMPLE(PKCS7_DIGEST, digest, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(PKCS7_DIGEST) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST) + +/* Specials for authenticated attributes */ + +/* When signing attributes we want to reorder them to match the sorted + * encoding. + */ + +ASN1_ITEM_TEMPLATE(PKCS7_ATTR_SIGN) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_SIGN) + +/* When verifying attributes we need to use the received order. So + * we use SEQUENCE OF and tag it to SET OF + */ + +ASN1_ITEM_TEMPLATE(PKCS7_ATTR_VERIFY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL, + V_ASN1_SET, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) +ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_VERIFY) diff --git a/src/lib/libcrypto/pkcs7/pk7_attr.c b/src/lib/libcrypto/pkcs7/pk7_attr.c new file mode 100644 index 0000000000..3b9c0fe3f2 --- /dev/null +++ b/src/lib/libcrypto/pkcs7/pk7_attr.c @@ -0,0 +1,85 @@ +/* pk7_attr.c */ +/* S/MIME code. + * Copyright (C) 1997-8 Dr S N Henson (shenson@bigfoot.com) + * All Rights Reserved. + * Redistribution of this code without the authors permission is expressly + * prohibited. + */ + +#include +#include +#include +#include +#include +#include +#include + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK *cap) +{ + ASN1_STRING *seq; + unsigned char *p, *pp; + int len; + len=i2d_ASN1_SET(cap,NULL,i2d_X509_ALGOR, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); + if(!(pp=(unsigned char *)Malloc(len))) { + PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + p=pp; + i2d_ASN1_SET(cap,&p,i2d_X509_ALGOR, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); + if(!(seq = ASN1_STRING_new())) { + PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + if(!ASN1_STRING_set (seq, pp, len)) { + PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + Free (pp); + return PKCS7_add_signed_attribute(si, NID_SMIMECapabilities, + V_ASN1_SEQUENCE, seq); +} + +STACK *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si) +{ + ASN1_TYPE *cap; + unsigned char *p; + cap = PKCS7_get_signed_attribute(si, NID_SMIMECapabilities); + if (!cap) return NULL; + p = cap->value.sequence->data; + return d2i_ASN1_SET (NULL, &p, cap->value.sequence->length, + (char *(*)())d2i_X509_ALGOR, X509_ALGOR_free, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL); +} + +/* Basic smime-capabilities OID and optional integer arg */ +int PKCS7_simple_smimecap(STACK *sk, int nid, int arg) +{ + X509_ALGOR *alg; + if(!(alg = X509_ALGOR_new())) { + PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = OBJ_nid2obj (nid); + if (arg > 0) { + ASN1_INTEGER *nbit; + if(!(alg->parameter = ASN1_TYPE_new())) { + PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + if(!(nbit = ASN1_INTEGER_new())) { + PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + if(!ASN1_INTEGER_set (nbit, arg)) { + PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP,ERR_R_MALLOC_FAILURE); + return 0; + } + alg->parameter->value.integer = nbit; + alg->parameter->type = V_ASN1_INTEGER; + } + sk_push (sk, (char *)alg); + return 1; +} diff --git a/src/lib/libcrypto/pkcs7/pk7_mime.c b/src/lib/libcrypto/pkcs7/pk7_mime.c new file mode 100644 index 0000000000..734643be28 --- /dev/null +++ b/src/lib/libcrypto/pkcs7/pk7_mime.c @@ -0,0 +1,673 @@ +/* pk7_mime.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 +#include "cryptlib.h" +#include +#include + +/* MIME and related routines */ + +/* MIME format structures + * Note that all are translated to lower case apart from + * parameter values. Quotes are stripped off + */ + +typedef struct { +char *name; /* Name of line e.g. "content-type" */ +char *value; /* Value of line e.g. "text/plain" */ +STACK /* MIME_PARAM */ *params; /* Zero or more parameters */ +} MIME_HEADER; + +typedef struct { +char *param_name; /* Param name e.g. "micalg" */ +char *param_value; /* Param value e.g. "sha1" */ +} MIME_PARAM; + + +static int B64_write_PKCS7(BIO *bio, PKCS7 *p7); +static PKCS7 *B64_read_PKCS7(BIO *bio); +static char * strip_ends(char *name); +static char * strip_start(char *name); +static char * strip_end(char *name); +static MIME_HEADER *mime_hdr_new(char *name, char *value); +static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); +static STACK *mime_parse_hdr(BIO *bio); +static int mime_hdr_cmp(MIME_HEADER **a, MIME_HEADER **b); +static int mime_param_cmp(MIME_PARAM **a, MIME_PARAM **b); +static void mime_param_free(MIME_PARAM *param); +static int mime_bound_check(char *line, int linelen, char *bound, int blen); +static int multi_split(BIO *bio, char *bound, STACK **ret); +static int iscrlf(char c); +static MIME_HEADER *mime_hdr_find(STACK *hdrs, char *name); +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name); +static void mime_hdr_free(MIME_HEADER *hdr); + +#define MAX_SMLEN 1024 +#define mime_debug(x) /* x */ + + +typedef void (*stkfree)(); + +/* Base 64 read and write of PKCS#7 structure */ + +static int B64_write_PKCS7(BIO *bio, PKCS7 *p7) +{ + BIO *b64; + if(!(b64 = BIO_new(BIO_f_base64()))) { + PKCS7err(PKCS7_F_B64_WRITE_PKCS7,ERR_R_MALLOC_FAILURE); + return 0; + } + bio = BIO_push(b64, bio); + i2d_PKCS7_bio(bio, p7); + BIO_flush(bio); + bio = BIO_pop(bio); + BIO_free(b64); + return 1; +} + +static PKCS7 *B64_read_PKCS7(BIO *bio) +{ + BIO *b64; + PKCS7 *p7; + if(!(b64 = BIO_new(BIO_f_base64()))) { + PKCS7err(PKCS7_F_B64_READ_PKCS7,ERR_R_MALLOC_FAILURE); + return 0; + } + bio = BIO_push(b64, bio); + if(!(p7 = d2i_PKCS7_bio(bio, NULL))) + PKCS7err(PKCS7_F_B64_READ_PKCS7,PKCS7_R_DECODE_ERROR); + BIO_flush(bio); + bio = BIO_pop(bio); + BIO_free(b64); + return p7; +} + +/* SMIME sender */ + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) +{ + char linebuf[MAX_SMLEN]; + char bound[33], c; + int i; + if((flags & PKCS7_DETACHED) && data) { + /* We want multipart/signed */ + /* Generate a random boundary */ + RAND_pseudo_bytes((unsigned char *)bound, 32); + for(i = 0; i < 32; i++) { + c = bound[i] & 0xf; + if(c < 10) c += '0'; + else c += 'A' - 10; + bound[i] = c; + } + bound[32] = 0; + BIO_printf(bio, "MIME-Version: 1.0\n"); + BIO_printf(bio, "Content-Type: multipart/signed ; "); + BIO_printf(bio, "protocol=\"application/x-pkcs7-signature\" ; "); + BIO_printf(bio, "micalg=sha1 ; boundary=\"----%s\"\n\n", bound); + BIO_printf(bio, "This is an S/MIME signed message\n\n"); + /* Now write out the first part */ + BIO_printf(bio, "------%s\r\n", bound); + if(flags & PKCS7_TEXT) BIO_printf(bio, "Content-Type: text/plain\n\n"); + while((i = BIO_read(data, linebuf, MAX_SMLEN)) > 0) + BIO_write(bio, linebuf, i); + BIO_printf(bio, "\n------%s\n", bound); + + /* Headers for signature */ + + BIO_printf(bio, "Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"\n"); + BIO_printf(bio, "Content-Transfer-Encoding: base64\n"); + BIO_printf(bio, "Content-Disposition: attachment; filename=\"smime.p7s\"\n\n"); + B64_write_PKCS7(bio, p7); + BIO_printf(bio,"\n------%s--\n\n", bound); + return 1; + } + /* MIME headers */ + BIO_printf(bio, "MIME-Version: 1.0\n"); + BIO_printf(bio, "Content-Disposition: attachment; filename=\"smime.p7m\"\n"); + BIO_printf(bio, "Content-Type: application/x-pkcs7-mime; name=\"smime.p7m\"\n"); + BIO_printf(bio, "Content-Transfer-Encoding: base64\n\n"); + B64_write_PKCS7(bio, p7); + BIO_printf(bio, "\n"); + return 1; +} + +/* SMIME reader: handle multipart/signed and opaque signing. + * in multipart case the content is placed in a memory BIO + * pointed to by "bcont". In opaque this is set to NULL + */ + +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) +{ + BIO *p7in; + STACK *headers = NULL; + STACK *parts = NULL; + MIME_HEADER *hdr; + MIME_PARAM *prm; + PKCS7 *p7; + int ret; + + if(bcont) *bcont = NULL; + + if (!(headers = mime_parse_hdr(bio))) { + PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_PARSE_ERROR); + return NULL; + } + + if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + sk_pop_free(headers, mime_hdr_free); + PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_CONTENT_TYPE); + return NULL; + } + + /* Handle multipart/signed */ + + if(!strcmp(hdr->value, "multipart/signed")) { + /* Split into two parts */ + prm = mime_param_find(hdr, "boundary"); + if(!prm || !prm->param_value) { + sk_pop_free(headers, mime_hdr_free); + PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BOUNDARY); + return NULL; + } + ret = multi_split(bio, prm->param_value, &parts); + sk_pop_free(headers, mime_hdr_free); + if(!ret || (sk_num(parts) != 2) ) { + PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BODY_FAILURE); + sk_pop_free(parts, (stkfree)BIO_free); + return NULL; + } + + /* Parse the signature piece */ + p7in = (BIO *)sk_value(parts, 1); + + if (!(headers = mime_parse_hdr(p7in))) { + PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_SIG_PARSE_ERROR); + sk_pop_free(parts, (stkfree)BIO_free); + return NULL; + } + + /* Get content type */ + + if(!(hdr = mime_hdr_find(headers, "content-type")) || + !hdr->value) { + sk_pop_free(headers, mime_hdr_free); + PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_SIG_CONTENT_TYPE); + return NULL; + } + + if(strcmp(hdr->value, "application/x-pkcs7-signature") && + strcmp(hdr->value, "application/pkcs7-signature")) { + sk_pop_free(headers, mime_hdr_free); + PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_SIG_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_pop_free(parts, (stkfree)BIO_free); + return NULL; + } + sk_pop_free(headers, mime_hdr_free); + /* Read in PKCS#7 */ + if(!(p7 = B64_read_PKCS7(p7in))) { + PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_PKCS7_SIG_PARSE_ERROR); + sk_pop_free(parts, (stkfree)BIO_free); + return NULL; + } + + if(bcont) { + *bcont = (BIO *)sk_value(parts, 0); + BIO_free(p7in); + sk_free(parts); + } else sk_pop_free(parts, (stkfree)BIO_free); + return p7; + } + + /* OK, if not multipart/signed try opaque signature */ + + if (strcmp (hdr->value, "application/x-pkcs7-mime") && + strcmp (hdr->value, "application/pkcs7-mime")) { + PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_pop_free(headers, mime_hdr_free); + return NULL; + } + + sk_pop_free(headers, mime_hdr_free); + + if(!(p7 = B64_read_PKCS7(bio))) { + PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_PKCS7_PARSE_ERROR); + return NULL; + } + return p7; + +} + +/* Copy text from one BIO to another making the output CRLF at EOL */ +int SMIME_crlf_copy(BIO *in, BIO *out, int flags) +{ + char eol; + int len; + char linebuf[MAX_SMLEN]; + if(flags & PKCS7_BINARY) { + while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) + BIO_write(out, linebuf, len); + return 1; + } + if(flags & PKCS7_TEXT) BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); + while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { + eol = 0; + while(iscrlf(linebuf[len - 1])) { + len--; + eol = 1; + } + BIO_write(out, linebuf, len); + if(eol) BIO_write(out, "\r\n", 2); + } + return 1; +} + +/* Strip off headers if they are text/plain */ +int SMIME_text(BIO *in, BIO *out) +{ + char iobuf[4096]; + int len; + STACK *headers; + MIME_HEADER *hdr; + if (!(headers = mime_parse_hdr(in))) { + PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR); + return 0; + } + if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE); + sk_pop_free(headers, mime_hdr_free); + return 0; + } + if (strcmp (hdr->value, "text/plain")) { + PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE); + ERR_add_error_data(2, "type: ", hdr->value); + sk_pop_free(headers, mime_hdr_free); + return 0; + } + sk_pop_free(headers, mime_hdr_free); + while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) + BIO_write(out, iobuf, len); + return 1; +} + +/* Split a multipart/XXX message body into component parts: result is + * canonical parts in a STACK of bios + */ + +static int multi_split(BIO *bio, char *bound, STACK **ret) +{ + char linebuf[MAX_SMLEN]; + int len, blen; + BIO *bpart = NULL; + STACK *parts; + char state, part, first; + blen = strlen(bound); + part = 0; + state = 0; + first = 1; + parts = sk_new(NULL); + *ret = parts; + while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + state = mime_bound_check(linebuf, len, bound, blen); + if(state == 1) { + first = 1; + part++; + } else if(state == 2) { + sk_push(parts, (char *)bpart); + return 1; + } else if(part) { + if(first) { + first = 0; + if(bpart) sk_push(parts, (char *)bpart); + bpart = BIO_new(BIO_s_mem()); + + } else BIO_write(bpart, "\r\n", 2); + /* Strip CR+LF from linebuf */ + while(iscrlf(linebuf[len - 1])) len--; + BIO_write(bpart, linebuf, len); + } + } + return 0; +} + +static int iscrlf(char c) +{ + if(c == '\r' || c == '\n') return 1; + return 0; +} + +/* This is the big one: parse MIME header lines up to message body */ + +#define MIME_INVALID 0 +#define MIME_START 1 +#define MIME_TYPE 2 +#define MIME_NAME 3 +#define MIME_VALUE 4 +#define MIME_QUOTE 5 +#define MIME_COMMENT 6 + + +static STACK *mime_parse_hdr(BIO *bio) +{ + char *p, *q, c; + char *ntmp; + char linebuf[MAX_SMLEN]; + MIME_HEADER *mhdr = NULL; + STACK *headers; + int len, state, save_state = 0; + headers = sk_new(mime_hdr_cmp); + while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { + /* If whitespace at line start then continuation line */ + if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME; + else state = MIME_START; + ntmp = NULL; + /* Go through all characters */ + for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { + + /* State machine to handle MIME headers + * if this looks horrible that's because it *is* + */ + + switch(state) { + case MIME_START: + if(c == ':') { + state = MIME_TYPE; + *p = 0; + ntmp = strip_ends(q); + q = p + 1; + } + break; + + case MIME_TYPE: + if(c == ';') { + mime_debug("Found End Value\n"); + *p = 0; + mhdr = mime_hdr_new(ntmp, strip_ends(q)); + sk_push(headers, (char *)mhdr); + ntmp = NULL; + q = p + 1; + state = MIME_NAME; + } else if(c == '(') { + save_state = state; + state = MIME_COMMENT; + } + break; + + case MIME_COMMENT: + if(c == ')') { + state = save_state; + } + break; + + case MIME_NAME: + if(c == '=') { + state = MIME_VALUE; + *p = 0; + ntmp = strip_ends(q); + q = p + 1; + } + break ; + + case MIME_VALUE: + if(c == ';') { + state = MIME_NAME; + *p = 0; + mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + ntmp = NULL; + q = p + 1; + } else if (c == '"') { + mime_debug("Found Quote\n"); + state = MIME_QUOTE; + } else if(c == '(') { + save_state = state; + state = MIME_COMMENT; + } + break; + + case MIME_QUOTE: + if(c == '"') { + mime_debug("Found Match Quote\n"); + state = MIME_VALUE; + } + break; + } + } + + if(state == MIME_TYPE) { + mhdr = mime_hdr_new(ntmp, strip_ends(q)); + sk_push(headers, (char *)mhdr); + } else if(state == MIME_VALUE) + mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); + if(p == linebuf) break; /* Blank line means end of headers */ +} + +return headers; + +} + +static char *strip_ends(char *name) +{ + return strip_end(strip_start(name)); +} + +/* Strip a parameter of whitespace from start of param */ +static char *strip_start(char *name) +{ + char *p, c; + /* Look for first non white space or quote */ + for(p = name; (c = *p) ;p++) { + if(c == '"') { + /* Next char is start of string if non null */ + if(p[1]) return p + 1; + /* Else null string */ + return NULL; + } + if(!isspace((unsigned char)c)) return p; + } + return NULL; +} + +/* As above but strip from end of string : maybe should handle brackets? */ +static char *strip_end(char *name) +{ + char *p, c; + if(!name) return NULL; + /* Look for first non white space or quote */ + for(p = name + strlen(name) - 1; p >= name ;p--) { + c = *p; + if(c == '"') { + if(p - 1 == name) return NULL; + *p = 0; + return name; + } + if(isspace((unsigned char)c)) *p = 0; + else return name; + } + return NULL; +} + +static MIME_HEADER *mime_hdr_new(char *name, char *value) +{ + MIME_HEADER *mhdr; + char *tmpname, *tmpval, *p; + int c; + if(name) { + if(!(tmpname = BUF_strdup(name))) return NULL; + for(p = tmpname ; *p; p++) { + c = *p; + if(isupper(c)) { + c = tolower(c); + *p = c; + } + } + } else tmpname = NULL; + if(value) { + if(!(tmpval = BUF_strdup(value))) return NULL; + for(p = tmpval ; *p; p++) { + c = *p; + if(isupper(c)) { + c = tolower(c); + *p = c; + } + } + } else tmpval = NULL; + mhdr = (MIME_HEADER *) Malloc(sizeof(MIME_HEADER)); + if(!mhdr) return NULL; + mhdr->name = tmpname; + mhdr->value = tmpval; + if(!(mhdr->params = sk_new(mime_param_cmp))) return NULL; + return mhdr; +} + +static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) +{ + char *tmpname, *tmpval, *p; + int c; + MIME_PARAM *mparam; + if(name) { + tmpname = BUF_strdup(name); + if(!tmpname) return 0; + for(p = tmpname ; *p; p++) { + c = *p; + if(isupper(c)) { + c = tolower(c); + *p = c; + } + } + } else tmpname = NULL; + if(value) { + tmpval = BUF_strdup(value); + if(!tmpval) return 0; + } else tmpval = NULL; + /* Parameter values are case sensitive so leave as is */ + mparam = (MIME_PARAM *) Malloc(sizeof(MIME_PARAM)); + if(!mparam) return 0; + mparam->param_name = tmpname; + mparam->param_value = tmpval; + sk_push(mhdr->params, (char *)mparam); + return 1; +} + +static int mime_hdr_cmp(MIME_HEADER **a, MIME_HEADER **b) +{ + return(strcmp((*a)->name, (*b)->name)); +} + +static int mime_param_cmp(MIME_PARAM **a, MIME_PARAM **b) +{ + return(strcmp((*a)->param_name, (*b)->param_name)); +} + +/* Find a header with a given name (if possible) */ + +static MIME_HEADER *mime_hdr_find(STACK *hdrs, char *name) +{ + MIME_HEADER htmp; + int idx; + htmp.name = name; + idx = sk_find(hdrs, (char *)&htmp); + if(idx < 0) return NULL; + return (MIME_HEADER *)sk_value(hdrs, idx); +} + +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) +{ + MIME_PARAM param; + int idx; + param.param_name = name; + idx = sk_find(hdr->params, (char *)¶m); + if(idx < 0) return NULL; + return (MIME_PARAM *)sk_value(hdr->params, idx); +} + +static void mime_hdr_free(MIME_HEADER *hdr) +{ + if(hdr->name) Free(hdr->name); + if(hdr->value) Free(hdr->value); + if(hdr->params) sk_pop_free(hdr->params, mime_param_free); + Free(hdr); +} + +static void mime_param_free(MIME_PARAM *param) +{ + if(param->param_name) Free(param->param_name); + if(param->param_value) Free(param->param_value); + Free(param); +} + +/* Check for a multipart boundary. Returns: + * 0 : no boundary + * 1 : part boundary + * 2 : final boundary + */ +static int mime_bound_check(char *line, int linelen, char *bound, int blen) +{ + if(linelen == -1) linelen = strlen(line); + if(blen == -1) blen = strlen(bound); + /* Quickly eliminate if line length too short */ + if(blen + 2 > linelen) return 0; + /* Check for part boundary */ + if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) { + if(!strncmp(line + blen + 2, "--", 2)) return 2; + else return 1; + } + return 0; +} diff --git a/src/lib/libcrypto/pkcs7/pk7_smime.c b/src/lib/libcrypto/pkcs7/pk7_smime.c new file mode 100644 index 0000000000..b41f42ed04 --- /dev/null +++ b/src/lib/libcrypto/pkcs7/pk7_smime.c @@ -0,0 +1,427 @@ +/* pk7_smime.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). + * + */ + +/* Simple PKCS#7 processing functions */ + +#include +#include "cryptlib.h" +#include +#include + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags) +{ + PKCS7 *p7; + PKCS7_SIGNER_INFO *si; + BIO *p7bio; + STACK *smcap; + int i; + + if(!X509_check_private_key(signcert, pkey)) { + PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return NULL; + } + + if(!(p7 = PKCS7_new())) { + PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); + return NULL; + } + + PKCS7_set_type(p7, NID_pkcs7_signed); + + PKCS7_content_new(p7, NID_pkcs7_data); + + if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) { + PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); + return NULL; + } + + if(!(flags & PKCS7_NOCERTS)) { + PKCS7_add_certificate(p7, signcert); + if(certs) for(i = 0; i < sk_X509_num(certs); i++) + PKCS7_add_certificate(p7, sk_X509_value(certs, i)); + } + + if(!(p7bio = PKCS7_dataInit(p7, NULL))) { + PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); + return NULL; + } + + + SMIME_crlf_copy(data, p7bio, flags); + + if(!(flags & PKCS7_NOATTR)) { + PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, + V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); + /* Add SMIMECapabilities */ + if(!(smcap = sk_new(NULL))) { + PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); + return NULL; + } +#ifndef NO_DES + PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1); +#endif +#ifndef NO_RC2 + PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128); + PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64); +#endif +#ifndef NO_DES + PKCS7_simple_smimecap (smcap, NID_des_cbc, -1); +#endif +#ifndef NO_RC2 + PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40); +#endif + PKCS7_add_attrib_smimecap (si, smcap); + sk_pop_free(smcap, X509_ALGOR_free); + } + + if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1); + + if (!PKCS7_dataFinal(p7,p7bio)) { + PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN); + return NULL; + } + + BIO_free_all(p7bio); + return p7; +} + +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags) +{ + STACK_OF(X509) *signers; + X509 *signer; + STACK_OF(PKCS7_SIGNER_INFO) *sinfos; + PKCS7_SIGNER_INFO *si; + X509_STORE_CTX cert_ctx; + char buf[4096]; + int i, j=0; + BIO *p7bio; + BIO *tmpout; + + if(!p7) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER); + return 0; + } + + if(!PKCS7_type_is_signed(p7)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + /* Check for no data and no content: no data to verify signature */ + if(PKCS7_get_detached(p7) && !indata) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT); + return 0; + } + + /* Check for data and content: two sets of data */ + if(!PKCS7_get_detached(p7) && indata) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CONTENT_AND_DATA_PRESENT); + return 0; + } + + sinfos = PKCS7_get_signer_info(p7); + + if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA); + return 0; + } + + + signers = PKCS7_get0_signers(p7, certs, flags); + + if(!signers) return 0; + + /* Now verify the certificates */ + + if (!(flags & PKCS7_NOVERIFY)) for (i = 0; i < sk_X509_num(signers); i++) { + signer = sk_X509_value (signers, i); + if (!(flags & PKCS7_NOCHAIN)) { + X509_STORE_CTX_init(&cert_ctx, store, signer, + p7->d.sign->cert); + X509_STORE_CTX_set_purpose(&cert_ctx, + X509_PURPOSE_SMIME_SIGN); + } else X509_STORE_CTX_init (&cert_ctx, store, signer, NULL); + i = X509_verify_cert(&cert_ctx); + if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx); + X509_STORE_CTX_cleanup(&cert_ctx); + if (i <= 0) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CERTIFICATE_VERIFY_ERROR); + ERR_add_error_data(2, "Verify error:", + X509_verify_cert_error_string(j)); + sk_X509_free(signers); + return 0; + } + /* Check for revocation status here */ + } + + p7bio=PKCS7_dataInit(p7,indata); + + if(flags & PKCS7_TEXT) { + if(!(tmpout = BIO_new(BIO_s_mem()))) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE); + goto err; + } + } else tmpout = out; + + /* We now have to 'read' from p7bio to calculate digests etc. */ + for (;;) + { + i=BIO_read(p7bio,buf,sizeof(buf)); + if (i <= 0) break; + if (tmpout) BIO_write(tmpout, buf, i); + } + + if(flags & PKCS7_TEXT) { + if(!SMIME_text(tmpout, out)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SMIME_TEXT_ERROR); + BIO_free(tmpout); + goto err; + } + BIO_free(tmpout); + } + + /* Now Verify All Signatures */ + if (!(flags & PKCS7_NOSIGS)) + for (i=0; iissuer_and_serial; + signer = NULL; + /* If any certificates passed they take priority */ + if (certs) signer = X509_find_by_issuer_and_serial (certs, + ias->issuer, ias->serial); + if (!signer && !(flags & PKCS7_NOINTERN) + && p7->d.sign->cert) signer = + X509_find_by_issuer_and_serial (p7->d.sign->cert, + ias->issuer, ias->serial); + if (!signer) { + PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); + sk_X509_free(signers); + return 0; + } + + sk_X509_push(signers, signer); + } + return signers; +} + + +/* Build a complete PKCS#7 enveloped data */ + +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, + int flags) +{ + PKCS7 *p7; + BIO *p7bio = NULL; + int i; + X509 *x509; + if(!(p7 = PKCS7_new())) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE); + return NULL; + } + + PKCS7_set_type(p7, NID_pkcs7_enveloped); + if(!PKCS7_set_cipher(p7, cipher)) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER); + goto err; + } + + for(i = 0; i < sk_X509_num(certs); i++) { + x509 = sk_X509_value(certs, i); + if(!PKCS7_add_recipient(p7, x509)) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT, + PKCS7_R_ERROR_ADDING_RECIPIENT); + goto err; + } + } + + if(!(p7bio = PKCS7_dataInit(p7, NULL))) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE); + goto err; + } + + SMIME_crlf_copy(in, p7bio, flags); + + BIO_flush(p7bio); + + if (!PKCS7_dataFinal(p7,p7bio)) { + PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR); + goto err; + } + BIO_free_all(p7bio); + + return p7; + + err: + + BIO_free(p7bio); + PKCS7_free(p7); + return NULL; + +} + +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) +{ + BIO *tmpmem; + int ret, i; + char buf[4096]; + + if(!p7) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER); + return 0; + } + + if(!PKCS7_type_is_enveloped(p7)) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE); + return 0; + } + + if(!X509_check_private_key(cert, pkey)) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, + PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); + return 0; + } + + if(!(tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert))) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR); + return 0; + } + + if (flags & PKCS7_TEXT) { + BIO *tmpbuf, *bread; + /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */ + if(!(tmpbuf = BIO_new(BIO_f_buffer()))) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + return 0; + } + if(!(bread = BIO_push(tmpbuf, tmpmem))) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + return 0; + } + ret = SMIME_text(bread, data); + BIO_free_all(bread); + return ret; + } else { + for(;;) { + i = BIO_read(tmpmem, buf, sizeof(buf)); + if(i <= 0) break; + BIO_write(data, buf, i); + } + BIO_free_all(tmpmem); + return 1; + } +} diff --git a/src/lib/libcrypto/rand/rand_err.c b/src/lib/libcrypto/rand/rand_err.c new file mode 100644 index 0000000000..d1263edf80 --- /dev/null +++ b/src/lib/libcrypto/rand/rand_err.c @@ -0,0 +1,93 @@ +/* crypto/rand/rand_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. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA RAND_str_functs[]= + { +{ERR_PACK(0,RAND_F_SSLEAY_RAND_BYTES,0), "SSLEAY_RAND_BYTES"}, +{0,NULL} + }; + +static ERR_STRING_DATA RAND_str_reasons[]= + { +{RAND_R_PRNG_NOT_SEEDED ,"prng not seeded"}, +{0,NULL} + }; + +#endif + +void ERR_load_RAND_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_RAND,RAND_str_functs); + ERR_load_strings(ERR_LIB_RAND,RAND_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/rand/rand_lib.c b/src/lib/libcrypto/rand/rand_lib.c new file mode 100644 index 0000000000..34c6d5b968 --- /dev/null +++ b/src/lib/libcrypto/rand/rand_lib.c @@ -0,0 +1,98 @@ +/* crypto/rand/rand_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 + +#ifdef NO_RAND +static RAND_METHOD *rand_meth=NULL; +#else +extern RAND_METHOD rand_ssleay_meth; +static RAND_METHOD *rand_meth= &rand_ssleay_meth; +#endif + +void RAND_set_rand_method(RAND_METHOD *meth) + { + rand_meth=meth; + } + +RAND_METHOD *RAND_get_rand_method(void) + { + return(rand_meth); + } + +void RAND_cleanup(void) + { + if (rand_meth != NULL) + rand_meth->cleanup(); + } + +void RAND_seed(const void *buf, int num) + { + if (rand_meth != NULL) + rand_meth->seed(buf,num); + } + +void RAND_bytes(unsigned char *buf, int num) + { + if (rand_meth != NULL) + rand_meth->bytes(buf,num); + } + diff --git a/src/lib/libcrypto/rc2/rc2.h b/src/lib/libcrypto/rc2/rc2.h new file mode 100644 index 0000000000..9571efb755 --- /dev/null +++ b/src/lib/libcrypto/rc2/rc2.h @@ -0,0 +1,99 @@ +/* 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 8 +#define RC2_KEY_LENGTH 16 + +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); +void RC2_ecb_encrypt(unsigned char *in,unsigned char *out,RC2_KEY *key, + int enc); +void RC2_encrypt(unsigned long *data,RC2_KEY *key); +void RC2_decrypt(unsigned long *data,RC2_KEY *key); +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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/libcrypto/rc4/rc4.h b/src/lib/libcrypto/rc4/rc4.h new file mode 100644 index 0000000000..7418c2a9a2 --- /dev/null +++ b/src/lib/libcrypto/rc4/rc4.h @@ -0,0 +1,88 @@ +/* crypto/rc4/rc4.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_RC4_H +#define HEADER_RC4_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NO_RC4 +#error RC4 is disabled. +#endif + +#include /* RC4_INT */ + +typedef struct rc4_key_st + { + RC4_INT x,y; + RC4_INT data[256]; + } RC4_KEY; + + +const char *RC4_options(void); +void RC4_set_key(RC4_KEY *key, int len, unsigned char *data); +void RC4(RC4_KEY *key, unsigned long len, unsigned char *indata, + unsigned char *outdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/libcrypto/rc4/rc4_locl.h b/src/lib/libcrypto/rc4/rc4_locl.h new file mode 100644 index 0000000000..3bb80b6ce9 --- /dev/null +++ b/src/lib/libcrypto/rc4/rc4_locl.h @@ -0,0 +1,4 @@ +#ifndef HEADER_RC4_LOCL_H +#define HEADER_RC4_LOCL_H +#include +#endif diff --git a/src/lib/libcrypto/rsa/rsa_asn1.c b/src/lib/libcrypto/rsa/rsa_asn1.c new file mode 100644 index 0000000000..1455a7e0e4 --- /dev/null +++ b/src/lib/libcrypto/rsa/rsa_asn1.c @@ -0,0 +1,121 @@ +/* rsa_asn1.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 + +static ASN1_METHOD method={ + (int (*)()) i2d_RSAPrivateKey, + (char *(*)())d2i_RSAPrivateKey, + (char *(*)())RSA_new, + (void (*)()) RSA_free}; + +ASN1_METHOD *RSAPrivateKey_asn1_meth(void) + { + return(&method); + } + +/* Override the default free and new methods */ +static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if(operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)RSA_new(); + if(*pval) return 2; + return 0; + } else if(operation == ASN1_OP_FREE_PRE) { + RSA_free((RSA *)*pval); + *pval = NULL; + return 2; + } + return 1; +} + +ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { + ASN1_SIMPLE(RSA, version, LONG), + ASN1_SIMPLE(RSA, n, BIGNUM), + ASN1_SIMPLE(RSA, e, BIGNUM), + ASN1_SIMPLE(RSA, d, BIGNUM), + ASN1_SIMPLE(RSA, p, BIGNUM), + ASN1_SIMPLE(RSA, q, BIGNUM), + ASN1_SIMPLE(RSA, dmp1, BIGNUM), + ASN1_SIMPLE(RSA, dmq1, BIGNUM), + ASN1_SIMPLE(RSA, iqmp, BIGNUM) +} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey) + + +ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { + ASN1_SIMPLE(RSA, n, BIGNUM), + ASN1_SIMPLE(RSA, e, BIGNUM), +} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey) + +RSA *RSAPublicKey_dup(RSA *rsa) + { + return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), rsa); + } + +RSA *RSAPrivateKey_dup(RSA *rsa) + { + return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), rsa); + } diff --git a/src/lib/libcrypto/rsa/rsa_chk.c b/src/lib/libcrypto/rsa/rsa_chk.c new file mode 100644 index 0000000000..91b9115798 --- /dev/null +++ b/src/lib/libcrypto/rsa/rsa_chk.c @@ -0,0 +1,184 @@ +/* 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/src/lib/libcrypto/rsa/rsa_oaep.c b/src/lib/libcrypto/rsa/rsa_oaep.c new file mode 100644 index 0000000000..843c40c864 --- /dev/null +++ b/src/lib/libcrypto/rsa/rsa_oaep.c @@ -0,0 +1,162 @@ +/* crypto/rsa/rsa_oaep.c */ +/* Written by Ulf Moeller. This software is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */ + +/* EME_OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ + +#if !defined(NO_SHA) && !defined(NO_SHA1) +#include +#include "cryptlib.h" +#include +#include +#include +#include + +int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen); + +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + unsigned char *from, int flen, unsigned char *param, int plen) + { + int i, emlen = tlen - 1; + unsigned char *db, *seed; + unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH]; + + if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return (0); + } + + if (emlen < 2 * SHA_DIGEST_LENGTH + 1) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL); + return (0); + } + + dbmask = Malloc(emlen - SHA_DIGEST_LENGTH); + if (dbmask == NULL) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); + return (0); + } + + to[0] = 0; + seed = to + 1; + db = to + SHA_DIGEST_LENGTH + 1; + + SHA1(param, plen, db); + memset(db + SHA_DIGEST_LENGTH, 0, + emlen - flen - 2 * SHA_DIGEST_LENGTH - 1); + db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01; + memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen); + RAND_bytes(seed, SHA_DIGEST_LENGTH); +#ifdef PKCS_TESTVECT + memcpy(seed, + "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f", + 20); +#endif + + MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH); + for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) + db[i] ^= dbmask[i]; + + MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH); + for (i = 0; i < SHA_DIGEST_LENGTH; i++) + seed[i] ^= seedmask[i]; + + Free(dbmask); + return (1); + } + +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + unsigned char *from, int flen, int num, unsigned char *param, + int plen) + { + int i, dblen, mlen = -1; + unsigned char *maskeddb; + int lzero; + unsigned char *db, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; + + if (--num < 2 * SHA_DIGEST_LENGTH + 1) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); + return (-1); + } + + dblen = num - SHA_DIGEST_LENGTH; + db = Malloc(dblen); + if (db == NULL) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); + return (-1); + } + + lzero = num - flen; + maskeddb = from - lzero + SHA_DIGEST_LENGTH; + + MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen); + for (i = lzero; i < SHA_DIGEST_LENGTH; i++) + seed[i] ^= from[i - lzero]; + + MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); + for (i = 0; i < dblen; i++) + db[i] ^= maskeddb[i]; + + SHA1(param, plen, phash); + + if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0) + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); + else + { + for (i = SHA_DIGEST_LENGTH; i < dblen; i++) + if (db[i] != 0x00) + break; + if (db[i] != 0x01 || i++ >= dblen) + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, + RSA_R_OAEP_DECODING_ERROR); + else + { + mlen = dblen - i; + if (tlen < mlen) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); + mlen = -1; + } + else + memcpy(to, db + i, mlen); + } + } + Free(db); + return (mlen); + } + +int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen) + { + long i, outlen = 0; + unsigned char cnt[4]; + SHA_CTX c; + unsigned char md[SHA_DIGEST_LENGTH]; + + for (i = 0; outlen < len; i++) + { + cnt[0] = (i >> 24) & 255, cnt[1] = (i >> 16) & 255, + cnt[2] = (i >> 8) & 255, cnt[3] = i & 255; + SHA1_Init(&c); + SHA1_Update(&c, seed, seedlen); + SHA1_Update(&c, cnt, 4); + if (outlen + SHA_DIGEST_LENGTH <= len) + { + SHA1_Final(mask + outlen, &c); + outlen += SHA_DIGEST_LENGTH; + } + else + { + SHA1_Final(md, &c); + memcpy(mask + outlen, md, len - outlen); + outlen = len; + } + } + return (0); + } +#endif diff --git a/src/lib/libcrypto/stack/safestack.h b/src/lib/libcrypto/stack/safestack.h new file mode 100644 index 0000000000..38934981e3 --- /dev/null +++ b/src/lib/libcrypto/stack/safestack.h @@ -0,0 +1,129 @@ +/* ==================================================================== + * 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/src/lib/libcrypto/ui/ui.h b/src/lib/libcrypto/ui/ui.h new file mode 100644 index 0000000000..735a2d988e --- /dev/null +++ b/src/lib/libcrypto/ui/ui.h @@ -0,0 +1,387 @@ +/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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_UI_H +#define HEADER_UI_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* The UI type is a holder for a specific user interface session. It can + contain an illimited number of informational or error strings as well + as things to prompt for, both passwords (noecho mode) and others (echo + mode), and verification of the same. All of these are called strings, + and are further described below. */ +typedef struct ui_st UI; + +/* All instances of UI have a reference to a method structure, which is a + ordered vector of functions that implement the lower level things to do. + There is an instruction on the implementation further down, in the section + for method implementors. */ +typedef struct ui_method_st UI_METHOD; + + +/* All the following functions return -1 or NULL on error and in some cases + (UI_process()) -2 if interrupted or in some other way cancelled. + When everything is fine, they return 0, a positive value or a non-NULL + pointer, all depending on their purpose. */ + +/* Creators and destructor. */ +UI *UI_new(void); +UI *UI_new_method(const UI_METHOD *method); +void UI_free(UI *ui); + +/* The following functions are used to add strings to be printed and prompt + strings to prompt for data. The names are UI_{add,dup}__string + and UI_{add,dup}_input_boolean. + + UI_{add,dup}__string have the following meanings: + add add a text or prompt string. The pointers given to these + functions are used verbatim, no copying is done. + dup make a copy of the text or prompt string, then add the copy + to the collection of strings in the user interface. + + The function is a name for the functionality that the given + string shall be used for. It can be one of: + input use the string as data prompt. + verify use the string as verification prompt. This + is used to verify a previous input. + info use the string for informational output. + error use the string for error output. + Honestly, there's currently no difference between info and error for the + moment. + + UI_{add,dup}_input_boolean have the same semantics for "add" and "dup", + and are typically used when one wants to prompt for a yes/no response. + + + All of the functions in this group take a UI and a prompt string. + The string input and verify addition functions also take a flag argument, + a buffer for the result to end up with, a minimum input size and a maximum + input size (the result buffer MUST be large enough to be able to contain + the maximum number of characters). Additionally, the verify addition + functions takes another buffer to compare the result against. + The boolean input functions take an action description string (which should + be safe to ignore if the expected user action is obvious, for example with + a dialog box with an OK button and a Cancel button), a string of acceptable + characters to mean OK and to mean Cancel. The two last strings are checked + to make sure they don't have common characters. Additionally, the same + flag argument as for the string input is taken, as well as a result buffer. + The result buffer is required to be at least one byte long. Depending on + the answer, the first character from the OK or the Cancel character strings + will be stored in the first byte of the result buffer. No NUL will be + added, so the result is *not* a string. + + On success, the all return an index of the added information. That index + is usefull when retrieving results with UI_get0_result(). */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, const char *test_buf); +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, const char *test_buf); +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_add_info_string(UI *ui, const char *text); +int UI_dup_info_string(UI *ui, const char *text); +int UI_add_error_string(UI *ui, const char *text); +int UI_dup_error_string(UI *ui, const char *text); + +/* These are the possible flags. They can be or'ed together. */ +/* Use to have echoing of input */ +#define UI_INPUT_FLAG_ECHO 0x01 +/* Use a default password. Where that password is found is completely + up to the application, it might for example be in the user data set + with UI_add_user_data(). It is not recommended to have more than + one input in each UI being marked with this flag, or the application + might get confused. */ +#define UI_INPUT_FLAG_DEFAULT_PWD 0x02 + +/* The user of these routines may want to define flags of their own. The core + UI won't look at those, but will pass them on to the method routines. They + must use higher bits so they don't get confused with the UI bits above. + UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good + example of use is this: + + #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE) + +*/ +#define UI_INPUT_FLAG_USER_BASE 16 + + +/* The following function helps construct a prompt. object_desc is a + textual short description of the object, for example "pass phrase", + and object_name is the name of the object (might be a card name or + a file name. + The returned string shall always be allocated on the heap with + OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). + + If the ui_method doesn't contain a pointer to a user-defined prompt + constructor, a default string is built, looking like this: + + "Enter {object_desc} for {object_name}:" + + So, if object_desc has the value "pass phrase" and object_name has + the value "foo.key", the resulting string is: + + "Enter pass phrase for foo.key:" +*/ +char *UI_construct_prompt(UI *ui_method, + const char *object_desc, const char *object_name); + + +/* The following function is used to store a pointer to user-specific data. + Any previous such pointer will be returned and replaced. + + For callback purposes, this function makes a lot more sense than using + ex_data, since the latter requires that different parts of OpenSSL or + applications share the same ex_data index. + + Note that the UI_OpenSSL() method completely ignores the user data. + Other methods may not, however. */ +void *UI_add_user_data(UI *ui, void *user_data); +/* We need a user data retrieving function as well. */ +void *UI_get0_user_data(UI *ui); + +/* Return the result associated with a prompt given with the index i. */ +const char *UI_get0_result(UI *ui, int i); + +/* When all strings have been added, process the whole thing. */ +int UI_process(UI *ui); + +/* Give a user interface parametrised control commands. This can be used to + send down an integer, a data pointer or a function pointer, as well as + be used to get information from a UI. */ +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)()); + +/* The commands */ +/* Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the + OpenSSL error stack before printing any info or added error messages and + before any prompting. */ +#define UI_CTRL_PRINT_ERRORS 1 +/* Check if a UI_process() is possible to do again with the same instance of + a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0 + if not. */ +#define UI_CTRL_IS_REDOABLE 2 + + +/* Some methods may use extra data */ +#define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg) +#define UI_get_app_data(s) UI_get_ex_data(s,0) +int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int UI_set_ex_data(UI *r,int idx,void *arg); +void *UI_get_ex_data(UI *r, int idx); + +/* Use specific methods instead of the built-in one */ +void UI_set_default_method(const UI_METHOD *meth); +const UI_METHOD *UI_get_default_method(void); +const UI_METHOD *UI_get_method(UI *ui); +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth); + +/* The method with all the built-in thingies */ +UI_METHOD *UI_OpenSSL(void); + + +/* ---------- For method writers ---------- */ +/* A method contains a number of functions that implement the low level + of the User Interface. The functions are: + + an opener This function starts a session, maybe by opening + a channel to a tty, or by opening a window. + a writer This function is called to write a given string, + maybe to the tty, maybe as a field label in a + window. + a flusher This function is called to flush everything that + has been output so far. It can be used to actually + display a dialog box after it has been built. + a reader This function is called to read a given prompt, + maybe from the tty, maybe from a field in a + window. Note that it's called wth all string + structures, not only the prompt ones, so it must + check such things itself. + a closer This function closes the session, maybe by closing + the channel to the tty, or closing the window. + + All these functions are expected to return: + + 0 on error. + 1 on success. + -1 on out-of-band events, for example if some prompting has + been canceled (by pressing Ctrl-C, for example). This is + only checked when returned by the flusher or the reader. + + The way this is used, the opener is first called, then the writer for all + strings, then the flusher, then the reader for all strings and finally the + closer. Note that if you want to prompt from a terminal or other command + line interface, the best is to have the reader also write the prompts + instead of having the writer do it. If you want to prompt from a dialog + box, the writer can be used to build up the contents of the box, and the + flusher to actually display the box and run the event loop until all data + has been given, after which the reader only grabs the given data and puts + them back into the UI strings. + + All method functions take a UI as argument. Additionally, the writer and + the reader take a UI_STRING. +*/ + +/* The UI_STRING type is the data structure that contains all the needed info + about a string or a prompt, including test data for a verification prompt. +*/ +DECLARE_STACK_OF(UI_STRING) +typedef struct ui_string_st UI_STRING; + +/* The different types of strings that are currently supported. + This is only needed by method authors. */ +enum UI_string_types + { + UIT_NONE=0, + UIT_PROMPT, /* Prompt for a string */ + UIT_VERIFY, /* Prompt for a string and verify */ + UIT_BOOLEAN, /* Prompt for a yes/no response */ + UIT_INFO, /* Send info to the user */ + UIT_ERROR /* Send an error message to the user */ + }; + +/* Create and manipulate methods */ +UI_METHOD *UI_create_method(char *name); +void UI_destroy_method(UI_METHOD *ui_method); +int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)); +int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis)); +int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui)); +int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis)); +int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)); +int (*UI_method_get_opener(UI_METHOD *method))(UI*); +int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*); +int (*UI_method_get_flusher(UI_METHOD *method))(UI*); +int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*); +int (*UI_method_get_closer(UI_METHOD *method))(UI*); + +/* The following functions are helpers for method writers to access relevant + data from a UI_STRING. */ + +/* Return type of the UI_STRING */ +enum UI_string_types UI_get_string_type(UI_STRING *uis); +/* Return input flags of the UI_STRING */ +int UI_get_input_flags(UI_STRING *uis); +/* Return the actual string to output (the prompt, info or error) */ +const char *UI_get0_output_string(UI_STRING *uis); +/* Return the optional action string to output (the boolean promtp instruction) */ +const char *UI_get0_action_string(UI_STRING *uis); +/* Return the result of a prompt */ +const char *UI_get0_result_string(UI_STRING *uis); +/* Return the string to test the result against. Only useful with verifies. */ +const char *UI_get0_test_string(UI_STRING *uis); +/* Return the required minimum size of the result */ +int UI_get_result_minsize(UI_STRING *uis); +/* Return the required maximum size of the result */ +int UI_get_result_maxsize(UI_STRING *uis); +/* Set the result of a UI_STRING. */ +int UI_set_result(UI *ui, UI_STRING *uis, const char *result); + + +/* A couple of popular utility functions */ +int UI_UTIL_read_pw_string(char *buf,int length,const char *prompt,int verify); +int UI_UTIL_read_pw(char *buf,char *buff,int size,const char *prompt,int verify); + + +/* 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. + */ +void ERR_load_UI_strings(void); + +/* Error codes for the UI functions. */ + +/* Function codes. */ +#define UI_F_GENERAL_ALLOCATE_BOOLEAN 108 +#define UI_F_GENERAL_ALLOCATE_PROMPT 109 +#define UI_F_GENERAL_ALLOCATE_STRING 100 +#define UI_F_UI_CTRL 111 +#define UI_F_UI_DUP_ERROR_STRING 101 +#define UI_F_UI_DUP_INFO_STRING 102 +#define UI_F_UI_DUP_INPUT_BOOLEAN 110 +#define UI_F_UI_DUP_INPUT_STRING 103 +#define UI_F_UI_DUP_VERIFY_STRING 106 +#define UI_F_UI_GET0_RESULT 107 +#define UI_F_UI_NEW_METHOD 104 +#define UI_F_UI_SET_RESULT 105 + +/* Reason codes. */ +#define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104 +#define UI_R_INDEX_TOO_LARGE 102 +#define UI_R_INDEX_TOO_SMALL 103 +#define UI_R_NO_RESULT_BUFFER 105 +#define UI_R_RESULT_TOO_LARGE 100 +#define UI_R_RESULT_TOO_SMALL 101 +#define UI_R_UNKNOWN_CONTROL_COMMAND 106 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/libcrypto/ui/ui_compat.h b/src/lib/libcrypto/ui/ui_compat.h new file mode 100644 index 0000000000..b35c9bb7fd --- /dev/null +++ b/src/lib/libcrypto/ui/ui_compat.h @@ -0,0 +1,83 @@ +/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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_UI_COMPAT_H +#define HEADER_UI_COMPAT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* The following functions were previously part of the DES section, + and are provided here for backward compatibility reasons. */ + +#define des_read_pw_string(b,l,p,v) \ + _ossl_old_des_read_pw_string((b),(l),(p),(v)) +#define des_read_pw(b,bf,s,p,v) \ + _ossl_old_des_read_pw((b),(bf),(s),(p),(v)) + +int _ossl_old_des_read_pw_string(char *buf,int length,const char *prompt,int verify); +int _ossl_old_des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/libcrypto/ui/ui_err.c b/src/lib/libcrypto/ui/ui_err.c new file mode 100644 index 0000000000..39a62ae737 --- /dev/null +++ b/src/lib/libcrypto/ui/ui_err.c @@ -0,0 +1,111 @@ +/* crypto/ui/ui_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 OPENSSL_NO_ERR +static ERR_STRING_DATA UI_str_functs[]= + { +{ERR_PACK(0,UI_F_GENERAL_ALLOCATE_BOOLEAN,0), "GENERAL_ALLOCATE_BOOLEAN"}, +{ERR_PACK(0,UI_F_GENERAL_ALLOCATE_PROMPT,0), "GENERAL_ALLOCATE_PROMPT"}, +{ERR_PACK(0,UI_F_GENERAL_ALLOCATE_STRING,0), "GENERAL_ALLOCATE_STRING"}, +{ERR_PACK(0,UI_F_UI_CTRL,0), "UI_ctrl"}, +{ERR_PACK(0,UI_F_UI_DUP_ERROR_STRING,0), "UI_dup_error_string"}, +{ERR_PACK(0,UI_F_UI_DUP_INFO_STRING,0), "UI_dup_info_string"}, +{ERR_PACK(0,UI_F_UI_DUP_INPUT_BOOLEAN,0), "UI_dup_input_boolean"}, +{ERR_PACK(0,UI_F_UI_DUP_INPUT_STRING,0), "UI_dup_input_string"}, +{ERR_PACK(0,UI_F_UI_DUP_VERIFY_STRING,0), "UI_dup_verify_string"}, +{ERR_PACK(0,UI_F_UI_GET0_RESULT,0), "UI_get0_result"}, +{ERR_PACK(0,UI_F_UI_NEW_METHOD,0), "UI_new_method"}, +{ERR_PACK(0,UI_F_UI_SET_RESULT,0), "UI_set_result"}, +{0,NULL} + }; + +static ERR_STRING_DATA UI_str_reasons[]= + { +{UI_R_COMMON_OK_AND_CANCEL_CHARACTERS ,"common ok and cancel characters"}, +{UI_R_INDEX_TOO_LARGE ,"index too large"}, +{UI_R_INDEX_TOO_SMALL ,"index too small"}, +{UI_R_NO_RESULT_BUFFER ,"no result buffer"}, +{UI_R_RESULT_TOO_LARGE ,"result too large"}, +{UI_R_RESULT_TOO_SMALL ,"result too small"}, +{UI_R_UNKNOWN_CONTROL_COMMAND ,"unknown control command"}, +{0,NULL} + }; + +#endif + +void ERR_load_UI_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(ERR_LIB_UI,UI_str_functs); + ERR_load_strings(ERR_LIB_UI,UI_str_reasons); +#endif + + } + } diff --git a/src/lib/libcrypto/ui/ui_lib.c b/src/lib/libcrypto/ui/ui_lib.c new file mode 100644 index 0000000000..16946cad95 --- /dev/null +++ b/src/lib/libcrypto/ui/ui_lib.c @@ -0,0 +1,899 @@ +/* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 "ui_locl.h" + +IMPLEMENT_STACK_OF(UI_STRING_ST) + +static const UI_METHOD *default_UI_meth=NULL; + +UI *UI_new(void) + { + return(UI_new_method(NULL)); + } + +UI *UI_new_method(const UI_METHOD *method) + { + UI *ret; + + ret=(UI *)OPENSSL_malloc(sizeof(UI)); + if (ret == NULL) + { + UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE); + return NULL; + } + if (method == NULL) + ret->meth=UI_get_default_method(); + else + ret->meth=method; + + ret->strings=NULL; + ret->user_data=NULL; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data); + return ret; + } + +static void free_string(UI_STRING *uis) + { + if (uis->flags & OUT_STRING_FREEABLE) + { + OPENSSL_free((char *)uis->out_string); + switch(uis->type) + { + case UIT_BOOLEAN: + OPENSSL_free((char *)uis->_.boolean_data.action_desc); + OPENSSL_free((char *)uis->_.boolean_data.ok_chars); + OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); + break; + default: + break; + } + } + OPENSSL_free(uis); + } + +void UI_free(UI *ui) + { + if (ui == NULL) + return; + sk_UI_STRING_pop_free(ui->strings,free_string); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); + OPENSSL_free(ui); + } + +static int allocate_string_stack(UI *ui) + { + if (ui->strings == NULL) + { + ui->strings=sk_UI_STRING_new_null(); + if (ui->strings == NULL) + { + return -1; + } + } + return 0; + } + +static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, + int prompt_freeable, enum UI_string_types type, int input_flags, + char *result_buf) + { + UI_STRING *ret = NULL; + + if (prompt == NULL) + { + UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,ERR_R_PASSED_NULL_PARAMETER); + } + else if (result_buf == NULL) + { + UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,UI_R_NO_RESULT_BUFFER); + } + else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING)))) + { + ret->out_string=prompt; + ret->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0; + ret->input_flags=input_flags; + ret->type=type; + ret->result_buf=result_buf; + } + return ret; + } + +static int general_allocate_string(UI *ui, const char *prompt, + int prompt_freeable, enum UI_string_types type, int input_flags, + char *result_buf, int minsize, int maxsize, const char *test_buf) + { + int ret = -1; + UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, + type, input_flags, result_buf); + + if (s) + { + if (allocate_string_stack(ui) >= 0) + { + s->_.string_data.result_minsize=minsize; + s->_.string_data.result_maxsize=maxsize; + s->_.string_data.test_buf=test_buf; + ret=sk_UI_STRING_push(ui->strings, s); + /* sk_push() returns 0 on error. Let's addapt that */ + if (ret <= 0) ret--; + } + else + free_string(s); + } + return ret; + } + +static int general_allocate_boolean(UI *ui, + const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int prompt_freeable, enum UI_string_types type, int input_flags, + char *result_buf) + { + int ret = -1; + UI_STRING *s; + const char *p; + + if (ok_chars == NULL) + { + UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER); + } + else if (cancel_chars == NULL) + { + UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER); + } + else + { + for(p = ok_chars; *p; p++) + { + if (strchr(cancel_chars, *p)) + { + UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, + UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); + } + } + + s = general_allocate_prompt(ui, prompt, prompt_freeable, + type, input_flags, result_buf); + + if (s) + { + if (allocate_string_stack(ui) >= 0) + { + s->_.boolean_data.action_desc = action_desc; + s->_.boolean_data.ok_chars = ok_chars; + s->_.boolean_data.cancel_chars = cancel_chars; + ret=sk_UI_STRING_push(ui->strings, s); + /* sk_push() returns 0 on error. + Let's addapt that */ + if (ret <= 0) ret--; + } + else + free_string(s); + } + } + return ret; + } + +/* Returns the index to the place in the stack or 0 for error. Uses a + direct reference to the prompt. */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize) + { + return general_allocate_string(ui, prompt, 0, + UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL); + } + +/* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize) + { + char *prompt_copy=NULL; + + if (prompt) + { + prompt_copy=BUF_strdup(prompt); + if (prompt_copy == NULL) + { + UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE); + return 0; + } + } + + return general_allocate_string(ui, prompt_copy, 1, + UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL); + } + +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, const char *test_buf) + { + return general_allocate_string(ui, prompt, 0, + UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf); + } + +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, const char *test_buf) + { + char *prompt_copy=NULL; + + if (prompt) + { + prompt_copy=BUF_strdup(prompt); + if (prompt_copy == NULL) + { + UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE); + return -1; + } + } + + return general_allocate_string(ui, prompt_copy, 1, + UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf); + } + +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf) + { + return general_allocate_boolean(ui, prompt, action_desc, + ok_chars, cancel_chars, 0, UIT_BOOLEAN, flags, result_buf); + } + +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf) + { + char *prompt_copy = NULL; + char *action_desc_copy = NULL; + char *ok_chars_copy = NULL; + char *cancel_chars_copy = NULL; + + if (prompt) + { + prompt_copy=BUF_strdup(prompt); + if (prompt_copy == NULL) + { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (action_desc) + { + action_desc_copy=BUF_strdup(action_desc); + if (action_desc_copy == NULL) + { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (ok_chars) + { + ok_chars_copy=BUF_strdup(ok_chars); + if (ok_chars_copy == NULL) + { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (cancel_chars) + { + cancel_chars_copy=BUF_strdup(cancel_chars); + if (cancel_chars_copy == NULL) + { + UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); + goto err; + } + } + + return general_allocate_boolean(ui, prompt_copy, action_desc_copy, + ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags, + result_buf); + err: + if (prompt_copy) OPENSSL_free(prompt_copy); + if (action_desc_copy) OPENSSL_free(action_desc_copy); + if (ok_chars_copy) OPENSSL_free(ok_chars_copy); + if (cancel_chars_copy) OPENSSL_free(cancel_chars_copy); + return -1; + } + +int UI_add_info_string(UI *ui, const char *text) + { + return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, + NULL); + } + +int UI_dup_info_string(UI *ui, const char *text) + { + char *text_copy=NULL; + + if (text) + { + text_copy=BUF_strdup(text); + if (text_copy == NULL) + { + UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE); + return -1; + } + } + + return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, + 0, 0, NULL); + } + +int UI_add_error_string(UI *ui, const char *text) + { + return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, + NULL); + } + +int UI_dup_error_string(UI *ui, const char *text) + { + char *text_copy=NULL; + + if (text) + { + text_copy=BUF_strdup(text); + if (text_copy == NULL) + { + UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE); + return -1; + } + } + return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, + 0, 0, NULL); + } + +char *UI_construct_prompt(UI *ui, const char *object_desc, + const char *object_name) + { + char *prompt = NULL; + + if (ui->meth->ui_construct_prompt) + prompt = ui->meth->ui_construct_prompt(ui, + object_desc, object_name); + else + { + char prompt1[] = "Enter "; + char prompt2[] = " for "; + char prompt3[] = ":"; + int len = 0; + + if (object_desc == NULL) + return NULL; + len = sizeof(prompt1) - 1 + strlen(object_desc); + if (object_name) + len += sizeof(prompt2) - 1 + strlen(object_name); + len += sizeof(prompt3) - 1; + + prompt = (char *)OPENSSL_malloc(len + 1); + strcpy(prompt, prompt1); + strcat(prompt, object_desc); + if (object_name) + { + strcat(prompt, prompt2); + strcat(prompt, object_name); + } + strcat(prompt, prompt3); + } + return prompt; + } + +void *UI_add_user_data(UI *ui, void *user_data) + { + void *old_data = ui->user_data; + ui->user_data = user_data; + return old_data; + } + +void *UI_get0_user_data(UI *ui) + { + return ui->user_data; + } + +const char *UI_get0_result(UI *ui, int i) + { + if (i < 0) + { + UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL); + return NULL; + } + if (i >= sk_UI_STRING_num(ui->strings)) + { + UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE); + return NULL; + } + return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); + } + +static int print_error(const char *str, size_t len, UI *ui) + { + UI_STRING uis; + + memset(&uis, 0, sizeof(uis)); + uis.type = UIT_ERROR; + uis.out_string = str; + + if (ui->meth->ui_write_string + && !ui->meth->ui_write_string(ui, &uis)) + return -1; + return 0; + } + +int UI_process(UI *ui) + { + int i, ok=0; + + if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) + return -1; + + if (ui->flags & UI_FLAG_PRINT_ERRORS) + ERR_print_errors_cb( + (int (*)(const char *, size_t, void *))print_error, + (void *)ui); + + for(i=0; istrings); i++) + { + if (ui->meth->ui_write_string + && !ui->meth->ui_write_string(ui, + sk_UI_STRING_value(ui->strings, i))) + { + ok=-1; + goto err; + } + } + + if (ui->meth->ui_flush) + switch(ui->meth->ui_flush(ui)) + { + case -1: /* Interrupt/Cancel/something... */ + ok = -2; + goto err; + case 0: /* Errors */ + ok = -1; + goto err; + default: /* Success */ + ok = 0; + break; + } + + for(i=0; istrings); i++) + { + if (ui->meth->ui_read_string) + { + switch(ui->meth->ui_read_string(ui, + sk_UI_STRING_value(ui->strings, i))) + { + case -1: /* Interrupt/Cancel/something... */ + ok = -2; + goto err; + case 0: /* Errors */ + ok = -1; + goto err; + default: /* Success */ + ok = 0; + break; + } + } + } + err: + if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) + return -1; + return ok; + } + +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)()) + { + if (ui == NULL) + { + UIerr(UI_F_UI_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + switch(cmd) + { + case UI_CTRL_PRINT_ERRORS: + { + int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS); + if (i) + ui->flags |= UI_FLAG_PRINT_ERRORS; + else + ui->flags &= ~UI_FLAG_PRINT_ERRORS; + return save_flag; + } + case UI_CTRL_IS_REDOABLE: + return !!(ui->flags & UI_FLAG_REDOABLE); + default: + break; + } + UIerr(UI_F_UI_CTRL,UI_R_UNKNOWN_CONTROL_COMMAND); + return -1; + } + +int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp, + new_func, dup_func, free_func); + } + +int UI_set_ex_data(UI *r, int idx, void *arg) + { + return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); + } + +void *UI_get_ex_data(UI *r, int idx) + { + return(CRYPTO_get_ex_data(&r->ex_data,idx)); + } + +void UI_set_default_method(const UI_METHOD *meth) + { + default_UI_meth=meth; + } + +const UI_METHOD *UI_get_default_method(void) + { + if (default_UI_meth == NULL) + { + default_UI_meth=UI_OpenSSL(); + } + return default_UI_meth; + } + +const UI_METHOD *UI_get_method(UI *ui) + { + return ui->meth; + } + +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) + { + ui->meth=meth; + return ui->meth; + } + + +UI_METHOD *UI_create_method(char *name) + { + UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD)); + + if (ui_method) + memset(ui_method, 0, sizeof(*ui_method)); + ui_method->name = BUF_strdup(name); + return ui_method; + } + +/* BIG FSCKING WARNING!!!! If you use this on a statically allocated method + (that is, it hasn't been allocated using UI_create_method(), you deserve + anything Murphy can throw at you and more! You have been warned. */ +void UI_destroy_method(UI_METHOD *ui_method) + { + OPENSSL_free(ui_method->name); + ui_method->name = NULL; + OPENSSL_free(ui_method); + } + +int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)) + { + if (method) + { + method->ui_open_session = opener; + return 0; + } + else + return -1; + } + +int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis)) + { + if (method) + { + method->ui_write_string = writer; + return 0; + } + else + return -1; + } + +int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui)) + { + if (method) + { + method->ui_flush = flusher; + return 0; + } + else + return -1; + } + +int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis)) + { + if (method) + { + method->ui_read_string = reader; + return 0; + } + else + return -1; + } + +int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)) + { + if (method) + { + method->ui_close_session = closer; + return 0; + } + else + return -1; + } + +int (*UI_method_get_opener(UI_METHOD *method))(UI*) + { + if (method) + return method->ui_open_session; + else + return NULL; + } + +int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*) + { + if (method) + return method->ui_write_string; + else + return NULL; + } + +int (*UI_method_get_flusher(UI_METHOD *method))(UI*) + { + if (method) + return method->ui_flush; + else + return NULL; + } + +int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*) + { + if (method) + return method->ui_read_string; + else + return NULL; + } + +int (*UI_method_get_closer(UI_METHOD *method))(UI*) + { + if (method) + return method->ui_close_session; + else + return NULL; + } + +enum UI_string_types UI_get_string_type(UI_STRING *uis) + { + if (!uis) + return UIT_NONE; + return uis->type; + } + +int UI_get_input_flags(UI_STRING *uis) + { + if (!uis) + return 0; + return uis->input_flags; + } + +const char *UI_get0_output_string(UI_STRING *uis) + { + if (!uis) + return NULL; + return uis->out_string; + } + +const char *UI_get0_action_string(UI_STRING *uis) + { + if (!uis) + return NULL; + switch(uis->type) + { + case UIT_PROMPT: + case UIT_BOOLEAN: + return uis->_.boolean_data.action_desc; + default: + return NULL; + } + } + +const char *UI_get0_result_string(UI_STRING *uis) + { + if (!uis) + return NULL; + switch(uis->type) + { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->result_buf; + default: + return NULL; + } + } + +const char *UI_get0_test_string(UI_STRING *uis) + { + if (!uis) + return NULL; + switch(uis->type) + { + case UIT_VERIFY: + return uis->_.string_data.test_buf; + default: + return NULL; + } + } + +int UI_get_result_minsize(UI_STRING *uis) + { + if (!uis) + return -1; + switch(uis->type) + { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->_.string_data.result_minsize; + default: + return -1; + } + } + +int UI_get_result_maxsize(UI_STRING *uis) + { + if (!uis) + return -1; + switch(uis->type) + { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->_.string_data.result_maxsize; + default: + return -1; + } + } + +int UI_set_result(UI *ui, UI_STRING *uis, const char *result) + { + int l = strlen(result); + + ui->flags &= ~UI_FLAG_REDOABLE; + + if (!uis) + return -1; + switch (uis->type) + { + case UIT_PROMPT: + case UIT_VERIFY: + { + char number1[20]; + char number2[20]; + + BIO_snprintf(number1, sizeof(number1), "%d", + uis->_.string_data.result_minsize); + BIO_snprintf(number2, sizeof(number2), "%d", + uis->_.string_data.result_maxsize); + + if (l < uis->_.string_data.result_minsize) + { + ui->flags |= UI_FLAG_REDOABLE; + UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_SMALL); + ERR_add_error_data(5,"You must type in ", + number1," to ",number2," characters"); + return -1; + } + if (l > uis->_.string_data.result_maxsize) + { + ui->flags |= UI_FLAG_REDOABLE; + UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_LARGE); + ERR_add_error_data(5,"You must type in ", + number1," to ",number2," characters"); + return -1; + } + } + + if (!uis->result_buf) + { + UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER); + return -1; + } + + strcpy(uis->result_buf, result); + break; + case UIT_BOOLEAN: + { + const char *p; + + if (!uis->result_buf) + { + UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER); + return -1; + } + + uis->result_buf[0] = '\0'; + for(p = result; *p; p++) + { + if (strchr(uis->_.boolean_data.ok_chars, *p)) + { + uis->result_buf[0] = + uis->_.boolean_data.ok_chars[0]; + break; + } + if (strchr(uis->_.boolean_data.cancel_chars, *p)) + { + uis->result_buf[0] = + uis->_.boolean_data.cancel_chars[0]; + break; + } + } + default: + break; + } + } + return 0; + } diff --git a/src/lib/libcrypto/ui/ui_locl.h b/src/lib/libcrypto/ui/ui_locl.h new file mode 100644 index 0000000000..7d3a75a619 --- /dev/null +++ b/src/lib/libcrypto/ui/ui_locl.h @@ -0,0 +1,148 @@ +/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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_UI_LOCL_H +#define HEADER_UI_LOCL_H + +#include + +struct ui_method_st + { + char *name; + + /* All the functions return 1 or non-NULL for success and 0 or NULL + for failure */ + + /* Open whatever channel for this, be it the console, an X window + or whatever. + This function should use the ex_data structure to save + intermediate data. */ + int (*ui_open_session)(UI *ui); + + int (*ui_write_string)(UI *ui, UI_STRING *uis); + + /* Flush the output. If a GUI dialog box is used, this function can + be used to actually display it. */ + int (*ui_flush)(UI *ui); + + int (*ui_read_string)(UI *ui, UI_STRING *uis); + + int (*ui_close_session)(UI *ui); + + /* Construct a prompt in a user-defined manner. object_desc is a + textual short description of the object, for example "pass phrase", + and object_name is the name of the object (might be a card name or + a file name. + The returned string shall always be allocated on the heap with + OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). */ + char *(*ui_construct_prompt)(UI *ui, const char *object_desc, + const char *object_name); + }; + +struct ui_string_st + { + enum UI_string_types type; /* Input */ + const char *out_string; /* Input */ + int input_flags; /* Flags from the user */ + + /* The following parameters are completely irrelevant for UIT_INFO, + and can therefore be set to 0 or NULL */ + char *result_buf; /* Input and Output: If not NULL, user-defined + with size in result_maxsize. Otherwise, it + may be allocated by the UI routine, meaning + result_minsize is going to be overwritten.*/ + union + { + struct + { + int result_minsize; /* Input: minimum required + size of the result. + */ + int result_maxsize; /* Input: maximum permitted + size of the result */ + + const char *test_buf; /* Input: test string to verify + against */ + } string_data; + struct + { + const char *action_desc; /* Input */ + const char *ok_chars; /* Input */ + const char *cancel_chars; /* Input */ + } boolean_data; + } _; + +#define OUT_STRING_FREEABLE 0x01 + int flags; /* flags for internal use */ + }; + +struct ui_st + { + const UI_METHOD *meth; + STACK_OF(UI_STRING) *strings; /* We might want to prompt for more + than one thing at a time, and + with different echoing status. */ + void *user_data; + CRYPTO_EX_DATA ex_data; + +#define UI_FLAG_REDOABLE 0x0001 +#define UI_FLAG_PRINT_ERRORS 0x0100 + int flags; + }; + +#endif diff --git a/src/lib/libcrypto/ui/ui_openssl.c b/src/lib/libcrypto/ui/ui_openssl.c new file mode 100644 index 0000000000..3aa03f74aa --- /dev/null +++ b/src/lib/libcrypto/ui/ui_openssl.c @@ -0,0 +1,661 @@ +/* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org) and others + * for the OpenSSL project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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). + * + */ + +/* The lowest level part of this file was previously in crypto/des/read_pwd.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 + +#if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) +# ifdef OPENSSL_UNISTD +# include OPENSSL_UNISTD +# else +# include +# endif +/* If unistd.h defines _POSIX_VERSION, we conclude that we + * are on a POSIX system and have sigaction and termios. */ +# if defined(_POSIX_VERSION) + +# define SIGACTION +# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) +# define TERMIOS +# endif + +# endif +#endif + +#ifdef WIN16TTY +# undef OPENSSL_SYS_WIN16 +# undef WIN16 +# undef _WINDOWS +# include +#endif + +/* 06-Apr-92 Luke Brennan Support for VMS */ +#include "ui_locl.h" +#include "cryptlib.h" +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */ +# include +# ifdef __DECC +# pragma message disable DOLLARID +# endif +#endif + +#ifdef WIN_CONSOLE_BUG +# include +# include +#endif + + +/* There are 5 types of terminal interface supported, + * TERMIO, TERMIOS, VMS, MSDOS and SGTTY + */ + +#if defined(__sgi) && !defined(TERMIOS) +# define TERMIOS +# undef TERMIO +# undef SGTTY +#endif + +#if defined(linux) && !defined(TERMIO) +# undef TERMIOS +# define TERMIO +# undef SGTTY +#endif + +#ifdef _LIBC +# undef TERMIOS +# define TERMIO +# undef SGTTY +#endif + +#if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && !defined(MAC_OS_GUSI_SOURCE) +# undef TERMIOS +# undef TERMIO +# define SGTTY +#endif + +#if defined(OPENSSL_SYS_VSWORKS) +#undef TERMIOS +#undef TERMIO +#undef SGTTY +#endif + +#ifdef TERMIOS +# include +# define TTY_STRUCT struct termios +# define TTY_FLAGS c_lflag +# define TTY_get(tty,data) tcgetattr(tty,data) +# define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data) +#endif + +#ifdef TERMIO +# include +# define TTY_STRUCT struct termio +# define TTY_FLAGS c_lflag +# define TTY_get(tty,data) ioctl(tty,TCGETA,data) +# define TTY_set(tty,data) ioctl(tty,TCSETA,data) +#endif + +#ifdef SGTTY +# include +# define TTY_STRUCT struct sgttyb +# define TTY_FLAGS sg_flags +# define TTY_get(tty,data) ioctl(tty,TIOCGETP,data) +# define TTY_set(tty,data) ioctl(tty,TIOCSETP,data) +#endif + +#if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MACINTOSH_CLASSIC) +# include +#endif + +#ifdef OPENSSL_SYS_MSDOS +# include +#endif + +#ifdef OPENSSL_SYS_VMS +# include +# include +# include +# include +struct IOSB { + short iosb$w_value; + short iosb$w_count; + long iosb$l_info; + }; +#endif + +#if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(MAC_OS_GUSI_SOURCE) +/* + * This one needs work. As a matter of fact the code is unoperational + * and this is only a trick to get it compiled. + * + */ +# define TTY_STRUCT int +#endif + +#ifndef NX509_SIG +# define NX509_SIG 32 +#endif + + +/* Define globals. They are protected by a lock */ +#ifdef SIGACTION +static struct sigaction savsig[NX509_SIG]; +#else +static void (*savsig[NX509_SIG])(int ); +#endif + +#ifdef OPENSSL_SYS_VMS +static struct IOSB iosb; +static $DESCRIPTOR(terminal,"TT"); +static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this will always suffice for the actual structures? */ +static long status; +static unsigned short channel = 0; +#else +#ifndef OPENSSL_SYS_MSDOS +static TTY_STRUCT tty_orig,tty_new; +#endif +#endif +static FILE *tty_in, *tty_out; +static int is_a_tty; + +/* Declare static functions */ +static void read_till_nl(FILE *); +static void recsig(int); +static void pushsig(void); +static void popsig(void); +#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16) +static int noecho_fgets(char *buf, int size, FILE *tty); +#endif +static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl); + +static int read_string(UI *ui, UI_STRING *uis); +static int write_string(UI *ui, UI_STRING *uis); + +static int open_console(UI *ui); +static int echo_console(UI *ui); +static int noecho_console(UI *ui); +static int close_console(UI *ui); + +static UI_METHOD ui_openssl = + { + "OpenSSL default user interface", + open_console, + write_string, + NULL, /* No flusher is needed for command lines */ + read_string, + close_console, + NULL + }; + +/* The method with all the built-in thingies */ +UI_METHOD *UI_OpenSSL(void) + { + return &ui_openssl; + } + +/* The following function makes sure that info and error strings are printed + before any prompt. */ +static int write_string(UI *ui, UI_STRING *uis) + { + switch (UI_get_string_type(uis)) + { + case UIT_ERROR: + case UIT_INFO: + fputs(UI_get0_output_string(uis), tty_out); + fflush(tty_out); + break; + default: + break; + } + return 1; + } + +static int read_string(UI *ui, UI_STRING *uis) + { + int ok = 0; + + switch (UI_get_string_type(uis)) + { + case UIT_BOOLEAN: + fputs(UI_get0_output_string(uis), tty_out); + fputs(UI_get0_action_string(uis), tty_out); + fflush(tty_out); + return read_string_inner(ui, uis, + UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 0); + case UIT_PROMPT: + fputs(UI_get0_output_string(uis), tty_out); + fflush(tty_out); + return read_string_inner(ui, uis, + UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1); + case UIT_VERIFY: + fprintf(tty_out,"Verifying - %s", + UI_get0_output_string(uis)); + fflush(tty_out); + if ((ok = read_string_inner(ui, uis, + UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1)) <= 0) + return ok; + if (strcmp(UI_get0_result_string(uis), + UI_get0_test_string(uis)) != 0) + { + fprintf(tty_out,"Verify failure\n"); + fflush(tty_out); + return 0; + } + break; + default: + break; + } + return 1; + } + + +/* Internal functions to read a string without echoing */ +static void read_till_nl(FILE *in) + { +#define SIZE 4 + char buf[SIZE+1]; + + do { + fgets(buf,SIZE,in); + } while (strchr(buf,'\n') == NULL); + } + +static sig_atomic_t intr_signal; + +static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) + { + static int ps; + int ok; + char result[BUFSIZ]; + int maxsize = BUFSIZ-1; + char *p; + +#ifndef OPENSSL_SYS_WIN16 + intr_signal=0; + ok=0; + ps=0; + + pushsig(); + ps=1; + + if (!echo && !noecho_console(ui)) + goto error; + ps=2; + + result[0]='\0'; +#ifdef OPENSSL_SYS_MSDOS + if (!echo) + { + noecho_fgets(result,maxsize,tty_in); + p=result; /* FIXME: noecho_fgets doesn't return errors */ + } + else + p=fgets(result,maxsize,tty_in); +#else + p=fgets(result,maxsize,tty_in); +#endif + if(!p) + goto error; + if (feof(tty_in)) goto error; + if (ferror(tty_in)) goto error; + if ((p=(char *)strchr(result,'\n')) != NULL) + { + if (strip_nl) + *p='\0'; + } + else + read_till_nl(tty_in); + if (UI_set_result(ui, uis, result) >= 0) + ok=1; + +error: + if (intr_signal == SIGINT) + ok=-1; + if (!echo) fprintf(tty_out,"\n"); + if (ps >= 2 && !echo && !echo_console(ui)) + ok=0; + + if (ps >= 1) + popsig(); +#else + ok=1; +#endif + + memset(result,0,BUFSIZ); + return ok; + } + + +/* Internal functions to open, handle and close a channel to the console. */ +static int open_console(UI *ui) + { + CRYPTO_w_lock(CRYPTO_LOCK_UI); + is_a_tty = 1; + +#if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_VSWORKS) + tty_in=stdin; + tty_out=stderr; +#else +# ifdef OPENSSL_SYS_MSDOS +# define DEV_TTY "con" +# else +# define DEV_TTY "/dev/tty" +# endif + if ((tty_in=fopen(DEV_TTY,"r")) == NULL) + tty_in=stdin; + if ((tty_out=fopen(DEV_TTY,"w")) == NULL) + tty_out=stderr; +#endif + +#if defined(TTY_get) && !defined(VMS) + if (TTY_get(fileno(tty_in),&tty_orig) == -1) + { +#ifdef ENOTTY + if (errno == ENOTTY) + is_a_tty=0; + else +#endif +#ifdef EINVAL + /* Ariel Glenn ariel@columbia.edu reports that solaris + * can return EINVAL instead. This should be ok */ + if (errno == EINVAL) + is_a_tty=0; + else +#endif + return 0; + } +#endif +#ifdef OPENSSL_SYS_VMS + status = sys$assign(&terminal,&channel,0,0); + if (status != SS$_NORMAL) + return 0; + status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0); + if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) + return 0; +#endif + return 1; + } + +static int noecho_console(UI *ui) + { +#ifdef TTY_FLAGS + memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig)); + tty_new.TTY_FLAGS &= ~ECHO; +#endif + +#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) + if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1)) + return 0; +#endif +#ifdef OPENSSL_SYS_VMS + tty_new[0] = tty_orig[0]; + tty_new[1] = tty_orig[1] | TT$M_NOECHO; + tty_new[2] = tty_orig[2]; + status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0); + if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) + return 0; +#endif + return 1; + } + +static int echo_console(UI *ui) + { +#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) + memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig)); + tty_new.TTY_FLAGS |= ECHO; +#endif + +#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) + if (is_a_tty && (TTY_set(fileno(tty_in),&tty_new) == -1)) + return 0; +#endif +#ifdef OPENSSL_SYS_VMS + tty_new[0] = tty_orig[0]; + tty_new[1] = tty_orig[1] & ~TT$M_NOECHO; + tty_new[2] = tty_orig[2]; + status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0); + if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) + return 0; +#endif + return 1; + } + +static int close_console(UI *ui) + { + if (tty_in != stderr) fclose(tty_in); + if (tty_out != stderr) fclose(tty_out); +#ifdef OPENSSL_SYS_VMS + status = sys$dassgn(channel); +#endif + CRYPTO_w_unlock(CRYPTO_LOCK_UI); + + return 1; + } + + +/* Internal functions to handle signals and act on them */ +static void pushsig(void) + { + int i; +#ifdef SIGACTION + struct sigaction sa; + + memset(&sa,0,sizeof sa); + sa.sa_handler=recsig; +#endif + + for (i=1; i +#include + +int UI_UTIL_read_pw_string(char *buf,int length,const char *prompt,int verify) + { + char buff[BUFSIZ]; + int ret; + + ret=UI_UTIL_read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify); + memset(buff,0,BUFSIZ); + return(ret); + } + +int UI_UTIL_read_pw(char *buf,char *buff,int size,const char *prompt,int verify) + { + int ok = 0; + UI *ui; + + ui = UI_new(); + if (ui) + { + ok = UI_add_input_string(ui,prompt,0,buf,0,BUFSIZ-1); + if (ok == 0 && verify) + ok = UI_add_verify_string(ui,prompt,0,buff,0,BUFSIZ-1, + buf); + if (ok == 0) + ok=UI_process(ui); + UI_free(ui); + } + return(ok); + } diff --git a/src/lib/libcrypto/util/mkerr.pl b/src/lib/libcrypto/util/mkerr.pl new file mode 100644 index 0000000000..4b3bccb13e --- /dev/null +++ b/src/lib/libcrypto/util/mkerr.pl @@ -0,0 +1,503 @@ +#!/usr/local/bin/perl -w + +my $config = "crypto/err/openssl.ec"; +my $debug = 0; +my $rebuild = 0; +my $static = 1; +my $recurse = 0; +my $reindex = 0; +my $dowrite = 0; + + +while (@ARGV) { + my $arg = $ARGV[0]; + if($arg eq "-conf") { + shift @ARGV; + $config = shift @ARGV; + } elsif($arg eq "-debug") { + $debug = 1; + shift @ARGV; + } elsif($arg eq "-rebuild") { + $rebuild = 1; + shift @ARGV; + } elsif($arg eq "-recurse") { + $recurse = 1; + shift @ARGV; + } elsif($arg eq "-reindex") { + $reindex = 1; + shift @ARGV; + } elsif($arg eq "-nostatic") { + $static = 0; + shift @ARGV; + } elsif($arg eq "-write") { + $dowrite = 1; + shift @ARGV; + } else { + last; + } +} + +if($recurse) { + @source = (, , ,, ); +} else { + @source = @ARGV; +} + +# Read in the config file + +open(IN, "<$config") || die "Can't open config file $config"; + +# Parse config file + +while() +{ + if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) { + $hinc{$1} = $2; + $cskip{$3} = $1; + if($3 ne "NONE") { + $csrc{$1} = $3; + $fmax{$1} = 99; + $rmax{$1} = 99; + $fnew{$1} = 0; + $rnew{$1} = 0; + } + } elsif (/^F\s+(\S+)/) { + # Add extra function with $1 + } elsif (/^R\s+(\S+)\s+(\S+)/) { + $rextra{$1} = $2; + $rcodes{$1} = $2; + } +} + +close IN; + +# Scan each header file in turn and make a list of error codes +# and function names + +while (($lib, $hdr) = each %hinc) +{ + next if($hdr eq "NONE"); + print STDERR "Scanning header file $hdr\n" if $debug; + open(IN, "<$hdr") || die "Can't open Header file $hdr\n"; + my $line = "", $def= ""; + while() { + last if(/BEGIN\s+ERROR\s+CODES/); + if ($line ne '') { + $_ = $line . $_; + $line = ''; + } + + if (/\\$/) { + $line = $_; + next; + } + + $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration + if ($cpp) { + $cpp = 0 if /^#.*endif/; + next; + } + + next if (/^#/); # skip preprocessor directives + + s/\/\*.*?\*\///gs; # ignore comments + s/{[^{}]*}//gs; # ignore {} blocks + + if (/{|\/\*/) { # Add a } so editor works... + $line = $_; + } else { + $def .= $_; + } + } + + foreach (split /;/, $def) { + s/^[\n\s]*//g; + s/[\n\s]*$//g; + next if(/typedef\W/); + if (/\(\*(\w*)\([^\)]+/) { + my $name = $1; + $name =~ tr/[a-z]/[A-Z]/; + $ftrans{$name} = $1; + } elsif (/\w+\W+(\w+)\W*\(\s*\)$/s){ + # K&R C + next ; + } elsif (/\w+\W+\w+\W*\(.*\)$/s) { + while (not /\(\)$/s) { + s/[^\(\)]*\)$/\)/s; + s/\([^\(\)]*\)\)$/\)/s; + } + s/\(void\)//; + /(\w+)\W*\(\)/s; + my $name = $1; + $name =~ tr/[a-z]/[A-Z]/; + $ftrans{$name} = $1; + } elsif (/\(/ and not (/=/ or /DECLARE_STACK/)) { + print STDERR "Header $hdr: cannot parse: $_;\n"; + } + } + + next if $reindex; + + # Scan function and reason codes and store them: keep a note of the + # maximum code used. + + while() { + if(/^#define\s+(\S+)\s+(\S+)/) { + $name = $1; + $code = $2; + unless($name =~ /^${lib}_([RF])_(\w+)$/) { + print STDERR "Invalid error code $name\n"; + next; + } + if($1 eq "R") { + $rcodes{$name} = $code; + if(!(exists $rextra{$name}) && + ($code > $rmax{$lib}) ) { + $rmax{$lib} = $code; + } + } else { + if($code > $fmax{$lib}) { + $fmax{$lib} = $code; + } + $fcodes{$name} = $code; + } + } + } + close IN; +} + +# Scan each C source file and look for function and reason codes +# This is done by looking for strings that "look like" function or +# reason codes: basically anything consisting of all upper case and +# numerics which has _F_ or _R_ in it and which has the name of an +# error library at the start. This seems to work fine except for the +# oddly named structure BIO_F_CTX which needs to be ignored. +# If a code doesn't exist in list compiled from headers then mark it +# with the value "X" as a place holder to give it a value later. +# Store all function and reason codes found in %ufcodes and %urcodes +# so all those unreferenced can be printed out. + + +foreach $file (@source) { + # Don't parse the error source file. + next if exists $cskip{$file}; + open(IN, "<$file") || die "Can't open source file $file\n"; + while() { + if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) { + next unless exists $csrc{$2}; + next if($1 eq "BIO_F_BUFFER_CTX"); + $ufcodes{$1} = 1; + if(!exists $fcodes{$1}) { + $fcodes{$1} = "X"; + $fnew{$2}++; + } + $notrans{$1} = 1 unless exists $ftrans{$3}; + } + if(/(([A-Z0-9]+)_R_[A-Z0-9_]+)/) { + next unless exists $csrc{$2}; + $urcodes{$1} = 1; + if(!exists $rcodes{$1}) { + $rcodes{$1} = "X"; + $rnew{$2}++; + } + } + } + close IN; +} + +# Now process each library in turn. + +foreach $lib (keys %csrc) +{ + my $hfile = $hinc{$lib}; + my $cfile = $csrc{$lib}; + if(!$fnew{$lib} && !$rnew{$lib}) { + print STDERR "$lib:\t\tNo new error codes\n"; + next unless $rebuild; + } else { + print STDERR "$lib:\t\t$fnew{$lib} New Functions,"; + print STDERR " $rnew{$lib} New Reasons.\n"; + next unless $dowrite; + } + + # If we get here then we have some new error codes so we + # need to rebuild the header file and C file. + + # Make a sorted list of error and reason codes for later use. + + my @function = sort grep(/^${lib}_/,keys %fcodes); + my @reasons = sort grep(/^${lib}_/,keys %rcodes); + + # Rewrite the header file + + open(IN, "<$hfile") || die "Can't Open Header File $hfile\n"; + + # Copy across the old file + while() { + push @out, $_; + last if (/BEGIN ERROR CODES/); + } + close IN; + + open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n"; + + print OUT @out; + undef @out; + print OUT <<"EOF"; +/* 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 $lib functions. */ + +/* Function codes. */ +EOF + + foreach $i (@function) { + $z=6-int(length($i)/8); + if($fcodes{$i} eq "X") { + $fcodes{$i} = ++$fmax{$lib}; + print STDERR "New Function code $i\n" if $debug; + } + printf OUT "#define $i%s $fcodes{$i}\n","\t" x $z; + } + + print OUT "\n/* Reason codes. */\n"; + + foreach $i (@reasons) { + $z=6-int(length($i)/8); + if($rcodes{$i} eq "X") { + $rcodes{$i} = ++$rmax{$lib}; + print STDERR "New Reason code $i\n" if $debug; + } + printf OUT "#define $i%s $rcodes{$i}\n","\t" x $z; + } + print OUT <<"EOF"; + +#ifdef __cplusplus +} +#endif +#endif + +EOF + close OUT; + + # Rewrite the C source file containing the error details. + + my $hincf; + if($static) { + $hfile =~ /([^\/]+)$/; + $hincf = ""; + } else { + $hincf = "\"$hfile\""; + } + + + open (OUT,">$cfile") || die "Can't open $cfile for writing"; + + print OUT <<"EOF"; +/* $cfile */ +/* ==================================================================== + * 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. + */ + +#include +#include +#include $hincf + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA ${lib}_str_functs[]= + { +EOF + # Add each function code: if a function name is found then use it. + foreach $i (@function) { + my $fn; + $i =~ /^${lib}_F_(\S+)$/; + $fn = $1; + if(exists $ftrans{$fn}) { + $fn = $ftrans{$fn}; + } + print OUT "{ERR_PACK(0,$i,0),\t\"$fn\"},\n"; + } + print OUT <<"EOF"; +{0,NULL} + }; + +static ERR_STRING_DATA ${lib}_str_reasons[]= + { +EOF + # Add each reason code. + foreach $i (@reasons) { + my $rn; + my $nspc = 0; + $i =~ /^${lib}_R_(\S+)$/; + $rn = $1; + $rn =~ tr/_[A-Z]/ [a-z]/; + $nspc = 40 - length($i) unless length($i) > 40; + $nspc = " " x $nspc; + print OUT "{${i}${nspc},\"$rn\"},\n"; + } +if($static) { + print OUT <<"EOF"; +{0,NULL} + }; + +#endif + +void ERR_load_${lib}_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_${lib},${lib}_str_functs); + ERR_load_strings(ERR_LIB_${lib},${lib}_str_reasons); +#endif + + } + } +EOF +} else { + print OUT <<"EOF"; +{0,NULL} + }; + +#endif + +#ifdef ${lib}_LIB_NAME +static ERR_STRING_DATA ${lib}_lib_name[]= + { +{0 ,${lib}_LIB_NAME}, +{0,NULL} + }; +#endif + + +int ${lib}_lib_error_code=0; + +void ERR_load_${lib}_strings(void) + { + static int init=1; + + if (${lib}_lib_error_code == 0) + ${lib}_lib_error_code=ERR_get_next_error_library(); + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(${lib}_lib_error_code,${lib}_str_functs); + ERR_load_strings(${lib}_lib_error_code,${lib}_str_reasons); +#endif + +#ifdef ${lib}_LIB_NAME + ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code,0,0); + ERR_load_strings(0,${lib}_lib_name); +#endif; + } + } + +void ERR_${lib}_error(int function, int reason, char *file, int line) + { + if (${lib}_lib_error_code == 0) + ${lib}_lib_error_code=ERR_get_next_error_library(); + ERR_PUT_error(${lib}_lib_error_code,function,reason,file,line); + } +EOF + +} + + close OUT; + +} + +if($debug && defined(%notrans)) { + print STDERR "The following function codes were not translated:\n"; + foreach(sort keys %notrans) + { + print STDERR "$_\n"; + } +} + +# Make a list of unreferenced function and reason codes + +foreach (keys %fcodes) { + push (@funref, $_) unless exists $ufcodes{$_}; +} + +foreach (keys %rcodes) { + push (@runref, $_) unless exists $urcodes{$_}; +} + +if($debug && defined(@funref) ) { + print STDERR "The following function codes were not referenced:\n"; + foreach(sort @funref) + { + print STDERR "$_\n"; + } +} + +if($debug && defined(@runref) ) { + print STDERR "The following reason codes were not referenced:\n"; + foreach(sort @runref) + { + print STDERR "$_\n"; + } +} diff --git a/src/lib/libcrypto/util/mkstack.pl b/src/lib/libcrypto/util/mkstack.pl new file mode 100644 index 0000000000..3ee13fe7c9 --- /dev/null +++ b/src/lib/libcrypto/util/mkstack.pl @@ -0,0 +1,124 @@ +#!/usr/local/bin/perl -w + +# This is a utility that searches out "DECLARE_STACK_OF()" +# declarations in .h and .c files, and updates/creates/replaces +# the corresponding macro declarations in crypto/stack/safestack.h. +# As it's not generally possible to have macros that generate macros, +# we need to control this from the "outside", here in this script. +# +# Geoff Thorpe, June, 2000 (with massive Perl-hacking +# help from Steve Robb) + +my $safestack = "crypto/stack/safestack"; + +my $do_write; +while (@ARGV) { + my $arg = $ARGV[0]; + if($arg eq "-write") { + $do_write = 1; + } + shift @ARGV; +} + + +@source = (, , , ); +foreach $file (@source) { + next if -l $file; + + # Open the .c/.h file for reading + open(IN, "< $file") || die "Can't open $file for reading: $!"; + + while() { + if (/^DECLARE_STACK_OF\(([^)]+)\)/) { + push @stacklst, $1; + } if (/^DECLARE_ASN1_SET_OF\(([^)]+)\)/) { + push @asn1setlst, $1; + } if (/^DECLARE_PKCS12_STACK_OF\(([^)]+)\)/) { + push @p12stklst, $1; + } + } + close(IN); +} + + + +my $old_stackfile = ""; +my $new_stackfile = ""; +my $inside_block = 0; +my $type_thing; + +open(IN, "< $safestack.h") || die "Can't open input file: $!"; +while() { + $old_stackfile .= $_; + + if (m|^/\* This block of defines is updated by util/mkstack.pl, please do not touch! \*/|) { + $inside_block = 1; + } + if (m|^/\* End of util/mkstack.pl block, you may now edit :-\) \*/|) { + $inside_block = 0; + } elsif ($inside_block == 0) { + $new_stackfile .= $_; + } + next if($inside_block != 1); + $new_stackfile .= "/* This block of defines is updated by util/mkstack.pl, please do not touch! */"; + + foreach $type_thing (sort @stacklst) { + $new_stackfile .= <$safestack.h" || die "Can't open output file"; + print OUT $new_stackfile; + close OUT; +} diff --git a/src/lib/libcrypto/x509/x509_att.c b/src/lib/libcrypto/x509/x509_att.c new file mode 100644 index 0000000000..caafde658f --- /dev/null +++ b/src/lib/libcrypto/x509/x509_att.c @@ -0,0 +1,326 @@ +/* crypto/x509/x509_att.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 +#include + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) +{ + if (!x) return 0; + return(sk_X509_ATTRIBUTE_num(x)); +} + +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos) +{ + ASN1_OBJECT *obj; + + obj=OBJ_nid2obj(nid); + if (obj == NULL) return(-2); + return(X509at_get_attr_by_OBJ(x,obj,lastpos)); +} + +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, ASN1_OBJECT *obj, + int lastpos) +{ + int n; + X509_ATTRIBUTE *ex; + + if (sk == NULL) return(-1); + lastpos++; + if (lastpos < 0) + lastpos=0; + n=sk_X509_ATTRIBUTE_num(sk); + for ( ; lastpos < n; lastpos++) + { + ex=sk_X509_ATTRIBUTE_value(sk,lastpos); + if (OBJ_cmp(ex->object,obj) == 0) + return(lastpos); + } + return(-1); +} + +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + return NULL; + else + return sk_X509_ATTRIBUTE_value(x,loc); +} + +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + X509_ATTRIBUTE *ret; + + if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + return(NULL); + ret=sk_X509_ATTRIBUTE_delete(x,loc); + return(ret); +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr) +{ + X509_ATTRIBUTE *new_attr=NULL; + STACK_OF(X509_ATTRIBUTE) *sk=NULL; + + if ((x != NULL) && (*x == NULL)) + { + if ((sk=sk_X509_ATTRIBUTE_new_null()) == NULL) + goto err; + } + else + sk= *x; + + if ((new_attr=X509_ATTRIBUTE_dup(attr)) == NULL) + goto err2; + if (!sk_X509_ATTRIBUTE_push(sk,new_attr)) + goto err; + if ((x != NULL) && (*x == NULL)) + *x=sk; + return(sk); +err: + X509err(X509_F_X509_ADD_ATTR,ERR_R_MALLOC_FAILURE); +err2: + if (new_attr != NULL) X509_ATTRIBUTE_free(new_attr); + if (sk != NULL) sk_X509_ATTRIBUTE_free(sk); + return(NULL); +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, + ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); + if(!attr) return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, + int nid, int type, + unsigned char *bytes, int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len); + if(!attr) return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +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 *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); + if(!attr) return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, void *data, int len) +{ + ASN1_OBJECT *obj; + X509_ATTRIBUTE *ret; + + obj=OBJ_nid2obj(nid); + if (obj == NULL) + { + X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID,X509_R_UNKNOWN_NID); + return(NULL); + } + ret=X509_ATTRIBUTE_create_by_OBJ(attr,obj,atrtype,data,len); + if (ret == NULL) ASN1_OBJECT_free(obj); + return(ret); +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + ASN1_OBJECT *obj, int atrtype, void *data, int len) +{ + X509_ATTRIBUTE *ret; + + if ((attr == NULL) || (*attr == NULL)) + { + if ((ret=X509_ATTRIBUTE_new()) == NULL) + { + X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ,ERR_R_MALLOC_FAILURE); + return(NULL); + } + } + else + ret= *attr; + + if (!X509_ATTRIBUTE_set1_object(ret,obj)) + goto err; + if (!X509_ATTRIBUTE_set1_data(ret,atrtype,data,len)) + goto err; + + if ((attr != NULL) && (*attr == NULL)) *attr=ret; + return(ret); +err: + if ((attr == NULL) || (ret != *attr)) + X509_ATTRIBUTE_free(ret); + return(NULL); +} + +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + char *atrname, int type, unsigned char *bytes, int len) + { + ASN1_OBJECT *obj; + X509_ATTRIBUTE *nattr; + + obj=OBJ_txt2obj(atrname, 0); + if (obj == NULL) + { + X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, + X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", atrname); + return(NULL); + } + nattr = X509_ATTRIBUTE_create_by_OBJ(attr,obj,type,bytes,len); + ASN1_OBJECT_free(obj); + return nattr; + } + +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, ASN1_OBJECT *obj) +{ + if ((attr == NULL) || (obj == NULL)) + return(0); + ASN1_OBJECT_free(attr->object); + attr->object=OBJ_dup(obj); + return(1); +} + +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, void *data, int len) +{ + ASN1_TYPE *ttmp; + ASN1_STRING *stmp; + int atype; + if (!attr) return 0; + if(attrtype & MBSTRING_FLAG) { + stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, + OBJ_obj2nid(attr->object)); + if(!stmp) { + X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_ASN1_LIB); + return 0; + } + atype = stmp->type; + } else { + if(!(stmp = ASN1_STRING_type_new(attrtype))) goto err; + if(!ASN1_STRING_set(stmp, data, len)) goto err; + atype = attrtype; + } + if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err; + if(!(ttmp = ASN1_TYPE_new())) goto err; + if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err; + attr->set = 1; + ASN1_TYPE_set(ttmp, atype, stmp); + return 1; + err: + X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE); + return 0; +} + +int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) +{ + if(attr->set) return sk_ASN1_TYPE_num(attr->value.set); + if(attr->value.single) return 1; + return 0; +} + +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) +{ + if (attr == NULL) return(NULL); + return(attr->object); +} + +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int atrtype, void *data) +{ + ASN1_TYPE *ttmp; + ttmp = X509_ATTRIBUTE_get0_type(attr, idx); + if(!ttmp) return NULL; + if(atrtype != ASN1_TYPE_get(ttmp)){ + X509err(X509_F_X509_ATTRIBUTE_GET0_DATA, X509_R_WRONG_TYPE); + return NULL; + } + return ttmp->value.ptr; +} + +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) +{ + if (attr == NULL) return(NULL); + if(idx >= X509_ATTRIBUTE_count(attr)) return NULL; + if(attr->set) return sk_ASN1_TYPE_value(attr->value.set, idx); + else return attr->value.single; +} diff --git a/src/lib/libcrypto/x509/x509_trs.c b/src/lib/libcrypto/x509/x509_trs.c new file mode 100644 index 0000000000..9f7d67952d --- /dev/null +++ b/src/lib/libcrypto/x509/x509_trs.c @@ -0,0 +1,263 @@ +/* x509_trs.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 + + +static int tr_cmp(X509_TRUST **a, X509_TRUST **b); +static void trtable_free(X509_TRUST *p); + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); +static int trust_any(X509_TRUST *trust, X509 *x, int flags); + +static int obj_trust(int id, X509 *x, int flags); +static int (*default_trust)(int id, X509 *x, int flags) = obj_trust; + +/* WARNING: the following table should be kept in order of trust + * and without any gaps so we can just subtract the minimum trust + * value to get an index into the table + */ + +static X509_TRUST trstandard[] = { +{X509_TRUST_ANY, 0, trust_any, "Any", 0, NULL}, +{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, NULL}, +{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Client", NID_server_auth, NULL}, +{X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, NULL}, +}; + +#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) + +IMPLEMENT_STACK_OF(X509_TRUST) + +static STACK_OF(X509_TRUST) *trtable = NULL; + +static int tr_cmp(X509_TRUST **a, X509_TRUST **b) +{ + return (*a)->trust - (*b)->trust; +} + +int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int) +{ +int (*oldtrust)(int , X509 *, int); +oldtrust = default_trust; +default_trust = trust; +return oldtrust; +} + + +int X509_check_trust(X509 *x, int id, int flags) +{ + X509_TRUST *pt; + int idx; + if(id == -1) return 1; + if(!(idx = X509_TRUST_get_by_id(id))) + return default_trust(id, x, flags); + pt = X509_TRUST_get0(idx); + return pt->check_trust(pt, x, flags); +} + +int X509_TRUST_get_count(void) +{ + if(!trtable) return X509_TRUST_COUNT; + return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; +} + +X509_TRUST * X509_TRUST_get0(int idx) +{ + if(idx < 0) return NULL; + if(idx < X509_TRUST_COUNT) return trstandard + idx; + return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); +} + +int X509_TRUST_get_by_id(int id) +{ + X509_TRUST tmp; + int idx; + if((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) + return id - X509_TRUST_MIN; + tmp.trust = id; + if(!trtable) return -1; + idx = sk_X509_TRUST_find(trtable, &tmp); + if(idx == -1) return -1; + return idx + X509_TRUST_COUNT; +} + +int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2) +{ + int idx; + X509_TRUST *trtmp; + /* This is set according to what we change: application can't set it */ + flags &= ~X509_TRUST_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_TRUST_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_TRUST_get_by_id(id); + /* Need a new entry */ + if(idx == -1) { + if(!(trtmp = Malloc(sizeof(X509_TRUST)))) { + X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + trtmp->flags = X509_TRUST_DYNAMIC; + } else trtmp = X509_TRUST_get0(idx); + + /* Free existing name if dynamic */ + if(trtmp->flags & X509_TRUST_DYNAMIC_NAME) Free(trtmp->name); + /* dup supplied name */ + if(!(trtmp->name = BUF_strdup(name))) { + X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + /* Keep the dynamic flag of existing entry */ + trtmp->flags &= X509_TRUST_DYNAMIC; + /* Set all other flags */ + trtmp->flags |= flags; + + trtmp->trust = id; + trtmp->check_trust = ck; + trtmp->arg1 = arg1; + trtmp->arg2 = arg2; + + /* If its a new entry manage the dynamic table */ + if(idx == -1) { + if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) { + X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + if (!sk_X509_TRUST_push(trtable, trtmp)) { + X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + } + return 1; +} + +static void trtable_free(X509_TRUST *p) + { + if(!p) return; + if (p->flags & X509_TRUST_DYNAMIC) + { + if (p->flags & X509_TRUST_DYNAMIC_NAME) + Free(p->name); + Free(p); + } + } + +void X509_TRUST_cleanup(void) +{ + int i; + for(i = 0; i < X509_TRUST_COUNT; i++) trtable_free(trstandard + i); + sk_X509_TRUST_pop_free(trtable, trtable_free); + trtable = NULL; +} + +int X509_TRUST_get_flags(X509_TRUST *xp) +{ + return xp->flags; +} + +char *X509_TRUST_get0_name(X509_TRUST *xp) +{ + return xp->name; +} + +int X509_TRUST_get_trust(X509_TRUST *xp) +{ + return xp->trust; +} + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) +{ + if(x->aux) return obj_trust(trust->arg1, x, flags); + /* we don't have any trust settings: for compatibility + * we return trusted if it is self signed + */ + X509_check_purpose(x, -1, 0); + if(x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED; + else return X509_TRUST_UNTRUSTED; +} + +static int obj_trust(int id, X509 *x, int flags) +{ + ASN1_OBJECT *obj; + int i; + X509_CERT_AUX *ax; + ax = x->aux; + if(!ax) return X509_TRUST_UNTRUSTED; + if(ax->reject) { + for(i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { + obj = sk_ASN1_OBJECT_value(ax->reject, i); + if(OBJ_obj2nid(obj) == id) return X509_TRUST_REJECTED; + } + } + if(ax->trust) { + for(i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { + obj = sk_ASN1_OBJECT_value(ax->trust, i); + if(OBJ_obj2nid(obj) == id) return X509_TRUST_TRUSTED; + } + } + return X509_TRUST_UNTRUSTED; +} + +static int trust_any(X509_TRUST *trust, X509 *x, int flags) +{ + return X509_TRUST_TRUSTED; +} diff --git a/src/lib/libcrypto/x509/x509cset.c b/src/lib/libcrypto/x509/x509cset.c new file mode 100644 index 0000000000..6cac440ea9 --- /dev/null +++ b/src/lib/libcrypto/x509/x509cset.c @@ -0,0 +1,169 @@ +/* crypto/x509/x509cset.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 +#include + +int X509_CRL_set_version(X509_CRL *x, long version) + { + if (x == NULL) return(0); + if (x->crl->version == NULL) + { + if ((x->crl->version=M_ASN1_INTEGER_new()) == NULL) + return(0); + } + return(ASN1_INTEGER_set(x->crl->version,version)); + } + +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) + { + if ((x == NULL) || (x->crl == NULL)) return(0); + return(X509_NAME_set(&x->crl->issuer,name)); + } + + +int X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm) + { + ASN1_TIME *in; + + if (x == NULL) return(0); + in=x->crl->lastUpdate; + if (in != tm) + { + in=M_ASN1_TIME_dup(tm); + if (in != NULL) + { + M_ASN1_TIME_free(x->crl->lastUpdate); + x->crl->lastUpdate=in; + } + } + return(in != NULL); + } + +int X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm) + { + ASN1_TIME *in; + + if (x == NULL) return(0); + in=x->crl->nextUpdate; + if (in != tm) + { + in=M_ASN1_TIME_dup(tm); + if (in != NULL) + { + M_ASN1_TIME_free(x->crl->nextUpdate); + x->crl->nextUpdate=in; + } + } + return(in != NULL); + } + +int X509_CRL_sort(X509_CRL *c) + { + int i; + X509_REVOKED *r; + /* sort the data so it will be written in serial + * number order */ + sk_X509_REVOKED_sort(c->crl->revoked); + for (i=0; icrl->revoked); i++) + { + r=sk_X509_REVOKED_value(c->crl->revoked,i); + r->sequence=i; + } + return 1; + } + +int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm) + { + ASN1_TIME *in; + + if (x == NULL) return(0); + in=x->revocationDate; + if (in != tm) + { + in=M_ASN1_TIME_dup(tm); + if (in != NULL) + { + M_ASN1_TIME_free(x->revocationDate); + x->revocationDate=in; + } + } + return(in != NULL); + } + +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) + { + ASN1_INTEGER *in; + + if (x == NULL) return(0); + in=x->serialNumber; + if (in != serial) + { + in=M_ASN1_INTEGER_dup(serial); + if (in != NULL) + { + M_ASN1_INTEGER_free(x->serialNumber); + x->serialNumber=in; + } + } + return(in != NULL); + } diff --git a/src/lib/libcrypto/x509/x509spki.c b/src/lib/libcrypto/x509/x509spki.c new file mode 100644 index 0000000000..b35c3f92e7 --- /dev/null +++ b/src/lib/libcrypto/x509/x509spki.c @@ -0,0 +1,121 @@ +/* x509spki.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 + +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->spkac == NULL)) return(0); + return(X509_PUBKEY_set(&(x->spkac->pubkey),pkey)); +} + +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) +{ + if ((x == NULL) || (x->spkac == NULL)) + return(NULL); + return(X509_PUBKEY_get(x->spkac->pubkey)); +} + +/* Load a Netscape SPKI from a base64 encoded string */ + +NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len) +{ + unsigned char *spki_der, *p; + int spki_len; + NETSCAPE_SPKI *spki; + if(len <= 0) len = strlen(str); + if (!(spki_der = Malloc(len + 1))) { + X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, ERR_R_MALLOC_FAILURE); + return NULL; + } + spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len); + if(spki_len < 0) { + X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, + X509_R_BASE64_DECODE_ERROR); + Free(spki_der); + return NULL; + } + p = spki_der; + spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); + Free(spki_der); + return spki; +} + +/* Generate a base64 encoded string from an SPKI */ + +char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) +{ + unsigned char *der_spki, *p; + char *b64_str; + int der_len; + der_len = i2d_NETSCAPE_SPKI(spki, NULL); + der_spki = Malloc(der_len); + b64_str = Malloc(der_len * 2); + if(!der_spki || !b64_str) { + X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE); + return NULL; + } + p = der_spki; + i2d_NETSCAPE_SPKI(spki, &p); + EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); + Free(der_spki); + return b64_str; +} diff --git a/src/lib/libcrypto/x509v3/ext_dat.h b/src/lib/libcrypto/x509v3/ext_dat.h new file mode 100644 index 0000000000..801a585a52 --- /dev/null +++ b/src/lib/libcrypto/x509v3/ext_dat.h @@ -0,0 +1,97 @@ +/* ext_dat.h */ +/* 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). + * + */ +/* This file contains a table of "standard" extensions */ + +extern X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; +extern X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info; +extern X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id; +extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_cpols, v3_crld; + +/* This table will be searched using OBJ_bsearch so it *must* kept in + * order of the ext_nid values. + */ + +static X509V3_EXT_METHOD *standard_exts[] = { +&v3_nscert, +&v3_ns_ia5_list[0], +&v3_ns_ia5_list[1], +&v3_ns_ia5_list[2], +&v3_ns_ia5_list[3], +&v3_ns_ia5_list[4], +&v3_ns_ia5_list[5], +&v3_ns_ia5_list[6], +&v3_skey_id, +&v3_key_usage, +&v3_pkey_usage_period, +&v3_alt[0], +&v3_alt[1], +&v3_bcons, +&v3_crl_num, +&v3_cpols, +&v3_akey_id, +&v3_crld, +&v3_ext_ku, +&v3_crl_reason, +&v3_sxnet, +&v3_info, +}; + +/* Number of standard extensions */ + +#define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *)) + diff --git a/src/lib/libcrypto/x509v3/v3_akey.c b/src/lib/libcrypto/x509v3/v3_akey.c new file mode 100644 index 0000000000..4099e6019e --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_akey.c @@ -0,0 +1,249 @@ +/* v3_akey.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 +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist); +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); + +X509V3_EXT_METHOD v3_akey_id = { +NID_authority_key_identifier, X509V3_EXT_MULTILINE, +(X509V3_EXT_NEW)AUTHORITY_KEYID_new, +(X509V3_EXT_FREE)AUTHORITY_KEYID_free, +(X509V3_EXT_D2I)d2i_AUTHORITY_KEYID, +(X509V3_EXT_I2D)i2d_AUTHORITY_KEYID, +NULL, NULL, +(X509V3_EXT_I2V)i2v_AUTHORITY_KEYID, +(X509V3_EXT_V2I)v2i_AUTHORITY_KEYID, +NULL,NULL, +NULL +}; + + +int i2d_AUTHORITY_KEYID(AUTHORITY_KEYID *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len_IMP_opt (a->keyid, i2d_ASN1_OCTET_STRING); + M_ASN1_I2D_len_IMP_opt (a->issuer, i2d_GENERAL_NAMES); + M_ASN1_I2D_len_IMP_opt (a->serial, i2d_ASN1_INTEGER); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put_IMP_opt (a->keyid, i2d_ASN1_OCTET_STRING, 0); + M_ASN1_I2D_put_IMP_opt (a->issuer, i2d_GENERAL_NAMES, 1); + M_ASN1_I2D_put_IMP_opt (a->serial, i2d_ASN1_INTEGER, 2); + + M_ASN1_I2D_finish(); +} + +AUTHORITY_KEYID *AUTHORITY_KEYID_new(void) +{ + AUTHORITY_KEYID *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, AUTHORITY_KEYID); + ret->keyid = NULL; + ret->issuer = NULL; + ret->serial = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_AUTHORITY_KEYID_NEW); +} + +AUTHORITY_KEYID *d2i_AUTHORITY_KEYID(AUTHORITY_KEYID **a, unsigned char **pp, + long length) +{ + M_ASN1_D2I_vars(a,AUTHORITY_KEYID *,AUTHORITY_KEYID_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get_IMP_opt (ret->keyid, d2i_ASN1_OCTET_STRING, 0, + V_ASN1_OCTET_STRING); + M_ASN1_D2I_get_IMP_opt (ret->issuer, d2i_GENERAL_NAMES, 1, + V_ASN1_SEQUENCE); + M_ASN1_D2I_get_IMP_opt (ret->serial, d2i_ASN1_INTEGER, 2, + V_ASN1_INTEGER); + M_ASN1_D2I_Finish(a, AUTHORITY_KEYID_free, ASN1_F_D2I_AUTHORITY_KEYID); +} + +void AUTHORITY_KEYID_free(AUTHORITY_KEYID *a) +{ + if (a == NULL) return; + ASN1_OCTET_STRING_free(a->keyid); + sk_GENERAL_NAME_pop_free(a->issuer, GENERAL_NAME_free); + ASN1_INTEGER_free (a->serial); + Free ((char *)a); +} + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist) +{ + char *tmp; + if(akeyid->keyid) { + tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length); + X509V3_add_value("keyid", tmp, &extlist); + Free(tmp); + } + if(akeyid->issuer) + extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); + if(akeyid->serial) { + tmp = hex_to_string(akeyid->serial->data, + akeyid->serial->length); + X509V3_add_value("serial", tmp, &extlist); + Free(tmp); + } + return extlist; +} + +/* Currently two options: + * keyid: use the issuers subject keyid, the value 'always' means its is + * an error if the issuer certificate doesn't have a key id. + * issuer: use the issuers cert issuer and serial number. The default is + * to only use this if keyid is not present. With the option 'always' + * this is always included. + */ + +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values) +{ +char keyid=0, issuer=0; +int i; +CONF_VALUE *cnf; +ASN1_OCTET_STRING *ikeyid = NULL; +X509_NAME *isname = NULL; +STACK_OF(GENERAL_NAME) * gens = NULL; +GENERAL_NAME *gen = NULL; +ASN1_INTEGER *serial = NULL; +X509_EXTENSION *ext; +X509 *cert; +AUTHORITY_KEYID *akeyid; +for(i = 0; i < sk_CONF_VALUE_num(values); i++) { + cnf = sk_CONF_VALUE_value(values, i); + if(!strcmp(cnf->name, "keyid")) { + keyid = 1; + if(cnf->value && !strcmp(cnf->value, "always")) keyid = 2; + } else if(!strcmp(cnf->name, "issuer")) { + issuer = 1; + if(cnf->value && !strcmp(cnf->value, "always")) issuer = 2; + } else { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,X509V3_R_UNKNOWN_OPTION); + ERR_add_error_data(2, "name=", cnf->name); + return NULL; + } +} + + + +if(!ctx || !ctx->issuer_cert) { + if(ctx && (ctx->flags==CTX_TEST)) return AUTHORITY_KEYID_new(); + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,X509V3_R_NO_ISSUER_CERTIFICATE); + return NULL; +} + +cert = ctx->issuer_cert; + +if(keyid) { + i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if((i >= 0) && (ext = X509_get_ext(cert, i))) + ikeyid = X509V3_EXT_d2i(ext); + if(keyid==2 && !ikeyid) { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); + return NULL; + } +} + +if((issuer && !ikeyid) || (issuer == 2)) { + isname = X509_NAME_dup(X509_get_issuer_name(cert)); + serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if(!isname || !serial) { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); + goto err; + } +} + +if(!(akeyid = AUTHORITY_KEYID_new())) goto err; + +if(isname) { + if(!(gens = sk_GENERAL_NAME_new(NULL)) || !(gen = GENERAL_NAME_new()) + || !sk_GENERAL_NAME_push(gens, gen)) { + X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,ERR_R_MALLOC_FAILURE); + goto err; + } + gen->type = GEN_DIRNAME; + gen->d.dirn = isname; +} + +akeyid->issuer = gens; +akeyid->serial = serial; +akeyid->keyid = ikeyid; + +return akeyid; + +err: +X509_NAME_free(isname); +ASN1_INTEGER_free(serial); +ASN1_OCTET_STRING_free(ikeyid); +return NULL; + +} + diff --git a/src/lib/libcrypto/x509v3/v3_akeya.c b/src/lib/libcrypto/x509v3/v3_akeya.c new file mode 100644 index 0000000000..2aafa26ba7 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_akeya.c @@ -0,0 +1,72 @@ +/* v3_akey_asn1.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 +#include + +ASN1_SEQUENCE(AUTHORITY_KEYID) = { + ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0), + ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1), + ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2) +} ASN1_SEQUENCE_END(AUTHORITY_KEYID) + +IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID) diff --git a/src/lib/libcrypto/x509v3/v3_alt.c b/src/lib/libcrypto/x509v3/v3_alt.c new file mode 100644 index 0000000000..b5e1f8af96 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_alt.c @@ -0,0 +1,402 @@ +/* v3_alt.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 + +static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens); +static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens); +X509V3_EXT_METHOD v3_alt[] = { +{ NID_subject_alt_name, 0, +(X509V3_EXT_NEW)GENERAL_NAMES_new, +(X509V3_EXT_FREE)GENERAL_NAMES_free, +(X509V3_EXT_D2I)d2i_GENERAL_NAMES, +(X509V3_EXT_I2D)i2d_GENERAL_NAMES, +NULL, NULL, +(X509V3_EXT_I2V)i2v_GENERAL_NAMES, +(X509V3_EXT_V2I)v2i_subject_alt, +NULL, NULL, NULL}, +{ NID_issuer_alt_name, 0, +(X509V3_EXT_NEW)GENERAL_NAMES_new, +(X509V3_EXT_FREE)GENERAL_NAMES_free, +(X509V3_EXT_D2I)d2i_GENERAL_NAMES, +(X509V3_EXT_I2D)i2d_GENERAL_NAMES, +NULL, NULL, +(X509V3_EXT_I2V)i2v_GENERAL_NAMES, +(X509V3_EXT_V2I)v2i_issuer_alt, +NULL, NULL, NULL}, +EXT_END +}; + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_NAME) *gens, STACK_OF(CONF_VALUE) *ret) +{ + int i; + GENERAL_NAME *gen; + for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + ret = i2v_GENERAL_NAME(method, gen, ret); + } + if(!ret) return sk_CONF_VALUE_new_null(); + return ret; +} + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, + GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) +{ + char oline[256]; + unsigned char *p; + switch (gen->type) + { + case GEN_OTHERNAME: + X509V3_add_value("othername","", &ret); + break; + + case GEN_X400: + X509V3_add_value("X400Name","", &ret); + break; + + case GEN_EDIPARTY: + X509V3_add_value("EdiPartyName","", &ret); + break; + + case GEN_EMAIL: + X509V3_add_value_uchar("email",gen->d.ia5->data, &ret); + break; + + case GEN_DNS: + X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret); + break; + + case GEN_URI: + X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret); + break; + + case GEN_DIRNAME: + X509_NAME_oneline(gen->d.dirn, oline, 256); + X509V3_add_value("DirName",oline, &ret); + break; + + case GEN_IPADD: + p = gen->d.ip->data; + /* BUG: doesn't support IPV6 */ + if(gen->d.ip->length != 4) { + X509V3_add_value("IP Address","", &ret); + break; + } + sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + X509V3_add_value("IP Address",oline, &ret); + break; + + case GEN_RID: + i2t_ASN1_OBJECT(oline, 256, gen->d.rid); + X509V3_add_value("Registered ID",oline, &ret); + break; + } + return ret; +} + +static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(GENERAL_NAME) *gens = NULL; + CONF_VALUE *cnf; + int i; + if(!(gens = sk_GENERAL_NAME_new(NULL))) { + X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); + return NULL; + } + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if(!name_cmp(cnf->name, "issuer") && cnf->value && + !strcmp(cnf->value, "copy")) { + if(!copy_issuer(ctx, gens)) goto err; + } else { + GENERAL_NAME *gen; + if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + sk_GENERAL_NAME_push(gens, gen); + } + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* Append subject altname of issuer to issuer alt name of subject */ + +static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) +{ + STACK_OF(GENERAL_NAME) *ialt; + GENERAL_NAME *gen; + X509_EXTENSION *ext; + int i; + if(ctx && (ctx->flags == CTX_TEST)) return 1; + if(!ctx || !ctx->issuer_cert) { + X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS); + goto err; + } + i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); + if(i < 0) return 1; + if(!(ext = X509_get_ext(ctx->issuer_cert, i)) || + !(ialt = X509V3_EXT_d2i(ext)) ) { + X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR); + goto err; + } + + for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) { + gen = sk_GENERAL_NAME_value(ialt, i); + if(!sk_GENERAL_NAME_push(gens, gen)) { + X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE); + goto err; + } + } + sk_GENERAL_NAME_free(ialt); + + return 1; + + err: + return 0; + +} + +static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(GENERAL_NAME) *gens = NULL; + CONF_VALUE *cnf; + int i; + if(!(gens = sk_GENERAL_NAME_new(NULL))) { + X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); + return NULL; + } + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if(!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "copy")) { + if(!copy_email(ctx, gens)) goto err; + } else { + GENERAL_NAME *gen; + if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + sk_GENERAL_NAME_push(gens, gen); + } + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* Copy any email addresses in a certificate or request to + * GENERAL_NAMES + */ + +static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) +{ + X509_NAME *nm; + ASN1_IA5STRING *email = NULL; + X509_NAME_ENTRY *ne; + GENERAL_NAME *gen = NULL; + int i; + if(ctx->flags == CTX_TEST) return 1; + if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) { + X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS); + goto err; + } + /* Find the subject name */ + if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert); + else nm = X509_REQ_get_subject_name(ctx->subject_req); + + /* Now add any email address(es) to STACK */ + i = -1; + while((i = X509_NAME_get_index_by_NID(nm, + NID_pkcs9_emailAddress, i)) > 0) { + ne = X509_NAME_get_entry(nm, i); + email = ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if(!email || !(gen = GENERAL_NAME_new())) { + X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); + goto err; + } + gen->d.ia5 = email; + email = NULL; + gen->type = GEN_EMAIL; + if(!sk_GENERAL_NAME_push(gens, gen)) { + X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); + goto err; + } + gen = NULL; + } + + + return 1; + + err: + GENERAL_NAME_free(gen); + ASN1_IA5STRING_free(email); + return 0; + +} + +STACK_OF(GENERAL_NAME) *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAME *gen; + STACK_OF(GENERAL_NAME) *gens = NULL; + CONF_VALUE *cnf; + int i; + if(!(gens = sk_GENERAL_NAME_new(NULL))) { + X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); + return NULL; + } + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err; + sk_GENERAL_NAME_push(gens, gen); + } + return gens; + err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + CONF_VALUE *cnf) +{ +char is_string = 0; +int type; +GENERAL_NAME *gen = NULL; + +char *name, *value; + +name = cnf->name; +value = cnf->value; + +if(!value) { + X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE); + return NULL; +} + +if(!(gen = GENERAL_NAME_new())) { + X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + return NULL; +} + +if(!name_cmp(name, "email")) { + is_string = 1; + type = GEN_EMAIL; +} else if(!name_cmp(name, "URI")) { + is_string = 1; + type = GEN_URI; +} else if(!name_cmp(name, "DNS")) { + is_string = 1; + type = GEN_DNS; +} else if(!name_cmp(name, "RID")) { + ASN1_OBJECT *obj; + if(!(obj = OBJ_txt2obj(value,0))) { + X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", value); + goto err; + } + gen->d.rid = obj; + type = GEN_RID; +} else if(!name_cmp(name, "IP")) { + int i1,i2,i3,i4; + unsigned char ip[4]; + if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) || + (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) || + (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) { + X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); + ERR_add_error_data(2, "value=", value); + goto err; + } + ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4; + if(!(gen->d.ip = ASN1_OCTET_STRING_new()) || + !ASN1_STRING_set(gen->d.ip, ip, 4)) { + X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + goto err; + } + type = GEN_IPADD; +} else { + X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION); + ERR_add_error_data(2, "name=", name); + goto err; +} + +if(is_string) { + if(!(gen->d.ia5 = ASN1_IA5STRING_new()) || + !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value, + strlen(value))) { + X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + goto err; + } +} + +gen->type = type; + +return gen; + +err: +GENERAL_NAME_free(gen); +return NULL; +} diff --git a/src/lib/libcrypto/x509v3/v3_bcons.c b/src/lib/libcrypto/x509v3/v3_bcons.c new file mode 100644 index 0000000000..de2f855c35 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_bcons.c @@ -0,0 +1,164 @@ +/* v3_bcons.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 +#include + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist); +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); + +X509V3_EXT_METHOD v3_bcons = { +NID_basic_constraints, 0, +(X509V3_EXT_NEW)BASIC_CONSTRAINTS_new, +(X509V3_EXT_FREE)BASIC_CONSTRAINTS_free, +(X509V3_EXT_D2I)d2i_BASIC_CONSTRAINTS, +(X509V3_EXT_I2D)i2d_BASIC_CONSTRAINTS, +NULL, NULL, +(X509V3_EXT_I2V)i2v_BASIC_CONSTRAINTS, +(X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS, +NULL,NULL, +NULL +}; + + +int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + if(a->ca) M_ASN1_I2D_len (a->ca, i2d_ASN1_BOOLEAN); + M_ASN1_I2D_len (a->pathlen, i2d_ASN1_INTEGER); + + M_ASN1_I2D_seq_total(); + + if (a->ca) M_ASN1_I2D_put (a->ca, i2d_ASN1_BOOLEAN); + M_ASN1_I2D_put (a->pathlen, i2d_ASN1_INTEGER); + M_ASN1_I2D_finish(); +} + +BASIC_CONSTRAINTS *BASIC_CONSTRAINTS_new(void) +{ + BASIC_CONSTRAINTS *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, BASIC_CONSTRAINTS); + ret->ca = 0; + ret->pathlen = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_BASIC_CONSTRAINTS_NEW); +} + +BASIC_CONSTRAINTS *d2i_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS **a, + unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,BASIC_CONSTRAINTS *,BASIC_CONSTRAINTS_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + if((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == + (V_ASN1_UNIVERSAL|V_ASN1_BOOLEAN) ) { + M_ASN1_D2I_get_int (ret->ca, d2i_ASN1_BOOLEAN); + } + M_ASN1_D2I_get_opt (ret->pathlen, d2i_ASN1_INTEGER, V_ASN1_INTEGER); + M_ASN1_D2I_Finish(a, BASIC_CONSTRAINTS_free, ASN1_F_D2I_BASIC_CONSTRAINTS); +} + +void BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a) +{ + if (a == NULL) return; + ASN1_INTEGER_free (a->pathlen); + Free ((char *)a); +} + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist) +{ + X509V3_add_value_bool("CA", bcons->ca, &extlist); + X509V3_add_value_int("pathlen", bcons->pathlen, &extlist); + return extlist; +} + +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values) +{ + BASIC_CONSTRAINTS *bcons=NULL; + CONF_VALUE *val; + int i; + if(!(bcons = BASIC_CONSTRAINTS_new())) { + X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, ERR_R_MALLOC_FAILURE); + return NULL; + } + for(i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if(!strcmp(val->name, "CA")) { + if(!X509V3_get_value_bool(val, &bcons->ca)) goto err; + } else if(!strcmp(val->name, "pathlen")) { + if(!X509V3_get_value_int(val, &bcons->pathlen)) goto err; + } else { + X509V3err(X509V3_F_V2I_BASIC_CONSTRAINTS, X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + return bcons; + err: + BASIC_CONSTRAINTS_free(bcons); + return NULL; +} + diff --git a/src/lib/libcrypto/x509v3/v3_bitst.c b/src/lib/libcrypto/x509v3/v3_bitst.c new file mode 100644 index 0000000000..9828ba15b3 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_bitst.c @@ -0,0 +1,147 @@ +/* v3_bitst.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 + +static ASN1_BIT_STRING *asn1_bit_string_new(void); +static ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *extlist); +static BIT_STRING_BITNAME ns_cert_type_table[] = { +{0, "SSL Client", "client"}, +{1, "SSL Server", "server"}, +{2, "S/MIME", "email"}, +{3, "Object Signing", "objsign"}, +{4, "Unused", "reserved"}, +{5, "SSL CA", "sslCA"}, +{6, "S/MIME CA", "emailCA"}, +{7, "Object Signing CA", "objCA"}, +{-1, NULL, NULL} +}; + +static BIT_STRING_BITNAME key_usage_type_table[] = { +{0, "Digital Signature", "digitalSignature"}, +{1, "Non Repudiation", "nonRepudiation"}, +{2, "Key Encipherment", "keyEncipherment"}, +{3, "Data Encipherment", "dataEncipherment"}, +{4, "Key Agreement", "keyAgreement"}, +{5, "Certificate Sign", "keyCertSign"}, +{6, "CRL Sign", "cRLSign"}, +{7, "Encipher Only", "encipherOnly"}, +{8, "Decipher Only", "decipherOnly"}, +{-1, NULL, NULL} +}; + + + +X509V3_EXT_METHOD v3_nscert = EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); +X509V3_EXT_METHOD v3_key_usage = EXT_BITSTRING(NID_key_usage, key_usage_type_table); + +static ASN1_BIT_STRING *asn1_bit_string_new(void) +{ + return ASN1_BIT_STRING_new(); +} + +static STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, STACK_OF(CONF_VALUE) *ret) +{ + BIT_STRING_BITNAME *bnam; + for(bnam =method->usr_data; bnam->lname; bnam++) { + if(ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) + X509V3_add_value(bnam->lname, NULL, &ret); + } + return ret; +} + +static ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *val; + ASN1_BIT_STRING *bs; + int i; + BIT_STRING_BITNAME *bnam; + if(!(bs = ASN1_BIT_STRING_new())) { + X509V3err(X509V3_F_V2I_ASN1_BIT_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + for(bnam = method->usr_data; bnam->lname; bnam++) { + if(!strcmp(bnam->sname, val->name) || + !strcmp(bnam->lname, val->name) ) { + ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1); + break; + } + } + if(!bnam->lname) { + X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, + X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); + X509V3_conf_err(val); + ASN1_BIT_STRING_free(bs); + return NULL; + } + } + return bs; +} + + diff --git a/src/lib/libcrypto/x509v3/v3_conf.c b/src/lib/libcrypto/x509v3/v3_conf.c new file mode 100644 index 0000000000..f19bb3ad84 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_conf.c @@ -0,0 +1,366 @@ +/* v3_conf.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). + * + */ +/* extension creation utilities */ + + + +#include +#include +#include "cryptlib.h" +#include +#include +#include + +static int v3_check_critical(char **value); +static int v3_check_generic(char **value); +static X509_EXTENSION *do_ext_conf(LHASH *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value); +static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type); +static char *conf_lhash_get_string(void *db, char *section, char *value); +static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section); +static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, + int crit, void *ext_struc); +/* LHASH *conf: Config file */ +/* char *name: Name */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, + char *value) +{ + int crit; + int ext_type; + X509_EXTENSION *ret; + crit = v3_check_critical(&value); + if((ext_type = v3_check_generic(&value))) + return v3_generic_extension(name, value, crit, ext_type); + ret = do_ext_conf(conf, ctx, OBJ_sn2nid(name), crit, value); + if(!ret) { + X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_ERROR_IN_EXTENSION); + ERR_add_error_data(4,"name=", name, ", value=", value); + } + return ret; +} + +/* LHASH *conf: Config file */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, + char *value) +{ + int crit; + int ext_type; + crit = v3_check_critical(&value); + if((ext_type = v3_check_generic(&value))) + return v3_generic_extension(OBJ_nid2sn(ext_nid), + value, crit, ext_type); + return do_ext_conf(conf, ctx, ext_nid, crit, value); +} + +/* LHASH *conf: Config file */ +/* char *value: Value */ +static X509_EXTENSION *do_ext_conf(LHASH *conf, X509V3_CTX *ctx, int ext_nid, + int crit, char *value) +{ + X509V3_EXT_METHOD *method; + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + void *ext_struc; + if(ext_nid == NID_undef) { + X509V3err(X509V3_F_DO_EXT_CONF,X509V3_R_UNKNOWN_EXTENSION_NAME); + return NULL; + } + if(!(method = X509V3_EXT_get_nid(ext_nid))) { + X509V3err(X509V3_F_DO_EXT_CONF,X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + /* Now get internal extension representation based on type */ + if(method->v2i) { + if(*value == '@') nval = CONF_get_section(conf, value + 1); + else nval = X509V3_parse_list(value); + if(!nval) { + X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_INVALID_EXTENSION_STRING); + ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value); + return NULL; + } + ext_struc = method->v2i(method, ctx, nval); + if(*value != '@') sk_CONF_VALUE_pop_free(nval, + X509V3_conf_free); + if(!ext_struc) return NULL; + } else if(method->s2i) { + if(!(ext_struc = method->s2i(method, ctx, value))) return NULL; + } else if(method->r2i) { + if(!ctx->db) { + X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_NO_CONFIG_DATABASE); + return NULL; + } + if(!(ext_struc = method->r2i(method, ctx, value))) return NULL; + } else { + X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); + ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); + return NULL; + } + + ext = do_ext_i2d(method, ext_nid, crit, ext_struc); + method->ext_free(ext_struc); + return ext; + +} + +static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, + int crit, void *ext_struc) +{ + unsigned char *ext_der, *p; + int ext_len; + ASN1_OCTET_STRING *ext_oct; + X509_EXTENSION *ext; + /* Convert internal representation to DER */ + ext_len = method->i2d(ext_struc, NULL); + if(!(ext_der = Malloc(ext_len))) goto merr; + p = ext_der; + method->i2d(ext_struc, &p); + if(!(ext_oct = ASN1_OCTET_STRING_new())) goto merr; + ext_oct->data = ext_der; + ext_oct->length = ext_len; + + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); + if(!ext) goto merr; + ASN1_OCTET_STRING_free(ext_oct); + + return ext; + + merr: + X509V3err(X509V3_F_DO_EXT_I2D,ERR_R_MALLOC_FAILURE); + return NULL; + +} + +/* Given an internal structure, nid and critical flag create an extension */ + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) +{ + X509V3_EXT_METHOD *method; + if(!(method = X509V3_EXT_get_nid(ext_nid))) { + X509V3err(X509V3_F_X509V3_EXT_I2D,X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + return do_ext_i2d(method, ext_nid, crit, ext_struc); +} + +/* Check the extension string for critical flag */ +static int v3_check_critical(char **value) +{ + char *p = *value; + if((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0; + p+=9; + while(isspace((unsigned char)*p)) p++; + *value = p; + return 1; +} + +/* Check extension string for generic extension and return the type */ +static int v3_check_generic(char **value) +{ + char *p = *value; + if((strlen(p) < 4) || strncmp(p, "DER:,", 4)) return 0; + p+=4; + while(isspace((unsigned char)*p)) p++; + *value = p; + return 1; +} + +/* Create a generic extension: for now just handle RAW type */ +static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, + int crit, int type) +{ +unsigned char *ext_der=NULL; +long ext_len; +ASN1_OBJECT *obj=NULL; +ASN1_OCTET_STRING *oct=NULL; +X509_EXTENSION *extension=NULL; +if(!(obj = OBJ_txt2obj(ext, 0))) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_NAME_ERROR); + ERR_add_error_data(2, "name=", ext); + goto err; +} + +if(!(ext_der = string_to_hex(value, &ext_len))) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR); + ERR_add_error_data(2, "value=", value); + goto err; +} + +if(!(oct = ASN1_OCTET_STRING_new())) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,ERR_R_MALLOC_FAILURE); + goto err; +} + +oct->data = ext_der; +oct->length = ext_len; +ext_der = NULL; + +extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + +err: +ASN1_OBJECT_free(obj); +ASN1_OCTET_STRING_free(oct); +if(ext_der) Free(ext_der); +return extension; +} + + +/* This is the main function: add a bunch of extensions based on a config file + * section + */ + +int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509 *cert) +{ + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + CONF_VALUE *val; + int i; + if(!(nval = CONF_get_section(conf, section))) return 0; + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value))) + return 0; + if(cert) X509_add_ext(cert, ext, -1); + X509_EXTENSION_free(ext); + } + return 1; +} + +/* Same as above but for a CRL */ + +int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509_CRL *crl) +{ + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + CONF_VALUE *val; + int i; + if(!(nval = CONF_get_section(conf, section))) return 0; + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value))) + return 0; + if(crl) X509_CRL_add_ext(crl, ext, -1); + X509_EXTENSION_free(ext); + } + return 1; +} + +/* Config database functions */ + +char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section) +{ + if(ctx->db_meth->get_string) + return ctx->db_meth->get_string(ctx->db, name, section); + return NULL; +} + +STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section) +{ + if(ctx->db_meth->get_section) + return ctx->db_meth->get_section(ctx->db, section); + return NULL; +} + +void X509V3_string_free(X509V3_CTX *ctx, char *str) +{ + if(!str) return; + if(ctx->db_meth->free_string) + ctx->db_meth->free_string(ctx->db, str); +} + +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) +{ + if(!section) return; + if(ctx->db_meth->free_section) + ctx->db_meth->free_section(ctx->db, section); +} + +static char *conf_lhash_get_string(void *db, char *section, char *value) +{ + return CONF_get_string(db, section, value); +} + +static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section) +{ + return CONF_get_section(db, section); +} + +static X509V3_CONF_METHOD conf_lhash_method = { +conf_lhash_get_string, +conf_lhash_get_section, +NULL, +NULL +}; + +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash) +{ + ctx->db_meth = &conf_lhash_method; + ctx->db = lhash; +} + +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, + X509_CRL *crl, int flags) +{ + ctx->issuer_cert = issuer; + ctx->subject_cert = subj; + ctx->crl = crl; + ctx->subject_req = req; + ctx->flags = flags; +} diff --git a/src/lib/libcrypto/x509v3/v3_cpols.c b/src/lib/libcrypto/x509v3/v3_cpols.c new file mode 100644 index 0000000000..b4d4883545 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_cpols.c @@ -0,0 +1,655 @@ +/* v3_cpols.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 +#include + +/* Certificate policies extension support: this one is a bit complex... */ + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out, int indent); +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value); +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent); +static void print_notice(BIO *out, USERNOTICE *notice, int indent); +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org); +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org); +static STACK *nref_nos(STACK_OF(CONF_VALUE) *nos); + +X509V3_EXT_METHOD v3_cpols = { +NID_certificate_policies, 0, +(X509V3_EXT_NEW)CERTIFICATEPOLICIES_new, +(X509V3_EXT_FREE)CERTIFICATEPOLICIES_free, +(X509V3_EXT_D2I)d2i_CERTIFICATEPOLICIES, +(X509V3_EXT_I2D)i2d_CERTIFICATEPOLICIES, +NULL, NULL, +NULL, NULL, +(X509V3_EXT_I2R)i2r_certpol, +(X509V3_EXT_R2I)r2i_certpol, +NULL +}; + + +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value) +{ + STACK_OF(POLICYINFO) *pols = NULL; + char *pstr; + POLICYINFO *pol; + ASN1_OBJECT *pobj; + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *cnf; + int i, ia5org; + pols = sk_POLICYINFO_new_null(); + vals = X509V3_parse_list(value); + ia5org = 0; + for(i = 0; i < sk_CONF_VALUE_num(vals); i++) { + cnf = sk_CONF_VALUE_value(vals, i); + if(cnf->value || !cnf->name ) { + X509V3err(X509V3_F_R2I_CERTPOL,X509V3_R_INVALID_POLICY_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pstr = cnf->name; + if(!strcmp(pstr,"ia5org")) { + ia5org = 1; + continue; + } else if(*pstr == '@') { + STACK_OF(CONF_VALUE) *polsect; + polsect = X509V3_get_section(ctx, pstr + 1); + if(!polsect) { + X509V3err(X509V3_F_R2I_CERTPOL,X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + pol = policy_section(ctx, polsect, ia5org); + X509V3_section_free(ctx, polsect); + if(!pol) goto err; + } else { + if(!(pobj = OBJ_txt2obj(cnf->name, 0))) { + X509V3err(X509V3_F_R2I_CERTPOL,X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol = POLICYINFO_new(); + pol->policyid = pobj; + } + sk_POLICYINFO_push(pols, pol); + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pols; + err: + sk_POLICYINFO_pop_free(pols, POLICYINFO_free); + return NULL; +} + +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org) +{ + int i; + CONF_VALUE *cnf; + POLICYINFO *pol; + POLICYQUALINFO *qual; + if(!(pol = POLICYINFO_new())) goto merr; + for(i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { + cnf = sk_CONF_VALUE_value(polstrs, i); + if(!strcmp(cnf->name, "policyIdentifier")) { + ASN1_OBJECT *pobj; + if(!(pobj = OBJ_txt2obj(cnf->value, 0))) { + X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol->policyid = pobj; + + } else if(!name_cmp(cnf->name, "CPS")) { + if(!pol->qualifiers) pol->qualifiers = + sk_POLICYQUALINFO_new_null(); + if(!(qual = POLICYQUALINFO_new())) goto merr; + if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) + goto merr; + qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); + qual->d.cpsuri = ASN1_IA5STRING_new(); + if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value, + strlen(cnf->value))) goto merr; + } else if(!name_cmp(cnf->name, "userNotice")) { + STACK_OF(CONF_VALUE) *unot; + if(*cnf->value != '@') { + X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_EXPECTED_A_SECTION_NAME); + X509V3_conf_err(cnf); + goto err; + } + unot = X509V3_get_section(ctx, cnf->value + 1); + if(!unot) { + X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_SECTION); + + X509V3_conf_err(cnf); + goto err; + } + qual = notice_section(ctx, unot, ia5org); + X509V3_section_free(ctx, unot); + if(!qual) goto err; + if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) + goto merr; + } else { + X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_OPTION); + + X509V3_conf_err(cnf); + goto err; + } + } + if(!pol->policyid) { + X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_NO_POLICY_IDENTIFIER); + goto err; + } + + return pol; + + merr: + X509V3err(X509V3_F_POLICY_SECTION,ERR_R_MALLOC_FAILURE); + + err: + POLICYINFO_free(pol); + return NULL; + + +} + +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org) +{ + int i; + CONF_VALUE *cnf; + USERNOTICE *not; + POLICYQUALINFO *qual; + if(!(qual = POLICYQUALINFO_new())) goto merr; + qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); + if(!(not = USERNOTICE_new())) goto merr; + qual->d.usernotice = not; + for(i = 0; i < sk_CONF_VALUE_num(unot); i++) { + cnf = sk_CONF_VALUE_value(unot, i); + if(!strcmp(cnf->name, "explicitText")) { + not->exptext = ASN1_VISIBLESTRING_new(); + if(!ASN1_STRING_set(not->exptext, cnf->value, + strlen(cnf->value))) goto merr; + } else if(!strcmp(cnf->name, "organization")) { + NOTICEREF *nref; + if(!not->noticeref) { + if(!(nref = NOTICEREF_new())) goto merr; + not->noticeref = nref; + } else nref = not->noticeref; + if(ia5org) nref->organization = ASN1_IA5STRING_new(); + else nref->organization = ASN1_VISIBLESTRING_new(); + if(!ASN1_STRING_set(nref->organization, cnf->value, + strlen(cnf->value))) goto merr; + } else if(!strcmp(cnf->name, "noticeNumbers")) { + NOTICEREF *nref; + STACK_OF(CONF_VALUE) *nos; + if(!not->noticeref) { + if(!(nref = NOTICEREF_new())) goto merr; + not->noticeref = nref; + } else nref = not->noticeref; + nos = X509V3_parse_list(cnf->value); + if(!nos || !sk_CONF_VALUE_num(nos)) { + X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_INVALID_NUMBERS); + X509V3_conf_err(cnf); + goto err; + } + nref->noticenos = nref_nos(nos); + sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); + if(!nref->noticenos) goto err; + } else { + X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_INVALID_OPTION); + + X509V3_conf_err(cnf); + goto err; + } + } + + if(not->noticeref && + (!not->noticeref->noticenos || !not->noticeref->organization)) { + X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + goto err; + } + + return qual; + + merr: + X509V3err(X509V3_F_NOTICE_SECTION,ERR_R_MALLOC_FAILURE); + + err: + POLICYQUALINFO_free(qual); + return NULL; +} + +static STACK *nref_nos(STACK_OF(CONF_VALUE) *nos) +{ + STACK *nnums; + CONF_VALUE *cnf; + ASN1_INTEGER *aint; + int i; + if(!(nnums = sk_new_null())) goto merr; + for(i = 0; i < sk_CONF_VALUE_num(nos); i++) { + cnf = sk_CONF_VALUE_value(nos, i); + if(!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { + X509V3err(X509V3_F_NREF_NOS,X509V3_R_INVALID_NUMBER); + goto err; + } + if(!sk_push(nnums, (char *)aint)) goto merr; + } + return nnums; + + merr: + X509V3err(X509V3_F_NOTICE_SECTION,ERR_R_MALLOC_FAILURE); + + err: + sk_pop_free(nnums, ASN1_STRING_free); + return NULL; +} + + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, + BIO *out, int indent) +{ + int i; + POLICYINFO *pinfo; + /* First print out the policy OIDs */ + for(i = 0; i < sk_POLICYINFO_num(pol); i++) { + pinfo = sk_POLICYINFO_value(pol, i); + BIO_printf(out, "%*sPolicy: ", indent, ""); + i2a_ASN1_OBJECT(out, pinfo->policyid); + BIO_puts(out, "\n"); + if(pinfo->qualifiers) + print_qualifiers(out, pinfo->qualifiers, indent + 2); + } + return 1; +} + + +int i2d_CERTIFICATEPOLICIES(STACK_OF(POLICYINFO) *a, unsigned char **pp) +{ + +return i2d_ASN1_SET_OF_POLICYINFO(a, pp, i2d_POLICYINFO, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE);} + +STACK_OF(POLICYINFO) *CERTIFICATEPOLICIES_new(void) +{ + return sk_POLICYINFO_new_null(); +} + +void CERTIFICATEPOLICIES_free(STACK_OF(POLICYINFO) *a) +{ + sk_POLICYINFO_pop_free(a, POLICYINFO_free); +} + +STACK_OF(POLICYINFO) *d2i_CERTIFICATEPOLICIES(STACK_OF(POLICYINFO) **a, + unsigned char **pp,long length) +{ +return d2i_ASN1_SET_OF_POLICYINFO(a, pp, length, d2i_POLICYINFO, + POLICYINFO_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); + +} + +IMPLEMENT_STACK_OF(POLICYINFO) +IMPLEMENT_ASN1_SET_OF(POLICYINFO) + +int i2d_POLICYINFO(POLICYINFO *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->policyid, i2d_ASN1_OBJECT); + M_ASN1_I2D_len_SEQUENCE_type(POLICYQUALINFO, a->qualifiers, + i2d_POLICYQUALINFO); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->policyid, i2d_ASN1_OBJECT); + M_ASN1_I2D_put_SEQUENCE_type(POLICYQUALINFO, a->qualifiers, + i2d_POLICYQUALINFO); + + M_ASN1_I2D_finish(); +} + +POLICYINFO *POLICYINFO_new(void) +{ + POLICYINFO *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, POLICYINFO); + ret->policyid = NULL; + ret->qualifiers = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_POLICYINFO_NEW); +} + +POLICYINFO *d2i_POLICYINFO(POLICYINFO **a, unsigned char **pp,long length) +{ + M_ASN1_D2I_vars(a,POLICYINFO *,POLICYINFO_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get(ret->policyid, d2i_ASN1_OBJECT); + if(!M_ASN1_D2I_end_sequence()) { + M_ASN1_D2I_get_seq_type (POLICYQUALINFO, ret->qualifiers, + d2i_POLICYQUALINFO, POLICYQUALINFO_free); + } + M_ASN1_D2I_Finish(a, POLICYINFO_free, ASN1_F_D2I_POLICYINFO); +} + +void POLICYINFO_free(POLICYINFO *a) +{ + if (a == NULL) return; + ASN1_OBJECT_free(a->policyid); + sk_POLICYQUALINFO_pop_free(a->qualifiers, POLICYQUALINFO_free); + Free (a); +} + +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, + int indent) +{ + POLICYQUALINFO *qualinfo; + int i; + for(i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { + qualinfo = sk_POLICYQUALINFO_value(quals, i); + switch(OBJ_obj2nid(qualinfo->pqualid)) + { + case NID_id_qt_cps: + BIO_printf(out, "%*sCPS: %s\n", indent, "", + qualinfo->d.cpsuri->data); + break; + + case NID_id_qt_unotice: + BIO_printf(out, "%*sUser Notice:\n", indent, ""); + print_notice(out, qualinfo->d.usernotice, indent + 2); + break; + + default: + BIO_printf(out, "%*sUnknown Qualifier: ", + indent + 2, ""); + + i2a_ASN1_OBJECT(out, qualinfo->pqualid); + BIO_puts(out, "\n"); + break; + } + } +} + +static void print_notice(BIO *out, USERNOTICE *notice, int indent) +{ + int i; + if(notice->noticeref) { + NOTICEREF *ref; + ref = notice->noticeref; + BIO_printf(out, "%*sOrganization: %s\n", indent, "", + ref->organization->data); + BIO_printf(out, "%*sNumber%s: ", indent, "", + (sk_num(ref->noticenos) > 1) ? "s" : ""); + for(i = 0; i < sk_num(ref->noticenos); i++) { + ASN1_INTEGER *num; + char *tmp; + num = (ASN1_INTEGER *)sk_value(ref->noticenos, i); + if(i) BIO_puts(out, ", "); + tmp = i2s_ASN1_INTEGER(NULL, num); + BIO_puts(out, tmp); + Free(tmp); + } + BIO_puts(out, "\n"); + } + if(notice->exptext) + BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", + notice->exptext->data); +} + + + +int i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->pqualid, i2d_ASN1_OBJECT); + switch(OBJ_obj2nid(a->pqualid)) { + case NID_id_qt_cps: + M_ASN1_I2D_len(a->d.cpsuri, i2d_ASN1_IA5STRING); + break; + + case NID_id_qt_unotice: + M_ASN1_I2D_len(a->d.usernotice, i2d_USERNOTICE); + break; + + default: + M_ASN1_I2D_len(a->d.other, i2d_ASN1_TYPE); + break; + } + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->pqualid, i2d_ASN1_OBJECT); + switch(OBJ_obj2nid(a->pqualid)) { + case NID_id_qt_cps: + M_ASN1_I2D_put(a->d.cpsuri, i2d_ASN1_IA5STRING); + break; + + case NID_id_qt_unotice: + M_ASN1_I2D_put(a->d.usernotice, i2d_USERNOTICE); + break; + + default: + M_ASN1_I2D_put(a->d.other, i2d_ASN1_TYPE); + break; + } + + M_ASN1_I2D_finish(); +} + +POLICYQUALINFO *POLICYQUALINFO_new(void) +{ + POLICYQUALINFO *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, POLICYQUALINFO); + ret->pqualid = NULL; + ret->d.other = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_POLICYQUALINFO_NEW); +} + +POLICYQUALINFO *d2i_POLICYQUALINFO(POLICYQUALINFO **a, unsigned char **pp, + long length) +{ + M_ASN1_D2I_vars(a,POLICYQUALINFO *,POLICYQUALINFO_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->pqualid, d2i_ASN1_OBJECT); + switch(OBJ_obj2nid(ret->pqualid)) { + case NID_id_qt_cps: + M_ASN1_D2I_get(ret->d.cpsuri, d2i_ASN1_IA5STRING); + break; + + case NID_id_qt_unotice: + M_ASN1_D2I_get(ret->d.usernotice, d2i_USERNOTICE); + break; + + default: + M_ASN1_D2I_get(ret->d.other, d2i_ASN1_TYPE); + break; + } + M_ASN1_D2I_Finish(a, POLICYQUALINFO_free, ASN1_F_D2I_POLICYQUALINFO); +} + +void POLICYQUALINFO_free(POLICYQUALINFO *a) +{ + if (a == NULL) return; + switch(OBJ_obj2nid(a->pqualid)) { + case NID_id_qt_cps: + ASN1_IA5STRING_free(a->d.cpsuri); + break; + + case NID_id_qt_unotice: + USERNOTICE_free(a->d.usernotice); + break; + + default: + ASN1_TYPE_free(a->d.other); + break; + } + + ASN1_OBJECT_free(a->pqualid); + Free (a); +} + +int i2d_USERNOTICE(USERNOTICE *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->noticeref, i2d_NOTICEREF); + M_ASN1_I2D_len (a->exptext, i2d_DISPLAYTEXT); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->noticeref, i2d_NOTICEREF); + M_ASN1_I2D_put (a->exptext, i2d_DISPLAYTEXT); + + M_ASN1_I2D_finish(); +} + +USERNOTICE *USERNOTICE_new(void) +{ + USERNOTICE *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, USERNOTICE); + ret->noticeref = NULL; + ret->exptext = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_USERNOTICE_NEW); +} + +USERNOTICE *d2i_USERNOTICE(USERNOTICE **a, unsigned char **pp,long length) +{ + M_ASN1_D2I_vars(a,USERNOTICE *,USERNOTICE_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get_opt(ret->noticeref, d2i_NOTICEREF, V_ASN1_SEQUENCE); + if (!M_ASN1_D2I_end_sequence()) { + M_ASN1_D2I_get(ret->exptext, d2i_DISPLAYTEXT); + } + M_ASN1_D2I_Finish(a, USERNOTICE_free, ASN1_F_D2I_USERNOTICE); +} + +void USERNOTICE_free(USERNOTICE *a) +{ + if (a == NULL) return; + NOTICEREF_free(a->noticeref); + DISPLAYTEXT_free(a->exptext); + Free (a); +} + +int i2d_NOTICEREF(NOTICEREF *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->organization, i2d_DISPLAYTEXT); + M_ASN1_I2D_len_SEQUENCE(a->noticenos, i2d_ASN1_INTEGER); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->organization, i2d_DISPLAYTEXT); + M_ASN1_I2D_put_SEQUENCE(a->noticenos, i2d_ASN1_INTEGER); + + M_ASN1_I2D_finish(); +} + +NOTICEREF *NOTICEREF_new(void) +{ + NOTICEREF *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, NOTICEREF); + ret->organization = NULL; + ret->noticenos = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_NOTICEREF_NEW); +} + +NOTICEREF *d2i_NOTICEREF(NOTICEREF **a, unsigned char **pp,long length) +{ + M_ASN1_D2I_vars(a,NOTICEREF *,NOTICEREF_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + /* This is to cope with some broken encodings that use IA5STRING for + * the organization field + */ + M_ASN1_D2I_get_opt(ret->organization, d2i_ASN1_IA5STRING, + V_ASN1_IA5STRING); + if(!ret->organization) { + M_ASN1_D2I_get(ret->organization, d2i_DISPLAYTEXT); + } + M_ASN1_D2I_get_seq(ret->noticenos, d2i_ASN1_INTEGER, ASN1_STRING_free); + M_ASN1_D2I_Finish(a, NOTICEREF_free, ASN1_F_D2I_NOTICEREF); +} + +void NOTICEREF_free(NOTICEREF *a) +{ + if (a == NULL) return; + DISPLAYTEXT_free(a->organization); + sk_pop_free(a->noticenos, ASN1_STRING_free); + Free (a); +} + +IMPLEMENT_STACK_OF(POLICYQUALINFO) +IMPLEMENT_ASN1_SET_OF(POLICYQUALINFO) diff --git a/src/lib/libcrypto/x509v3/v3_crld.c b/src/lib/libcrypto/x509v3/v3_crld.c new file mode 100644 index 0000000000..897ffb63e4 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_crld.c @@ -0,0 +1,283 @@ +/* v3_crld.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 +#include + +static STACK_OF(CONF_VALUE) *i2v_crld(X509V3_EXT_METHOD *method, + STACK_OF(DIST_POINT) *crld, STACK_OF(CONF_VALUE) *extlist); +static STACK_OF(DIST_POINT) *v2i_crld(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +X509V3_EXT_METHOD v3_crld = { +NID_crl_distribution_points, X509V3_EXT_MULTILINE, +(X509V3_EXT_NEW)CRL_DIST_POINTS_new, +(X509V3_EXT_FREE)CRL_DIST_POINTS_free, +(X509V3_EXT_D2I)d2i_CRL_DIST_POINTS, +(X509V3_EXT_I2D)i2d_CRL_DIST_POINTS, +NULL, NULL, +(X509V3_EXT_I2V)i2v_crld, +(X509V3_EXT_V2I)v2i_crld, +NULL, NULL, NULL +}; + +static STACK_OF(CONF_VALUE) *i2v_crld(X509V3_EXT_METHOD *method, + STACK_OF(DIST_POINT) *crld, STACK_OF(CONF_VALUE) *exts) +{ + DIST_POINT *point; + int i; + for(i = 0; i < sk_DIST_POINT_num(crld); i++) { + point = sk_DIST_POINT_value(crld, i); + if(point->distpoint->fullname) { + exts = i2v_GENERAL_NAMES(NULL, + point->distpoint->fullname, exts); + } + if(point->reasons) + X509V3_add_value("reasons","", &exts); + if(point->CRLissuer) + X509V3_add_value("CRLissuer","", &exts); + if(point->distpoint->relativename) + X509V3_add_value("RelativeName","", &exts); + } + return exts; +} + +static STACK_OF(DIST_POINT) *v2i_crld(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(DIST_POINT) *crld = NULL; + STACK_OF(GENERAL_NAME) *gens = NULL; + GENERAL_NAME *gen = NULL; + CONF_VALUE *cnf; + int i; + if(!(crld = sk_DIST_POINT_new(NULL))) goto merr; + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + DIST_POINT *point; + cnf = sk_CONF_VALUE_value(nval, i); + if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err; + if(!(gens = GENERAL_NAMES_new())) goto merr; + if(!sk_GENERAL_NAME_push(gens, gen)) goto merr; + gen = NULL; + if(!(point = DIST_POINT_new())) goto merr; + if(!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); + goto merr; + } + if(!(point->distpoint = DIST_POINT_NAME_new())) goto merr; + point->distpoint->fullname = gens; + gens = NULL; + } + return crld; + + merr: + X509V3err(X509V3_F_V2I_CRLD,ERR_R_MALLOC_FAILURE); + err: + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + sk_DIST_POINT_pop_free(crld, DIST_POINT_free); + return NULL; +} + +int i2d_CRL_DIST_POINTS(STACK_OF(DIST_POINT) *a, unsigned char **pp) +{ + +return i2d_ASN1_SET_OF_DIST_POINT(a, pp, i2d_DIST_POINT, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE);} + +STACK_OF(DIST_POINT) *CRL_DIST_POINTS_new(void) +{ + return sk_DIST_POINT_new_null(); +} + +void CRL_DIST_POINTS_free(STACK_OF(DIST_POINT) *a) +{ + sk_DIST_POINT_pop_free(a, DIST_POINT_free); +} + +STACK_OF(DIST_POINT) *d2i_CRL_DIST_POINTS(STACK_OF(DIST_POINT) **a, + unsigned char **pp,long length) +{ +return d2i_ASN1_SET_OF_DIST_POINT(a, pp, length, d2i_DIST_POINT, + DIST_POINT_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); + +} + +IMPLEMENT_STACK_OF(DIST_POINT) +IMPLEMENT_ASN1_SET_OF(DIST_POINT) + +int i2d_DIST_POINT(DIST_POINT *a, unsigned char **pp) +{ + int v = 0; + M_ASN1_I2D_vars(a); + /* NB: underlying type is a CHOICE so need EXPLICIT tagging */ + M_ASN1_I2D_len_EXP_opt (a->distpoint, i2d_DIST_POINT_NAME, 0, v); + M_ASN1_I2D_len_IMP_opt (a->reasons, i2d_ASN1_BIT_STRING); + M_ASN1_I2D_len_IMP_opt (a->CRLissuer, i2d_GENERAL_NAMES); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put_EXP_opt (a->distpoint, i2d_DIST_POINT_NAME, 0, v); + M_ASN1_I2D_put_IMP_opt (a->reasons, i2d_ASN1_BIT_STRING, 1); + M_ASN1_I2D_put_IMP_opt (a->CRLissuer, i2d_GENERAL_NAMES, 2); + + M_ASN1_I2D_finish(); +} + +DIST_POINT *DIST_POINT_new(void) +{ + DIST_POINT *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, DIST_POINT); + ret->distpoint = NULL; + ret->reasons = NULL; + ret->CRLissuer = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_DIST_POINT_NEW); +} + +DIST_POINT *d2i_DIST_POINT(DIST_POINT **a, unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,DIST_POINT *,DIST_POINT_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get_EXP_opt (ret->distpoint, d2i_DIST_POINT_NAME, 0); + M_ASN1_D2I_get_IMP_opt (ret->reasons, d2i_ASN1_BIT_STRING, 1, + V_ASN1_BIT_STRING); + M_ASN1_D2I_get_IMP_opt (ret->CRLissuer, d2i_GENERAL_NAMES, 2, + V_ASN1_SEQUENCE); + M_ASN1_D2I_Finish(a, DIST_POINT_free, ASN1_F_D2I_DIST_POINT); +} + +void DIST_POINT_free(DIST_POINT *a) +{ + if (a == NULL) return; + DIST_POINT_NAME_free(a->distpoint); + ASN1_BIT_STRING_free(a->reasons); + sk_GENERAL_NAME_pop_free(a->CRLissuer, GENERAL_NAME_free); + Free ((char *)a); +} + +int i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **pp) +{ + int v = 0; + M_ASN1_I2D_vars(a); + + if(a->fullname) { + M_ASN1_I2D_len_IMP_opt (a->fullname, i2d_GENERAL_NAMES); + } else { + M_ASN1_I2D_len_EXP_opt (a->relativename, i2d_X509_NAME, 1, v); + } + + /* Don't want a SEQUENCE so... */ + if(pp == NULL) return ret; + p = *pp; + + if(a->fullname) { + M_ASN1_I2D_put_IMP_opt (a->fullname, i2d_GENERAL_NAMES, 0); + } else { + M_ASN1_I2D_put_EXP_opt (a->relativename, i2d_X509_NAME, 1, v); + } + M_ASN1_I2D_finish(); +} + +DIST_POINT_NAME *DIST_POINT_NAME_new(void) +{ + DIST_POINT_NAME *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, DIST_POINT_NAME); + ret->fullname = NULL; + ret->relativename = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_DIST_POINT_NAME_NEW); +} + +void DIST_POINT_NAME_free(DIST_POINT_NAME *a) +{ + if (a == NULL) return; + X509_NAME_free(a->relativename); + sk_GENERAL_NAME_pop_free(a->fullname, GENERAL_NAME_free); + Free ((char *)a); +} + +DIST_POINT_NAME *d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, unsigned char **pp, + long length) +{ + unsigned char _tmp, tag; + M_ASN1_D2I_vars(a,DIST_POINT_NAME *,DIST_POINT_NAME_new); + M_ASN1_D2I_Init(); + c.slen = length; + + _tmp = M_ASN1_next; + tag = _tmp & ~V_ASN1_CONSTRUCTED; + + if(tag == (0|V_ASN1_CONTEXT_SPECIFIC)) { + M_ASN1_D2I_get_imp(ret->fullname, d2i_GENERAL_NAMES, + V_ASN1_SEQUENCE); + } else if (tag == (1|V_ASN1_CONTEXT_SPECIFIC)) { + M_ASN1_D2I_get_EXP_opt (ret->relativename, d2i_X509_NAME, 1); + } else { + c.error = ASN1_R_BAD_TAG; + goto err; + } + + M_ASN1_D2I_Finish(a, DIST_POINT_NAME_free, ASN1_F_D2I_DIST_POINT_NAME); +} diff --git a/src/lib/libcrypto/x509v3/v3_enum.c b/src/lib/libcrypto/x509v3/v3_enum.c new file mode 100644 index 0000000000..db423548ff --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_enum.c @@ -0,0 +1,103 @@ +/* v3_enum.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 + +static ASN1_ENUMERATED *asn1_enumerated_new(void); + +static ENUMERATED_NAMES crl_reasons[] = { +{0, "Unspecified", "unspecified"}, +{1, "Key Compromise", "keyCompromise"}, +{2, "CA Compromise", "CACompromise"}, +{3, "Affiliation Changed", "affiliationChanged"}, +{4, "Superseded", "superseded"}, +{5, "Cessation Of Operation", "cessationOfOperation"}, +{6, "Certificate Hold", "certificateHold"}, +{8, "Remove From CRL", "removeFromCRL"}, +{-1, NULL, NULL} +}; + +X509V3_EXT_METHOD v3_crl_reason = { +NID_crl_reason, 0, +(X509V3_EXT_NEW)asn1_enumerated_new, +(X509V3_EXT_FREE)ASN1_STRING_free, +(X509V3_EXT_D2I)d2i_ASN1_ENUMERATED, +(X509V3_EXT_I2D)i2d_ASN1_ENUMERATED, +(X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE, +(X509V3_EXT_S2I)NULL, +NULL, NULL, NULL, NULL, crl_reasons}; + + +static ASN1_ENUMERATED *asn1_enumerated_new(void) +{ + return ASN1_ENUMERATED_new(); +} + +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, + ASN1_ENUMERATED *e) +{ + ENUMERATED_NAMES *enam; + long strval; + strval = ASN1_ENUMERATED_get(e); + for(enam = method->usr_data; enam->lname; enam++) { + if(strval == enam->bitnum) return BUF_strdup(enam->lname); + } + return i2s_ASN1_ENUMERATED(method, e); +} diff --git a/src/lib/libcrypto/x509v3/v3_extku.c b/src/lib/libcrypto/x509v3/v3_extku.c new file mode 100644 index 0000000000..e039d21cbf --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_extku.c @@ -0,0 +1,150 @@ +/* v3_extku.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 + +static STACK_OF(ASN1_OBJECT) *v2i_ext_ku(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_ext_ku(X509V3_EXT_METHOD *method, + STACK_OF(ASN1_OBJECT) *eku, STACK_OF(CONF_VALUE) *extlist); +X509V3_EXT_METHOD v3_ext_ku = { +NID_ext_key_usage, 0, +(X509V3_EXT_NEW)ext_ku_new, +(X509V3_EXT_FREE)ext_ku_free, +(X509V3_EXT_D2I)d2i_ext_ku, +(X509V3_EXT_I2D)i2d_ext_ku, +NULL, NULL, +(X509V3_EXT_I2V)i2v_ext_ku, +(X509V3_EXT_V2I)v2i_ext_ku, +NULL,NULL, +NULL +}; + +STACK_OF(ASN1_OBJECT) *ext_ku_new(void) +{ + return sk_ASN1_OBJECT_new_null(); +} + +void ext_ku_free(STACK_OF(ASN1_OBJECT) *eku) +{ + sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free); + return; +} + +int i2d_ext_ku(STACK_OF(ASN1_OBJECT) *a, unsigned char **pp) +{ + return i2d_ASN1_SET_OF_ASN1_OBJECT(a, pp, i2d_ASN1_OBJECT, + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, IS_SEQUENCE); +} + +STACK_OF(ASN1_OBJECT) *d2i_ext_ku(STACK_OF(ASN1_OBJECT) **a, + unsigned char **pp, long length) +{ + return d2i_ASN1_SET_OF_ASN1_OBJECT(a, pp, length, d2i_ASN1_OBJECT, + ASN1_OBJECT_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); +} + + + +static STACK_OF(CONF_VALUE) *i2v_ext_ku(X509V3_EXT_METHOD *method, + STACK_OF(ASN1_OBJECT) *eku, STACK_OF(CONF_VALUE) *ext_list) +{ +int i; +ASN1_OBJECT *obj; +char obj_tmp[80]; +for(i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + obj = sk_ASN1_OBJECT_value(eku, i); + i2t_ASN1_OBJECT(obj_tmp, 80, obj); + X509V3_add_value(NULL, obj_tmp, &ext_list); +} +return ext_list; +} + +static STACK_OF(ASN1_OBJECT) *v2i_ext_ku(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ +STACK_OF(ASN1_OBJECT) *extku; +char *extval; +ASN1_OBJECT *objtmp; +CONF_VALUE *val; +int i; + +if(!(extku = sk_ASN1_OBJECT_new(NULL))) { + X509V3err(X509V3_F_V2I_EXT_KU,ERR_R_MALLOC_FAILURE); + return NULL; +} + +for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if(val->value) extval = val->value; + else extval = val->name; + if(!(objtmp = OBJ_txt2obj(extval, 0))) { + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + X509V3err(X509V3_F_V2I_EXT_KU,X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + sk_ASN1_OBJECT_push(extku, objtmp); +} +return extku; +} diff --git a/src/lib/libcrypto/x509v3/v3_genn.c b/src/lib/libcrypto/x509v3/v3_genn.c new file mode 100644 index 0000000000..af716232f8 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_genn.c @@ -0,0 +1,237 @@ +/* v3_genn.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 +#include + +int i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **pp) +{ + unsigned char *p; + int ret; + + ret = 0; + + /* Save the location of initial TAG */ + if(pp) p = *pp; + else p = NULL; + + /* GEN_DNAME needs special treatment because of EXPLICIT tag */ + + if(a->type == GEN_DIRNAME) { + int v = 0; + M_ASN1_I2D_len_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v); + if(!p) return ret; + M_ASN1_I2D_put_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v); + *pp = p; + return ret; + } + + switch(a->type) { + + case GEN_OTHERNAME: + case GEN_X400: + case GEN_EDIPARTY: + ret = i2d_ASN1_TYPE(a->d.other, pp); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + ret = i2d_ASN1_IA5STRING(a->d.ia5, pp); + break; + + case GEN_IPADD: + ret = i2d_ASN1_OCTET_STRING(a->d.ip, pp); + break; + + case GEN_RID: + ret = i2d_ASN1_OBJECT(a->d.rid, pp); + break; + } + /* Replace TAG with IMPLICIT value */ + if(p) *p = (*p & V_ASN1_CONSTRUCTED) | a->type; + return ret; +} + +GENERAL_NAME *GENERAL_NAME_new() +{ + GENERAL_NAME *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, GENERAL_NAME); + ret->type = -1; + ret->d.ptr = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_GENERAL_NAME_NEW); +} + +GENERAL_NAME *d2i_GENERAL_NAME(GENERAL_NAME **a, unsigned char **pp, + long length) +{ + unsigned char _tmp; + M_ASN1_D2I_vars(a,GENERAL_NAME *,GENERAL_NAME_new); + M_ASN1_D2I_Init(); + c.slen = length; + + _tmp = M_ASN1_next; + ret->type = _tmp & ~V_ASN1_CONSTRUCTED; + + switch(ret->type) { + /* Just put these in a "blob" for now */ + case GEN_OTHERNAME: + case GEN_X400: + case GEN_EDIPARTY: + M_ASN1_D2I_get_imp(ret->d.other, d2i_ASN1_TYPE,V_ASN1_SEQUENCE); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + M_ASN1_D2I_get_imp(ret->d.ia5, d2i_ASN1_IA5STRING, + V_ASN1_IA5STRING); + break; + + case GEN_DIRNAME: + M_ASN1_D2I_get_EXP_opt(ret->d.dirn, d2i_X509_NAME, 4); + break; + + case GEN_IPADD: + M_ASN1_D2I_get_imp(ret->d.ip, d2i_ASN1_OCTET_STRING, + V_ASN1_OCTET_STRING); + break; + + case GEN_RID: + M_ASN1_D2I_get_imp(ret->d.rid, d2i_ASN1_OBJECT,V_ASN1_OBJECT); + break; + + default: + c.error = ASN1_R_BAD_TAG; + goto err; + } + + c.slen = 0; + M_ASN1_D2I_Finish(a, GENERAL_NAME_free, ASN1_F_D2I_GENERAL_NAME); +} + +void GENERAL_NAME_free(GENERAL_NAME *a) +{ + if (a == NULL) return; + switch(a->type) { + case GEN_OTHERNAME: + case GEN_X400: + case GEN_EDIPARTY: + ASN1_TYPE_free(a->d.other); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + + ASN1_IA5STRING_free(a->d.ia5); + break; + + case GEN_DIRNAME: + X509_NAME_free(a->d.dirn); + break; + + case GEN_IPADD: + ASN1_OCTET_STRING_free(a->d.ip); + break; + + case GEN_RID: + ASN1_OBJECT_free(a->d.rid); + break; + + } + Free ((char *)a); +} + +/* Now the GeneralNames versions: a SEQUENCE OF GeneralName These are needed as + * an explicit functions. + */ + +STACK_OF(GENERAL_NAME) *GENERAL_NAMES_new() +{ + return sk_GENERAL_NAME_new(NULL); +} + +void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *a) +{ + sk_GENERAL_NAME_pop_free(a, GENERAL_NAME_free); +} + +STACK_OF(GENERAL_NAME) *d2i_GENERAL_NAMES(STACK_OF(GENERAL_NAME) **a, + unsigned char **pp, long length) +{ +return d2i_ASN1_SET_OF_GENERAL_NAME(a, pp, length, d2i_GENERAL_NAME, + GENERAL_NAME_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); +} + +int i2d_GENERAL_NAMES(STACK_OF(GENERAL_NAME) *a, unsigned char **pp) +{ +return i2d_ASN1_SET_OF_GENERAL_NAME(a, pp, i2d_GENERAL_NAME, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); +} + +IMPLEMENT_STACK_OF(GENERAL_NAME) +IMPLEMENT_ASN1_SET_OF(GENERAL_NAME) + diff --git a/src/lib/libcrypto/x509v3/v3_ia5.c b/src/lib/libcrypto/x509v3/v3_ia5.c new file mode 100644 index 0000000000..3446c5cd6a --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_ia5.c @@ -0,0 +1,116 @@ +/* v3_ia5.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 + +static ASN1_IA5STRING *ia5string_new(void); +static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5); +static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); +X509V3_EXT_METHOD v3_ns_ia5_list[] = { +EXT_IA5STRING(NID_netscape_base_url), +EXT_IA5STRING(NID_netscape_revocation_url), +EXT_IA5STRING(NID_netscape_ca_revocation_url), +EXT_IA5STRING(NID_netscape_renewal_url), +EXT_IA5STRING(NID_netscape_ca_policy_url), +EXT_IA5STRING(NID_netscape_ssl_server_name), +EXT_IA5STRING(NID_netscape_comment), +EXT_END +}; + + +static ASN1_IA5STRING *ia5string_new(void) +{ + return ASN1_IA5STRING_new(); +} + +static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + ASN1_IA5STRING *ia5) +{ + char *tmp; + if(!ia5 || !ia5->length) return NULL; + tmp = Malloc(ia5->length + 1); + memcpy(tmp, ia5->data, ia5->length); + tmp[ia5->length] = 0; + return tmp; +} + +static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_IA5STRING *ia5; + if(!str) { + X509V3err(X509V3_F_S2I_ASN1_IA5STRING,X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if(!(ia5 = ASN1_IA5STRING_new())) goto err; + if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str, + strlen(str))) { + ASN1_IA5STRING_free(ia5); + goto err; + } + return ia5; + err: + X509V3err(X509V3_F_S2I_ASN1_IA5STRING,ERR_R_MALLOC_FAILURE); + return NULL; +} + diff --git a/src/lib/libcrypto/x509v3/v3_info.c b/src/lib/libcrypto/x509v3/v3_info.c new file mode 100644 index 0000000000..78d2135046 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_info.c @@ -0,0 +1,236 @@ +/* v3_info.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 +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, + STACK_OF(ACCESS_DESCRIPTION) *ainfo, + STACK_OF(CONF_VALUE) *ret); +static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +X509V3_EXT_METHOD v3_info = +{ NID_info_access, X509V3_EXT_MULTILINE, +(X509V3_EXT_NEW)AUTHORITY_INFO_ACCESS_new, +(X509V3_EXT_FREE)AUTHORITY_INFO_ACCESS_free, +(X509V3_EXT_D2I)d2i_AUTHORITY_INFO_ACCESS, +(X509V3_EXT_I2D)i2d_AUTHORITY_INFO_ACCESS, +NULL, NULL, +(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS, +(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, +NULL, NULL, NULL}; + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, + STACK_OF(ACCESS_DESCRIPTION) *ainfo, + STACK_OF(CONF_VALUE) *ret) +{ + ACCESS_DESCRIPTION *desc; + int i; + char objtmp[80], *ntmp; + CONF_VALUE *vtmp; + for(i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) { + desc = sk_ACCESS_DESCRIPTION_value(ainfo, i); + ret = i2v_GENERAL_NAME(method, desc->location, ret); + if(!ret) break; + vtmp = sk_CONF_VALUE_value(ret, i); + i2t_ASN1_OBJECT(objtmp, 80, desc->method); + ntmp = Malloc(strlen(objtmp) + strlen(vtmp->name) + 5); + if(!ntmp) { + X509V3err(X509V3_F_I2V_AUTHORITY_INFO_ACCESS, + ERR_R_MALLOC_FAILURE); + return NULL; + } + strcpy(ntmp, objtmp); + strcat(ntmp, " - "); + strcat(ntmp, vtmp->name); + Free(vtmp->name); + vtmp->name = ntmp; + + } + if(!ret) return sk_CONF_VALUE_new_null(); + return ret; +} + +static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(ACCESS_DESCRIPTION) *ainfo = NULL; + CONF_VALUE *cnf, ctmp; + ACCESS_DESCRIPTION *acc; + int i, objlen; + char *objtmp, *ptmp; + if(!(ainfo = sk_ACCESS_DESCRIPTION_new(NULL))) { + X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,ERR_R_MALLOC_FAILURE); + return NULL; + } + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if(!(acc = ACCESS_DESCRIPTION_new()) + || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) { + X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,ERR_R_MALLOC_FAILURE); + goto err; + } + ptmp = strchr(cnf->name, ';'); + if(!ptmp) { + X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,X509V3_R_INVALID_SYNTAX); + goto err; + } + objlen = ptmp - cnf->name; + ctmp.name = ptmp + 1; + ctmp.value = cnf->value; + if(!(acc->location = v2i_GENERAL_NAME(method, ctx, &ctmp))) + goto err; + if(!(objtmp = Malloc(objlen + 1))) { + X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,ERR_R_MALLOC_FAILURE); + goto err; + } + strncpy(objtmp, cnf->name, objlen); + objtmp[objlen] = 0; + acc->method = OBJ_txt2obj(objtmp, 0); + if(!acc->method) { + X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", objtmp); + Free(objtmp); + goto err; + } + Free(objtmp); + + } + return ainfo; + err: + sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free); + return NULL; +} + +int i2d_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len(a->method, i2d_ASN1_OBJECT); + M_ASN1_I2D_len(a->location, i2d_GENERAL_NAME); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put(a->method, i2d_ASN1_OBJECT); + M_ASN1_I2D_put(a->location, i2d_GENERAL_NAME); + + M_ASN1_I2D_finish(); +} + +ACCESS_DESCRIPTION *ACCESS_DESCRIPTION_new(void) +{ + ACCESS_DESCRIPTION *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, ACCESS_DESCRIPTION); + ret->method = OBJ_nid2obj(NID_undef); + ret->location = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_ACCESS_DESCRIPTION_NEW); +} + +ACCESS_DESCRIPTION *d2i_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION **a, unsigned char **pp, + long length) +{ + M_ASN1_D2I_vars(a,ACCESS_DESCRIPTION *,ACCESS_DESCRIPTION_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get(ret->method, d2i_ASN1_OBJECT); + M_ASN1_D2I_get(ret->location, d2i_GENERAL_NAME); + M_ASN1_D2I_Finish(a, ACCESS_DESCRIPTION_free, ASN1_F_D2I_ACCESS_DESCRIPTION); +} + +void ACCESS_DESCRIPTION_free(ACCESS_DESCRIPTION *a) +{ + if (a == NULL) return; + ASN1_OBJECT_free(a->method); + GENERAL_NAME_free(a->location); + Free (a); +} + +STACK_OF(ACCESS_DESCRIPTION) *AUTHORITY_INFO_ACCESS_new(void) +{ + return sk_ACCESS_DESCRIPTION_new(NULL); +} + +void AUTHORITY_INFO_ACCESS_free(STACK_OF(ACCESS_DESCRIPTION) *a) +{ + sk_ACCESS_DESCRIPTION_pop_free(a, ACCESS_DESCRIPTION_free); +} + +STACK_OF(ACCESS_DESCRIPTION) *d2i_AUTHORITY_INFO_ACCESS(STACK_OF(ACCESS_DESCRIPTION) **a, + unsigned char **pp, long length) +{ +return d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(a, pp, length, d2i_ACCESS_DESCRIPTION, + ACCESS_DESCRIPTION_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); +} + +int i2d_AUTHORITY_INFO_ACCESS(STACK_OF(ACCESS_DESCRIPTION) *a, unsigned char **pp) +{ +return i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(a, pp, i2d_ACCESS_DESCRIPTION, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); +} + +IMPLEMENT_STACK_OF(ACCESS_DESCRIPTION) +IMPLEMENT_ASN1_SET_OF(ACCESS_DESCRIPTION) + + diff --git a/src/lib/libcrypto/x509v3/v3_int.c b/src/lib/libcrypto/x509v3/v3_int.c new file mode 100644 index 0000000000..637dd5e128 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_int.c @@ -0,0 +1,79 @@ +/* v3_int.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 + +static ASN1_INTEGER *asn1_integer_new(void); + +X509V3_EXT_METHOD v3_crl_num = { +NID_crl_number, 0, +(X509V3_EXT_NEW)asn1_integer_new, +(X509V3_EXT_FREE)ASN1_STRING_free, +(X509V3_EXT_D2I)d2i_ASN1_INTEGER, +(X509V3_EXT_I2D)i2d_ASN1_INTEGER, +(X509V3_EXT_I2S)i2s_ASN1_INTEGER, +(X509V3_EXT_S2I)NULL, +NULL, NULL, NULL, NULL, NULL}; + + +static ASN1_INTEGER *asn1_integer_new(void) +{ + return ASN1_INTEGER_new(); +} diff --git a/src/lib/libcrypto/x509v3/v3_lib.c b/src/lib/libcrypto/x509v3/v3_lib.c new file mode 100644 index 0000000000..a0aa5de794 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_lib.c @@ -0,0 +1,177 @@ +/* v3_lib.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). + * + */ +/* X509 v3 extension utilities */ + +#include +#include "cryptlib.h" +#include +#include + +static STACK *ext_list = NULL; + +static int ext_cmp(X509V3_EXT_METHOD **a, X509V3_EXT_METHOD **b); +static void ext_list_free(X509V3_EXT_METHOD *ext); + +int X509V3_EXT_add(X509V3_EXT_METHOD *ext) +{ + if(!ext_list && !(ext_list = sk_new(ext_cmp))) { + X509V3err(X509V3_F_X509V3_EXT_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + if(!sk_push(ext_list, (char *)ext)) { + X509V3err(X509V3_F_X509V3_EXT_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +static int ext_cmp(X509V3_EXT_METHOD **a, X509V3_EXT_METHOD **b) +{ + return ((*a)->ext_nid - (*b)->ext_nid); +} + +X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) +{ + X509V3_EXT_METHOD tmp; + int idx; + tmp.ext_nid = nid; + if(!ext_list || (tmp.ext_nid < 0) ) return NULL; + idx = sk_find(ext_list, (char *)&tmp); + if(idx == -1) return NULL; + return (X509V3_EXT_METHOD *)sk_value(ext_list, idx); +} + +X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext) +{ + int nid; + if((nid = OBJ_obj2nid(ext->object)) == NID_undef) return NULL; + return X509V3_EXT_get_nid(nid); +} + + +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) +{ + for(;extlist->ext_nid!=-1;extlist++) + if(!X509V3_EXT_add(extlist)) return 0; + return 1; +} + +int X509V3_EXT_add_alias(int nid_to, int nid_from) +{ + X509V3_EXT_METHOD *ext, *tmpext; + if(!(ext = X509V3_EXT_get_nid(nid_from))) { + X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,X509V3_R_EXTENSION_NOT_FOUND); + return 0; + } + if(!(tmpext = (X509V3_EXT_METHOD *)Malloc(sizeof(X509V3_EXT_METHOD)))) { + X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,ERR_R_MALLOC_FAILURE); + return 0; + } + *tmpext = *ext; + tmpext->ext_nid = nid_to; + tmpext->ext_flags |= X509V3_EXT_DYNAMIC; + return 1; +} + +void X509V3_EXT_cleanup(void) +{ + sk_pop_free(ext_list, ext_list_free); + ext_list = NULL; +} + +static void ext_list_free(X509V3_EXT_METHOD *ext) +{ + if(ext->ext_flags & X509V3_EXT_DYNAMIC) Free(ext); +} + +extern X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; +extern X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet; +extern X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id; + +extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_cpols, v3_crld; + +int X509V3_add_standard_extensions(void) +{ + X509V3_EXT_add_list(v3_ns_ia5_list); + X509V3_EXT_add_list(v3_alt); + X509V3_EXT_add(&v3_bcons); + X509V3_EXT_add(&v3_nscert); + X509V3_EXT_add(&v3_key_usage); + X509V3_EXT_add(&v3_ext_ku); + X509V3_EXT_add(&v3_skey_id); + X509V3_EXT_add(&v3_akey_id); + X509V3_EXT_add(&v3_pkey_usage_period); + X509V3_EXT_add(&v3_crl_num); + X509V3_EXT_add(&v3_sxnet); + X509V3_EXT_add(&v3_crl_reason); + X509V3_EXT_add(&v3_cpols); + X509V3_EXT_add(&v3_crld); + return 1; +} + +/* Return an extension internal structure */ + +void *X509V3_EXT_d2i(X509_EXTENSION *ext) +{ + X509V3_EXT_METHOD *method; + unsigned char *p; + if(!(method = X509V3_EXT_get(ext)) || !method->d2i) return NULL; + p = ext->value->data; + return method->d2i(NULL, &p, ext->value->length); +} + diff --git a/src/lib/libcrypto/x509v3/v3_ocsp.c b/src/lib/libcrypto/x509v3/v3_ocsp.c new file mode 100644 index 0000000000..083112314e --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_ocsp.c @@ -0,0 +1,272 @@ +/* v3_ocsp.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 +#include + +/* OCSP extensions and a couple of CRL entry extensions + */ + +static int i2r_ocsp_crlid(X509V3_EXT_METHOD *method, void *nonce, BIO *out, int indent); +static int i2r_ocsp_acutoff(X509V3_EXT_METHOD *method, void *nonce, BIO *out, int indent); +static int i2r_object(X509V3_EXT_METHOD *method, void *obj, BIO *out, int indent); + +static void *ocsp_nonce_new(void); +static int i2d_ocsp_nonce(void *a, unsigned char **pp); +static void *d2i_ocsp_nonce(void *a, unsigned char **pp, long length); +static void ocsp_nonce_free(void *a); +static int i2r_ocsp_nonce(X509V3_EXT_METHOD *method, void *nonce, BIO *out, int indent); + +static int i2r_ocsp_nocheck(X509V3_EXT_METHOD *method, void *nocheck, BIO *out, int indent); +static void *s2i_ocsp_nocheck(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); +static int i2r_ocsp_serviceloc(X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind); + +X509V3_EXT_METHOD v3_ocsp_crlid = { + NID_id_pkix_OCSP_CrlID, 0, ASN1_ITEM_ref(OCSP_CRLID), + 0,0,0,0, + 0,0, + 0,0, + i2r_ocsp_crlid,0, + NULL +}; + +X509V3_EXT_METHOD v3_ocsp_acutoff = { + NID_id_pkix_OCSP_archiveCutoff, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + 0,0,0,0, + 0,0, + 0,0, + i2r_ocsp_acutoff,0, + NULL +}; + +X509V3_EXT_METHOD v3_crl_invdate = { + NID_invalidity_date, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME), + 0,0,0,0, + 0,0, + 0,0, + i2r_ocsp_acutoff,0, + NULL +}; + +X509V3_EXT_METHOD v3_crl_hold = { + NID_hold_instruction_code, 0, ASN1_ITEM_ref(ASN1_OBJECT), + 0,0,0,0, + 0,0, + 0,0, + i2r_object,0, + NULL +}; + +X509V3_EXT_METHOD v3_ocsp_nonce = { + NID_id_pkix_OCSP_Nonce, 0, NULL, + ocsp_nonce_new, + ocsp_nonce_free, + d2i_ocsp_nonce, + i2d_ocsp_nonce, + 0,0, + 0,0, + i2r_ocsp_nonce,0, + NULL +}; + +X509V3_EXT_METHOD v3_ocsp_nocheck = { + NID_id_pkix_OCSP_noCheck, 0, ASN1_ITEM_ref(ASN1_NULL), + 0,0,0,0, + 0,s2i_ocsp_nocheck, + 0,0, + i2r_ocsp_nocheck,0, + NULL +}; + +X509V3_EXT_METHOD v3_ocsp_serviceloc = { + NID_id_pkix_OCSP_serviceLocator, 0, ASN1_ITEM_ref(OCSP_SERVICELOC), + 0,0,0,0, + 0,0, + 0,0, + i2r_ocsp_serviceloc,0, + NULL +}; + +static int i2r_ocsp_crlid(X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) +{ + OCSP_CRLID *a = in; + if (a->crlUrl) + { + if (!BIO_printf(bp, "%*scrlUrl: ", ind, "")) goto err; + if (!ASN1_STRING_print(bp, (ASN1_STRING*)a->crlUrl)) goto err; + if (!BIO_write(bp, "\n", 1)) goto err; + } + if (a->crlNum) + { + if (!BIO_printf(bp, "%*scrlNum: ", ind, "")) goto err; + if (!i2a_ASN1_INTEGER(bp, a->crlNum)) goto err; + if (!BIO_write(bp, "\n", 1)) goto err; + } + if (a->crlTime) + { + if (!BIO_printf(bp, "%*scrlTime: ", ind, "")) goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) goto err; + if (!BIO_write(bp, "\n", 1)) goto err; + } + return 1; + err: + return 0; +} + +static int i2r_ocsp_acutoff(X509V3_EXT_METHOD *method, void *cutoff, BIO *bp, int ind) +{ + if (!BIO_printf(bp, "%*s", ind, "")) return 0; + if(!ASN1_GENERALIZEDTIME_print(bp, cutoff)) return 0; + return 1; +} + + +static int i2r_object(X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind) +{ + if (!BIO_printf(bp, "%*s", ind, "")) return 0; + if(!i2a_ASN1_OBJECT(bp, oid)) return 0; + return 1; +} + +/* OCSP nonce. This is needs special treatment because it doesn't have + * an ASN1 encoding at all: it just contains arbitrary data. + */ + +static void *ocsp_nonce_new(void) +{ + return ASN1_OCTET_STRING_new(); +} + +static int i2d_ocsp_nonce(void *a, unsigned char **pp) +{ + ASN1_OCTET_STRING *os = a; + if(pp) { + memcpy(*pp, os->data, os->length); + *pp += os->length; + } + return os->length; +} + +static void *d2i_ocsp_nonce(void *a, unsigned char **pp, long length) +{ + ASN1_OCTET_STRING *os, **pos; + pos = a; + if(!pos || !*pos) os = ASN1_OCTET_STRING_new(); + else os = *pos; + if(!ASN1_OCTET_STRING_set(os, *pp, length)) goto err; + + *pp += length; + + if(pos) *pos = os; + return os; + + err: + if(os && (!pos || (*pos != os))) M_ASN1_OCTET_STRING_free(os); + OCSPerr(OCSP_F_D2I_OCSP_NONCE, ERR_R_MALLOC_FAILURE); + return NULL; +} + +static void ocsp_nonce_free(void *a) +{ + M_ASN1_OCTET_STRING_free(a); +} + +static int i2r_ocsp_nonce(X509V3_EXT_METHOD *method, void *nonce, BIO *out, int indent) +{ + if(BIO_printf(out, "%*s", indent, "") <= 0) return 0; + if(i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) return 0; + return 1; +} + +/* Nocheck is just a single NULL. Don't print anything and always set it */ + +static int i2r_ocsp_nocheck(X509V3_EXT_METHOD *method, void *nocheck, BIO *out, int indent) +{ + return 1; +} + +static void *s2i_ocsp_nocheck(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) +{ + return ASN1_NULL_new(); +} + +static int i2r_ocsp_serviceloc(X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) + { + int i; + OCSP_SERVICELOC *a = in; + ACCESS_DESCRIPTION *ad; + + if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) goto err; + if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) goto err; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) + { + ad = sk_ACCESS_DESCRIPTION_value(a->locator,i); + if (BIO_printf(bp, "\n%*s", (2*ind), "") <= 0) + goto err; + if(i2a_ASN1_OBJECT(bp, ad->method) <= 0) goto err; + if(BIO_puts(bp, " - ") <= 0) goto err; + if(GENERAL_NAME_print(bp, ad->location) <= 0) goto err; + } + return 1; +err: + return 0; + } diff --git a/src/lib/libcrypto/x509v3/v3_pku.c b/src/lib/libcrypto/x509v3/v3_pku.c new file mode 100644 index 0000000000..c13e7d8f45 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_pku.c @@ -0,0 +1,151 @@ +/* v3_pku.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 + +static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, BIO *out, int indent); +/* +static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); +*/ +X509V3_EXT_METHOD v3_pkey_usage_period = { +NID_private_key_usage_period, 0, +(X509V3_EXT_NEW)PKEY_USAGE_PERIOD_new, +(X509V3_EXT_FREE)PKEY_USAGE_PERIOD_free, +(X509V3_EXT_D2I)d2i_PKEY_USAGE_PERIOD, +(X509V3_EXT_I2D)i2d_PKEY_USAGE_PERIOD, +NULL, NULL, NULL, NULL, +(X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL, +NULL +}; + +int i2d_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len_IMP_opt (a->notBefore, i2d_ASN1_GENERALIZEDTIME); + M_ASN1_I2D_len_IMP_opt (a->notAfter, i2d_ASN1_GENERALIZEDTIME); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put_IMP_opt (a->notBefore, i2d_ASN1_GENERALIZEDTIME, 0); + M_ASN1_I2D_put_IMP_opt (a->notAfter, i2d_ASN1_GENERALIZEDTIME, 1); + + M_ASN1_I2D_finish(); +} + +PKEY_USAGE_PERIOD *PKEY_USAGE_PERIOD_new(void) +{ + PKEY_USAGE_PERIOD *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, PKEY_USAGE_PERIOD); + ret->notBefore = NULL; + ret->notAfter = NULL; + return (ret); + M_ASN1_New_Error(ASN1_F_PKEY_USAGE_PERIOD_NEW); +} + +PKEY_USAGE_PERIOD *d2i_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD **a, + unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,PKEY_USAGE_PERIOD *,PKEY_USAGE_PERIOD_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get_IMP_opt (ret->notBefore, d2i_ASN1_GENERALIZEDTIME, 0, + V_ASN1_GENERALIZEDTIME); + M_ASN1_D2I_get_IMP_opt (ret->notAfter, d2i_ASN1_GENERALIZEDTIME, 1, + V_ASN1_GENERALIZEDTIME); + M_ASN1_D2I_Finish(a, PKEY_USAGE_PERIOD_free, ASN1_F_D2I_PKEY_USAGE_PERIOD); +} + +void PKEY_USAGE_PERIOD_free(PKEY_USAGE_PERIOD *a) +{ + if (a == NULL) return; + ASN1_GENERALIZEDTIME_free(a->notBefore); + ASN1_GENERALIZEDTIME_free(a->notAfter); + Free ((char *)a); +} + +static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, + PKEY_USAGE_PERIOD *usage, BIO *out, int indent) +{ + BIO_printf(out, "%*s", indent, ""); + if(usage->notBefore) { + BIO_write(out, "Not Before: ", 12); + ASN1_GENERALIZEDTIME_print(out, usage->notBefore); + if(usage->notAfter) BIO_write(out, ", ", 2); + } + if(usage->notAfter) { + BIO_write(out, "Not After: ", 11); + ASN1_GENERALIZEDTIME_print(out, usage->notAfter); + } + return 1; +} + +/* +static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values) +X509V3_EXT_METHOD *method; +X509V3_CTX *ctx; +STACK_OF(CONF_VALUE) *values; +{ +return NULL; +} +*/ diff --git a/src/lib/libcrypto/x509v3/v3_prn.c b/src/lib/libcrypto/x509v3/v3_prn.c new file mode 100644 index 0000000000..dc20c6bdba --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_prn.c @@ -0,0 +1,135 @@ +/* v3_prn.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). + * + */ +/* X509 v3 extension utilities */ + +#include +#include "cryptlib.h" +#include +#include + +/* Extension printing routines */ + +/* Print out a name+value stack */ + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml) +{ + int i; + CONF_VALUE *nval; + if(!val) return; + if(!ml || !sk_CONF_VALUE_num(val)) { + BIO_printf(out, "%*s", indent, ""); + if(!sk_CONF_VALUE_num(val)) BIO_puts(out, "\n"); + } + for(i = 0; i < sk_CONF_VALUE_num(val); i++) { + if(ml) BIO_printf(out, "%*s", indent, ""); + else if(i > 0) BIO_printf(out, ", "); + nval = sk_CONF_VALUE_value(val, i); + if(!nval->name) BIO_puts(out, nval->value); + else if(!nval->value) BIO_puts(out, nval->name); + else BIO_printf(out, "%s:%s", nval->name, nval->value); + if(ml) BIO_puts(out, "\n"); + } +} + +/* Main routine: print out a general extension */ + +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, int flag, int indent) +{ + char *ext_str = NULL, *value = NULL; + unsigned char *p; + X509V3_EXT_METHOD *method; + STACK_OF(CONF_VALUE) *nval = NULL; + int ok = 1; + if(!(method = X509V3_EXT_get(ext))) return 0; + p = ext->value->data; + if(!(ext_str = method->d2i(NULL, &p, ext->value->length))) return 0; + if(method->i2s) { + if(!(value = method->i2s(method, ext_str))) { + ok = 0; + goto err; + } + BIO_printf(out, "%*s%s", indent, "", value); + } else if(method->i2v) { + if(!(nval = method->i2v(method, ext_str, NULL))) { + ok = 0; + goto err; + } + X509V3_EXT_val_prn(out, nval, indent, + method->ext_flags & X509V3_EXT_MULTILINE); + } else if(method->i2r) { + if(!method->i2r(method, ext_str, out, indent)) ok = 0; + } else ok = 0; + + err: + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + if(value) Free(value); + method->ext_free(ext_str); + return ok; +} + +#ifndef NO_FP_API +int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) +{ + BIO *bio_tmp; + int ret; + if(!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) return 0; + ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); + BIO_free(bio_tmp); + return ret; +} +#endif diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c new file mode 100644 index 0000000000..b7494ebcd5 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_purp.c @@ -0,0 +1,456 @@ +/* v3_purp.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 + + +static void x509v3_cache_extensions(X509 *x); + +static int ca_check(X509 *x); +static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca); +static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); +static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); +static int purpose_smime(X509 *x, int ca); +static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca); +static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca); +static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca); + +static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b); +static void xptable_free(X509_PURPOSE *p); + +static X509_PURPOSE xstandard[] = { + {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, "SSL client", "sslclient", NULL}, + {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, "SSL server", "sslserver", NULL}, + {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, + {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL}, + {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, + {X509_PURPOSE_CRL_SIGN, X509_TRUST_ANY, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL}, +}; + +#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) + +IMPLEMENT_STACK_OF(X509_PURPOSE) + +static STACK_OF(X509_PURPOSE) *xptable = NULL; + +static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b) +{ + return (*a)->purpose - (*b)->purpose; +} + +int X509_check_purpose(X509 *x, int id, int ca) +{ + int idx; + X509_PURPOSE *pt; + if(!(x->ex_flags & EXFLAG_SET)) { + CRYPTO_w_lock(CRYPTO_LOCK_X509); + x509v3_cache_extensions(x); + CRYPTO_w_unlock(CRYPTO_LOCK_X509); + } + if(id == -1) return 1; + idx = X509_PURPOSE_get_by_id(id); + if(idx == -1) return -1; + pt = X509_PURPOSE_get0(idx); + return pt->check_purpose(pt, x, ca); +} + +int X509_PURPOSE_get_count(void) +{ + if(!xptable) return X509_PURPOSE_COUNT; + return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; +} + +X509_PURPOSE * X509_PURPOSE_get0(int idx) +{ + if(idx < 0) return NULL; + if(idx < X509_PURPOSE_COUNT) return xstandard + idx; + return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); +} + +int X509_PURPOSE_get_by_sname(char *sname) +{ + int i; + X509_PURPOSE *xptmp; + for(i = 0; i < X509_PURPOSE_get_count(); i++) { + xptmp = X509_PURPOSE_get0(i); + if(!strcmp(xptmp->sname, sname)) return i; + } + return -1; +} + + +int X509_PURPOSE_get_by_id(int purpose) +{ + X509_PURPOSE tmp; + int idx; + if((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) + return purpose - X509_PURPOSE_MIN; + tmp.purpose = purpose; + if(!xptable) return -1; + idx = sk_X509_PURPOSE_find(xptable, &tmp); + if(idx == -1) return -1; + return idx + X509_PURPOSE_COUNT; +} + +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck)(X509_PURPOSE *, X509 *, int), + char *name, char *sname, void *arg) +{ + int idx; + X509_PURPOSE *ptmp; + /* This is set according to what we change: application can't set it */ + flags &= ~X509_PURPOSE_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_PURPOSE_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_PURPOSE_get_by_id(id); + /* Need a new entry */ + if(idx == -1) { + if(!(ptmp = Malloc(sizeof(X509_PURPOSE)))) { + X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + ptmp->flags = X509_PURPOSE_DYNAMIC; + } else ptmp = X509_PURPOSE_get0(idx); + + /* Free existing name if dynamic */ + if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { + Free(ptmp->name); + Free(ptmp->sname); + } + /* dup supplied name */ + ptmp->name = BUF_strdup(name); + ptmp->sname = BUF_strdup(sname); + if(!ptmp->name || !ptmp->sname) { + X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + /* Keep the dynamic flag of existing entry */ + ptmp->flags &= X509_PURPOSE_DYNAMIC; + /* Set all other flags */ + ptmp->flags |= flags; + + ptmp->purpose = id; + ptmp->trust = trust; + ptmp->check_purpose = ck; + ptmp->usr_data = arg; + + /* If its a new entry manage the dynamic table */ + if(idx == -1) { + if(!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) { + X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + if (!sk_X509_PURPOSE_push(xptable, ptmp)) { + X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); + return 0; + } + } + return 1; +} + +static void xptable_free(X509_PURPOSE *p) + { + if(!p) return; + if (p->flags & X509_PURPOSE_DYNAMIC) + { + if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + Free(p->name); + Free(p->sname); + } + Free(p); + } + } + +void X509_PURPOSE_cleanup(void) +{ + int i; + sk_X509_PURPOSE_pop_free(xptable, xptable_free); + for(i = 0; i < X509_PURPOSE_COUNT; i++) xptable_free(xstandard + i); + xptable = NULL; +} + +int X509_PURPOSE_get_id(X509_PURPOSE *xp) +{ + return xp->purpose; +} + +char *X509_PURPOSE_get0_name(X509_PURPOSE *xp) +{ + return xp->name; +} + +char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp) +{ + return xp->sname; +} + +int X509_PURPOSE_get_trust(X509_PURPOSE *xp) +{ + return xp->trust; +} + +#ifndef NO_SHA +static void x509v3_cache_extensions(X509 *x) +{ + BASIC_CONSTRAINTS *bs; + ASN1_BIT_STRING *usage; + ASN1_BIT_STRING *ns; + STACK_OF(ASN1_OBJECT) *extusage; + int i; + if(x->ex_flags & EXFLAG_SET) return; + X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); + /* Does subject name match issuer ? */ + if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) + x->ex_flags |= EXFLAG_SS; + /* V1 should mean no extensions ... */ + if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1; + /* Handle basic constraints */ + if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { + if(bs->ca) x->ex_flags |= EXFLAG_CA; + if(bs->pathlen) { + if((bs->pathlen->type == V_ASN1_NEG_INTEGER) + || !bs->ca) { + x->ex_flags |= EXFLAG_INVALID; + x->ex_pathlen = 0; + } else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); + } else x->ex_pathlen = -1; + BASIC_CONSTRAINTS_free(bs); + x->ex_flags |= EXFLAG_BCONS; + } + /* Handle key usage */ + if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { + if(usage->length > 0) { + x->ex_kusage = usage->data[0]; + if(usage->length > 1) + x->ex_kusage |= usage->data[1] << 8; + } else x->ex_kusage = 0; + x->ex_flags |= EXFLAG_KUSAGE; + ASN1_BIT_STRING_free(usage); + } + x->ex_xkusage = 0; + if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { + x->ex_flags |= EXFLAG_XKUSAGE; + for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { + switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) { + case NID_server_auth: + x->ex_xkusage |= XKU_SSL_SERVER; + break; + + case NID_client_auth: + x->ex_xkusage |= XKU_SSL_CLIENT; + break; + + case NID_email_protect: + x->ex_xkusage |= XKU_SMIME; + break; + + case NID_code_sign: + x->ex_xkusage |= XKU_CODE_SIGN; + break; + + case NID_ms_sgc: + case NID_ns_sgc: + x->ex_xkusage |= XKU_SGC; + } + } + sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + } + + if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { + if(ns->length > 0) x->ex_nscert = ns->data[0]; + else x->ex_nscert = 0; + x->ex_flags |= EXFLAG_NSCERT; + ASN1_BIT_STRING_free(ns); + } + x->ex_flags |= EXFLAG_SET; +} +#endif + +/* CA checks common to all purposes + * return codes: + * 0 not a CA + * 1 is a CA + * 2 basicConstraints absent so "maybe" a CA + * 3 basicConstraints absent but self signed V1. + */ + +#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define ku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) +#define xku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) +#define ns_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) + +static int ca_check(X509 *x) +{ + /* keyUsage if present should allow cert signing */ + if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; + if(x->ex_flags & EXFLAG_BCONS) { + if(x->ex_flags & EXFLAG_CA) return 1; + /* If basicConstraints says not a CA then say so */ + else return 0; + } else { + if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3; + else return 2; + } +} + + +static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca) +{ + if(xku_reject(x,XKU_SSL_CLIENT)) return 0; + if(ca) { + int ca_ret; + ca_ret = ca_check(x); + if(!ca_ret) return 0; + /* check nsCertType if present */ + if(x->ex_flags & EXFLAG_NSCERT) { + if(x->ex_nscert & NS_SSL_CA) return ca_ret; + return 0; + } + if(ca_ret != 2) return ca_ret; + else return 0; + } + /* We need to do digital signatures with it */ + if(ku_reject(x,KU_DIGITAL_SIGNATURE)) return 0; + /* nsCertType if present should allow SSL client use */ + if(ns_reject(x, NS_SSL_CLIENT)) return 0; + return 1; +} + +static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) +{ + if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0; + /* Otherwise same as SSL client for a CA */ + if(ca) return check_purpose_ssl_client(xp, x, 1); + + if(ns_reject(x, NS_SSL_SERVER)) return 0; + /* Now as for keyUsage: we'll at least need to sign OR encipher */ + if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT)) return 0; + + return 1; + +} + +static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) +{ + int ret; + ret = check_purpose_ssl_server(xp, x, ca); + if(!ret || ca) return ret; + /* We need to encipher or Netscape complains */ + if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0; + return ret; +} + +/* common S/MIME checks */ +static int purpose_smime(X509 *x, int ca) +{ + if(xku_reject(x,XKU_SMIME)) return 0; + if(ca) { + int ca_ret; + ca_ret = ca_check(x); + if(!ca_ret) return 0; + /* check nsCertType if present */ + if(x->ex_flags & EXFLAG_NSCERT) { + if(x->ex_nscert & NS_SMIME_CA) return ca_ret; + return 0; + } + if(ca_ret != 2) return ca_ret; + else return 0; + } + if(x->ex_flags & EXFLAG_NSCERT) { + if(x->ex_nscert & NS_SMIME) return 1; + /* Workaround for some buggy certificates */ + if(x->ex_nscert & NS_SSL_CLIENT) return 2; + return 0; + } + return 1; +} + +static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if(!ret || ca) return ret; + if(ku_reject(x, KU_DIGITAL_SIGNATURE)) return 0; + return ret; +} + +static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca) +{ + int ret; + ret = purpose_smime(x, ca); + if(!ret || ca) return ret; + if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0; + return ret; +} + +static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca) +{ + if(ca) { + int ca_ret; + if((ca_ret = ca_check(x)) != 2) return ca_ret; + else return 0; + } + if(ku_reject(x, KU_CRL_SIGN)) return 0; + return 1; +} diff --git a/src/lib/libcrypto/x509v3/v3_skey.c b/src/lib/libcrypto/x509v3/v3_skey.c new file mode 100644 index 0000000000..fb3e36014d --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_skey.c @@ -0,0 +1,156 @@ +/* v3_skey.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 + +static ASN1_OCTET_STRING *octet_string_new(void); +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); +X509V3_EXT_METHOD v3_skey_id = { +NID_subject_key_identifier, 0, +(X509V3_EXT_NEW)octet_string_new, +(X509V3_EXT_FREE)ASN1_STRING_free, +(X509V3_EXT_D2I)d2i_ASN1_OCTET_STRING, +(X509V3_EXT_I2D)i2d_ASN1_OCTET_STRING, +(X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING, +(X509V3_EXT_S2I)s2i_skey_id, +NULL, NULL, NULL, NULL, NULL}; + + +static ASN1_OCTET_STRING *octet_string_new(void) +{ + return ASN1_OCTET_STRING_new(); +} + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + ASN1_OCTET_STRING *oct) +{ + return hex_to_string(oct->data, oct->length); +} + +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_OCTET_STRING *oct; + long length; + + if(!(oct = ASN1_OCTET_STRING_new())) { + X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + + if(!(oct->data = string_to_hex(str, &length))) { + ASN1_OCTET_STRING_free(oct); + return NULL; + } + + oct->length = length; + + return oct; + +} + +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str) +{ + ASN1_OCTET_STRING *oct; + ASN1_BIT_STRING *pk; + unsigned char pkey_dig[EVP_MAX_MD_SIZE]; + EVP_MD_CTX md; + unsigned int diglen; + + if(strcmp(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str); + + if(!(oct = ASN1_OCTET_STRING_new())) { + X509V3err(X509V3_F_S2I_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE); + return NULL; + } + + if(ctx && (ctx->flags == CTX_TEST)) return oct; + + if(!ctx || (!ctx->subject_req && !ctx->subject_cert)) { + X509V3err(X509V3_F_S2I_ASN1_SKEY_ID,X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if(ctx->subject_req) + pk = ctx->subject_req->req_info->pubkey->public_key; + else pk = ctx->subject_cert->cert_info->key->public_key; + + if(!pk) { + X509V3err(X509V3_F_S2I_ASN1_SKEY_ID,X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + EVP_DigestInit(&md, EVP_sha1()); + EVP_DigestUpdate(&md, pk->data, pk->length); + EVP_DigestFinal(&md, pkey_dig, &diglen); + + if(!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { + X509V3err(X509V3_F_S2I_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE); + goto err; + } + + return oct; + + err: + ASN1_OCTET_STRING_free(oct); + return NULL; +} diff --git a/src/lib/libcrypto/x509v3/v3_sxnet.c b/src/lib/libcrypto/x509v3/v3_sxnet.c new file mode 100644 index 0000000000..0687bb4e3d --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_sxnet.c @@ -0,0 +1,340 @@ +/* v3_sxnet.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 +#include + +/* Support for Thawte strong extranet extension */ + +#define SXNET_TEST + +static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, int indent); +#ifdef SXNET_TEST +static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +#endif +X509V3_EXT_METHOD v3_sxnet = { +NID_sxnet, X509V3_EXT_MULTILINE, +(X509V3_EXT_NEW)SXNET_new, +(X509V3_EXT_FREE)SXNET_free, +(X509V3_EXT_D2I)d2i_SXNET, +(X509V3_EXT_I2D)i2d_SXNET, +NULL, NULL, +NULL, +#ifdef SXNET_TEST +(X509V3_EXT_V2I)sxnet_v2i, +#else +NULL, +#endif +(X509V3_EXT_I2R)sxnet_i2r, +NULL, +NULL +}; + + +int i2d_SXNET(SXNET *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->version, i2d_ASN1_INTEGER); + M_ASN1_I2D_len_SEQUENCE_type (SXNETID, a->ids, i2d_SXNETID); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->version, i2d_ASN1_INTEGER); + M_ASN1_I2D_put_SEQUENCE_type (SXNETID, a->ids, i2d_SXNETID); + + M_ASN1_I2D_finish(); +} + +SXNET *SXNET_new(void) +{ + SXNET *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, SXNET); + M_ASN1_New(ret->version,ASN1_INTEGER_new); + M_ASN1_New(ret->ids,sk_SXNETID_new_null); + return (ret); + M_ASN1_New_Error(ASN1_F_SXNET_NEW); +} + +SXNET *d2i_SXNET(SXNET **a, unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,SXNET *,SXNET_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get (ret->version, d2i_ASN1_INTEGER); + M_ASN1_D2I_get_seq_type (SXNETID, ret->ids, d2i_SXNETID, SXNETID_free); + M_ASN1_D2I_Finish(a, SXNET_free, ASN1_F_D2I_SXNET); +} + +void SXNET_free(SXNET *a) +{ + if (a == NULL) return; + ASN1_INTEGER_free(a->version); + sk_SXNETID_pop_free(a->ids, SXNETID_free); + Free (a); +} + +int i2d_SXNETID(SXNETID *a, unsigned char **pp) +{ + M_ASN1_I2D_vars(a); + + M_ASN1_I2D_len (a->zone, i2d_ASN1_INTEGER); + M_ASN1_I2D_len (a->user, i2d_ASN1_OCTET_STRING); + + M_ASN1_I2D_seq_total(); + + M_ASN1_I2D_put (a->zone, i2d_ASN1_INTEGER); + M_ASN1_I2D_put (a->user, i2d_ASN1_OCTET_STRING); + + M_ASN1_I2D_finish(); +} + +SXNETID *SXNETID_new(void) +{ + SXNETID *ret=NULL; + ASN1_CTX c; + M_ASN1_New_Malloc(ret, SXNETID); + ret->zone = NULL; + M_ASN1_New(ret->user,ASN1_OCTET_STRING_new); + return (ret); + M_ASN1_New_Error(ASN1_F_SXNETID_NEW); +} + +SXNETID *d2i_SXNETID(SXNETID **a, unsigned char **pp, long length) +{ + M_ASN1_D2I_vars(a,SXNETID *,SXNETID_new); + M_ASN1_D2I_Init(); + M_ASN1_D2I_start_sequence(); + M_ASN1_D2I_get(ret->zone, d2i_ASN1_INTEGER); + M_ASN1_D2I_get(ret->user, d2i_ASN1_OCTET_STRING); + M_ASN1_D2I_Finish(a, SXNETID_free, ASN1_F_D2I_SXNETID); +} + +void SXNETID_free(SXNETID *a) +{ + if (a == NULL) return; + ASN1_INTEGER_free(a->zone); + ASN1_OCTET_STRING_free(a->user); + Free (a); +} + +static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, + int indent) +{ + long v; + char *tmp; + SXNETID *id; + int i; + v = ASN1_INTEGER_get(sx->version); + BIO_printf(out, "%*sVersion: %d (0x%X)", indent, "", v + 1, v); + for(i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + tmp = i2s_ASN1_INTEGER(NULL, id->zone); + BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp); + Free(tmp); + ASN1_OCTET_STRING_print(out, id->user); + } + return 1; +} + +#ifdef SXNET_TEST + +/* NBB: this is used for testing only. It should *not* be used for anything + * else because it will just take static IDs from the configuration file and + * they should really be separate values for each user. + */ + + +static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *cnf; + SXNET *sx = NULL; + int i; + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if(!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1)) + return NULL; + } + return sx; +} + + +#endif + +/* Strong Extranet utility functions */ + +/* Add an id given the zone as an ASCII number */ + +int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, + int userlen) +{ + ASN1_INTEGER *izone = NULL; + if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) { + X509V3err(X509V3_F_SXNET_ADD_ASC,X509V3_R_ERROR_CONVERTING_ZONE); + return 0; + } + return SXNET_add_id_INTEGER(psx, izone, user, userlen); +} + +/* Add an id given the zone as an unsigned long */ + +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, + int userlen) +{ + ASN1_INTEGER *izone = NULL; + if(!(izone = ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { + X509V3err(X509V3_F_SXNET_ADD_ID_ULONG,ERR_R_MALLOC_FAILURE); + ASN1_INTEGER_free(izone); + return 0; + } + return SXNET_add_id_INTEGER(psx, izone, user, userlen); + +} + +/* Add an id given the zone as an ASN1_INTEGER. + * Note this version uses the passed integer and doesn't make a copy so don't + * free it up afterwards. + */ + +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, char *user, + int userlen) +{ + SXNET *sx = NULL; + SXNETID *id = NULL; + if(!psx || !zone || !user) { + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER,X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + if(userlen == -1) userlen = strlen(user); + if(userlen > 64) { + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER,X509V3_R_USER_TOO_LONG); + return 0; + } + if(!*psx) { + if(!(sx = SXNET_new())) goto err; + if(!ASN1_INTEGER_set(sx->version, 0)) goto err; + *psx = sx; + } else sx = *psx; + if(SXNET_get_id_INTEGER(sx, zone)) { + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER,X509V3_R_DUPLICATE_ZONE_ID); + return 0; + } + + if(!(id = SXNETID_new())) goto err; + if(userlen == -1) userlen = strlen(user); + + if(!ASN1_OCTET_STRING_set(id->user, user, userlen)) goto err; + if(!sk_SXNETID_push(sx->ids, id)) goto err; + id->zone = zone; + return 1; + + err: + X509V3err(X509V3_F_SXNET_ADD_ID_INTEGER,ERR_R_MALLOC_FAILURE); + SXNETID_free(id); + SXNET_free(sx); + *psx = NULL; + return 0; +} + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone) +{ + ASN1_INTEGER *izone = NULL; + ASN1_OCTET_STRING *oct; + if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) { + X509V3err(X509V3_F_SXNET_GET_ID_ASC,X509V3_R_ERROR_CONVERTING_ZONE); + return NULL; + } + oct = SXNET_get_id_INTEGER(sx, izone); + ASN1_INTEGER_free(izone); + return oct; +} + +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone) +{ + ASN1_INTEGER *izone = NULL; + ASN1_OCTET_STRING *oct; + if(!(izone = ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { + X509V3err(X509V3_F_SXNET_GET_ID_ULONG,ERR_R_MALLOC_FAILURE); + ASN1_INTEGER_free(izone); + return NULL; + } + oct = SXNET_get_id_INTEGER(sx, izone); + ASN1_INTEGER_free(izone); + return oct; +} + +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone) +{ + SXNETID *id; + int i; + for(i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + if(!ASN1_INTEGER_cmp(id->zone, zone)) return id->user; + } + return NULL; +} + +IMPLEMENT_STACK_OF(SXNETID) +IMPLEMENT_ASN1_SET_OF(SXNETID) diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c new file mode 100644 index 0000000000..40f71c71b4 --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3_utl.c @@ -0,0 +1,418 @@ +/* v3_utl.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). + * + */ +/* X509 v3 extension utilities */ + + +#include +#include +#include "cryptlib.h" +#include +#include + +static char *strip_spaces(char *name); + +/* Add a CONF_VALUE name value pair to stack */ + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + CONF_VALUE *vtmp = NULL; + char *tname = NULL, *tvalue = NULL; + if(name && !(tname = BUF_strdup(name))) goto err; + if(value && !(tvalue = BUF_strdup(value))) goto err;; + if(!(vtmp = (CONF_VALUE *)Malloc(sizeof(CONF_VALUE)))) goto err; + if(!*extlist && !(*extlist = sk_CONF_VALUE_new(NULL))) goto err; + vtmp->section = NULL; + vtmp->name = tname; + vtmp->value = tvalue; + if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err; + return 1; + err: + X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE); + if(vtmp) Free(vtmp); + if(tname) Free(tname); + if(tvalue) Free(tvalue); + return 0; +} + +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist) + { + return X509V3_add_value(name,(const char *)value,extlist); + } + +/* Free function for STACK_OF(CONF_VALUE) */ + +void X509V3_conf_free(CONF_VALUE *conf) +{ + if(!conf) return; + if(conf->name) Free(conf->name); + if(conf->value) Free(conf->value); + if(conf->section) Free(conf->section); + Free((char *)conf); +} + +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); + return X509V3_add_value(name, "FALSE", extlist); +} + +int X509V3_add_value_bool_nf(char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); + return 1; +} + + +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) +{ + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + if(!a) return NULL; + if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || + !(strtmp = BN_bn2dec(bntmp)) ) + X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} + +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) +{ + BIGNUM *bntmp = NULL; + char *strtmp = NULL; + if(!a) return NULL; + if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || + !(strtmp = BN_bn2dec(bntmp)) ) + X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} + +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) +{ + BIGNUM *bn = NULL; + ASN1_INTEGER *aint; + bn = BN_new(); + if(!value) { + X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); + return 0; + } + if(!BN_dec2bn(&bn, value)) { + X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); + return 0; + } + + if(!(aint = BN_to_ASN1_INTEGER(bn, NULL))) { + X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR); + return 0; + } + BN_free(bn); + return aint; +} + +int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist) +{ + char *strtmp; + int ret; + if(!aint) return 1; + if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0; + ret = X509V3_add_value(name, strtmp, extlist); + Free(strtmp); + return ret; +} + +int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) +{ + char *btmp; + if(!(btmp = value->value)) goto err; + if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") + || !strcmp(btmp, "Y") || !strcmp(btmp, "y") + || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { + *asn1_bool = 0xff; + return 1; + } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") + || !strcmp(btmp, "N") || !strcmp(btmp, "n") + || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { + *asn1_bool = 0; + return 1; + } + err: + X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING); + X509V3_conf_err(value); + return 0; +} + +int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) +{ + ASN1_INTEGER *itmp; + if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { + X509V3_conf_err(value); + return 0; + } + *aint = itmp; + return 1; +} + +#define HDR_NAME 1 +#define HDR_VALUE 2 + +/*#define DEBUG*/ + +STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) +{ + char *p, *q, c; + char *ntmp, *vtmp; + STACK_OF(CONF_VALUE) *values = NULL; + char *linebuf; + int state; + /* We are going to modify the line so copy it first */ + linebuf = BUF_strdup(line); + state = HDR_NAME; + ntmp = NULL; + /* Go through all characters */ + for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { + + switch(state) { + case HDR_NAME: + if(c == ':') { + state = HDR_VALUE; + *p = 0; + ntmp = strip_spaces(q); + if(!ntmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); + goto err; + } + q = p + 1; + } else if(c == ',') { + *p = 0; + ntmp = strip_spaces(q); + q = p + 1; +#ifdef DEBUG + printf("%s\n", ntmp); +#endif + if(!ntmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + break ; + + case HDR_VALUE: + if(c == ',') { + state = HDR_NAME; + *p = 0; + vtmp = strip_spaces(q); +#ifdef DEBUG + printf("%s\n", ntmp); +#endif + if(!vtmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + ntmp = NULL; + q = p + 1; + } + + } + } + + if(state == HDR_VALUE) { + vtmp = strip_spaces(q); +#ifdef DEBUG + printf("%s=%s\n", ntmp, vtmp); +#endif + if(!vtmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + } else { + ntmp = strip_spaces(q); +#ifdef DEBUG + printf("%s\n", ntmp); +#endif + if(!ntmp) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } +Free(linebuf); +return values; + +err: +Free(linebuf); +sk_CONF_VALUE_pop_free(values, X509V3_conf_free); +return NULL; + +} + +/* Delete leading and trailing spaces from a string */ +static char *strip_spaces(char *name) +{ + char *p, *q; + /* Skip over leading spaces */ + p = name; + while(*p && isspace((unsigned char)*p)) p++; + if(!*p) return NULL; + q = p + strlen(p) - 1; + while((q != p) && isspace((unsigned char)*q)) q--; + if(p != q) q[1] = 0; + if(!*p) return NULL; + return p; +} + +/* hex string utilities */ + +/* Given a buffer of length 'len' return a Malloc'ed string with its + * hex representation + */ + +char *hex_to_string(unsigned char *buffer, long len) +{ + char *tmp, *q; + unsigned char *p; + int i; + static char hexdig[] = "0123456789ABCDEF"; + if(!buffer || !len) return NULL; + if(!(tmp = Malloc(len * 3 + 1))) { + X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + q = tmp; + for(i = 0, p = buffer; i < len; i++,p++) { + *q++ = hexdig[(*p >> 4) & 0xf]; + *q++ = hexdig[*p & 0xf]; + *q++ = ':'; + } + q[-1] = 0; + return tmp; +} + +/* Give a string of hex digits convert to + * a buffer + */ + +unsigned char *string_to_hex(char *str, long *len) +{ + unsigned char *hexbuf, *q; + unsigned char ch, cl, *p; + if(!str) { + X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if(!(hexbuf = Malloc(strlen(str) >> 1))) goto err; + for(p = (unsigned char *)str, q = hexbuf; *p;) { + ch = *p++; + if(ch == ':') continue; + cl = *p++; + if(!cl) { + X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS); + Free(hexbuf); + return NULL; + } + if(isupper(ch)) ch = tolower(ch); + if(isupper(cl)) cl = tolower(cl); + + if((ch >= '0') && (ch <= '9')) ch -= '0'; + else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10; + else goto badhex; + + if((cl >= '0') && (cl <= '9')) cl -= '0'; + else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10; + else goto badhex; + + *q++ = (ch << 4) | cl; + } + + if(len) *len = q - hexbuf; + + return hexbuf; + + err: + if(hexbuf) Free(hexbuf); + X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE); + return NULL; + + badhex: + Free(hexbuf); + X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT); + return NULL; + +} + +/* V2I name comparison function: returns zero if 'name' matches + * cmp or cmp.* + */ + +int name_cmp(const char *name, const char *cmp) +{ + int len, ret; + char c; + len = strlen(cmp); + if((ret = strncmp(name, cmp, len))) return ret; + c = name[len]; + if(!c || (c=='.')) return 0; + return 1; +} diff --git a/src/lib/libcrypto/x509v3/v3err.c b/src/lib/libcrypto/x509v3/v3err.c new file mode 100644 index 0000000000..50efa8d99d --- /dev/null +++ b/src/lib/libcrypto/x509v3/v3err.c @@ -0,0 +1,171 @@ +/* crypto/x509v3/v3err.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. + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA X509V3_str_functs[]= + { +{ERR_PACK(0,X509V3_F_COPY_EMAIL,0), "COPY_EMAIL"}, +{ERR_PACK(0,X509V3_F_COPY_ISSUER,0), "COPY_ISSUER"}, +{ERR_PACK(0,X509V3_F_DO_EXT_CONF,0), "DO_EXT_CONF"}, +{ERR_PACK(0,X509V3_F_DO_EXT_I2D,0), "DO_EXT_I2D"}, +{ERR_PACK(0,X509V3_F_HEX_TO_STRING,0), "hex_to_string"}, +{ERR_PACK(0,X509V3_F_I2S_ASN1_ENUMERATED,0), "i2s_ASN1_ENUMERATED"}, +{ERR_PACK(0,X509V3_F_I2S_ASN1_INTEGER,0), "i2s_ASN1_INTEGER"}, +{ERR_PACK(0,X509V3_F_NOTICE_SECTION,0), "NOTICE_SECTION"}, +{ERR_PACK(0,X509V3_F_NREF_NOS,0), "NREF_NOS"}, +{ERR_PACK(0,X509V3_F_POLICY_SECTION,0), "POLICY_SECTION"}, +{ERR_PACK(0,X509V3_F_R2I_CERTPOL,0), "R2I_CERTPOL"}, +{ERR_PACK(0,X509V3_F_S2I_ASN1_IA5STRING,0), "S2I_ASN1_IA5STRING"}, +{ERR_PACK(0,X509V3_F_S2I_ASN1_INTEGER,0), "s2i_ASN1_INTEGER"}, +{ERR_PACK(0,X509V3_F_S2I_ASN1_OCTET_STRING,0), "s2i_ASN1_OCTET_STRING"}, +{ERR_PACK(0,X509V3_F_S2I_ASN1_SKEY_ID,0), "S2I_ASN1_SKEY_ID"}, +{ERR_PACK(0,X509V3_F_S2I_S2I_SKEY_ID,0), "S2I_S2I_SKEY_ID"}, +{ERR_PACK(0,X509V3_F_STRING_TO_HEX,0), "string_to_hex"}, +{ERR_PACK(0,X509V3_F_SXNET_ADD_ASC,0), "SXNET_ADD_ASC"}, +{ERR_PACK(0,X509V3_F_SXNET_ADD_ID_INTEGER,0), "SXNET_add_id_INTEGER"}, +{ERR_PACK(0,X509V3_F_SXNET_ADD_ID_ULONG,0), "SXNET_add_id_ulong"}, +{ERR_PACK(0,X509V3_F_SXNET_GET_ID_ASC,0), "SXNET_get_id_asc"}, +{ERR_PACK(0,X509V3_F_SXNET_GET_ID_ULONG,0), "SXNET_get_id_ulong"}, +{ERR_PACK(0,X509V3_F_V2I_ASN1_BIT_STRING,0), "V2I_ASN1_BIT_STRING"}, +{ERR_PACK(0,X509V3_F_V2I_AUTHORITY_KEYID,0), "V2I_AUTHORITY_KEYID"}, +{ERR_PACK(0,X509V3_F_V2I_BASIC_CONSTRAINTS,0), "V2I_BASIC_CONSTRAINTS"}, +{ERR_PACK(0,X509V3_F_V2I_CRLD,0), "V2I_CRLD"}, +{ERR_PACK(0,X509V3_F_V2I_EXT_KU,0), "V2I_EXT_KU"}, +{ERR_PACK(0,X509V3_F_V2I_GENERAL_NAME,0), "v2i_GENERAL_NAME"}, +{ERR_PACK(0,X509V3_F_V2I_GENERAL_NAMES,0), "v2i_GENERAL_NAMES"}, +{ERR_PACK(0,X509V3_F_V3_GENERIC_EXTENSION,0), "V3_GENERIC_EXTENSION"}, +{ERR_PACK(0,X509V3_F_X509V3_ADD_VALUE,0), "X509V3_add_value"}, +{ERR_PACK(0,X509V3_F_X509V3_EXT_ADD,0), "X509V3_EXT_add"}, +{ERR_PACK(0,X509V3_F_X509V3_EXT_ADD_ALIAS,0), "X509V3_EXT_add_alias"}, +{ERR_PACK(0,X509V3_F_X509V3_EXT_CONF,0), "X509V3_EXT_conf"}, +{ERR_PACK(0,X509V3_F_X509V3_EXT_I2D,0), "X509V3_EXT_i2d"}, +{ERR_PACK(0,X509V3_F_X509V3_GET_VALUE_BOOL,0), "X509V3_get_value_bool"}, +{ERR_PACK(0,X509V3_F_X509V3_PARSE_LIST,0), "X509V3_parse_list"}, +{0,NULL} + }; + +static ERR_STRING_DATA X509V3_str_reasons[]= + { +{X509V3_R_BAD_IP_ADDRESS ,"bad ip address"}, +{X509V3_R_BAD_OBJECT ,"bad object"}, +{X509V3_R_BN_DEC2BN_ERROR ,"bn dec2bn error"}, +{X509V3_R_BN_TO_ASN1_INTEGER_ERROR ,"bn to asn1 integer error"}, +{X509V3_R_DUPLICATE_ZONE_ID ,"duplicate zone id"}, +{X509V3_R_ERROR_CONVERTING_ZONE ,"error converting zone"}, +{X509V3_R_ERROR_IN_EXTENSION ,"error in extension"}, +{X509V3_R_EXPECTED_A_SECTION_NAME ,"expected a section name"}, +{X509V3_R_EXTENSION_NAME_ERROR ,"extension name error"}, +{X509V3_R_EXTENSION_NOT_FOUND ,"extension not found"}, +{X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED,"extension setting not supported"}, +{X509V3_R_EXTENSION_VALUE_ERROR ,"extension value error"}, +{X509V3_R_ILLEGAL_HEX_DIGIT ,"illegal hex digit"}, +{X509V3_R_INVALID_BOOLEAN_STRING ,"invalid boolean string"}, +{X509V3_R_INVALID_EXTENSION_STRING ,"invalid extension string"}, +{X509V3_R_INVALID_NAME ,"invalid name"}, +{X509V3_R_INVALID_NULL_ARGUMENT ,"invalid null argument"}, +{X509V3_R_INVALID_NULL_NAME ,"invalid null name"}, +{X509V3_R_INVALID_NULL_VALUE ,"invalid null value"}, +{X509V3_R_INVALID_NUMBER ,"invalid number"}, +{X509V3_R_INVALID_NUMBERS ,"invalid numbers"}, +{X509V3_R_INVALID_OBJECT_IDENTIFIER ,"invalid object identifier"}, +{X509V3_R_INVALID_OPTION ,"invalid option"}, +{X509V3_R_INVALID_POLICY_IDENTIFIER ,"invalid policy identifier"}, +{X509V3_R_INVALID_SECTION ,"invalid section"}, +{X509V3_R_ISSUER_DECODE_ERROR ,"issuer decode error"}, +{X509V3_R_MISSING_VALUE ,"missing value"}, +{X509V3_R_NEED_ORGANIZATION_AND_NUMBERS ,"need organization and numbers"}, +{X509V3_R_NO_CONFIG_DATABASE ,"no config database"}, +{X509V3_R_NO_ISSUER_CERTIFICATE ,"no issuer certificate"}, +{X509V3_R_NO_ISSUER_DETAILS ,"no issuer details"}, +{X509V3_R_NO_POLICY_IDENTIFIER ,"no policy identifier"}, +{X509V3_R_NO_PUBLIC_KEY ,"no public key"}, +{X509V3_R_NO_SUBJECT_DETAILS ,"no subject details"}, +{X509V3_R_ODD_NUMBER_OF_DIGITS ,"odd number of digits"}, +{X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS ,"unable to get issuer details"}, +{X509V3_R_UNABLE_TO_GET_ISSUER_KEYID ,"unable to get issuer keyid"}, +{X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT ,"unknown bit string argument"}, +{X509V3_R_UNKNOWN_EXTENSION ,"unknown extension"}, +{X509V3_R_UNKNOWN_EXTENSION_NAME ,"unknown extension name"}, +{X509V3_R_UNKNOWN_OPTION ,"unknown option"}, +{X509V3_R_UNSUPPORTED_OPTION ,"unsupported option"}, +{X509V3_R_USER_TOO_LONG ,"user too long"}, +{0,NULL} + }; + +#endif + +void ERR_load_X509V3_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_X509V3,X509V3_str_functs); + ERR_load_strings(ERR_LIB_X509V3,X509V3_str_reasons); +#endif + + } + } diff --git a/src/lib/libssl/LICENSE b/src/lib/libssl/LICENSE new file mode 100644 index 0000000000..b9e18d5e7b --- /dev/null +++ b/src/lib/libssl/LICENSE @@ -0,0 +1,127 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-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). + * + */ + + 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/src/lib/libssl/doc/openssl.cnf b/src/lib/libssl/doc/openssl.cnf new file mode 100644 index 0000000000..d70dd25622 --- /dev/null +++ b/src/lib/libssl/doc/openssl.cnf @@ -0,0 +1,214 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +RANDFILE = $ENV::HOME/.rnd +oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extentions to add to the cert + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = md5 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 40 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +[ v3_ca ] + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# RAW DER hex encoding of an extension: beware experts only! +# 1.2.3.5=RAW:02:03 +# You can even override a supported extension: +# basicConstraints= critical, RAW:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always diff --git a/src/lib/libssl/doc/openssl.txt b/src/lib/libssl/doc/openssl.txt new file mode 100644 index 0000000000..91b85e5f14 --- /dev/null +++ b/src/lib/libssl/doc/openssl.txt @@ -0,0 +1,1174 @@ + +This is some preliminary documentation for OpenSSL. + +============================================================================== + BUFFER Library +============================================================================== + +The buffer library handles simple character arrays. Buffers are used for +various purposes in the library, most notably memory BIOs. + +The library uses the BUF_MEM structure defined in buffer.h: + +typedef struct buf_mem_st +{ + int length; /* current number of bytes */ + char *data; + int max; /* size of buffer */ +} BUF_MEM; + +'length' is the current size of the buffer in bytes, 'max' is the amount of +memory allocated to the buffer. There are three functions which handle these +and one "miscellaneous" function. + +BUF_MEM *BUF_MEM_new() + +This allocates a new buffer of zero size. Returns the buffer or NULL on error. + +void BUF_MEM_free(BUF_MEM *a) + +This frees up an already existing buffer. The data is zeroed before freeing +up in case the buffer contains sensitive data. + +int BUF_MEM_grow(BUF_MEM *str, int len) + +This changes the size of an already existing buffer. It returns zero on error +or the new size (i.e. 'len'). Any data already in the buffer is preserved if +it increases in size. + +char * BUF_strdup(char *str) + +This is the previously mentioned strdup function: like the standard library +strdup() it copies a null terminated string into a block of allocated memory +and returns a pointer to the allocated block. + +Unlike the standard C library strdup() this function uses Malloc() and so +should be used in preference to the standard library strdup() because it can +be used for memory leak checking or replacing the malloc() function. + +The memory allocated from BUF_strdup() should be freed up using the Free() +function. + +============================================================================== + OpenSSL X509V3 extension configuration +============================================================================== + +OpenSSL X509V3 extension configuration: preliminary documentation. + +INTRODUCTION. + +For OpenSSL 0.9.2 the extension code has be considerably enhanced. It is now +possible to add and print out common X509 V3 certificate and CRL extensions. + +BEGINNERS NOTE + +For most simple applications you don't need to know too much about extensions: +the default openssl.cnf values will usually do sensible things. + +If you want to know more you can initially quickly look through the sections +describing how the standard OpenSSL utilities display and add extensions and +then the list of supported extensions. + +For more technical information about the meaning of extensions see: + +http://www.imc.org/ietf-pkix/ +http://home.netscape.com/eng/security/certs.html + +PRINTING EXTENSIONS. + +Extension values are automatically printed out for supported extensions. + +openssl x509 -in cert.pem -text +openssl crl -in crl.pem -text + +will give information in the extension printout, for example: + + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Subject Key Identifier: + 73:FE:F7:59:A7:E1:26:84:44:D6:44:36:EE:79:1A:95:7C:B1:4B:15 + X509v3 Authority Key Identifier: + keyid:73:FE:F7:59:A7:E1:26:84:44:D6:44:36:EE:79:1A:95:7C:B1:4B:15, DirName:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/Email=email@1.address/Email=email@2.address, serial:00 + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Subject Alternative Name: + email:email@1.address, email:email@2.address + +CONFIGURATION FILES. + +The OpenSSL utilities 'ca' and 'req' can now have extension sections listing +which certificate extensions to include. In each case a line: + +x509_extensions = extension_section + +indicates which section contains the extensions. In the case of 'req' the +extension section is used when the -x509 option is present to create a +self signed root certificate. + +The 'x509' utility also supports extensions when it signs a certificate. +The -extfile option is used to set the configuration file containing the +extensions. In this case a line with: + +extensions = extension_section + +in the nameless (default) section is used. If no such line is included then +it uses the default section. + +You can also add extensions to CRLs: a line + +crl_extensions = crl_extension_section + +will include extensions when the -gencrl option is used with the 'ca' utility. +You can add any extension to a CRL but of the supported extensions only +issuerAltName and authorityKeyIdentifier make any real sense. Note: these are +CRL extensions NOT CRL *entry* extensions which cannot currently be generated. +CRL entry extensions can be displayed. + +NB. At this time Netscape Communicator rejects V2 CRLs: to get an old V1 CRL +you should not include a crl_extensions line in the configuration file. + +As with all configuration files you can use the inbuilt environment expansion +to allow the values to be passed in the environment. Therefore if you have +several extension sections used for different purposes you can have a line: + +x509_extensions = $ENV::ENV_EXT + +and set the ENV_EXT environment variable before calling the relevant utility. + +EXTENSION SYNTAX. + +Extensions have the basic form: + +extension_name=[critical,] extension_options + +the use of the critical option makes the extension critical. Extreme caution +should be made when using the critical flag. If an extension is marked +as critical then any client that does not understand the extension should +reject it as invalid. Some broken software will reject certificates which +have *any* critical extensions (these violates PKIX but we have to live +with it). + +There are three main types of extension: string extensions, multi-valued +extensions, and raw extensions. + +String extensions simply have a string which contains either the value itself +or how it is obtained. + +For example: + +nsComment="This is a Comment" + +Multi-valued extensions have a short form and a long form. The short form +is a list of names and values: + +basicConstraints=critical,CA:true,pathlen:1 + +The long form allows the values to be placed in a separate section: + +basicConstraints=critical,@bs_section + +[bs_section] + +CA=true +pathlen=1 + +Both forms are equivalent. However it should be noted that in some cases the +same name can appear multiple times, for example, + +subjectAltName=email:steve@here,email:steve@there + +in this case an equivalent long form is: + +subjectAltName=@alt_section + +[alt_section] + +email.1=steve@here +email.2=steve@there + +This is because the configuration file code cannot handle the same name +occurring twice in the same extension. + +The syntax of raw extensions is governed by the extension code: it can +for example contain data in multiple sections. The correct syntax to +use is defined by the extension code itself: check out the certificate +policies extension for an example. + +In addition it is also possible to use the word DER to include arbitrary +data in any extension. + +1.2.3.4=critical,DER:01:02:03:04 +1.2.3.4=DER:01020304 + +The value following DER is a hex dump of the DER encoding of the extension +Any extension can be placed in this form to override the default behaviour. +For example: + +basicConstraints=critical,DER:00:01:02:03 + +WARNING: DER should be used with caution. It is possible to create totally +invalid extensions unless care is taken. + +CURRENTLY SUPPORTED EXTENSIONS. + +If you aren't sure about extensions then they can be largely ignored: its only +when you want to do things like restrict certificate usage when you need to +worry about them. + +The only extension that a beginner might want to look at is Basic Constraints. +If in addition you want to try Netscape object signing the you should also +look at Netscape Certificate Type. + +Literal String extensions. + +In each case the 'value' of the extension is placed directly in the +extension. Currently supported extensions in this category are: nsBaseUrl, +nsRevocationUrl, nsCaRevocationUrl, nsRenewalUrl, nsCaPolicyUrl, +nsSslServerName and nsComment. + +For example: + +nsComment="This is a test comment" + +Bit Strings. + +Bit string extensions just consist of a list of supported bits, currently +two extensions are in this category: PKIX keyUsage and the Netscape specific +nsCertType. + +nsCertType (netscape certificate type) takes the flags: client, server, email, +objsign, reserved, sslCA, emailCA, objCA. + +keyUsage (PKIX key usage) takes the flags: digitalSignature, nonRepudiation, +keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, +encipherOnly, decipherOnly. + +For example: + +nsCertType=server + +keyUsage=digitalSignature, nonRepudiation + +Hints on Netscape Certificate Type. + +Other than Basic Constraints this is the only extension a beginner might +want to use, if you want to try Netscape object signing, otherwise it can +be ignored. + +If you want a certificate that can be used just for object signing then: + +nsCertType=objsign + +will do the job. If you want to use it as a normal end user and server +certificate as well then + +nsCertType=objsign,email,server + +is more appropriate. You cannot use a self signed certificate for object +signing (well Netscape signtool can but it cheats!) so you need to create +a CA certificate and sign an end user certificate with it. + +Side note: If you want to conform to the Netscape specifications then you +should really also set: + +nsCertType=objCA + +in the *CA* certificate for just an object signing CA and + +nsCertType=objCA,emailCA,sslCA + +for everything. Current Netscape software doesn't enforce this so it can +be omitted. + +Basic Constraints. + +This is generally the only extension you need to worry about for simple +applications. If you want your certificate to be usable as a CA certificate +(in addition to an end user certificate) then you set this to: + +basicConstraints=CA:TRUE + +if you want to be certain the certificate cannot be used as a CA then do: + +basicConstraints=CA:FALSE + +The rest of this section describes more advanced usage. + +Basic constraints is a multi-valued extension that supports a CA and an +optional pathlen option. The CA option takes the values true and false and +pathlen takes an integer. Note if the CA option is false the pathlen option +should be omitted. + +The pathlen parameter indicates the maximum number of CAs that can appear +below this one in a chain. So if you have a CA with a pathlen of zero it can +only be used to sign end user certificates and not further CAs. This all +assumes that the software correctly interprets this extension of course. + +Examples: + +basicConstraints=CA:TRUE +basicConstraints=critical,CA:TRUE, pathlen:0 + +NOTE: for a CA to be considered valid it must have the CA option set to +TRUE. An end user certificate MUST NOT have the CA value set to true. +According to PKIX recommendations it should exclude the extension entirely, +however some software may require CA set to FALSE for end entity certificates. + +Subject Key Identifier. + +This is really a string extension and can take two possible values. Either +a hex string giving details of the extension value to include or the word +'hash' which then automatically follow PKIX guidelines in selecting and +appropriate key identifier. The use of the hex string is strongly discouraged. + +Example: subjectKeyIdentifier=hash + +Authority Key Identifier. + +The authority key identifier extension permits two options. keyid and issuer: +both can take the optional value "always". + +If the keyid option is present an attempt is made to copy the subject key +identifier from the parent certificate. If the value "always" is present +then an error is returned if the option fails. + +The issuer option copies the issuer and serial number from the issuer +certificate. Normally this will only be done if the keyid option fails or +is not included: the "always" flag will always include the value. + +Subject Alternative Name. + +The subject alternative name extension allows various literal values to be +included in the configuration file. These include "email" (an email address) +"URI" a uniform resource indicator, "DNS" (a DNS domain name), RID (a +registered ID: OBJECT IDENTIFIER) and IP (and IP address). + +Also the email option include a special 'copy' value. This will automatically +include and email addresses contained in the certificate subject name in +the extension. + +Examples: + +subjectAltName=email:copy,email:my@other.address,URL:http://my.url.here/ +subjectAltName=email:my@other.address,RID:1.2.3.4 + +Issuer Alternative Name. + +The issuer alternative name option supports all the literal options of +subject alternative name. It does *not* support the email:copy option because +that would not make sense. It does support an additional issuer:copy option +that will copy all the subject alternative name values from the issuer +certificate (if possible). + +CRL distribution points. + +This is a multi-valued extension that supports all the literal options of +subject alternative name. Of the few software packages that currently interpret +this extension most only interpret the URI option. + +Currently each option will set a new DistributionPoint with the fullName +field set to the given value. + +Other fields like cRLissuer and reasons cannot currently be set or displayed: +at this time no examples were available that used these fields. + +If you see this extension with when you attempt to print it out +or it doesn't appear to display correctly then let me know, including the +certificate (mail me at steve@openssl.org) . + +Examples: + +crlDistributionPoints=URI:http://www.myhost.com/myca.crl +crlDistributionPoints=URI:http://www.my.com/my.crl,URI:http://www.oth.com/my.crl + +Certificate Policies. + +This is a RAW extension. It attempts to display the contents of this extension: +unfortunately this extension is often improperly encoded. + +The certificate policies extension will rarely be used in practice: few +software packages interpret it correctly or at all. IE5 does partially +support this extension: but it needs the 'ia5org' option because it will +only correctly support a broken encoding. Of the options below only the +policy OID, explicitText and CPS options are displayed with IE5. + +All the fields of this extension can be set by using the appropriate syntax. + +If you follow the PKIX recommendations of not including any qualifiers and just +using only one OID then you just include the value of that OID. Multiple OIDs +can be set separated by commas, for example: + +certificatePolicies= 1.2.4.5, 1.1.3.4 + +If you wish to include qualifiers then the policy OID and qualifiers need to +be specified in a separate section: this is done by using the @section syntax +instead of a literal OID value. + +The section referred to must include the policy OID using the name +policyIdentifier, cPSuri qualifiers can be included using the syntax: + +CPS.nnn=value + +userNotice qualifiers can be set using the syntax: + +userNotice.nnn=@notice + +The value of the userNotice qualifier is specified in the relevant section. +This section can include explicitText, organization and noticeNumbers +options. explicitText and organization are text strings, noticeNumbers is a +comma separated list of numbers. The organization and noticeNumbers options +(if included) must BOTH be present. If you use the userNotice option with IE5 +then you need the 'ia5org' option at the top level to modify the encoding: +otherwise it will not be interpreted properly. + +Example: + +certificatePolicies=ia5org,1.2.3.4,1.5.6.7.8,@polsect + +[polsect] + +policyIdentifier = 1.3.5.8 +CPS.1="http://my.host.name/" +CPS.2="http://my.your.name/" +userNotice.1=@notice + +[notice] + +explicitText="Explicit Text Here" +organization="Organisation Name" +noticeNumbers=1,2,3,4 + +TECHNICAL NOTE: the ia5org option changes the type of the 'organization' field, +according to PKIX it should be of type DisplayText but Verisign uses an +IA5STRING and IE5 needs this too. + +Display only extensions. + +Some extensions are only partially supported and currently are only displayed +but cannot be set. These include private key usage period, CRL number, and +CRL reason. + +============================================================================== + X509V3 Extension code: programmers guide +============================================================================== + +The purpose of the extension code is twofold. It allows an extension to be +created from a string or structure describing its contents and it prints out an +extension in a human or machine readable form. + +1. Initialisation and cleanup. + +X509V3_add_standard_extensions(); + +This function should be called before any other extension code. It adds support +for some common PKIX and Netscape extensions. Additional custom extensions can +be added as well (see later). + +void X509V3_EXT_cleanup(void); + +This function should be called last to cleanup the extension code. After this +call no other extension calls should be made. + +2. Printing and parsing extensions. + +The simplest way to print out extensions is via the standard X509 printing +routines: if you use the standard X509_print() function, the supported +extensions will be printed out automatically. + +The following functions allow finer control over extension display: + +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, int flag, int indent); +int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); + +These two functions print out an individual extension to a BIO or FILE pointer. +Currently the flag argument is unused and should be set to 0. The 'indent' +argument is the number of spaces to indent each line. + +void *X509V3_EXT_d2i(X509_EXTENSION *ext); + +This function parses an extension and returns its internal structure. The +precise structure you get back depends on the extension being parsed. If the +extension if basicConstraints you will get back a pointer to a +BASIC_CONSTRAINTS structure. Check out the source in crypto/x509v3 for more +details about the structures returned. The returned structure should be freed +after use using the relevant free function, BASIC_CONSTRAINTS_free() for +example. + +3. Generating extensions. + +An extension will typically be generated from a configuration file, or some +other kind of configuration database. + +int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509 *cert); +int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509_CRL *crl); + +These functions add all the extensions in the given section to the given +certificate or CRL. They will normally be called just before the certificate +or CRL is due to be signed. Both return 0 on error on non zero for success. + +In each case 'conf' is the LHASH pointer of the configuration file to use +and 'section' is the section containing the extension details. + +See the 'context functions' section for a description of the ctx paramater. + + +X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, + char *value); + +This function returns an extension based on a name and value pair, if the +pair will not need to access other sections in a config file (or there is no +config file) then the 'conf' parameter can be set to NULL. + +X509_EXTENSION *X509V3_EXT_conf_nid(char *conf, X509V3_CTX *ctx, int nid, + char *value); + +This function creates an extension in the same way as X509V3_EXT_conf() but +takes the NID of the extension rather than its name. + +For example to produce basicConstraints with the CA flag and a path length of +10: + +x = X509V3_EXT_conf_nid(NULL, NULL, NID_basicConstraints, "CA:TRUE,pathlen:10"); + + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); + +This function sets up an extension from its internal structure. The ext_nid +parameter is the NID of the extension and 'crit' is the critical flag. + +4. Context functions. + +The following functions set and manipulate an extension context structure. +The purpose of the extension context is to allow the extension code to +access various structures relating to the "environment" of the certificate: +for example the issuers certificate or the certificate request. + +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +This function sets up an X509V3_CTX structure with details of the certificate +environment: specifically the issuers certificate, the subject certificate, +the certificate request and the CRL: if these are not relevant or not +available then they can be set to NULL. The 'flags' parameter should be set +to zero. + +X509V3_set_ctx_test(ctx) + +This macro is used to set the 'ctx' structure to a 'test' value: this is to +allow the syntax of an extension (or configuration file) to be tested. + +X509V3_set_ctx_nodb(ctx) + +This macro is used when no configuration database is present. + +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash); + +This function is used to set the configuration database when it is an LHASH +structure: typically a configuration file. + +The following functions are used to access a configuration database: they +should only be used in RAW extensions. + +char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section); + +This function returns the value of the parameter "name" in "section", or NULL +if there has been an error. + +void X509V3_string_free(X509V3_CTX *ctx, char *str); + +This function frees up the string returned by the above function. + +STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section); + +This function returns a whole section as a STACK_OF(CONF_VALUE) . + +void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); + +This function frees up the STACK returned by the above function. + +Note: it is possible to use the extension code with a custom configuration +database. To do this the "db_meth" element of the X509V3_CTX structure should +be set to an X509V3_CTX_METHOD structure. This structure contains the following +function pointers: + +char * (*get_string)(void *db, char *section, char *value); +STACK_OF(CONF_VALUE) * (*get_section)(void *db, char *section); +void (*free_string)(void *db, char * string); +void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section); + +these will be called and passed the 'db' element in the X509V3_CTX structure +to access the database. If a given function is not implemented or not required +it can be set to NULL. + +5. String helper functions. + +There are several "i2s" and "s2i" functions that convert structures to and +from ASCII strings. In all the "i2s" cases the returned string should be +freed using Free() after use. Since some of these are part of other extension +code they may take a 'method' parameter. Unless otherwise stated it can be +safely set to NULL. + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct); + +This returns a hex string from an ASN1_OCTET_STRING. + +char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint); +char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint); + +These return a string decimal representations of an ASN1_INTEGER and an +ASN1_ENUMERATED type, respectively. + +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); + +This converts an ASCII hex string to an ASN1_OCTET_STRING. + +ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value); + +This converts a decimal ASCII string into an ASN1_INTEGER. + +6. Multi valued extension helper functions. + +The following functions can be used to manipulate STACKs of CONF_VALUE +structures, as used by multi valued extensions. + +int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool); + +This function expects a boolean value in 'value' and sets 'asn1_bool' to +it. That is it sets it to 0 for FALSE or 0xff for TRUE. The following +strings are acceptable: "TRUE", "true", "Y", "y", "YES", "yes", "FALSE" +"false", "N", "n", "NO" or "no". + +int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint); + +This accepts a decimal integer of arbitrary length and sets an ASN1_INTEGER. + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); + +This simply adds a string name and value pair. + +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); + +The same as above but for an unsigned character value. + +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); + +This adds either "TRUE" or "FALSE" depending on the value of 'ans1_bool' + +int X509V3_add_value_bool_nf(char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); + +This is the same as above except it adds nothing if asn1_bool is FALSE. + +int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); + +This function adds the value of the ASN1_INTEGER in decimal form. + +7. Other helper functions. + + + +ADDING CUSTOM EXTENSIONS. + +Currently there are three types of supported extensions. + +String extensions are simple strings where the value is placed directly in the +extensions, and the string returned is printed out. + +Multi value extensions are passed a STACK_OF(CONF_VALUE) name and value pairs +or return a STACK_OF(CONF_VALUE). + +Raw extensions are just passed a BIO or a value and it is the extensions +responsiblity to handle all the necessary printing. + +There are two ways to add an extension. One is simply as an alias to an already +existing extension. An alias is an extension that is identical in ASN1 structure +to an existing extension but has a different OBJECT IDENTIFIER. This can be +done by calling: + +int X509V3_EXT_add_alias(int nid_to, int nid_from); + +'nid_to' is the new extension NID and 'nid_from' is the already existing +extension NID. + +Alternatively an extension can be written from scratch. This involves writing +the ASN1 code to encode and decode the extension and functions to print out and +generate the extension from strings. The relevant functions are then placed in +a X509V3_EXT_METHOD structure and int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +called. + +The X509V3_EXT_METHOD structure is described below. + +strut { +int ext_nid; +int ext_flags; +X509V3_EXT_NEW ext_new; +X509V3_EXT_FREE ext_free; +X509V3_EXT_D2I d2i; +X509V3_EXT_I2D i2d; +X509V3_EXT_I2S i2s; +X509V3_EXT_S2I s2i; +X509V3_EXT_I2V i2v; +X509V3_EXT_V2I v2i; +X509V3_EXT_R2I r2i; +X509V3_EXT_I2R i2r; + +void *usr_data; +}; + +The elements have the following meanings. + +ext_nid is the NID of the object identifier of the extension. + +ext_flags is set of flags. Currently the only external flag is + X509V3_EXT_MULTILINE which means a multi valued extensions + should be printed on separate lines. + +usr_data is an extension specific pointer to any relevant data. This + allows extensions to share identical code but have different + uses. An example of this is the bit string extension which uses + usr_data to contain a list of the bit names. + +All the remaining elements are function pointers. + +ext_new is a pointer to a function that allocates memory for the + extension ASN1 structure: for example ASN1_OBJECT_new(). + +ext_free is a pointer to a function that free up memory of the extension + ASN1 structure: for example ASN1_OBJECT_free(). + +d2i is the standard ASN1 function that converts a DER buffer into + the internal ASN1 structure: for example d2i_ASN1_IA5STRING(). + +i2d is the standard ASN1 function that converts the internal + structure into the DER representation: for example + i2d_ASN1_IA5STRING(). + +The remaining functions are depend on the type of extension. One i2X and +one X2i should be set and the rest set to NULL. The types set do not need +to match up, for example the extension could be set using the multi valued +v2i function and printed out using the raw i2r. + +All functions have the X509V3_EXT_METHOD passed to them in the 'method' +parameter and an X509V3_CTX structure. Extension code can then access the +parent structure via the 'method' parameter to for example make use of the value +of usr_data. If the code needs to use detail relating to the request it can +use the 'ctx' parameter. + +A note should be given here about the 'flags' member of the 'ctx' parameter. +If it has the value CTX_TEST then the configuration syntax is being checked +and no actual certificate or CRL exists. Therefore any attempt in the config +file to access such information should silently succeed. If the syntax is OK +then it should simply return a (possibly bogus) extension, otherwise it +should return NULL. + +char *i2s(struct v3_ext_method *method, void *ext); + +This function takes the internal structure in the ext parameter and returns +a Malloc'ed string representing its value. + +void * s2i(struct v3_ext_method *method, struct v3_ext_ctx *ctx, char *str); + +This function takes the string representation in the ext parameter and returns +an allocated internal structure: ext_free() will be used on this internal +structure after use. + +i2v and v2i handle a STACK_OF(CONF_VALUE): + +typedef struct +{ + char *section; + char *name; + char *value; +} CONF_VALUE; + +Only the name and value members are currently used. + +STACK_OF(CONF_VALUE) * i2v(struct v3_ext_method *method, void *ext); + +This function is passed the internal structure in the ext parameter and +returns a STACK of CONF_VALUE structures. The values of name, value, +section and the structure itself will be freed up with Free after use. +Several helper functions are available to add values to this STACK. + +void * v2i(struct v3_ext_method *method, struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values); + +This function takes a STACK_OF(CONF_VALUE) structures and should set the +values of the external structure. This typically uses the name element to +determine which structure element to set and the value element to determine +what to set it to. Several helper functions are available for this +purpose (see above). + +int i2r(struct v3_ext_method *method, void *ext, BIO *out, int indent); + +This function is passed the internal extension structure in the ext parameter +and sends out a human readable version of the extension to out. The 'indent' +paremeter should be noted to determine the necessary amount of indentation +needed on the output. + +void * r2i(struct v3_ext_method *method, struct v3_ext_ctx *ctx, char *str); + +This is just passed the string representation of the extension. It is intended +to be used for more elaborate extensions where the standard single and multi +valued options are insufficient. They can use the 'ctx' parameter to parse the +configuration database themselves. See the context functions section for details +of how to do this. + +Note: although this type takes the same parameters as the "r2s" function there +is a subtle difference. Whereas an "r2i" function can access a configuration +database an "s2i" function MUST NOT. This is so the internal code can safely +assume that an "s2i" function will work without a configuration database. + +============================================================================== + PKCS#12 Library +============================================================================== + +This section describes the internal PKCS#12 support. There are very few +differences between the old external library and the new internal code at +present. This may well change because the external library will not be updated +much in future. + +This version now includes a couple of high level PKCS#12 functions which +generally "do the right thing" and should make it much easier to handle PKCS#12 +structures. + +HIGH LEVEL FUNCTIONS. + +For most applications you only need concern yourself with the high level +functions. They can parse and generate simple PKCS#12 files as produced by +Netscape and MSIE or indeed any compliant PKCS#12 file containing a single +private key and certificate pair. + +1. Initialisation and cleanup. + +No special initialisation is needed for the internal PKCS#12 library: the +standard SSLeay_add_all_algorithms() is sufficient. If you do not wish to +add all algorithms (you should at least add SHA1 though) then you can manually +initialise the PKCS#12 library with: + +PKCS12_PBE_add(); + +The memory allocated by the PKCS#12 library is freed up when EVP_cleanup() is +called or it can be directly freed with: + +EVP_PBE_cleanup(); + +after this call (or EVP_cleanup() ) no more PKCS#12 library functions should +be called. + +2. I/O functions. + +i2d_PKCS12_bio(bp, p12) + +This writes out a PKCS12 structure to a BIO. + +i2d_PKCS12_fp(fp, p12) + +This is the same but for a FILE pointer. + +d2i_PKCS12_bio(bp, p12) + +This reads in a PKCS12 structure from a BIO. + +d2i_PKCS12_fp(fp, p12) + +This is the same but for a FILE pointer. + +3. Parsing and creation functions. + +3.1 Parsing with PKCS12_parse(). + +int PKCS12_parse(PKCS12 *p12, char *pass, EVP_PKEY **pkey, X509 **cert, + STACK **ca); + +This function takes a PKCS12 structure and a password (ASCII, null terminated) +and returns the private key, the corresponding certificate and any CA +certificates. If any of these is not required it can be passed as a NULL. +The 'ca' parameter should be either NULL, a pointer to NULL or a valid STACK +structure. Typically to read in a PKCS#12 file you might do: + +p12 = d2i_PKCS12_fp(fp, NULL); +PKCS12_parse(p12, password, &pkey, &cert, NULL); /* CAs not wanted */ +PKCS12_free(p12); + +3.2 PKCS#12 creation with PKCS12_create(). + +PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, + STACK *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype); + +This function will create a PKCS12 structure from a given password, name, +private key, certificate and optional STACK of CA certificates. The remaining +5 parameters can be set to 0 and sensible defaults will be used. + +The parameters nid_key and nid_cert are the key and certificate encryption +algorithms, iter is the encryption iteration count, mac_iter is the MAC +iteration count and keytype is the type of private key. If you really want +to know what these last 5 parameters do then read the low level section. + +Typically to create a PKCS#12 file the following could be used: + +p12 = PKCS12_create(pass, "My Certificate", pkey, cert, NULL, 0,0,0,0,0); +i2d_PKCS12_fp(fp, p12); +PKCS12_free(p12); + +LOW LEVEL FUNCTIONS. + +In some cases the high level functions do not provide the necessary +functionality. For example if you want to generate or parse more complex +PKCS#12 files. The sample pkcs12 application uses the low level functions +to display details about the internal structure of a PKCS#12 file. + +Introduction. + +This is a brief description of how a PKCS#12 file is represented internally: +some knowledge of PKCS#12 is assumed. + +A PKCS#12 object contains several levels. + +At the lowest level is a PKCS12_SAFEBAG. This can contain a certificate, a +CRL, a private key, encrypted or unencrypted, a set of safebags (so the +structure can be nested) or other secrets (not documented at present). +A safebag can optionally have attributes, currently these are: a unicode +friendlyName (a Unicode string) or a localKeyID (a string of bytes). + +At the next level is an authSafe which is a set of safebags collected into +a PKCS#7 ContentInfo. This can be just plain data, or encrypted itself. + +At the top level is the PKCS12 structure itself which contains a set of +authSafes in an embedded PKCS#7 Contentinfo of type data. In addition it +contains a MAC which is a kind of password protected digest to preserve +integrity (so any unencrypted stuff below can't be tampered with). + +The reason for these levels is so various objects can be encrypted in various +ways. For example you might want to encrypt a set of private keys with +triple-DES and then include the related certificates either unencrypted or +with lower encryption. Yes it's the dreaded crypto laws at work again which +allow strong encryption on private keys and only weak encryption on other +stuff. + +To build one of these things you turn all certificates and keys into safebags +(with optional attributes). You collect the safebags into (one or more) STACKS +and convert these into authsafes (encrypted or unencrypted). The authsafes +are collected into a STACK and added to a PKCS12 structure. Finally a MAC +inserted. + +Pulling one apart is basically the reverse process. The MAC is verified against +the given password. The authsafes are extracted and each authsafe split into +a set of safebags (possibly involving decryption). Finally the safebags are +decomposed into the original keys and certificates and the attributes used to +match up private key and certificate pairs. + +Anyway here are the functions that do the dirty work. + +1. Construction functions. + +1.1 Safebag functions. + +M_PKCS12_x5092certbag(x509) + +This macro takes an X509 structure and returns a certificate bag. The +X509 structure can be freed up after calling this function. + +M_PKCS12_x509crl2certbag(crl) + +As above but for a CRL. + +PKCS8_PRIV_KEY_INFO *PKEY2PKCS8(EVP_PKEY *pkey) + +Take a private key and convert it into a PKCS#8 PrivateKeyInfo structure. +Works for both RSA and DSA private keys. NB since the PKCS#8 PrivateKeyInfo +structure contains a private key data in plain text form it should be free'd +up as soon as it has been encrypted for security reasons (freeing up the +structure zeros out the sensitive data). This can be done with +PKCS8_PRIV_KEY_INFO_free(). + +PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage) + +This sets the key type when a key is imported into MSIE or Outlook 98. Two +values are currently supported: KEY_EX and KEY_SIG. KEY_EX is an exchange type +key that can also be used for signing but its size is limited in the export +versions of MS software to 512 bits, it is also the default. KEY_SIG is a +signing only key but the keysize is unlimited (well 16K is supposed to work). +If you are using the domestic version of MSIE then you can ignore this because +KEY_EX is not limited and can be used for both. + +PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8) + +Convert a PKCS8 private key structure into a keybag. This routine embeds the +p8 structure in the keybag so p8 should not be freed up or used after it is +called. The p8 structure will be freed up when the safebag is freed. + +PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8) + +Convert a PKCS#8 structure into a shrouded key bag (encrypted). p8 is not +embedded and can be freed up after use. + +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen) +int PKCS12_add_friendlyname(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen) + +Add a local key id or a friendlyname to a safebag. + +1.2 Authsafe functions. + +PKCS7 *PKCS12_pack_p7data(STACK *sk) +Take a stack of safebags and convert them into an unencrypted authsafe. The +stack of safebags can be freed up after calling this function. + +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int iter, STACK *bags); + +As above but encrypted. + +1.3 PKCS12 functions. + +PKCS12 *PKCS12_init(int mode) + +Initialise a PKCS12 structure (currently mode should be NID_pkcs7_data). + +M_PKCS12_pack_authsafes(p12, safes) + +This macro takes a STACK of authsafes and adds them to a PKCS#12 structure. + +int PKCS12_set_mac(PKCS12 *p12, unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int iter, EVP_MD *md_type); + +Add a MAC to a PKCS12 structure. If EVP_MD is NULL use SHA-1, the spec suggests +that SHA-1 should be used. + +2. Extraction Functions. + +2.1 Safebags. + +M_PKCS12_bag_type(bag) + +Return the type of "bag". Returns one of the following + +NID_keyBag +NID_pkcs8ShroudedKeyBag 7 +NID_certBag 8 +NID_crlBag 9 +NID_secretBag 10 +NID_safeContentsBag 11 + +M_PKCS12_cert_bag_type(bag) + +Returns type of certificate bag, following are understood. + +NID_x509Certificate 14 +NID_sdsiCertificate 15 + +M_PKCS12_crl_bag_type(bag) + +Returns crl bag type, currently only NID_crlBag is recognised. + +M_PKCS12_certbag2x509(bag) + +This macro extracts an X509 certificate from a certificate bag. + +M_PKCS12_certbag2x509crl(bag) + +As above but for a CRL. + +EVP_PKEY * PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) + +Extract a private key from a PKCS8 private key info structure. + +M_PKCS12_decrypt_skey(bag, pass, passlen) + +Decrypt a shrouded key bag and return a PKCS8 private key info structure. +Works with both RSA and DSA keys + +char *PKCS12_get_friendlyname(bag) + +Returns the friendlyName of a bag if present or NULL if none. The returned +string is a null terminated ASCII string allocated with Malloc(). It should +thus be freed up with Free() after use. + +2.2 AuthSafe functions. + +M_PKCS12_unpack_p7data(p7) + +Extract a STACK of safe bags from a PKCS#7 data ContentInfo. + +#define M_PKCS12_unpack_p7encdata(p7, pass, passlen) + +As above but for an encrypted content info. + +2.3 PKCS12 functions. + +M_PKCS12_unpack_authsafes(p12) + +Extract a STACK of authsafes from a PKCS12 structure. + +M_PKCS12_mac_present(p12) + +Check to see if a MAC is present. + +int PKCS12_verify_mac(PKCS12 *p12, unsigned char *pass, int passlen) + +Verify a MAC on a PKCS12 structure. Returns an error if MAC not present. + + +Notes. + +1. All the function return 0 or NULL on error. +2. Encryption based functions take a common set of parameters. These are +described below. + +pass, passlen +ASCII password and length. The password on the MAC is called the "integrity +password" the encryption password is called the "privacy password" in the +PKCS#12 documentation. The passwords do not have to be the same. If -1 is +passed for the length it is worked out by the function itself (currently +this is sometimes done whatever is passed as the length but that may change). + +salt, saltlen +A 'salt' if salt is NULL a random salt is used. If saltlen is also zero a +default length is used. + +iter +Iteration count. This is a measure of how many times an internal function is +called to encrypt the data. The larger this value is the longer it takes, it +makes dictionary attacks on passwords harder. NOTE: Some implementations do +not support an iteration count on the MAC. If the password for the MAC and +encryption is the same then there is no point in having a high iteration +count for encryption if the MAC has no count. The MAC could be attacked +and the password used for the main decryption. + +pbe_nid +This is the NID of the password based encryption method used. The following are +supported. +NID_pbe_WithSHA1And128BitRC4 +NID_pbe_WithSHA1And40BitRC4 +NID_pbe_WithSHA1And3_Key_TripleDES_CBC +NID_pbe_WithSHA1And2_Key_TripleDES_CBC +NID_pbe_WithSHA1And128BitRC2_CBC +NID_pbe_WithSHA1And40BitRC2_CBC + +Which you use depends on the implementation you are exporting to. "Export +grade" (i.e. cryptographically challenged) products cannot support all +algorithms. Typically you may be able to use any encryption on shrouded key +bags but they must then be placed in an unencrypted authsafe. Other authsafes +may only support 40bit encryption. Of course if you are using SSLeay +throughout you can strongly encrypt everything and have high iteration counts +on everything. + +3. For decryption routines only the password and length are needed. + +4. Unlike the external version the nid's of objects are the values of the +constants: that is NID_certBag is the real nid, therefore there is no +PKCS12_obj_offset() function. Note the object constants are not the same as +those of the external version. If you use these constants then you will need +to recompile your code. + +5. With the exception of PKCS12_MAKE_KEYBAG(), after calling any function or +macro of the form PKCS12_MAKE_SOMETHING(other) the "other" structure can be +reused or freed up safely. + diff --git a/src/lib/libssl/doc/standards.txt b/src/lib/libssl/doc/standards.txt new file mode 100644 index 0000000000..61ccc5d7e0 --- /dev/null +++ b/src/lib/libssl/doc/standards.txt @@ -0,0 +1,121 @@ +Standards related to OpenSSL +============================ + +[Please, this is currently a draft. I made a first try at finding + documents that describe parts of what OpenSSL implements. There are + big gaps, and I've most certainly done something wrong. Please + correct whatever is... Also, this note should be removed when this + file is reaching a somewhat correct state. -- Richard Levitte] + + +All pointers in here will be either URL's or blobs of text borrowed +from miscellaneous indexes, like rfc-index.txt (index of RFCs), +1id-index.txt (index of Internet drafts) and the like. + +To find the latest possible RFCs, it's recommended to either browse +ftp://ftp.isi.edu/in-notes/ or go to http://www.rfc-editor.org/ and +use the search mechanism found there. +To find the latest possible Internet drafts, it's recommended to +browse ftp://ftp.isi.edu/internet-drafts/. +To find the latest possible PKCS, it's recommended to browse +http://www.rsasecurity.com/rsalabs/pkcs/. + + +Implemented: +------------ + +These are documents that describe things that are implemented in OpenSSL. + +1319 The MD2 Message-Digest Algorithm. B. Kaliski. April 1992. + (Format: TXT=25661 bytes) (Status: INFORMATIONAL) + +1320 The MD4 Message-Digest Algorithm. R. Rivest. April 1992. (Format: + TXT=32407 bytes) (Status: INFORMATIONAL) + +1321 The MD5 Message-Digest Algorithm. R. Rivest. April 1992. (Format: + TXT=35222 bytes) (Status: INFORMATIONAL) + +2246 The TLS Protocol Version 1.0. T. Dierks, C. Allen. January 1999. + (Format: TXT=170401 bytes) (Status: PROPOSED STANDARD) + +2268 A Description of the RC2(r) Encryption Algorithm. R. Rivest. + January 1998. (Format: TXT=19048 bytes) (Status: INFORMATIONAL) + +2314 PKCS 10: Certification Request Syntax Version 1.5. B. Kaliski. + March 1998. (Format: TXT=15814 bytes) (Status: INFORMATIONAL) + +2315 PKCS 7: Cryptographic Message Syntax Version 1.5. B. Kaliski. + March 1998. (Format: TXT=69679 bytes) (Status: INFORMATIONAL) + +2437 PKCS #1: RSA Cryptography Specifications Version 2.0. B. Kaliski, + J. Staddon. October 1998. (Format: TXT=73529 bytes) (Obsoletes + RFC2313) (Status: INFORMATIONAL) + +2459 Internet X.509 Public Key Infrastructure Certificate and CRL + Profile. R. Housley, W. Ford, W. Polk, D. Solo. January 1999. + (Format: TXT=278438 bytes) (Status: PROPOSED STANDARD) + +PKCS#8: Private-Key Information Syntax Standard + +PKCS#12: Personal Information Exchange Syntax Standard, version 1.0. + + +Related: +-------- + +These are documents that are close to OpenSSL, for example the +STARTTLS documents. + +1421 Privacy Enhancement for Internet Electronic Mail: Part I: Message + Encryption and Authentication Procedures. J. Linn. February 1993. + (Format: TXT=103894 bytes) (Obsoletes RFC1113) (Status: PROPOSED + STANDARD) + +1422 Privacy Enhancement for Internet Electronic Mail: Part II: + Certificate-Based Key Management. S. Kent. February 1993. (Format: + TXT=86085 bytes) (Obsoletes RFC1114) (Status: PROPOSED STANDARD) + +1423 Privacy Enhancement for Internet Electronic Mail: Part III: + Algorithms, Modes, and Identifiers. D. Balenson. February 1993. + (Format: TXT=33277 bytes) (Obsoletes RFC1115) (Status: PROPOSED + STANDARD) + +1424 Privacy Enhancement for Internet Electronic Mail: Part IV: Key + Certification and Related Services. B. Kaliski. February 1993. + (Format: TXT=17537 bytes) (Status: PROPOSED STANDARD) + +2487 SMTP Service Extension for Secure SMTP over TLS. P. Hoffman. + January 1999. (Format: TXT=15120 bytes) (Status: PROPOSED STANDARD) + +2585 Internet X.509 Public Key Infrastructure Operational Protocols: + FTP and HTTP. R. Housley, P. Hoffman. May 1999. (Format: TXT=14813 + bytes) (Status: PROPOSED STANDARD) + +2595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999. + (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD) + +2712 Addition of Kerberos Cipher Suites to Transport Layer Security + (TLS). A. Medvinsky, M. Hur. October 1999. (Format: TXT=13763 bytes) + (Status: PROPOSED STANDARD) + +2817 Upgrading to TLS Within HTTP/1.1. R. Khare, S. Lawrence. May + 2000. (Format: TXT=27598 bytes) (Updates RFC2616) (Status: PROPOSED + STANDARD) + +2818 HTTP Over TLS. E. Rescorla. May 2000. (Format: TXT=15170 bytes) + (Status: INFORMATIONAL) + + "Securing FTP with TLS", 01/27/2000, + + +To be implemented: +------------------ + +These are documents that describe things that are planed to be +implemented in the hopefully short future. + +2560 X.509 Internet Public Key Infrastructure Online Certificate + Status Protocol - OCSP. M. Myers, R. Ankney, A. Malpani, S. Galperin, + C. Adams. June 1999. (Format: TXT=43243 bytes) (Status: PROPOSED + STANDARD) + diff --git a/src/lib/libssl/test/VMSca-response.1 b/src/lib/libssl/test/VMSca-response.1 new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/lib/libssl/test/VMSca-response.1 @@ -0,0 +1 @@ + diff --git a/src/lib/libssl/test/VMSca-response.2 b/src/lib/libssl/test/VMSca-response.2 new file mode 100644 index 0000000000..9b48ee4cf9 --- /dev/null +++ b/src/lib/libssl/test/VMSca-response.2 @@ -0,0 +1,2 @@ +y +y diff --git a/src/lib/libssl/test/bctest b/src/lib/libssl/test/bctest new file mode 100644 index 0000000000..bdb3218f7a --- /dev/null +++ b/src/lib/libssl/test/bctest @@ -0,0 +1,111 @@ +#!/bin/sh + +# This script is used by test/Makefile.ssl to check whether a sane 'bc' +# is installed. +# ('make test_bn' should not try to run 'bc' if it does not exist or if +# it is a broken 'bc' version that is known to cause trouble.) +# +# If 'bc' works, we also test if it knows the 'print' command. +# +# In any case, output an appropriate command line for running (or not +# running) bc. + + +IFS=: +try_without_dir=true +# First we try "bc", then "$dir/bc" for each item in $PATH. +for dir in dummy:$PATH; do + if [ "$try_without_dir" = true ]; then + # first iteration + bc=bc + try_without_dir=false + else + # second and later iterations + bc="$dir/bc" + if [ ! -f "$bc" ]; then # '-x' is not available on Ultrix + bc='' + fi + fi + + if [ ! "$bc" = '' ]; then + failure=none + + + # Test for SunOS 5.[78] bc bug + "$bc" >tmp.bctest <<\EOF +obase=16 +ibase=16 +a=AD88C418F31B3FC712D0425001D522B3AE9134FF3A98C13C1FCC1682211195406C1A6C66C6A\ +CEEC1A0EC16950233F77F1C2F2363D56DD71A36C57E0B2511FC4BA8F22D261FE2E9356D99AF57\ +10F3817C0E05BF79C423C3F66FDF321BE8D3F18F625D91B670931C1EF25F28E489BDA1C5422D1\ +C3F6F7A1AD21585746ECC4F10A14A778AF56F08898E965E9909E965E0CB6F85B514150C644759\ +3BE731877B16EA07B552088FF2EA728AC5E0FF3A23EB939304519AB8B60F2C33D6BA0945B66F0\ +4FC3CADF855448B24A9D7640BCF473E +b=DCE91E7D120B983EA9A104B5A96D634DD644C37657B1C7860B45E6838999B3DCE5A555583C6\ +9209E41F413422954175A06E67FFEF6746DD652F0F48AEFECC3D8CAC13523BDAAD3F5AF4212BD\ +8B3CD64126E1A82E190228020C05B91C8B141F1110086FC2A4C6ED631EBA129D04BB9A19FC53D\ +3ED0E2017D60A68775B75481449 +(a/b)*b + (a%b) - a +EOF + if [ 0 != "`cat tmp.bctest`" ]; then + failure=SunOStest + fi + + + if [ "$failure" = none ]; then + # Test for SCO bc bug. + "$bc" >tmp.bctest <<\EOF +obase=16 +ibase=16 +-FFDD63BA1A4648F0D804F8A1C66C53F0D2110590E8A3907EC73B4AEC6F15AC177F176F2274D2\ +9DC8022EA0D7DD3ABE9746D2D46DD3EA5B5F6F69DF12877E0AC5E7F5ADFACEE54573F5D256A06\ +11B5D2BC24947724E22AE4EC3FB0C39D9B4694A01AFE5E43B4D99FB9812A0E4A5773D8B254117\ +1239157EC6E3D8D50199 * -FFDD63BA1A4648F0D804F8A1C66C53F0D2110590E8A3907EC73B4\ +AEC6F15AC177F176F2274D29DC8022EA0D7DD3ABE9746D2D46DD3EA5B5F6F69DF12877E0AC5E7\ +F5ADFACEE54573F5D256A0611B5D2BC24947724E22AE4EC3FB0C39D9B4694A01AFE5E43B4D99F\ +B9812A0E4A5773D8B2541171239157EC6E3D8D50199 - FFBACC221682DA464B6D7F123482522\ +02EDAEDCA38C3B69E9B7BBCD6165A9CD8716C4903417F23C09A85B851961F92C217258CEEB866\ +85EFCC5DD131853A02C07A873B8E2AF2E40C6D5ED598CD0E8F35AD49F3C3A17FDB7653E4E2DC4\ +A8D23CC34686EE4AD01F7407A7CD74429AC6D36DBF0CB6A3E302D0E5BDFCD048A3B90C1BE5AA8\ +E16C3D5884F9136B43FF7BB443764153D4AEC176C681B078F4CC53D6EB6AB76285537DDEE7C18\ +8C72441B52EDBDDBC77E02D34E513F2AABF92F44109CAFE8242BD0ECBAC5604A94B02EA44D43C\ +04E9476E6FBC48043916BFA1485C6093603600273C9C33F13114D78064AE42F3DC466C7DA543D\ +89C8D71 +AD534AFBED2FA39EE9F40E20FCF9E2C861024DB98DDCBA1CD118C49CA55EEBC20D6BA51B2271C\ +928B693D6A73F67FEB1B4571448588B46194617D25D910C6A9A130CC963155CF34079CB218A44\ +8A1F57E276D92A33386DDCA3D241DB78C8974ABD71DD05B0FA555709C9910D745185E6FE108E3\ +37F1907D0C56F8BFBF52B9704 % -E557905B56B13441574CAFCE2BD257A750B1A8B2C88D0E36\ +E18EF7C38DAC80D3948E17ED63AFF3B3467866E3B89D09A81B3D16B52F6A3C7134D3C6F5123E9\ +F617E3145BBFBE9AFD0D6E437EA4FF6F04BC67C4F1458B4F0F47B64 - 1C2BBBB19B74E86FD32\ +9E8DB6A8C3B1B9986D57ED5419C2E855F7D5469E35E76334BB42F4C43E3F3A31B9697C171DAC4\ +D97935A7E1A14AD209D6CF811F55C6DB83AA9E6DFECFCD6669DED7171EE22A40C6181615CAF3F\ +5296964 +EOF + if [ "0 +0" != "`cat tmp.bctest`" ]; then + failure=SCOtest + fi + fi + + + if [ "$failure" = none ]; then + # bc works; now check if it knows the 'print' command. + if [ "OK" = "`echo 'print \"OK\"' | $bc 2>/dev/null`" ] + then + echo "$bc" + else + echo "sed 's/print.*//' | $bc" + fi + exit 0 + fi + + echo "$bc does not work properly ('$failure' failed). Looking for another bc ..." >&2 + fi +done + +echo "No working bc found. Consider installing GNU bc." >&2 +if [ "$1" = ignore ]; then + echo "cat >/dev/null" + exit 0 +fi +exit 1 -- cgit v1.2.3-55-g6feb From 15b5d84f9da2ce4bfae8580e56e34a859f74ad71 Mon Sep 17 00:00:00 2001 From: markus <> Date: Thu, 5 Sep 2002 12:51:50 +0000 Subject: import openssl-0.9.7-beta1 --- src/lib/libcrypto/aes/aes_cfb.c | 2 +- src/lib/libcrypto/aes/aes_ctr.c | 2 +- src/lib/libcrypto/asn1/a_bitstr.c | 120 +- src/lib/libcrypto/asn1/a_bool.c | 17 +- src/lib/libcrypto/asn1/a_bytes.c | 78 +- src/lib/libcrypto/asn1/a_d2i_fp.c | 87 +- src/lib/libcrypto/asn1/a_digest.c | 49 +- src/lib/libcrypto/asn1/a_dup.c | 37 +- src/lib/libcrypto/asn1/a_enum.c | 182 +- src/lib/libcrypto/asn1/a_i2d_fp.c | 70 +- src/lib/libcrypto/asn1/a_int.c | 281 ++- src/lib/libcrypto/asn1/a_mbstr.c | 20 +- src/lib/libcrypto/asn1/a_object.c | 195 +- src/lib/libcrypto/asn1/a_octet.c | 33 +- src/lib/libcrypto/asn1/a_print.c | 56 +- src/lib/libcrypto/asn1/a_set.c | 117 +- src/lib/libcrypto/asn1/a_sign.c | 195 +- src/lib/libcrypto/asn1/a_strex.c | 32 +- src/lib/libcrypto/asn1/a_strnid.c | 29 +- src/lib/libcrypto/asn1/a_time.c | 79 +- src/lib/libcrypto/asn1/a_type.c | 256 +-- src/lib/libcrypto/asn1/a_utf8.c | 162 +- src/lib/libcrypto/asn1/a_verify.c | 92 +- src/lib/libcrypto/asn1/asn1.h | 1180 +++++++----- src/lib/libcrypto/asn1/asn1_err.c | 308 ++- src/lib/libcrypto/asn1/asn1_lib.c | 154 +- src/lib/libcrypto/asn1/asn1_mac.h | 377 +++- src/lib/libcrypto/asn1/asn1_par.c | 198 +- src/lib/libcrypto/asn1/asn_pack.c | 56 +- src/lib/libcrypto/asn1/d2i_pr.c | 56 +- src/lib/libcrypto/asn1/d2i_pu.c | 33 +- src/lib/libcrypto/asn1/evp_asn1.c | 62 +- src/lib/libcrypto/asn1/f_enum.c | 6 +- src/lib/libcrypto/asn1/f_int.c | 39 +- src/lib/libcrypto/asn1/f_string.c | 32 +- src/lib/libcrypto/asn1/i2d_pr.c | 20 +- src/lib/libcrypto/asn1/i2d_pu.c | 20 +- src/lib/libcrypto/asn1/n_pkey.c | 346 ++-- src/lib/libcrypto/asn1/nsseq.c | 64 +- src/lib/libcrypto/asn1/p5_pbe.c | 52 +- src/lib/libcrypto/asn1/p5_pbev2.c | 137 +- src/lib/libcrypto/asn1/p8_pkey.c | 81 +- src/lib/libcrypto/asn1/t_crl.c | 49 +- src/lib/libcrypto/asn1/t_pkey.c | 117 +- src/lib/libcrypto/asn1/t_req.c | 112 +- src/lib/libcrypto/asn1/t_spki.c | 6 +- src/lib/libcrypto/asn1/t_x509.c | 424 ++-- src/lib/libcrypto/asn1/t_x509a.c | 10 +- src/lib/libcrypto/asn1/x_algor.c | 179 +- src/lib/libcrypto/asn1/x_attrib.c | 128 +- src/lib/libcrypto/asn1/x_crl.c | 371 +--- src/lib/libcrypto/asn1/x_exten.c | 209 +- src/lib/libcrypto/asn1/x_info.c | 19 +- src/lib/libcrypto/asn1/x_long.c | 10 +- src/lib/libcrypto/asn1/x_name.c | 371 ++-- src/lib/libcrypto/asn1/x_pkey.c | 35 +- src/lib/libcrypto/asn1/x_pubkey.c | 236 ++- src/lib/libcrypto/asn1/x_req.c | 223 +-- src/lib/libcrypto/asn1/x_sig.c | 64 +- src/lib/libcrypto/asn1/x_spki.c | 128 +- src/lib/libcrypto/asn1/x_val.c | 63 +- src/lib/libcrypto/asn1/x_x509.c | 187 +- src/lib/libcrypto/asn1/x_x509a.c | 83 +- src/lib/libcrypto/bf/asm/bf-586.pl | 4 +- src/lib/libcrypto/bf/bf_cbc.c | 39 +- src/lib/libcrypto/bf/bf_cfb64.c | 12 +- src/lib/libcrypto/bf/bf_ecb.c | 20 +- src/lib/libcrypto/bf/bf_enc.c | 129 +- src/lib/libcrypto/bf/bf_locl.h | 6 +- src/lib/libcrypto/bf/bf_ofb64.c | 11 +- src/lib/libcrypto/bf/bf_pi.h | 2 +- src/lib/libcrypto/bf/bf_skey.c | 11 +- src/lib/libcrypto/bf/blowfish.h | 67 +- src/lib/libcrypto/bio/b_dump.c | 129 +- src/lib/libcrypto/bio/b_print.c | 771 +++++++- src/lib/libcrypto/bio/b_sock.c | 386 ++-- src/lib/libcrypto/bio/bf_buff.c | 120 +- src/lib/libcrypto/bio/bf_lbuf.c | 12 +- src/lib/libcrypto/bio/bf_nbio.c | 79 +- src/lib/libcrypto/bio/bf_null.c | 73 +- src/lib/libcrypto/bio/bio.h | 456 ++--- src/lib/libcrypto/bio/bio_cb.c | 15 +- src/lib/libcrypto/bio/bio_err.c | 149 +- src/lib/libcrypto/bio/bio_lib.c | 208 +- src/lib/libcrypto/bio/bss_acpt.c | 167 +- src/lib/libcrypto/bio/bss_bio.c | 318 ++- src/lib/libcrypto/bio/bss_conn.c | 220 +-- src/lib/libcrypto/bio/bss_fd.c | 226 ++- src/lib/libcrypto/bio/bss_file.c | 91 +- src/lib/libcrypto/bio/bss_log.c | 325 +++- src/lib/libcrypto/bio/bss_mem.c | 130 +- src/lib/libcrypto/bio/bss_null.c | 57 +- src/lib/libcrypto/bio/bss_sock.c | 220 +-- src/lib/libcrypto/bn/asm/bn-586.pl | 295 ++- src/lib/libcrypto/bn/asm/pa-risc2.s | 2024 ++++++++++++++++---- src/lib/libcrypto/bn/asm/pa-risc2W.s | 2 +- src/lib/libcrypto/bn/bn.h | 290 ++- src/lib/libcrypto/bn/bn_add.c | 206 +- src/lib/libcrypto/bn/bn_asm.c | 178 +- src/lib/libcrypto/bn/bn_blind.c | 47 +- src/lib/libcrypto/bn/bn_ctx.c | 17 +- src/lib/libcrypto/bn/bn_div.c | 221 ++- src/lib/libcrypto/bn/bn_err.c | 142 +- src/lib/libcrypto/bn/bn_exp.c | 600 ++++-- src/lib/libcrypto/bn/bn_exp2.c | 382 ++-- src/lib/libcrypto/bn/bn_gcd.c | 389 +++- src/lib/libcrypto/bn/bn_lcl.h | 291 ++- src/lib/libcrypto/bn/bn_lib.c | 571 ++++-- src/lib/libcrypto/bn/bn_mod.c | 251 ++- src/lib/libcrypto/bn/bn_mont.c | 335 ++-- src/lib/libcrypto/bn/bn_mpi.c | 11 +- src/lib/libcrypto/bn/bn_mul.c | 1158 ++++++++++- src/lib/libcrypto/bn/bn_prime.c | 459 +++-- src/lib/libcrypto/bn/bn_prime.h | 4 +- src/lib/libcrypto/bn/bn_prime.pl | 71 +- src/lib/libcrypto/bn/bn_print.c | 67 +- src/lib/libcrypto/bn/bn_rand.c | 216 ++- src/lib/libcrypto/bn/bn_recp.c | 183 +- src/lib/libcrypto/bn/bn_shift.c | 27 +- src/lib/libcrypto/bn/bn_sqr.c | 214 ++- src/lib/libcrypto/bn/bn_word.c | 47 +- src/lib/libcrypto/buffer/buf_err.c | 128 +- src/lib/libcrypto/buffer/buffer.c | 34 +- src/lib/libcrypto/buffer/buffer.h | 25 +- src/lib/libcrypto/cast/asm/cast-586.pl | 267 +-- src/lib/libcrypto/cast/c_cfb64.c | 25 +- src/lib/libcrypto/cast/c_ecb.c | 14 +- src/lib/libcrypto/cast/c_enc.c | 43 +- src/lib/libcrypto/cast/c_ofb64.c | 16 +- src/lib/libcrypto/cast/c_skey.c | 11 +- src/lib/libcrypto/cast/cast.h | 38 +- src/lib/libcrypto/cast/cast_lcl.h | 30 +- src/lib/libcrypto/cast/cast_s.h | 16 +- src/lib/libcrypto/comp/c_rle.c | 1 + src/lib/libcrypto/comp/c_zlib.c | 141 +- src/lib/libcrypto/comp/comp.h | 9 +- src/lib/libcrypto/comp/comp_err.c | 7 +- src/lib/libcrypto/comp/comp_lib.c | 6 +- src/lib/libcrypto/conf/conf.h | 170 +- src/lib/libcrypto/conf/conf_api.c | 49 +- src/lib/libcrypto/conf/conf_api.h | 12 +- src/lib/libcrypto/conf/conf_def.c | 62 +- src/lib/libcrypto/conf/conf_def.h | 143 +- src/lib/libcrypto/conf/conf_err.c | 150 +- src/lib/libcrypto/conf/conf_lib.c | 196 +- src/lib/libcrypto/conf/keysets.pl | 164 +- src/lib/libcrypto/cpt_err.c | 134 +- src/lib/libcrypto/cryptlib.c | 303 ++- src/lib/libcrypto/cryptlib.h | 38 +- src/lib/libcrypto/crypto.h | 430 +++-- src/lib/libcrypto/cversion.c | 45 +- src/lib/libcrypto/des/asm/crypt586.pl | 12 +- src/lib/libcrypto/des/asm/des-586.pl | 30 +- src/lib/libcrypto/des/asm/desboth.pl | 16 +- src/lib/libcrypto/des/cbc_cksm.c | 18 +- src/lib/libcrypto/des/cbc_enc.c | 78 +- src/lib/libcrypto/des/cfb64ede.c | 39 +- src/lib/libcrypto/des/cfb64enc.c | 27 +- src/lib/libcrypto/des/cfb_enc.c | 18 +- src/lib/libcrypto/des/des.h | 303 ++- src/lib/libcrypto/des/des_enc.c | 165 +- src/lib/libcrypto/des/des_locl.h | 89 +- src/lib/libcrypto/des/ecb3_enc.c | 20 +- src/lib/libcrypto/des/ecb_enc.c | 26 +- src/lib/libcrypto/des/ede_cbcm_enc.c | 24 +- src/lib/libcrypto/des/enc_read.c | 90 +- src/lib/libcrypto/des/enc_writ.c | 73 +- src/lib/libcrypto/des/fcrypt.c | 96 +- src/lib/libcrypto/des/fcrypt_b.c | 13 +- src/lib/libcrypto/des/ncbc_enc.c | 52 +- src/lib/libcrypto/des/ofb64ede.c | 32 +- src/lib/libcrypto/des/ofb64enc.c | 24 +- src/lib/libcrypto/des/ofb_enc.c | 16 +- src/lib/libcrypto/des/pcbc_enc.c | 23 +- src/lib/libcrypto/des/qud_cksm.c | 53 +- src/lib/libcrypto/des/rand_key.c | 162 +- src/lib/libcrypto/des/set_key.c | 273 ++- src/lib/libcrypto/des/spr.h | 2 +- src/lib/libcrypto/des/str2key.c | 70 +- src/lib/libcrypto/des/xcbc_enc.c | 57 +- src/lib/libcrypto/dh/dh.h | 131 +- src/lib/libcrypto/dh/dh_check.c | 18 +- src/lib/libcrypto/dh/dh_err.c | 126 +- src/lib/libcrypto/dh/dh_gen.c | 63 +- src/lib/libcrypto/dh/dh_key.c | 131 +- src/lib/libcrypto/dh/dh_lib.c | 159 +- src/lib/libcrypto/doc/DH_set_method.pod | 64 +- src/lib/libcrypto/doc/DSA_set_method.pod | 63 +- src/lib/libcrypto/doc/ERR_error_string.pod | 16 +- src/lib/libcrypto/doc/ERR_get_error.pod | 30 +- src/lib/libcrypto/doc/ERR_remove_state.pod | 2 +- src/lib/libcrypto/doc/EVP_DigestInit.pod | 124 +- src/lib/libcrypto/doc/EVP_EncryptInit.pod | 412 +++- src/lib/libcrypto/doc/EVP_OpenInit.pod | 28 +- src/lib/libcrypto/doc/EVP_SealInit.pod | 18 +- src/lib/libcrypto/doc/EVP_SignInit.pod | 41 +- src/lib/libcrypto/doc/EVP_VerifyInit.pod | 39 +- src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod | 59 +- .../libcrypto/doc/OpenSSL_add_all_algorithms.pod | 5 +- src/lib/libcrypto/doc/RAND_add.pod | 25 +- src/lib/libcrypto/doc/RAND_load_file.pod | 2 +- src/lib/libcrypto/doc/RAND_set_rand_method.pod | 4 +- src/lib/libcrypto/doc/RSA_generate_key.pod | 2 +- src/lib/libcrypto/doc/RSA_get_ex_new_index.pod | 14 +- src/lib/libcrypto/doc/RSA_print.pod | 5 +- src/lib/libcrypto/doc/RSA_public_encrypt.pod | 6 +- src/lib/libcrypto/doc/RSA_set_method.pod | 83 +- src/lib/libcrypto/doc/bn.pod | 18 +- src/lib/libcrypto/doc/dh.pod | 9 +- src/lib/libcrypto/doc/dsa.pod | 9 +- src/lib/libcrypto/doc/evp.pod | 2 +- src/lib/libcrypto/doc/rsa.pod | 17 +- src/lib/libcrypto/dsa/dsa.h | 180 +- src/lib/libcrypto/dsa/dsa_asn1.c | 200 +- src/lib/libcrypto/dsa/dsa_err.c | 133 +- src/lib/libcrypto/dsa/dsa_gen.c | 220 +-- src/lib/libcrypto/dsa/dsa_key.c | 25 +- src/lib/libcrypto/dsa/dsa_lib.c | 176 +- src/lib/libcrypto/dsa/dsa_ossl.c | 39 +- src/lib/libcrypto/dsa/dsa_sign.c | 166 +- src/lib/libcrypto/dsa/dsa_vrf.c | 109 +- src/lib/libcrypto/dso/dso.h | 168 +- src/lib/libcrypto/dso/dso_dlfcn.c | 99 +- src/lib/libcrypto/dso/dso_err.c | 23 +- src/lib/libcrypto/dso/dso_lib.c | 179 +- src/lib/libcrypto/ec/ec_lib.c | 8 + src/lib/libcrypto/engine/README | 483 ++--- src/lib/libcrypto/engine/eng_all.c | 22 +- src/lib/libcrypto/engine/eng_fat.c | 3 +- src/lib/libcrypto/engine/eng_init.c | 3 +- src/lib/libcrypto/engine/eng_list.c | 2 +- src/lib/libcrypto/engine/engine.h | 650 +++++-- src/lib/libcrypto/err/err.c | 938 ++++++--- src/lib/libcrypto/err/err.h | 260 +-- src/lib/libcrypto/err/err_all.c | 83 +- src/lib/libcrypto/err/err_prn.c | 62 +- src/lib/libcrypto/err/openssl.ec | 34 +- src/lib/libcrypto/evp/bio_b64.c | 93 +- src/lib/libcrypto/evp/bio_enc.c | 126 +- src/lib/libcrypto/evp/bio_md.c | 101 +- src/lib/libcrypto/evp/c_all.c | 130 +- src/lib/libcrypto/evp/digest.c | 259 ++- src/lib/libcrypto/evp/e_aes.c | 4 +- src/lib/libcrypto/evp/e_bf.c | 16 +- src/lib/libcrypto/evp/e_cast.c | 16 +- src/lib/libcrypto/evp/e_des.c | 21 +- src/lib/libcrypto/evp/e_des3.c | 88 +- src/lib/libcrypto/evp/e_idea.c | 22 +- src/lib/libcrypto/evp/e_null.c | 42 +- src/lib/libcrypto/evp/e_rc2.c | 67 +- src/lib/libcrypto/evp/e_rc4.c | 75 +- src/lib/libcrypto/evp/e_xcbc_d.c | 82 +- src/lib/libcrypto/evp/encode.c | 74 +- src/lib/libcrypto/evp/evp.h | 875 +++++---- src/lib/libcrypto/evp/evp_enc.c | 452 +++-- src/lib/libcrypto/evp/evp_err.c | 174 +- src/lib/libcrypto/evp/evp_key.c | 67 +- src/lib/libcrypto/evp/evp_lib.c | 55 +- src/lib/libcrypto/evp/evp_locl.h | 125 +- src/lib/libcrypto/evp/evp_pbe.c | 18 +- src/lib/libcrypto/evp/evp_pkey.c | 296 ++- src/lib/libcrypto/evp/m_dss.c | 31 +- src/lib/libcrypto/evp/m_dss1.c | 30 +- src/lib/libcrypto/evp/m_md4.c | 27 +- src/lib/libcrypto/evp/m_md5.c | 31 +- src/lib/libcrypto/evp/m_null.c | 31 +- src/lib/libcrypto/evp/m_ripemd.c | 31 +- src/lib/libcrypto/evp/m_sha1.c | 30 +- src/lib/libcrypto/evp/names.c | 244 +-- src/lib/libcrypto/evp/p5_crpt.c | 43 +- src/lib/libcrypto/evp/p5_crpt2.c | 17 +- src/lib/libcrypto/evp/p_dec.c | 23 +- src/lib/libcrypto/evp/p_enc.c | 23 +- src/lib/libcrypto/evp/p_lib.c | 145 +- src/lib/libcrypto/evp/p_open.c | 52 +- src/lib/libcrypto/evp/p_seal.c | 52 +- src/lib/libcrypto/evp/p_sign.c | 31 +- src/lib/libcrypto/evp/p_verify.c | 19 +- src/lib/libcrypto/ex_data.c | 646 +++++-- src/lib/libcrypto/hmac/hmac.c | 79 +- src/lib/libcrypto/hmac/hmac.h | 40 +- src/lib/libcrypto/idea/idea.h | 20 +- src/lib/libcrypto/lhash/lh_stats.c | 49 +- src/lib/libcrypto/lhash/lhash.c | 171 +- src/lib/libcrypto/lhash/lhash.h | 126 +- src/lib/libcrypto/md32_common.h | 57 +- src/lib/libcrypto/md4/md4.h | 14 +- src/lib/libcrypto/md4/md4_dgst.c | 3 +- src/lib/libcrypto/md4/md4_locl.h | 2 +- src/lib/libcrypto/md5/asm/md5-586.pl | 40 +- src/lib/libcrypto/md5/md5.h | 57 +- src/lib/libcrypto/md5/md5_dgst.c | 398 ++-- src/lib/libcrypto/md5/md5_locl.h | 167 +- src/lib/libcrypto/md5/md5_one.c | 28 +- src/lib/libcrypto/mem_dbg.c | 263 ++- src/lib/libcrypto/objects/o_names.c | 229 ++- src/lib/libcrypto/objects/obj_dat.c | 359 ++-- src/lib/libcrypto/objects/obj_dat.pl | 112 +- src/lib/libcrypto/objects/obj_err.c | 123 +- src/lib/libcrypto/objects/obj_lib.c | 39 +- src/lib/libcrypto/objects/obj_mac.num | 121 +- src/lib/libcrypto/objects/objects.h | 444 ++++- src/lib/libcrypto/objects/objects.pl | 17 +- src/lib/libcrypto/objects/objects.txt | 800 +++++++- src/lib/libcrypto/opensslv.h | 84 +- src/lib/libcrypto/pem/pem.h | 612 +++--- src/lib/libcrypto/pem/pem2.h | 8 + src/lib/libcrypto/pem/pem_all.c | 480 +---- src/lib/libcrypto/pem/pem_err.c | 129 +- src/lib/libcrypto/pem/pem_info.c | 99 +- src/lib/libcrypto/pem/pem_lib.c | 329 ++-- src/lib/libcrypto/pem/pem_seal.c | 84 +- src/lib/libcrypto/pem/pem_sign.c | 33 +- src/lib/libcrypto/perlasm/cbc.pl | 2 +- src/lib/libcrypto/perlasm/x86asm.pl | 17 +- src/lib/libcrypto/pkcs12/p12_add.c | 97 +- src/lib/libcrypto/pkcs12/p12_attr.c | 155 +- src/lib/libcrypto/pkcs12/p12_crpt.c | 10 +- src/lib/libcrypto/pkcs12/p12_crt.c | 37 +- src/lib/libcrypto/pkcs12/p12_decr.c | 77 +- src/lib/libcrypto/pkcs12/p12_init.c | 12 +- src/lib/libcrypto/pkcs12/p12_key.c | 96 +- src/lib/libcrypto/pkcs12/p12_kiss.c | 175 +- src/lib/libcrypto/pkcs12/p12_mutl.c | 35 +- src/lib/libcrypto/pkcs12/p12_npas.c | 47 +- src/lib/libcrypto/pkcs12/p12_utl.c | 58 +- src/lib/libcrypto/pkcs12/pk12err.c | 9 +- src/lib/libcrypto/pkcs12/pkcs12.h | 153 +- src/lib/libcrypto/pkcs7/pk7_attr.c | 90 +- src/lib/libcrypto/pkcs7/pk7_doit.c | 833 ++++++-- src/lib/libcrypto/pkcs7/pk7_lib.c | 208 +- src/lib/libcrypto/pkcs7/pk7_mime.c | 144 +- src/lib/libcrypto/pkcs7/pk7_smime.c | 60 +- src/lib/libcrypto/pkcs7/pkcs7.h | 390 ++-- src/lib/libcrypto/pkcs7/pkcs7err.c | 174 +- src/lib/libcrypto/rand/rand.h | 72 +- src/lib/libcrypto/rand/rand_err.c | 10 +- src/lib/libcrypto/rand/rand_lib.c | 104 +- src/lib/libcrypto/rand/randfile.c | 141 +- src/lib/libcrypto/rc2/rc2.h | 28 +- src/lib/libcrypto/rc2/rc2_cbc.c | 19 +- src/lib/libcrypto/rc2/rc2_ecb.c | 12 +- src/lib/libcrypto/rc2/rc2_skey.c | 8 +- src/lib/libcrypto/rc2/rc2cfb64.c | 13 +- src/lib/libcrypto/rc2/rc2ofb64.c | 12 +- src/lib/libcrypto/rc4/asm/rc4-586.pl | 2 +- src/lib/libcrypto/rc4/rc4.h | 14 +- src/lib/libcrypto/rc4/rc4_enc.c | 194 +- src/lib/libcrypto/rc4/rc4_skey.c | 12 +- src/lib/libcrypto/ripemd/asm/rmd-586.pl | 112 +- src/lib/libcrypto/ripemd/ripemd.h | 46 +- src/lib/libcrypto/ripemd/rmd_dgst.c | 471 +++-- src/lib/libcrypto/ripemd/rmd_locl.h | 182 +- src/lib/libcrypto/ripemd/rmd_one.c | 9 +- src/lib/libcrypto/rsa/rsa.h | 319 +-- src/lib/libcrypto/rsa/rsa_chk.c | 2 +- src/lib/libcrypto/rsa/rsa_eay.c | 555 ++++-- src/lib/libcrypto/rsa/rsa_err.c | 142 +- src/lib/libcrypto/rsa/rsa_gen.c | 120 +- src/lib/libcrypto/rsa/rsa_lib.c | 263 ++- src/lib/libcrypto/rsa/rsa_none.c | 47 +- src/lib/libcrypto/rsa/rsa_oaep.c | 292 +-- src/lib/libcrypto/rsa/rsa_pk1.c | 75 +- src/lib/libcrypto/rsa/rsa_saos.c | 41 +- src/lib/libcrypto/rsa/rsa_sign.c | 192 +- src/lib/libcrypto/rsa/rsa_ssl.c | 37 +- src/lib/libcrypto/sha/asm/sha1-586.pl | 115 +- src/lib/libcrypto/sha/sha.h | 72 +- src/lib/libcrypto/sha/sha1_one.c | 9 +- src/lib/libcrypto/sha/sha1dgst.c | 407 +--- src/lib/libcrypto/sha/sha_locl.h | 522 +++-- src/lib/libcrypto/stack/safestack.h | 1515 ++++++++++++++- src/lib/libcrypto/stack/stack.c | 163 +- src/lib/libcrypto/stack/stack.h | 41 +- src/lib/libcrypto/txt_db/txt_db.c | 79 +- src/lib/libcrypto/txt_db/txt_db.h | 29 +- src/lib/libcrypto/ui/ui_openssl.c | 2 +- src/lib/libcrypto/util/mkerr.pl | 234 ++- src/lib/libcrypto/util/mkstack.pl | 2 +- src/lib/libcrypto/x509/by_dir.c | 96 +- src/lib/libcrypto/x509/by_file.c | 106 +- src/lib/libcrypto/x509/x509.h | 1161 ++++++----- src/lib/libcrypto/x509/x509_att.c | 26 +- src/lib/libcrypto/x509/x509_cmp.c | 204 +- src/lib/libcrypto/x509/x509_d2.c | 23 +- src/lib/libcrypto/x509/x509_def.c | 18 +- src/lib/libcrypto/x509/x509_err.c | 162 +- src/lib/libcrypto/x509/x509_ext.c | 142 +- src/lib/libcrypto/x509/x509_lu.c | 481 +++-- src/lib/libcrypto/x509/x509_obj.c | 75 +- src/lib/libcrypto/x509/x509_r2x.c | 36 +- src/lib/libcrypto/x509/x509_req.c | 194 +- src/lib/libcrypto/x509/x509_set.c | 54 +- src/lib/libcrypto/x509/x509_trs.c | 65 +- src/lib/libcrypto/x509/x509_txt.c | 48 +- src/lib/libcrypto/x509/x509_v3.c | 237 +-- src/lib/libcrypto/x509/x509_vfy.c | 1067 ++++++++--- src/lib/libcrypto/x509/x509_vfy.h | 261 +-- src/lib/libcrypto/x509/x509name.c | 205 +- src/lib/libcrypto/x509/x509rset.c | 20 +- src/lib/libcrypto/x509/x509spki.c | 13 +- src/lib/libcrypto/x509/x509type.c | 13 +- src/lib/libcrypto/x509/x_all.c | 523 ++--- src/lib/libcrypto/x509v3/ext_dat.h | 16 +- src/lib/libcrypto/x509v3/v3_akey.c | 83 +- src/lib/libcrypto/x509v3/v3_alt.c | 129 +- src/lib/libcrypto/x509v3/v3_bcons.c | 58 +- src/lib/libcrypto/x509v3/v3_bitst.c | 11 +- src/lib/libcrypto/x509v3/v3_conf.c | 387 ++-- src/lib/libcrypto/x509v3/v3_cpols.c | 355 +--- src/lib/libcrypto/x509v3/v3_crld.c | 181 +- src/lib/libcrypto/x509v3/v3_enum.c | 19 +- src/lib/libcrypto/x509v3/v3_extku.c | 132 +- src/lib/libcrypto/x509v3/v3_genn.c | 210 +- src/lib/libcrypto/x509v3/v3_ia5.c | 15 +- src/lib/libcrypto/x509v3/v3_info.c | 138 +- src/lib/libcrypto/x509v3/v3_int.c | 18 +- src/lib/libcrypto/x509v3/v3_lib.c | 190 +- src/lib/libcrypto/x509v3/v3_pku.c | 61 +- src/lib/libcrypto/x509v3/v3_prn.c | 112 +- src/lib/libcrypto/x509v3/v3_purp.c | 271 ++- src/lib/libcrypto/x509v3/v3_skey.c | 32 +- src/lib/libcrypto/x509v3/v3_sxnet.c | 132 +- src/lib/libcrypto/x509v3/v3_utl.c | 171 +- src/lib/libcrypto/x509v3/v3err.c | 16 +- src/lib/libcrypto/x509v3/x509v3.h | 730 ++++++- src/lib/libssl/LICENSE | 2 +- src/lib/libssl/bio_ssl.c | 115 +- src/lib/libssl/doc/openssl.cnf | 51 +- src/lib/libssl/doc/openssl.txt | 179 +- src/lib/libssl/doc/standards.txt | 19 +- src/lib/libssl/s23_clnt.c | 86 +- src/lib/libssl/s23_lib.c | 101 +- src/lib/libssl/s23_pkt.c | 15 +- src/lib/libssl/s23_srvr.c | 338 ++-- src/lib/libssl/s3_both.c | 295 ++- src/lib/libssl/s3_clnt.c | 760 +++++--- src/lib/libssl/s3_lib.c | 1139 +++++++++-- src/lib/libssl/s3_pkt.c | 1064 ++++++---- src/lib/libssl/s3_srvr.c | 890 ++++++--- src/lib/libssl/ssl.h | 1625 ++++++++++------ src/lib/libssl/ssl2.h | 25 +- src/lib/libssl/ssl3.h | 205 +- src/lib/libssl/ssl_algs.c | 49 +- src/lib/libssl/ssl_asn1.c | 126 +- src/lib/libssl/ssl_cert.c | 665 ++++++- src/lib/libssl/ssl_ciph.c | 1034 ++++++---- src/lib/libssl/ssl_err.c | 202 +- src/lib/libssl/ssl_err2.c | 8 +- src/lib/libssl/ssl_lib.c | 1484 +++++++++----- src/lib/libssl/ssl_locl.h | 535 +++--- src/lib/libssl/ssl_rsa.c | 364 ++-- src/lib/libssl/ssl_sess.c | 431 +++-- src/lib/libssl/ssl_stat.c | 126 +- src/lib/libssl/ssl_txt.c | 112 +- src/lib/libssl/t1_clnt.c | 16 +- src/lib/libssl/t1_enc.c | 418 ++-- src/lib/libssl/t1_lib.c | 36 +- src/lib/libssl/t1_meth.c | 10 +- src/lib/libssl/t1_srvr.c | 18 +- src/lib/libssl/test/methtest.c | 6 +- src/lib/libssl/test/tcrl | 2 +- src/lib/libssl/test/testca | 2 +- src/lib/libssl/test/testenc | 12 +- src/lib/libssl/test/testgen | 16 +- src/lib/libssl/test/testp7.pem | 86 +- src/lib/libssl/test/testsid.pem | 4 +- src/lib/libssl/test/testss | 26 +- src/lib/libssl/test/testssl | 127 +- src/lib/libssl/test/tpkcs7 | 2 +- src/lib/libssl/test/tpkcs7d | 4 +- src/lib/libssl/test/treq | 7 +- src/lib/libssl/test/trsa | 7 +- src/lib/libssl/test/tsid | 2 +- src/lib/libssl/test/tx509 | 2 +- src/lib/libssl/tls1.h | 85 +- 476 files changed, 46811 insertions(+), 27019 deletions(-) diff --git a/src/lib/libcrypto/aes/aes_cfb.c b/src/lib/libcrypto/aes/aes_cfb.c index 9b2917298a..41c2a5ec3d 100644 --- a/src/lib/libcrypto/aes/aes_cfb.c +++ b/src/lib/libcrypto/aes/aes_cfb.c @@ -137,7 +137,7 @@ void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, } else { while (l--) { if (n == 0) { - AES_decrypt(ivec, ivec, key); + AES_encrypt(ivec, ivec, key); } c = *(in); *(out++) = *(in++) ^ ivec[n]; diff --git a/src/lib/libcrypto/aes/aes_ctr.c b/src/lib/libcrypto/aes/aes_ctr.c index 8e800481de..aea3db2092 100644 --- a/src/lib/libcrypto/aes/aes_ctr.c +++ b/src/lib/libcrypto/aes/aes_ctr.c @@ -106,8 +106,8 @@ void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, while (l--) { if (n == 0) { - AES_ctr128_inc(counter); AES_encrypt(counter, tmp, key); + AES_ctr128_inc(counter); } *(out++) = *(in++) ^ tmp[n]; n = (n+1) % AES_BLOCK_SIZE; diff --git a/src/lib/libcrypto/asn1/a_bitstr.c b/src/lib/libcrypto/asn1/a_bitstr.c index 2c10120651..ed0bdfbde1 100644 --- a/src/lib/libcrypto/asn1/a_bitstr.c +++ b/src/lib/libcrypto/asn1/a_bitstr.c @@ -58,78 +58,86 @@ #include #include "cryptlib.h" -#include "asn1.h" +#include -/* ASN1err(ASN1_F_ASN1_STRING_NEW,ASN1_R_STRING_TOO_SHORT); - * ASN1err(ASN1_F_D2I_ASN1_BIT_STRING,ASN1_R_EXPECTING_A_BIT_STRING); - */ +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) +{ return M_ASN1_BIT_STRING_set(x, d, len); } -int i2d_ASN1_BIT_STRING(a,pp) -ASN1_BIT_STRING *a; -unsigned char **pp; +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) { - int ret,j,r,bits; + int ret,j,bits,len; unsigned char *p,*d; if (a == NULL) return(0); - /* our bit strings are always a multiple of 8 :-) */ - bits=0; - ret=1+a->length; - r=ASN1_object_size(0,ret,V_ASN1_BIT_STRING); - if (pp == NULL) return(r); + len=a->length; + + if (len > 0) + { + if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) + { + bits=(int)a->flags&0x07; + } + else + { + for ( ; len > 0; len--) + { + if (a->data[len-1]) break; + } + j=a->data[len-1]; + if (j & 0x01) bits=0; + else if (j & 0x02) bits=1; + else if (j & 0x04) bits=2; + else if (j & 0x08) bits=3; + else if (j & 0x10) bits=4; + else if (j & 0x20) bits=5; + else if (j & 0x40) bits=6; + else if (j & 0x80) bits=7; + else bits=0; /* should not happen */ + } + } + else + bits=0; + + ret=1+len; + if (pp == NULL) return(ret); + p= *pp; - ASN1_put_object(&p,0,ret,V_ASN1_BIT_STRING,V_ASN1_UNIVERSAL); - if (bits == 0) - j=0; - else j=8-bits; - *(p++)=(unsigned char)j; + *(p++)=(unsigned char)bits; d=a->data; - memcpy(p,d,a->length); - p+=a->length; - if (a->length > 0) p[-1]&=(0xff< 0) p[-1]&=(0xff<flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */ + ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|(i&0x07)); /* set */ + if (len-- > 1) /* using one because of the bits left byte */ { - s=(unsigned char *)Malloc((int)len); + s=(unsigned char *)OPENSSL_malloc((int)len); if (s == NULL) { i=ERR_R_MALLOC_FAILURE; @@ -143,7 +151,7 @@ long length; s=NULL; ret->length=(int)len; - if (ret->data != NULL) Free((char *)ret->data); + if (ret->data != NULL) OPENSSL_free(ret->data); ret->data=s; ret->type=V_ASN1_BIT_STRING; if (a != NULL) (*a)=ret; @@ -152,16 +160,13 @@ long length; err: ASN1err(ASN1_F_D2I_ASN1_BIT_STRING,i); if ((ret != NULL) && ((a == NULL) || (*a != ret))) - ASN1_BIT_STRING_free(ret); + M_ASN1_BIT_STRING_free(ret); return(NULL); } /* These next 2 functions from Goetz Babin-Ebell */ -int ASN1_BIT_STRING_set_bit(a,n,value) -ASN1_BIT_STRING *a; -int n; -int value; +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) { int w,v,iv; unsigned char *c; @@ -169,29 +174,30 @@ int value; w=n/8; v=1<<(7-(n&0x07)); iv= ~v; + if (!value) v=0; + + a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */ if (a == NULL) return(0); if ((a->length < (w+1)) || (a->data == NULL)) { if (!value) return(1); /* Don't need to set */ if (a->data == NULL) - c=(unsigned char *)Malloc(w+1); + c=(unsigned char *)OPENSSL_malloc(w+1); else - c=(unsigned char *)Realloc(a->data,w+1); + c=(unsigned char *)OPENSSL_realloc(a->data,w+1); if (c == NULL) return(0); + if (w+1-a->length > 0) memset(c+a->length, 0, w+1-a->length); a->data=c; a->length=w+1; - c[w]=0; - } + } a->data[w]=((a->data[w])&iv)|v; while ((a->length > 0) && (a->data[a->length-1] == 0)) a->length--; return(1); } -int ASN1_BIT_STRING_get_bit(a,n) -ASN1_BIT_STRING *a; -int n; +int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n) { int w,v; diff --git a/src/lib/libcrypto/asn1/a_bool.c b/src/lib/libcrypto/asn1/a_bool.c index 41a95aa278..24333ea4d5 100644 --- a/src/lib/libcrypto/asn1/a_bool.c +++ b/src/lib/libcrypto/asn1/a_bool.c @@ -58,15 +58,9 @@ #include #include "cryptlib.h" -#include "asn1.h" +#include -/* ASN1err(ASN1_F_D2I_ASN1_BOOLEAN,ASN1_R_EXPECTING_A_BOOLEAN); - * ASN1err(ASN1_F_D2I_ASN1_BOOLEAN,ASN1_R_BOOLEAN_IS_WRONG_LENGTH); - */ - -int i2d_ASN1_BOOLEAN(a,pp) -int a; -unsigned char **pp; +int i2d_ASN1_BOOLEAN(int a, unsigned char **pp) { int r; unsigned char *p; @@ -81,10 +75,7 @@ unsigned char **pp; return(r); } -int d2i_ASN1_BOOLEAN(a, pp, length) -int *a; -unsigned char **pp; -long length; +int d2i_ASN1_BOOLEAN(int *a, unsigned char **pp, long length) { int ret= -1; unsigned char *p; @@ -119,3 +110,5 @@ err: ASN1err(ASN1_F_D2I_ASN1_BOOLEAN,i); return(ret); } + + diff --git a/src/lib/libcrypto/asn1/a_bytes.c b/src/lib/libcrypto/asn1/a_bytes.c index 14168d61ad..bb88660f58 100644 --- a/src/lib/libcrypto/asn1/a_bytes.c +++ b/src/lib/libcrypto/asn1/a_bytes.c @@ -58,38 +58,13 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" +#include -/* ASN1err(ASN1_F_ASN1_TYPE_NEW,ASN1_R_ERROR_STACK); - * ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,ASN1_R_ERROR_STACK); - * ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,ASN1_R_WRONG_TYPE); - * ASN1err(ASN1_F_ASN1_COLLATE_PRIMATIVE,ASN1_R_WRONG_TAG); +static int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c); +/* type is a 'bitmap' of acceptable string types. */ - -static unsigned long tag2bit[32]={ -0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ -B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */ -B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */ -B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 12-15 */ -0, 0, B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, -B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,0, -0,B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, -B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, - }; - -#ifndef NOPROTO -static int asn1_collate_primative(ASN1_STRING *a, ASN1_CTX *c); -#else -static int asn1_collate_primative(); -#endif - -/* type is a 'bitmap' of acceptable string types to be accepted. - */ -ASN1_STRING *d2i_ASN1_type_bytes(a, pp, length, type) -ASN1_STRING **a; -unsigned char **pp; -long length; -int type; +ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, unsigned char **pp, + long length, int type) { ASN1_STRING *ret=NULL; unsigned char *p,*s; @@ -106,7 +81,7 @@ int type; i=ASN1_R_TAG_VALUE_TOO_HIGH;; goto err; } - if (!(tag2bit[tag] & type)) + if (!(ASN1_tag2bit(tag) & type)) { i=ASN1_R_WRONG_TYPE; goto err; @@ -125,7 +100,7 @@ int type; if (len != 0) { - s=(unsigned char *)Malloc((int)len+1); + s=(unsigned char *)OPENSSL_malloc((int)len+1); if (s == NULL) { i=ERR_R_MALLOC_FAILURE; @@ -138,7 +113,7 @@ int type; else s=NULL; - if (ret->data != NULL) Free((char *)ret->data); + if (ret->data != NULL) OPENSSL_free(ret->data); ret->length=(int)len; ret->data=s; ret->type=tag; @@ -152,11 +127,7 @@ err: return(NULL); } -int i2d_ASN1_bytes(a, pp, tag, xclass) -ASN1_STRING *a; -unsigned char **pp; -int tag; -int xclass; +int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass) { int ret,r,constructed; unsigned char *p; @@ -182,12 +153,8 @@ int xclass; return(r); } -ASN1_STRING *d2i_ASN1_bytes(a, pp, length, Ptag, Pclass) -ASN1_STRING **a; -unsigned char **pp; -long length; -int Ptag; -int Pclass; +ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, unsigned char **pp, long length, + int Ptag, int Pclass) { ASN1_STRING *ret=NULL; unsigned char *p,*s; @@ -227,7 +194,7 @@ int Pclass; c.tag=Ptag; c.xclass=Pclass; c.max=(length == 0)?0:(p+length); - if (!asn1_collate_primative(ret,&c)) + if (!asn1_collate_primitive(ret,&c)) goto err; else { @@ -240,8 +207,8 @@ int Pclass; { if ((ret->length < len) || (ret->data == NULL)) { - if (ret->data != NULL) Free((char *)ret->data); - s=(unsigned char *)Malloc((int)len); + if (ret->data != NULL) OPENSSL_free(ret->data); + s=(unsigned char *)OPENSSL_malloc((int)len + 1); if (s == NULL) { i=ERR_R_MALLOC_FAILURE; @@ -251,12 +218,13 @@ int Pclass; else s=ret->data; memcpy(s,p,(int)len); + s[len] = '\0'; p+=len; } else { s=NULL; - if (ret->data != NULL) Free((char *)ret->data); + if (ret->data != NULL) OPENSSL_free(ret->data); } ret->length=(int)len; @@ -275,13 +243,11 @@ err: } -/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapes - * them into the one struture that is then returned */ +/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse + * them into the one structure that is then returned */ /* There have been a few bug fixes for this function from * Paul Keogh , many thanks to him */ -static int asn1_collate_primative(a,c) -ASN1_STRING *a; -ASN1_CTX *c; +static int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c) { ASN1_STRING *os=NULL; BUF_MEM b; @@ -333,14 +299,14 @@ ASN1_CTX *c; if (!asn1_Finish(c)) goto err; a->length=num; - if (a->data != NULL) Free(a->data); + if (a->data != NULL) OPENSSL_free(a->data); a->data=(unsigned char *)b.data; if (os != NULL) ASN1_STRING_free(os); return(1); err: - ASN1err(ASN1_F_ASN1_COLLATE_PRIMATIVE,c->error); + ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE,c->error); if (os != NULL) ASN1_STRING_free(os); - if (b.data != NULL) Free(b.data); + if (b.data != NULL) OPENSSL_free(b.data); return(0); } diff --git a/src/lib/libcrypto/asn1/a_d2i_fp.c b/src/lib/libcrypto/asn1/a_d2i_fp.c index d952836a91..a80fbe9ff7 100644 --- a/src/lib/libcrypto/asn1/a_d2i_fp.c +++ b/src/lib/libcrypto/asn1/a_d2i_fp.c @@ -58,17 +58,16 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "asn1_mac.h" +#include +#include -#define HEADER_SIZE 8 +static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); + +#ifndef NO_OLD_ASN1 +#ifndef OPENSSL_NO_FP_API -#ifndef NO_FP_API -char *ASN1_d2i_fp(xnew,d2i,in,x) -char *(*xnew)(); -char *(*d2i)(); -FILE *in; -unsigned char **x; +char *ASN1_d2i_fp(char *(*xnew)(), char *(*d2i)(), FILE *in, + unsigned char **x) { BIO *b; char *ret; @@ -85,16 +84,68 @@ unsigned char **x; } #endif -char *ASN1_d2i_bio(xnew,d2i,in,x) -char *(*xnew)(); -char *(*d2i)(); -BIO *in; -unsigned char **x; +char *ASN1_d2i_bio(char *(*xnew)(), char *(*d2i)(), BIO *in, + unsigned char **x) + { + BUF_MEM *b = NULL; + unsigned char *p; + char *ret=NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if(len < 0) goto err; + + p=(unsigned char *)b->data; + ret=d2i(x,&p,len); +err: + if (b != NULL) BUF_MEM_free(b); + return(ret); + } + +#endif + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) + { + BUF_MEM *b = NULL; + unsigned char *p; + void *ret=NULL; + int len; + + len = asn1_d2i_read_bio(in, &b); + if(len < 0) goto err; + + p=(unsigned char *)b->data; + ret=ASN1_item_d2i(x,&p,len, it); +err: + if (b != NULL) BUF_MEM_free(b); + return(ret); + } + +#ifndef OPENSSL_NO_FP_API +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) + { + BIO *b; + char *ret; + + if ((b=BIO_new(BIO_s_file())) == NULL) + { + ASN1err(ASN1_F_ASN1_D2I_FP,ERR_R_BUF_LIB); + return(NULL); + } + BIO_set_fp(b,in,BIO_NOCLOSE); + ret=ASN1_item_d2i_bio(it,b,x); + BIO_free(b); + return(ret); + } +#endif + +#define HEADER_SIZE 8 +static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) { BUF_MEM *b; unsigned char *p; int i; - char *ret=NULL; + int ret=-1; ASN1_CTX c; int want=HEADER_SIZE; int eos=0; @@ -105,7 +156,7 @@ unsigned char **x; if (b == NULL) { ASN1err(ASN1_F_ASN1_D2I_BIO,ERR_R_MALLOC_FAILURE); - return(NULL); + return -1; } ERR_clear_error(); @@ -193,8 +244,8 @@ unsigned char **x; } } - p=(unsigned char *)b->data; - ret=d2i(x,&p,off); + *pb = b; + return off; err: if (b != NULL) BUF_MEM_free(b); return(ret); diff --git a/src/lib/libcrypto/asn1/a_digest.c b/src/lib/libcrypto/asn1/a_digest.c index 8ddb65b0dc..4931e222a0 100644 --- a/src/lib/libcrypto/asn1/a_digest.c +++ b/src/lib/libcrypto/asn1/a_digest.c @@ -58,34 +58,49 @@ #include #include -#include -#include #include "cryptlib.h" -#include "evp.h" -#include "x509.h" -#include "buffer.h" -int ASN1_digest(i2d,type,data,md,len) -int (*i2d)(); -EVP_MD *type; -char *data; -unsigned char *md; -unsigned int *len; +#ifndef NO_SYS_TYPES_H +# include +#endif + +#include +#include +#include + +#ifndef NO_ASN1_OLD + +int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len) { - EVP_MD_CTX ctx; int i; unsigned char *str,*p; i=i2d(data,NULL); - if ((str=(unsigned char *)Malloc(i)) == NULL) return(0); + if ((str=(unsigned char *)OPENSSL_malloc(i)) == NULL) return(0); p=str; i2d(data,&p); - EVP_DigestInit(&ctx,type); - EVP_DigestUpdate(&ctx,str,i); - EVP_DigestFinal(&ctx,md,len); - Free(str); + EVP_Digest(str, i, md, len, type, NULL); + OPENSSL_free(str); + return(1); + } + +#endif + + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, + unsigned char *md, unsigned int *len) + { + int i; + unsigned char *str = NULL; + + i=ASN1_item_i2d(asn,&str, it); + if (!str) return(0); + + EVP_Digest(str, i, md, len, type, NULL); + OPENSSL_free(str); return(1); } diff --git a/src/lib/libcrypto/asn1/a_dup.c b/src/lib/libcrypto/asn1/a_dup.c index 961b4cb069..58a017884c 100644 --- a/src/lib/libcrypto/asn1/a_dup.c +++ b/src/lib/libcrypto/asn1/a_dup.c @@ -58,14 +58,11 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" +#include -#define READ_CHUNK 2048 +#ifndef NO_OLD_ASN1 -char *ASN1_dup(i2d,d2i,x) -int (*i2d)(); -char *(*d2i)(); -char *x; +char *ASN1_dup(int (*i2d)(), char *(*d2i)(), char *x) { unsigned char *b,*p; long i; @@ -74,13 +71,37 @@ char *x; if (x == NULL) return(NULL); i=(long)i2d(x,NULL); - b=(unsigned char *)Malloc((unsigned int)i+10); + b=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); if (b == NULL) { ASN1err(ASN1_F_ASN1_DUP,ERR_R_MALLOC_FAILURE); return(NULL); } p= b; i=i2d(x,&p); p= b; ret=d2i(NULL,&p,i); - Free((char *)b); + OPENSSL_free(b); + return(ret); + } + +#endif + +/* ASN1_ITEM version of dup: this follows the model above except we don't need + * to allocate the buffer. At some point this could be rewritten to directly dup + * the underlying structure instead of doing and encode and decode. + */ + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x) + { + unsigned char *b = NULL, *p; + long i; + void *ret; + + if (x == NULL) return(NULL); + + i=ASN1_item_i2d(x,&b,it); + if (b == NULL) + { ASN1err(ASN1_F_ASN1_DUP,ERR_R_MALLOC_FAILURE); return(NULL); } + p= b; + ret=ASN1_item_d2i(NULL,&p,i, it); + OPENSSL_free(b); return(ret); } diff --git a/src/lib/libcrypto/asn1/a_enum.c b/src/lib/libcrypto/asn1/a_enum.c index 9239ecc439..ad8f0ffd1a 100644 --- a/src/lib/libcrypto/asn1/a_enum.c +++ b/src/lib/libcrypto/asn1/a_enum.c @@ -65,162 +65,6 @@ * for comments on encoding see a_int.c */ -int i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **pp) - { - int pad=0,ret,r,i,t; - unsigned char *p,*n,pb=0; - - if ((a == NULL) || (a->data == NULL)) return(0); - t=a->type; - if (a->length == 0) - ret=1; - else - { - ret=a->length; - i=a->data[0]; - if ((t == V_ASN1_ENUMERATED) && (i > 127)) { - pad=1; - pb=0; - } else if(t == V_ASN1_NEG_ENUMERATED) { - if(i>128) { - pad=1; - pb=0xFF; - } else if(i == 128) { - for(i = 1; i < a->length; i++) if(a->data[i]) { - pad=1; - pb=0xFF; - break; - } - } - } - ret+=pad; - } - r=ASN1_object_size(0,ret,V_ASN1_ENUMERATED); - if (pp == NULL) return(r); - p= *pp; - - ASN1_put_object(&p,0,ret,V_ASN1_ENUMERATED,V_ASN1_UNIVERSAL); - if (pad) *(p++)=pb; - if (a->length == 0) - *(p++)=0; - else if (t == V_ASN1_ENUMERATED) - { - memcpy(p,a->data,(unsigned int)a->length); - p+=a->length; - } - else { - /* Begin at the end of the encoding */ - n=a->data + a->length - 1; - p += a->length - 1; - i = a->length; - /* Copy zeros to destination as long as source is zero */ - while(!*n) { - *(p--) = 0; - n--; - i--; - } - /* Complement and increment next octet */ - *(p--) = ((*(n--)) ^ 0xff) + 1; - i--; - /* Complement any octets left */ - for(;i > 0; i--) *(p--) = *(n--) ^ 0xff; - p += a->length; - } - - *pp=p; - return(r); - } - -ASN1_ENUMERATED *d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, unsigned char **pp, - long length) - { - ASN1_ENUMERATED *ret=NULL; - unsigned char *p,*to,*s; - long len; - int inf,tag,xclass; - int i; - - if ((a == NULL) || ((*a) == NULL)) - { - if ((ret=ASN1_ENUMERATED_new()) == NULL) return(NULL); - ret->type=V_ASN1_ENUMERATED; - } - else - ret=(*a); - - p= *pp; - inf=ASN1_get_object(&p,&len,&tag,&xclass,length); - if (inf & 0x80) - { - i=ASN1_R_BAD_OBJECT_HEADER; - goto err; - } - - if (tag != V_ASN1_ENUMERATED) - { - i=ASN1_R_EXPECTING_AN_ENUMERATED; - goto err; - } - - /* We must Malloc stuff, even for 0 bytes otherwise it - * signifies a missing NULL parameter. */ - s=(unsigned char *)Malloc((int)len+1); - if (s == NULL) - { - i=ERR_R_MALLOC_FAILURE; - goto err; - } - to=s; - if (*p & 0x80) /* a negative number */ - { - ret->type=V_ASN1_NEG_ENUMERATED; - if ((*p == 0xff) && (len != 1)) { - p++; - len--; - } - i = len; - p += i - 1; - to += i - 1; - while((!*p) && i) { - *(to--) = 0; - i--; - p--; - } - if(!i) { - *s = 1; - s[len] = 0; - p += len; - len++; - } else { - *(to--) = (*(p--) ^ 0xff) + 1; - i--; - for(;i > 0; i--) *(to--) = *(p--) ^ 0xff; - p += len; - } - } else { - ret->type=V_ASN1_ENUMERATED; - if ((*p == 0) && (len != 1)) - { - p++; - len--; - } - memcpy(s,p,(int)len); - p+=len; - } - - if (ret->data != NULL) Free((char *)ret->data); - ret->data=s; - ret->length=(int)len; - if (a != NULL) (*a)=ret; - *pp=p; - return(ret); -err: - ASN1err(ASN1_F_D2I_ASN1_ENUMERATED,i); - if ((ret != NULL) && ((a == NULL) || (*a != ret))) - ASN1_ENUMERATED_free(ret); - return(NULL); - } - int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) { int i,j,k; @@ -231,8 +75,8 @@ int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) if (a->length < (sizeof(long)+1)) { if (a->data != NULL) - Free((char *)a->data); - if ((a->data=(unsigned char *)Malloc(sizeof(long)+1)) != NULL) + OPENSSL_free(a->data); + if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL) memset((char *)a->data,0,sizeof(long)+1); } if (a->data == NULL) @@ -270,7 +114,7 @@ long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a) if (i == V_ASN1_NEG_ENUMERATED) neg=1; else if (i != V_ASN1_ENUMERATED) - return(0); + return -1; if (a->length > sizeof(long)) { @@ -278,7 +122,7 @@ long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a) return(0xffffffffL); } if (a->data == NULL) - return(0); + return 0; for (i=0; ilength; i++) { @@ -295,7 +139,7 @@ ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai) int len,j; if (ai == NULL) - ret=ASN1_ENUMERATED_new(); + ret=M_ASN1_ENUMERATED_new(); else ret=ai; if (ret == NULL) @@ -307,11 +151,21 @@ ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai) else ret->type=V_ASN1_ENUMERATED; j=BN_num_bits(bn); len=((j == 0)?0:((j/8)+1)); - ret->data=(unsigned char *)Malloc(len+4); + if (ret->length < len+4) + { + unsigned char *new_data=OPENSSL_realloc(ret->data, len+4); + if (!new_data) + { + ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); + goto err; + } + ret->data=new_data; + } + ret->length=BN_bn2bin(bn,ret->data); return(ret); err: - if (ret != ai) ASN1_ENUMERATED_free(ret); + if (ret != ai) M_ASN1_ENUMERATED_free(ret); return(NULL); } @@ -321,6 +175,6 @@ BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn) if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL) ASN1err(ASN1_F_ASN1_ENUMERATED_TO_BN,ASN1_R_BN_LIB); - if(ai->type == V_ASN1_NEG_ENUMERATED) bn->neg = 1; + else if(ai->type == V_ASN1_NEG_ENUMERATED) ret->neg = 1; return(ret); } diff --git a/src/lib/libcrypto/asn1/a_i2d_fp.c b/src/lib/libcrypto/asn1/a_i2d_fp.c index 66c3df68d5..f4f1b73ebe 100644 --- a/src/lib/libcrypto/asn1/a_i2d_fp.c +++ b/src/lib/libcrypto/asn1/a_i2d_fp.c @@ -58,14 +58,13 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "asn1_mac.h" +#include +#include -#ifndef NO_FP_API -int ASN1_i2d_fp(i2d,out,x) -int (*i2d)(); -FILE *out; -unsigned char *x; +#ifndef NO_OLD_ASN1 + +#ifndef OPENSSL_NO_FP_API +int ASN1_i2d_fp(int (*i2d)(), FILE *out, unsigned char *x) { BIO *b; int ret; @@ -82,17 +81,14 @@ unsigned char *x; } #endif -int ASN1_i2d_bio(i2d,out,x) -int (*i2d)(); -BIO *out; -unsigned char *x; +int ASN1_i2d_bio(int (*i2d)(), BIO *out, unsigned char *x) { char *b; unsigned char *p; int i,j=0,n,ret=1; n=i2d(x,NULL); - b=(char *)Malloc(n); + b=(char *)OPENSSL_malloc(n); if (b == NULL) { ASN1err(ASN1_F_ASN1_I2D_BIO,ERR_R_MALLOC_FAILURE); @@ -114,6 +110,54 @@ unsigned char *x; j+=i; n-=i; } - Free((char *)b); + OPENSSL_free(b); + return(ret); + } + +#endif + +#ifndef OPENSSL_NO_FP_API +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) + { + BIO *b; + int ret; + + if ((b=BIO_new(BIO_s_file())) == NULL) + { + ASN1err(ASN1_F_ASN1_I2D_FP,ERR_R_BUF_LIB); + return(0); + } + BIO_set_fp(b,out,BIO_NOCLOSE); + ret=ASN1_item_i2d_bio(it,b,x); + BIO_free(b); + return(ret); + } +#endif + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) + { + unsigned char *b = NULL; + int i,j=0,n,ret=1; + + n = ASN1_item_i2d(x, &b, it); + if (b == NULL) + { + ASN1err(ASN1_F_ASN1_I2D_BIO,ERR_R_MALLOC_FAILURE); + return(0); + } + + for (;;) + { + i=BIO_write(out,&(b[j]),n); + if (i == n) break; + if (i <= 0) + { + ret=0; + break; + } + j+=i; + n-=i; + } + OPENSSL_free(b); return(ret); } diff --git a/src/lib/libcrypto/asn1/a_int.c b/src/lib/libcrypto/asn1/a_int.c index df79cf99bb..edb243c021 100644 --- a/src/lib/libcrypto/asn1/a_int.c +++ b/src/lib/libcrypto/asn1/a_int.c @@ -58,68 +58,197 @@ #include #include "cryptlib.h" -#include "asn1.h" +#include -/* ASN1err(ASN1_F_D2I_ASN1_INTEGER,ASN1_R_EXPECTING_AN_INTEGER); +ASN1_INTEGER *ASN1_INTEGER_dup(ASN1_INTEGER *x) +{ return M_ASN1_INTEGER_dup(x);} + +int ASN1_INTEGER_cmp(ASN1_INTEGER *x, ASN1_INTEGER *y) +{ return M_ASN1_INTEGER_cmp(x,y);} + +/* + * This converts an ASN1 INTEGER into its content encoding. + * The internal representation is an ASN1_STRING whose data is a big endian + * representation of the value, ignoring the sign. The sign is determined by + * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative. + * + * Positive integers are no problem: they are almost the same as the DER + * encoding, except if the first byte is >= 0x80 we need to add a zero pad. + * + * Negative integers are a bit trickier... + * The DER representation of negative integers is in 2s complement form. + * The internal form is converted by complementing each octet and finally + * adding one to the result. This can be done less messily with a little trick. + * If the internal form has trailing zeroes then they will become FF by the + * complement and 0 by the add one (due to carry) so just copy as many trailing + * zeros to the destination as there are in the source. The carry will add one + * to the last none zero octet: so complement this octet and add one and finally + * complement any left over until you get to the start of the string. + * + * Padding is a little trickier too. If the first bytes is > 0x80 then we pad + * with 0xff. However if the first byte is 0x80 and one of the following bytes + * is non-zero we pad with 0xff. The reason for this distinction is that 0x80 + * followed by optional zeros isn't padded. */ -int i2d_ASN1_INTEGER(a,pp) -ASN1_INTEGER *a; -unsigned char **pp; +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) { - int pad=0,ret,r,i,t; - unsigned char *p,*pt,*n,pb=0; + int pad=0,ret,i,neg; + unsigned char *p,*n,pb=0; if ((a == NULL) || (a->data == NULL)) return(0); - t=a->type; + neg=a->type & V_ASN1_NEG; if (a->length == 0) ret=1; else { ret=a->length; i=a->data[0]; - if ((t == V_ASN1_INTEGER) && (i > 127)) - { + if (!neg && (i > 127)) { pad=1; pb=0; + } else if(neg) { + if(i>128) { + pad=1; + pb=0xFF; + } else if(i == 128) { + /* + * Special case: if any other bytes non zero we pad: + * otherwise we don't. + */ + for(i = 1; i < a->length; i++) if(a->data[i]) { + pad=1; + pb=0xFF; + break; + } } - else if ((t == V_ASN1_NEG_INTEGER) && (i>128)) - { - pad=1; - pb=0xFF; - } + } ret+=pad; } - r=ASN1_object_size(0,ret,V_ASN1_INTEGER); - if (pp == NULL) return(r); + if (pp == NULL) return(ret); p= *pp; - ASN1_put_object(&p,0,ret,V_ASN1_INTEGER,V_ASN1_UNIVERSAL); if (pad) *(p++)=pb; - if (a->length == 0) - *(p++)=0; - else if (t == V_ASN1_INTEGER) + if (a->length == 0) *(p++)=0; + else if (!neg) memcpy(p,a->data,(unsigned int)a->length); + else { + /* Begin at the end of the encoding */ + n=a->data + a->length - 1; + p += a->length - 1; + i = a->length; + /* Copy zeros to destination as long as source is zero */ + while(!*n) { + *(p--) = 0; + n--; + i--; + } + /* Complement and increment next octet */ + *(p--) = ((*(n--)) ^ 0xff) + 1; + i--; + /* Complement any octets left */ + for(;i > 0; i--) *(p--) = *(n--) ^ 0xff; + } + + *pp+=ret; + return(ret); + } + +/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */ + +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, unsigned char **pp, + long len) + { + ASN1_INTEGER *ret=NULL; + unsigned char *p,*to,*s, *pend; + int i; + + if ((a == NULL) || ((*a) == NULL)) { - memcpy(p,a->data,(unsigned int)a->length); - p+=a->length; + if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL); + ret->type=V_ASN1_INTEGER; } else + ret=(*a); + + p= *pp; + pend = p + len; + + /* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it + * signifies a missing NULL parameter. */ + s=(unsigned char *)OPENSSL_malloc((int)len+1); + if (s == NULL) { - n=a->data; - pt=p; - for (i=a->length; i>0; i--) - *(p++)= (*(n++)^0xFF)+1; - if (!pad) *pt|=0x80; + i=ERR_R_MALLOC_FAILURE; + goto err; } + to=s; + if(!len) { + /* Strictly speaking this is an illegal INTEGER but we + * tolerate it. + */ + ret->type=V_ASN1_INTEGER; + } else if (*p & 0x80) /* a negative number */ + { + ret->type=V_ASN1_NEG_INTEGER; + if ((*p == 0xff) && (len != 1)) { + p++; + len--; + } + i = len; + p += i - 1; + to += i - 1; + while((!*p) && i) { + *(to--) = 0; + i--; + p--; + } + /* Special case: if all zeros then the number will be of + * the form FF followed by n zero bytes: this corresponds to + * 1 followed by n zero bytes. We've already written n zeros + * so we just append an extra one and set the first byte to + * a 1. This is treated separately because it is the only case + * where the number of bytes is larger than len. + */ + if(!i) { + *s = 1; + s[len] = 0; + len++; + } else { + *(to--) = (*(p--) ^ 0xff) + 1; + i--; + for(;i > 0; i--) *(to--) = *(p--) ^ 0xff; + } + } else { + ret->type=V_ASN1_INTEGER; + if ((*p == 0) && (len != 1)) + { + p++; + len--; + } + memcpy(s,p,(int)len); + } - *pp=p; - return(r); + if (ret->data != NULL) OPENSSL_free(ret->data); + ret->data=s; + ret->length=(int)len; + if (a != NULL) (*a)=ret; + *pp=pend; + return(ret); +err: + ASN1err(ASN1_F_D2I_ASN1_INTEGER,i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + M_ASN1_INTEGER_free(ret); + return(NULL); } -ASN1_INTEGER *d2i_ASN1_INTEGER(a, pp, length) -ASN1_INTEGER **a; -unsigned char **pp; -long length; + +/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of + * ASN1 integers: some broken software can encode a positive INTEGER + * with its MSB set as negative (it doesn't add a padding zero). + */ + +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, unsigned char **pp, + long length) { ASN1_INTEGER *ret=NULL; unsigned char *p,*to,*s; @@ -129,7 +258,7 @@ long length; if ((a == NULL) || ((*a) == NULL)) { - if ((ret=ASN1_INTEGER_new()) == NULL) return(NULL); + if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL); ret->type=V_ASN1_INTEGER; } else @@ -149,29 +278,17 @@ long length; goto err; } - /* We must Malloc stuff, even for 0 bytes otherwise it + /* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it * signifies a missing NULL parameter. */ - s=(unsigned char *)Malloc((int)len+1); + s=(unsigned char *)OPENSSL_malloc((int)len+1); if (s == NULL) { i=ERR_R_MALLOC_FAILURE; goto err; } to=s; - if (*p & 0x80) /* a negative number */ - { - ret->type=V_ASN1_NEG_INTEGER; - if (*p == 0xff) - { - p++; - len--; - } - for (i=(int)len; i>0; i--) - *(to++)= (*(p++)^0xFF)+1; - } - else - { - ret->type=V_ASN1_INTEGER; + ret->type=V_ASN1_INTEGER; + if(len) { if ((*p == 0) && (len != 1)) { p++; @@ -179,24 +296,22 @@ long length; } memcpy(s,p,(int)len); p+=len; - } + } - if (ret->data != NULL) Free((char *)ret->data); + if (ret->data != NULL) OPENSSL_free(ret->data); ret->data=s; ret->length=(int)len; if (a != NULL) (*a)=ret; *pp=p; return(ret); err: - ASN1err(ASN1_F_D2I_ASN1_INTEGER,i); + ASN1err(ASN1_F_D2I_ASN1_UINTEGER,i); if ((ret != NULL) && ((a == NULL) || (*a != ret))) - ASN1_INTEGER_free(ret); + M_ASN1_INTEGER_free(ret); return(NULL); } -int ASN1_INTEGER_set(a,v) -ASN1_INTEGER *a; -long v; +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) { int i,j,k; unsigned char buf[sizeof(long)+1]; @@ -206,8 +321,8 @@ long v; if (a->length < (sizeof(long)+1)) { if (a->data != NULL) - Free((char *)a->data); - if ((a->data=(unsigned char *)Malloc(sizeof(long)+1)) != NULL) + OPENSSL_free(a->data); + if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL) memset((char *)a->data,0,sizeof(long)+1); } if (a->data == NULL) @@ -229,15 +344,13 @@ long v; d>>=8; } j=0; - if (v < 0) a->data[j++]=0; for (k=i-1; k >=0; k--) a->data[j++]=buf[k]; a->length=j; return(1); } -long ASN1_INTEGER_get(a) -ASN1_INTEGER *a; +long ASN1_INTEGER_get(ASN1_INTEGER *a) { int neg=0,i; long r=0; @@ -247,7 +360,7 @@ ASN1_INTEGER *a; if (i == V_ASN1_NEG_INTEGER) neg=1; else if (i != V_ASN1_INTEGER) - return(0); + return -1; if (a->length > sizeof(long)) { @@ -255,7 +368,7 @@ ASN1_INTEGER *a; return(0xffffffffL); } if (a->data == NULL) - return(0); + return 0; for (i=0; ilength; i++) { @@ -266,40 +379,56 @@ ASN1_INTEGER *a; return(r); } -ASN1_INTEGER *BN_to_ASN1_INTEGER(bn,ai) -BIGNUM *bn; -ASN1_INTEGER *ai; +ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai) { ASN1_INTEGER *ret; int len,j; if (ai == NULL) - ret=ASN1_INTEGER_new(); + ret=M_ASN1_INTEGER_new(); else ret=ai; if (ret == NULL) { - ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ASN1_R_ERROR_STACK); + ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_NESTED_ASN1_ERROR); goto err; } - ret->type=V_ASN1_INTEGER; + if(bn->neg) ret->type = V_ASN1_NEG_INTEGER; + else ret->type=V_ASN1_INTEGER; j=BN_num_bits(bn); len=((j == 0)?0:((j/8)+1)); - ret->data=(unsigned char *)Malloc(len+4); + if (ret->length < len+4) + { + unsigned char *new_data=OPENSSL_realloc(ret->data, len+4); + if (!new_data) + { + ASN1err(ASN1_F_BN_TO_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); + goto err; + } + ret->data=new_data; + } ret->length=BN_bn2bin(bn,ret->data); + /* Correct zero case */ + if(!ret->length) + { + ret->data[0] = 0; + ret->length = 1; + } return(ret); err: - if (ret != ai) ASN1_INTEGER_free(ret); + if (ret != ai) M_ASN1_INTEGER_free(ret); return(NULL); } -BIGNUM *ASN1_INTEGER_to_BN(ai,bn) -ASN1_INTEGER *ai; -BIGNUM *bn; +BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai, BIGNUM *bn) { BIGNUM *ret; if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL) ASN1err(ASN1_F_ASN1_INTEGER_TO_BN,ASN1_R_BN_LIB); + else if(ai->type == V_ASN1_NEG_INTEGER) ret->neg = 1; return(ret); } + +IMPLEMENT_STACK_OF(ASN1_INTEGER) +IMPLEMENT_ASN1_SET_OF(ASN1_INTEGER) diff --git a/src/lib/libcrypto/asn1/a_mbstr.c b/src/lib/libcrypto/asn1/a_mbstr.c index 7a710d5459..5d981c6553 100644 --- a/src/lib/libcrypto/asn1/a_mbstr.c +++ b/src/lib/libcrypto/asn1/a_mbstr.c @@ -92,6 +92,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, { int str_type; int ret; + char free_out; int outform, outlen; ASN1_STRING *dest; unsigned char *p; @@ -180,14 +181,16 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, } if(!out) return str_type; if(*out) { + free_out = 0; dest = *out; if(dest->data) { dest->length = 0; - Free(dest->data); + OPENSSL_free(dest->data); dest->data = NULL; } dest->type = str_type; } else { + free_out = 1; dest = ASN1_STRING_type_new(str_type); if(!dest) { ASN1err(ASN1_F_ASN1_MBSTRING_COPY, @@ -228,8 +231,8 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, cpyfunc = cpy_utf8; break; } - if(!(p = Malloc(outlen + 1))) { - ASN1_STRING_free(dest); + if(!(p = OPENSSL_malloc(outlen + 1))) { + if(free_out) ASN1_STRING_free(dest); ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE); return -1; } @@ -258,8 +261,8 @@ static int traverse_string(const unsigned char *p, int len, int inform, value |= *p++; len -= 2; } else if(inform == MBSTRING_UNIV) { - value = *p++ << 24; - value |= *p++ << 16; + value = ((unsigned long)*p++) << 24; + value |= ((unsigned long)*p++) << 16; value |= *p++ << 8; value |= *p++; len -= 4; @@ -382,9 +385,16 @@ static int is_printable(unsigned long value) /* Note: we can't use 'isalnum' because certain accented * characters may count as alphanumeric in some environments. */ +#ifndef CHARSET_EBCDIC if((ch >= 'a') && (ch <= 'z')) return 1; if((ch >= 'A') && (ch <= 'Z')) return 1; if((ch >= '0') && (ch <= '9')) return 1; if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1; +#else /*CHARSET_EBCDIC*/ + if((ch >= os_toascii['a']) && (ch <= os_toascii['z'])) return 1; + if((ch >= os_toascii['A']) && (ch <= os_toascii['Z'])) return 1; + if((ch >= os_toascii['0']) && (ch <= os_toascii['9'])) return 1; + if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch])) return 1; +#endif /*CHARSET_EBCDIC*/ return 0; } diff --git a/src/lib/libcrypto/asn1/a_object.c b/src/lib/libcrypto/asn1/a_object.c index 5a7eeef8d8..71ce7c3896 100644 --- a/src/lib/libcrypto/asn1/a_object.c +++ b/src/lib/libcrypto/asn1/a_object.c @@ -58,25 +58,19 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "asn1.h" -#include "objects.h" +#include +#include +#include -/* ASN1err(ASN1_F_ASN1_OBJECT_NEW,ASN1_R_EXPECTING_AN_OBJECT); - * ASN1err(ASN1_F_D2I_ASN1_OBJECT,ASN1_R_BAD_OBJECT_HEADER); - * ASN1err(ASN1_F_I2T_ASN1_OBJECT,ASN1_R_BAD_OBJECT_HEADER); - */ - -int i2d_ASN1_OBJECT(a, pp) -ASN1_OBJECT *a; -unsigned char **pp; +int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) { unsigned char *p; + int objsize; if ((a == NULL) || (a->data == NULL)) return(0); - if (pp == NULL) - return(ASN1_object_size(0,a->length,V_ASN1_OBJECT)); + objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT); + if (pp == NULL) return objsize; p= *pp; ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL); @@ -84,17 +78,14 @@ unsigned char **pp; p+=a->length; *pp=p; - return(a->length); + return(objsize); } -int a2d_ASN1_OBJECT(out,olen,buf,num) -unsigned char *out; -int olen; -char *buf; -int num; +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) { int i,first,len=0,c; - char tmp[24],*p; + char tmp[24]; + const char *p; unsigned long l; if (num == 0) @@ -180,85 +171,12 @@ err: return(0); } -int i2t_ASN1_OBJECT(buf,buf_len,a) -char *buf; -int buf_len; -ASN1_OBJECT *a; - { - int i,idx=0,n=0,len,nid; - unsigned long l; - unsigned char *p; - char *s; - char tbuf[32]; - - if (buf_len <= 0) return(0); - - if ((a == NULL) || (a->data == NULL)) - { - buf[0]='\0'; - return(0); - } - - nid=OBJ_obj2nid(a); - if (nid == NID_undef) - { - len=a->length; - p=a->data; +int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a) +{ + return OBJ_obj2txt(buf, buf_len, a, 0); +} - idx=0; - l=0; - while (idx < a->length) - { - l|=(p[idx]&0x7f); - if (!(p[idx] & 0x80)) break; - l<<=7L; - idx++; - } - idx++; - i=(int)(l/40); - if (i > 2) i=2; - l-=(long)(i*40); - - sprintf(tbuf,"%d.%ld",i,l); - i=strlen(tbuf); - strncpy(buf,tbuf,buf_len); - buf_len-=i; - buf+=i; - n+=i; - - l=0; - for (; idx 0) - strncpy(buf,tbuf,buf_len); - buf_len-=i; - buf+=i; - n+=i; - l=0; - } - l<<=7L; - } - } - else - { - s=(char *)OBJ_nid2ln(nid); - if (s == NULL) - s=(char *)OBJ_nid2sn(nid); - strncpy(buf,s,buf_len); - n=strlen(s); - } - buf[buf_len-1]='\0'; - return(n); - } - -int i2a_ASN1_OBJECT(bp,a) -BIO *bp; -ASN1_OBJECT *a; +int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a) { char buf[80]; int i; @@ -271,28 +189,15 @@ ASN1_OBJECT *a; return(i); } -ASN1_OBJECT *d2i_ASN1_OBJECT(a, pp, length) -ASN1_OBJECT **a; -unsigned char **pp; -long length; - { - ASN1_OBJECT *ret=NULL; +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, unsigned char **pp, + long length) +{ unsigned char *p; long len; int tag,xclass; int inf,i; - - /* only the ASN1_OBJECTs from the 'table' will have values - * for ->sn or ->ln */ - if ((a == NULL) || ((*a) == NULL) || - !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) - { - if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL); - } - else ret=(*a); - + ASN1_OBJECT *ret = NULL; p= *pp; - inf=ASN1_get_object(&p,&len,&tag,&xclass,length); if (inf & 0x80) { @@ -305,10 +210,36 @@ long length; i=ASN1_R_EXPECTING_AN_OBJECT; goto err; } + ret = c2i_ASN1_OBJECT(a, &p, len); + if(ret) *pp = p; + return ret; +err: + ASN1err(ASN1_F_D2I_ASN1_OBJECT,i); + if ((ret != NULL) && ((a == NULL) || (*a != ret))) + ASN1_OBJECT_free(ret); + return(NULL); +} +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, unsigned char **pp, + long len) + { + ASN1_OBJECT *ret=NULL; + unsigned char *p; + int i; + + /* only the ASN1_OBJECTs from the 'table' will have values + * for ->sn or ->ln */ + if ((a == NULL) || ((*a) == NULL) || + !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) + { + if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL); + } + else ret=(*a); + + p= *pp; if ((ret->data == NULL) || (ret->length < len)) { - if (ret->data != NULL) Free((char *)ret->data); - ret->data=(unsigned char *)Malloc((int)len); + if (ret->data != NULL) OPENSSL_free(ret->data); + ret->data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1); ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA; if (ret->data == NULL) { i=ERR_R_MALLOC_FAILURE; goto err; } @@ -330,11 +261,11 @@ err: return(NULL); } -ASN1_OBJECT *ASN1_OBJECT_new() +ASN1_OBJECT *ASN1_OBJECT_new(void) { ASN1_OBJECT *ret; - ret=(ASN1_OBJECT *)Malloc(sizeof(ASN1_OBJECT)); + ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); if (ret == NULL) { ASN1err(ASN1_F_ASN1_OBJECT_NEW,ERR_R_MALLOC_FAILURE); @@ -349,31 +280,29 @@ ASN1_OBJECT *ASN1_OBJECT_new() return(ret); } -void ASN1_OBJECT_free(a) -ASN1_OBJECT *a; +void ASN1_OBJECT_free(ASN1_OBJECT *a) { if (a == NULL) return; if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { - if (a->sn != NULL) Free(a->sn); - if (a->ln != NULL) Free(a->ln); +#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */ + if (a->sn != NULL) OPENSSL_free((void *)a->sn); + if (a->ln != NULL) OPENSSL_free((void *)a->ln); +#endif a->sn=a->ln=NULL; } if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { - if (a->data != NULL) Free(a->data); + if (a->data != NULL) OPENSSL_free(a->data); a->data=NULL; a->length=0; } if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) - Free((char *)a); + OPENSSL_free(a); } -ASN1_OBJECT *ASN1_OBJECT_create(nid,data,len,sn,ln) -int nid; -unsigned char *data; -int len; -char *sn,*ln; +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln) { ASN1_OBJECT o; @@ -382,8 +311,10 @@ char *sn,*ln; o.data=data; o.nid=nid; o.length=len; - o.flags=ASN1_OBJECT_FLAG_DYNAMIC| - ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|ASN1_OBJECT_FLAG_DYNAMIC_DATA; + o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS| + ASN1_OBJECT_FLAG_DYNAMIC_DATA; return(OBJ_dup(&o)); } +IMPLEMENT_STACK_OF(ASN1_OBJECT) +IMPLEMENT_ASN1_SET_OF(ASN1_OBJECT) diff --git a/src/lib/libcrypto/asn1/a_octet.c b/src/lib/libcrypto/asn1/a_octet.c index be3f172a8c..9690bae0f1 100644 --- a/src/lib/libcrypto/asn1/a_octet.c +++ b/src/lib/libcrypto/asn1/a_octet.c @@ -58,33 +58,14 @@ #include #include "cryptlib.h" -#include "asn1.h" +#include -/* ASN1err(ASN1_F_D2I_ASN1_OCTET_STRING,ASN1_R_EXPECTING_AN_OCTET_STRING); - */ - -int i2d_ASN1_OCTET_STRING(a, pp) -ASN1_OCTET_STRING *a; -unsigned char **pp; - { - return(i2d_ASN1_bytes((ASN1_STRING *)a,pp, - V_ASN1_OCTET_STRING,V_ASN1_UNIVERSAL)); - } +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(ASN1_OCTET_STRING *x) +{ return M_ASN1_OCTET_STRING_dup(x); } -ASN1_OCTET_STRING *d2i_ASN1_OCTET_STRING(a, pp, length) -ASN1_OCTET_STRING **a; -unsigned char **pp; -long length; - { - ASN1_OCTET_STRING *ret=NULL; +int ASN1_OCTET_STRING_cmp(ASN1_OCTET_STRING *a, ASN1_OCTET_STRING *b) +{ return M_ASN1_OCTET_STRING_cmp(a, b); } - ret=(ASN1_OCTET_STRING *)d2i_ASN1_bytes((ASN1_STRING **)a, - pp,length,V_ASN1_OCTET_STRING,V_ASN1_UNIVERSAL); - if (ret == NULL) - { - ASN1err(ASN1_F_D2I_ASN1_OCTET_STRING,ASN1_R_ERROR_STACK); - return(NULL); - } - return(ret); - } +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, unsigned char *d, int len) +{ return M_ASN1_OCTET_STRING_set(x, d, len); } diff --git a/src/lib/libcrypto/asn1/a_print.c b/src/lib/libcrypto/asn1/a_print.c index 3023361dee..8035513f04 100644 --- a/src/lib/libcrypto/asn1/a_print.c +++ b/src/lib/libcrypto/asn1/a_print.c @@ -58,49 +58,9 @@ #include #include "cryptlib.h" -#include "asn1.h" +#include -/* ASN1err(ASN1_F_D2I_ASN1_PRINT_TYPE,ASN1_R_WRONG_PRINTABLE_TYPE); - * ASN1err(ASN1_F_D2I_ASN1_PRINT_TYPE,ASN1_R_TAG_VALUE_TOO_HIGH); - */ - -int i2d_ASN1_IA5STRING(a,pp) -ASN1_IA5STRING *a; -unsigned char **pp; - { return(M_i2d_ASN1_IA5STRING(a,pp)); } - -ASN1_IA5STRING *d2i_ASN1_IA5STRING(a,pp,l) -ASN1_IA5STRING **a; -unsigned char **pp; -long l; - { return(M_d2i_ASN1_IA5STRING(a,pp,l)); } - -ASN1_T61STRING *d2i_ASN1_T61STRING(a,pp,l) -ASN1_T61STRING **a; -unsigned char **pp; -long l; - { return(M_d2i_ASN1_T61STRING(a,pp,l)); } - -ASN1_PRINTABLESTRING *d2i_ASN1_PRINTABLESTRING(a,pp,l) -ASN1_PRINTABLESTRING **a; -unsigned char **pp; -long l; - { return(M_d2i_ASN1_PRINTABLESTRING(a,pp,l)); } - -int i2d_ASN1_PRINTABLE(a,pp) -ASN1_STRING *a; -unsigned char **pp; - { return(M_i2d_ASN1_PRINTABLE(a,pp)); } - -ASN1_STRING *d2i_ASN1_PRINTABLE(a,pp,l) -ASN1_STRING **a; -unsigned char **pp; -long l; - { return(M_d2i_ASN1_PRINTABLE(a,pp,l)); } - -int ASN1_PRINTABLE_type(s,len) -unsigned char *s; -int len; +int ASN1_PRINTABLE_type(unsigned char *s, int len) { int c; int ia5=0; @@ -112,6 +72,7 @@ int len; while ((*s) && (len-- != 0)) { c= *(s++); +#ifndef CHARSET_EBCDIC if (!( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || (c == ' ') || @@ -125,14 +86,20 @@ int len; ia5=1; if (c&0x80) t61=1; +#else + if (!isalnum(c) && (c != ' ') && + strchr("'()+,-./:=?", c) == NULL) + ia5=1; + if (os_toascii[c] & 0x80) + t61=1; +#endif } if (t61) return(V_ASN1_T61STRING); if (ia5) return(V_ASN1_IA5STRING); return(V_ASN1_PRINTABLESTRING); } -int ASN1_UNIVERSALSTRING_to_string(s) -ASN1_UNIVERSALSTRING *s; +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s) { int i; unsigned char *p; @@ -158,4 +125,3 @@ ASN1_UNIVERSALSTRING *s; s->type=ASN1_PRINTABLE_type(s->data,s->length); return(1); } - diff --git a/src/lib/libcrypto/asn1/a_set.c b/src/lib/libcrypto/asn1/a_set.c index 17c49946cf..0f839822ff 100644 --- a/src/lib/libcrypto/asn1/a_set.c +++ b/src/lib/libcrypto/asn1/a_set.c @@ -58,21 +58,42 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" +#include -/* ASN1err(ASN1_F_ASN1_TYPE_NEW,ERR_R_MALLOC_FAILURE); +#ifndef NO_ASN1_OLD + +typedef struct + { + unsigned char *pbData; + int cbData; + } MYBLOB; + +/* SetBlobCmp + * This function compares two elements of SET_OF block */ +static int SetBlobCmp(const void *elem1, const void *elem2 ) + { + const MYBLOB *b1 = (const MYBLOB *)elem1; + const MYBLOB *b2 = (const MYBLOB *)elem2; + int r; + + r = memcmp(b1->pbData, b2->pbData, + b1->cbData < b2->cbData ? b1->cbData : b2->cbData); + if(r != 0) + return r; + return b1->cbData-b2->cbData; + } -int i2d_ASN1_SET(a,pp,func,ex_tag,ex_class) -STACK *a; -unsigned char **pp; -int (*func)(); -int ex_tag; -int ex_class; +/* int is_set: if TRUE, then sort the contents (i.e. it isn't a SEQUENCE) */ +int i2d_ASN1_SET(STACK *a, unsigned char **pp, int (*func)(), int ex_tag, + int ex_class, int is_set) { int ret=0,r; int i; unsigned char *p; + unsigned char *pStart, *pTempMem; + MYBLOB *rgSetBlob; + int totSize; if (a == NULL) return(0); for (i=sk_num(a)-1; i>=0; i--) @@ -82,26 +103,64 @@ int ex_class; p= *pp; ASN1_put_object(&p,1,ret,ex_tag,ex_class); - for (i=0; i #include -#include -#include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "x509.h" -#include "objects.h" -#include "buffer.h" -#include "pem.h" -int ASN1_sign(i2d,algor1,algor2,signature,data,pkey,type) -int (*i2d)(); -X509_ALGOR *algor1; -X509_ALGOR *algor2; -ASN1_BIT_STRING *signature; -char *data; -EVP_PKEY *pkey; -EVP_MD *type; +#ifndef NO_SYS_TYPES_H +# include +#endif + +#include +#include +#include +#include +#include + +#ifndef NO_ASN1_OLD + +int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey, + const EVP_MD *type) { EVP_MD_CTX ctx; unsigned char *p,*buf_in=NULL,*buf_out=NULL; int i,inl=0,outl=0,outll=0; X509_ALGOR *a; + EVP_MD_CTX_init(&ctx); for (i=0; i<2; i++) { if (i == 0) @@ -90,7 +143,14 @@ EVP_MD *type; else a=algor2; if (a == NULL) continue; - if ( (a->parameter == NULL) || + if (type->pkey_type == NID_dsaWithSHA1) + { + /* special case: RFC 2459 tells us to omit 'parameters' + * with id-dsa-with-sha1 */ + ASN1_TYPE_free(a->parameter); + a->parameter = NULL; + } + else if ((a->parameter == NULL) || (a->parameter->type != V_ASN1_NULL)) { ASN1_TYPE_free(a->parameter); @@ -111,9 +171,9 @@ EVP_MD *type; } } inl=i2d(data,NULL); - buf_in=(unsigned char *)Malloc((unsigned int)inl); + buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); outll=outl=EVP_PKEY_size(pkey); - buf_out=(unsigned char *)Malloc((unsigned int)outl); + buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl); if ((buf_in == NULL) || (buf_out == NULL)) { outl=0; @@ -123,7 +183,7 @@ EVP_MD *type; p=buf_in; i2d(data,&p); - EVP_SignInit(&ctx,type); + EVP_SignInit_ex(&ctx,type, NULL); EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl); if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out, (unsigned int *)&outl,pkey)) @@ -132,16 +192,103 @@ EVP_MD *type; ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB); goto err; } - if (signature->data != NULL) Free((char *)signature->data); + if (signature->data != NULL) OPENSSL_free(signature->data); signature->data=buf_out; buf_out=NULL; signature->length=outl; + /* In the interests of compatibility, I'll make sure that + * the bit string has a 'not-used bits' value of 0 + */ + signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); + signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; +err: + EVP_MD_CTX_cleanup(&ctx); + if (buf_in != NULL) + { memset((char *)buf_in,0,(unsigned int)inl); OPENSSL_free(buf_in); } + if (buf_out != NULL) + { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); } + return(outl); + } + +#endif + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, + const EVP_MD *type) + { + EVP_MD_CTX ctx; + unsigned char *buf_in=NULL,*buf_out=NULL; + int i,inl=0,outl=0,outll=0; + X509_ALGOR *a; + + EVP_MD_CTX_init(&ctx); + for (i=0; i<2; i++) + { + if (i == 0) + a=algor1; + else + a=algor2; + if (a == NULL) continue; + if (type->pkey_type == NID_dsaWithSHA1) + { + /* special case: RFC 2459 tells us to omit 'parameters' + * with id-dsa-with-sha1 */ + ASN1_TYPE_free(a->parameter); + a->parameter = NULL; + } + else if ((a->parameter == NULL) || + (a->parameter->type != V_ASN1_NULL)) + { + ASN1_TYPE_free(a->parameter); + if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err; + a->parameter->type=V_ASN1_NULL; + } + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(type->pkey_type); + if (a->algorithm == NULL) + { + ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_UNKNOWN_OBJECT_TYPE); + goto err; + } + if (a->algorithm->length == 0) + { + ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); + goto err; + } + } + inl=ASN1_item_i2d(asn,&buf_in, it); + outll=outl=EVP_PKEY_size(pkey); + buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl); + if ((buf_in == NULL) || (buf_out == NULL)) + { + outl=0; + ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE); + goto err; + } + EVP_SignInit_ex(&ctx,type, NULL); + EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl); + if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out, + (unsigned int *)&outl,pkey)) + { + outl=0; + ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB); + goto err; + } + if (signature->data != NULL) OPENSSL_free(signature->data); + signature->data=buf_out; + buf_out=NULL; + signature->length=outl; + /* In the interests of compatibility, I'll make sure that + * the bit string has a 'not-used bits' value of 0 + */ + signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); + signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; err: - memset(&ctx,0,sizeof(ctx)); + EVP_MD_CTX_cleanup(&ctx); if (buf_in != NULL) - { memset((char *)buf_in,0,(unsigned int)inl); Free((char *)buf_in); } + { memset((char *)buf_in,0,(unsigned int)inl); OPENSSL_free(buf_in); } if (buf_out != NULL) - { memset((char *)buf_out,0,outll); Free((char *)buf_out); } + { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); } return(outl); } diff --git a/src/lib/libcrypto/asn1/a_strex.c b/src/lib/libcrypto/asn1/a_strex.c index 569b811998..128aa7e772 100644 --- a/src/lib/libcrypto/asn1/a_strex.c +++ b/src/lib/libcrypto/asn1/a_strex.c @@ -371,6 +371,8 @@ static int do_indent(char_io *io_ch, void *arg, int indent) return 1; } +#define FN_WIDTH_LN 25 +#define FN_WIDTH_SN 10 static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, int indent, unsigned long flags) @@ -456,19 +458,29 @@ static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, val = X509_NAME_ENTRY_get_data(ent); fn_nid = OBJ_obj2nid(fn); if(fn_opt != XN_FLAG_FN_NONE) { - int objlen; + int objlen, fld_len; if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) { OBJ_obj2txt(objtmp, 80, fn, 1); + fld_len = 0; /* XXX: what should this be? */ objbuf = objtmp; } else { - if(fn_opt == XN_FLAG_FN_SN) + if(fn_opt == XN_FLAG_FN_SN) { + fld_len = FN_WIDTH_SN; objbuf = OBJ_nid2sn(fn_nid); - else if(fn_opt == XN_FLAG_FN_LN) + } else if(fn_opt == XN_FLAG_FN_LN) { + fld_len = FN_WIDTH_LN; objbuf = OBJ_nid2ln(fn_nid); - else objbuf = ""; + } else { + fld_len = 0; /* XXX: what should this be? */ + objbuf = ""; + } } objlen = strlen(objbuf); if(!io_ch(arg, objbuf, objlen)) return -1; + if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { + if (!do_indent(io_ch, arg, fld_len - objlen)) return -1; + outlen += fld_len - objlen; + } if(!io_ch(arg, sep_eq, sep_eq_len)) return -1; outlen += objlen + sep_eq_len; } @@ -491,12 +503,24 @@ static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags) { + if(flags == XN_FLAG_COMPAT) + return X509_NAME_print(out, nm, indent); return do_name_ex(send_bio_chars, out, nm, indent, flags); } int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags) { + if(flags == XN_FLAG_COMPAT) + { + BIO *btmp; + int ret; + btmp = BIO_new_fp(fp, BIO_NOCLOSE); + if(!btmp) return -1; + ret = X509_NAME_print(btmp, nm, indent); + BIO_free(btmp); + return ret; + } return do_name_ex(send_fp_chars, fp, nm, indent, flags); } diff --git a/src/lib/libcrypto/asn1/a_strnid.c b/src/lib/libcrypto/asn1/a_strnid.c index ab8417ffab..04789d1c63 100644 --- a/src/lib/libcrypto/asn1/a_strnid.c +++ b/src/lib/libcrypto/asn1/a_strnid.c @@ -65,8 +65,9 @@ static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; static void st_free(ASN1_STRING_TABLE *tbl); -static int sk_table_cmp(ASN1_STRING_TABLE **a, ASN1_STRING_TABLE **b); -static int table_cmp(ASN1_STRING_TABLE *a, ASN1_STRING_TABLE *b); +static int sk_table_cmp(const ASN1_STRING_TABLE * const *a, + const ASN1_STRING_TABLE * const *b); +static int table_cmp(const void *a, const void *b); /* This is the global mask for the mbstring functions: this is use to @@ -104,9 +105,9 @@ int ASN1_STRING_set_default_mask_asc(char *p) mask = strtoul(p + 5, &end, 0); if(*end) return 0; } else if(!strcmp(p, "nombstr")) - mask = ~(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING); + mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)); else if(!strcmp(p, "pkix")) - mask = ~B_ASN1_T61STRING; + mask = ~((unsigned long)B_ASN1_T61STRING); else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING; else if(!strcmp(p, "default")) mask = 0xFFFFFFFFL; @@ -132,7 +133,7 @@ ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, if(tbl) { mask = tbl->mask; if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask; - ret = ASN1_mbstring_ncopy(out, in, inlen, inform, tbl->mask, + ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, tbl->minsize, tbl->maxsize); } else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask); if(ret <= 0) return NULL; @@ -169,18 +170,22 @@ static ASN1_STRING_TABLE tbl_standard[] = { {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, +{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, {NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, -{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK} +{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, +{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK} }; -static int sk_table_cmp(ASN1_STRING_TABLE **a, ASN1_STRING_TABLE **b) +static int sk_table_cmp(const ASN1_STRING_TABLE * const *a, + const ASN1_STRING_TABLE * const *b) { return (*a)->nid - (*b)->nid; } -static int table_cmp(ASN1_STRING_TABLE *a, ASN1_STRING_TABLE *b) +static int table_cmp(const void *a, const void *b) { - return a->nid - b->nid; + const ASN1_STRING_TABLE *sa = a, *sb = b; + return sa->nid - sb->nid; } ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) @@ -192,7 +197,7 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) ttmp = (ASN1_STRING_TABLE *) OBJ_bsearch((char *)&fnd, (char *)tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), - sizeof(ASN1_STRING_TABLE), (int(*)())table_cmp); + sizeof(ASN1_STRING_TABLE), table_cmp); if(ttmp) return ttmp; if(!stable) return NULL; idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); @@ -213,7 +218,7 @@ int ASN1_STRING_TABLE_add(int nid, return 0; } if(!(tmp = ASN1_STRING_TABLE_get(nid))) { - tmp = Malloc(sizeof(ASN1_STRING_TABLE)); + tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); if(!tmp) { ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); @@ -241,7 +246,7 @@ void ASN1_STRING_TABLE_cleanup(void) static void st_free(ASN1_STRING_TABLE *tbl) { - if(tbl->flags & STABLE_FLAGS_MALLOC) Free(tbl); + if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl); } IMPLEMENT_STACK_OF(ASN1_STRING_TABLE) diff --git a/src/lib/libcrypto/asn1/a_time.c b/src/lib/libcrypto/asn1/a_time.c index c1690a5694..27ddd30899 100644 --- a/src/lib/libcrypto/asn1/a_time.c +++ b/src/lib/libcrypto/asn1/a_time.c @@ -64,8 +64,14 @@ #include #include #include "cryptlib.h" -#include +#include "o_time.h" +#include +IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) + +IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) + +#if 0 int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) { #ifdef CHARSET_EBCDIC @@ -89,35 +95,64 @@ int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp) ASN1err(ASN1_F_I2D_ASN1_TIME,ASN1_R_EXPECTING_A_TIME); return -1; } - - -ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **a, unsigned char **pp, long length) - { - unsigned char tag; - tag = **pp & ~V_ASN1_CONSTRUCTED; - if(tag == (V_ASN1_UTCTIME|V_ASN1_UNIVERSAL)) - return d2i_ASN1_UTCTIME(a, pp, length); - if(tag == (V_ASN1_GENERALIZEDTIME|V_ASN1_UNIVERSAL)) - return d2i_ASN1_GENERALIZEDTIME(a, pp, length); - ASN1err(ASN1_F_D2I_ASN1_TIME,ASN1_R_EXPECTING_A_TIME); - return(NULL); - } +#endif ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) { struct tm *ts; -#if defined(THREADS) && !defined(WIN32) struct tm data; -#endif -#if defined(THREADS) && !defined(WIN32) - gmtime_r(&t,&data); - ts=&data; /* should return &data, but doesn't on some systems, so we don't even look at the return value */ -#else - ts=gmtime(&t); -#endif + ts=OPENSSL_gmtime(&t,&data); + if (ts == NULL) + return NULL; if((ts->tm_year >= 50) && (ts->tm_year < 150)) return ASN1_UTCTIME_set(s, t); return ASN1_GENERALIZEDTIME_set(s,t); } + +int ASN1_TIME_check(ASN1_TIME *t) + { + if (t->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_check(t); + else if (t->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_check(t); + return 0; + } + +/* Convert an ASN1_TIME structure to GeneralizedTime */ +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) + { + ASN1_GENERALIZEDTIME *ret; + char *str; + + if (!ASN1_TIME_check(t)) return NULL; + + if (!out || !*out) + { + if (!(ret = ASN1_GENERALIZEDTIME_new ())) + return NULL; + if (out) *out = ret; + } + else ret = *out; + + /* If already GeneralizedTime just copy across */ + if (t->type == V_ASN1_GENERALIZEDTIME) + { + if(!ASN1_STRING_set(ret, t->data, t->length)) + return NULL; + return ret; + } + + /* grow the string */ + if (!ASN1_STRING_set(ret, NULL, t->length + 2)) + return NULL; + str = (char *)ret->data; + /* Work out the century and prepend */ + if (t->data[0] >= '5') strcpy(str, "19"); + else strcpy(str, "20"); + + strcat(str, (char *)t->data); + + return ret; + } diff --git a/src/lib/libcrypto/asn1/a_type.c b/src/lib/libcrypto/asn1/a_type.c index 7c0004084c..96e111cf23 100644 --- a/src/lib/libcrypto/asn1/a_type.c +++ b/src/lib/libcrypto/asn1/a_type.c @@ -57,219 +57,10 @@ */ #include +#include #include "cryptlib.h" -#include "asn1_mac.h" -/* ASN1err(ASN1_F_ASN1_TYPE_NEW,ASN1_R_ERROR_STACK); - * ASN1err(ASN1_F_D2I_ASN1_BYTES,ASN1_R_ERROR_STACK); - * ASN1err(ASN1_F_D2I_ASN1_BYTES,ASN1_R_WRONG_TAG); - * ASN1err(ASN1_F_ASN1_COLLATE_PRIMATIVE,ASN1_R_WRONG_TAG); - */ - -#ifndef NOPROTO -static void ASN1_TYPE_component_free(ASN1_TYPE *a); -#else -static void ASN1_TYPE_component_free(); -#endif - -int i2d_ASN1_TYPE(a,pp) -ASN1_TYPE *a; -unsigned char **pp; - { - int r=0; - - if (a == NULL) return(0); - - switch (a->type) - { - case V_ASN1_NULL: - if (pp != NULL) - ASN1_put_object(pp,0,0,V_ASN1_NULL,V_ASN1_UNIVERSAL); - r=2; - break; - case V_ASN1_INTEGER: - case V_ASN1_NEG_INTEGER: - r=i2d_ASN1_INTEGER(a->value.integer,pp); - break; - case V_ASN1_BIT_STRING: - r=i2d_ASN1_BIT_STRING(a->value.bit_string,pp); - break; - case V_ASN1_OCTET_STRING: - r=i2d_ASN1_OCTET_STRING(a->value.octet_string,pp); - break; - case V_ASN1_OBJECT: - r=i2d_ASN1_OBJECT(a->value.object,pp); - break; - case V_ASN1_PRINTABLESTRING: - r=M_i2d_ASN1_PRINTABLESTRING(a->value.printablestring,pp); - break; - case V_ASN1_T61STRING: - r=M_i2d_ASN1_T61STRING(a->value.t61string,pp); - break; - case V_ASN1_IA5STRING: - r=M_i2d_ASN1_IA5STRING(a->value.ia5string,pp); - break; - case V_ASN1_GENERALSTRING: - r=M_i2d_ASN1_GENERALSTRING(a->value.generalstring,pp); - break; - case V_ASN1_UNIVERSALSTRING: - r=M_i2d_ASN1_UNIVERSALSTRING(a->value.universalstring,pp); - break; - case V_ASN1_BMPSTRING: - r=M_i2d_ASN1_BMPSTRING(a->value.bmpstring,pp); - break; - case V_ASN1_UTCTIME: - r=i2d_ASN1_UTCTIME(a->value.utctime,pp); - break; - case V_ASN1_SET: - case V_ASN1_SEQUENCE: - if (a->value.set == NULL) - r=0; - else - { - r=a->value.set->length; - if (pp != NULL) - { - memcpy(*pp,a->value.set->data,r); - *pp+=r; - } - } - break; - } - return(r); - } - -ASN1_TYPE *d2i_ASN1_TYPE(a,pp,length) -ASN1_TYPE **a; -unsigned char **pp; -long length; - { - ASN1_TYPE *ret=NULL; - unsigned char *q,*p,*max; - int inf,tag,xclass; - long len; - - if ((a == NULL) || ((*a) == NULL)) - { - if ((ret=ASN1_TYPE_new()) == NULL) goto err; - } - else - ret=(*a); - - p= *pp; - q=p; - max=(p+length); - - inf=ASN1_get_object(&q,&len,&tag,&xclass,length); - if (inf & 0x80) goto err; - - ASN1_TYPE_component_free(ret); - - switch (tag) - { - case V_ASN1_NULL: - p=q; - ret->value.ptr=NULL; - break; - case V_ASN1_INTEGER: - if ((ret->value.integer= - d2i_ASN1_INTEGER(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_BIT_STRING: - if ((ret->value.bit_string= - d2i_ASN1_BIT_STRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_OCTET_STRING: - if ((ret->value.octet_string= - d2i_ASN1_OCTET_STRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_OBJECT: - if ((ret->value.object= - d2i_ASN1_OBJECT(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_PRINTABLESTRING: - if ((ret->value.printablestring= - d2i_ASN1_PRINTABLESTRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_T61STRING: - if ((ret->value.t61string= - M_d2i_ASN1_T61STRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_IA5STRING: - if ((ret->value.ia5string= - M_d2i_ASN1_IA5STRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_GENERALSTRING: - if ((ret->value.generalstring= - M_d2i_ASN1_GENERALSTRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_UNIVERSALSTRING: - if ((ret->value.universalstring= - M_d2i_ASN1_UNIVERSALSTRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_BMPSTRING: - if ((ret->value.bmpstring= - M_d2i_ASN1_BMPSTRING(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_UTCTIME: - if ((ret->value.utctime= - d2i_ASN1_UTCTIME(NULL,&p,max-p)) == NULL) - goto err; - break; - case V_ASN1_SET: - case V_ASN1_SEQUENCE: - /* Sets and sequences are left complete */ - if ((ret->value.set=ASN1_STRING_new()) == NULL) goto err; - ret->value.set->type=tag; - len+=(q-p); - if (!ASN1_STRING_set(ret->value.set,p,(int)len)) goto err; - p+=len; - break; - default: - ASN1err(ASN1_F_D2I_ASN1_TYPE,ASN1_R_BAD_TYPE); - goto err; - } - - ret->type=tag; - if (a != NULL) (*a)=ret; - *pp=p; - return(ret); -err: - if ((ret != NULL) && ((a == NULL) || (*a != ret))) ASN1_TYPE_free(ret); - return(NULL); - } - -ASN1_TYPE *ASN1_TYPE_new() - { - ASN1_TYPE *ret=NULL; - - M_ASN1_New_Malloc(ret,ASN1_TYPE); - ret->type= -1; - ret->value.ptr=NULL; - return(ret); - M_ASN1_New_Error(ASN1_F_ASN1_TYPE_NEW); - } - -void ASN1_TYPE_free(a) -ASN1_TYPE *a; - { - if (a == NULL) return; - ASN1_TYPE_component_free(a); - Free((char *)(char *)a); - } - -int ASN1_TYPE_get(a) -ASN1_TYPE *a; +int ASN1_TYPE_get(ASN1_TYPE *a) { if (a->value.ptr != NULL) return(a->type); @@ -277,49 +68,14 @@ ASN1_TYPE *a; return(0); } -void ASN1_TYPE_set(a,type,value) -ASN1_TYPE *a; -int type; -char *value; +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) { if (a->value.ptr != NULL) - ASN1_TYPE_component_free(a); + ASN1_primitive_free((ASN1_VALUE **)&a, NULL); a->type=type; a->value.ptr=value; } -static void ASN1_TYPE_component_free(a) -ASN1_TYPE *a; - { - if (a == NULL) return; - - if (a->value.ptr != NULL) - { - switch (a->type) - { - case V_ASN1_OBJECT: - ASN1_OBJECT_free(a->value.object); - break; - case V_ASN1_INTEGER: - case V_ASN1_NEG_INTEGER: - case V_ASN1_BIT_STRING: - case V_ASN1_OCTET_STRING: - case V_ASN1_PRINTABLESTRING: - case V_ASN1_T61STRING: - case V_ASN1_IA5STRING: - case V_ASN1_UNIVERSALSTRING: - case V_ASN1_GENERALSTRING: - case V_ASN1_UTCTIME: - case V_ASN1_SET: - case V_ASN1_SEQUENCE: - ASN1_STRING_free((ASN1_STRING *)a->value.ptr); - break; - default: - /* MEMORY LEAK */ - break; - } - a->type=0; - a->value.ptr=NULL; - } - } +IMPLEMENT_STACK_OF(ASN1_TYPE) +IMPLEMENT_ASN1_SET_OF(ASN1_TYPE) diff --git a/src/lib/libcrypto/asn1/a_utf8.c b/src/lib/libcrypto/asn1/a_utf8.c index 4a8a92e9e4..508e11e527 100644 --- a/src/lib/libcrypto/asn1/a_utf8.c +++ b/src/lib/libcrypto/asn1/a_utf8.c @@ -60,24 +60,152 @@ #include "cryptlib.h" #include -int i2d_ASN1_UTF8STRING(ASN1_UTF8STRING *a, unsigned char **pp) - { - return(i2d_ASN1_bytes((ASN1_STRING *)a,pp, - V_ASN1_UTF8STRING,V_ASN1_UNIVERSAL)); - } -ASN1_UTF8STRING *d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **a, unsigned char **pp, - long length) - { - ASN1_UTF8STRING *ret=NULL; +/* UTF8 utilities */ + +/* This parses a UTF8 string one character at a time. It is passed a pointer + * to the string and the length of the string. It sets 'value' to the value of + * the current character. It returns the number of characters read or a + * negative error code: + * -1 = string too short + * -2 = illegal character + * -3 = subsequent characters not of the form 10xxxxxx + * -4 = character encoded incorrectly (not minimal length). + */ + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val) +{ + const unsigned char *p; + unsigned long value; + int ret; + if(len <= 0) return 0; + p = str; - ret=(ASN1_UTF8STRING *)d2i_ASN1_bytes((ASN1_STRING **)a, - pp,length,V_ASN1_UTF8STRING,V_ASN1_UNIVERSAL); - if (ret == NULL) - { - ASN1err(ASN1_F_D2I_ASN1_UTF8STRING,ERR_R_NESTED_ASN1_ERROR); - return(NULL); + /* Check syntax and work out the encoded value (if correct) */ + if((*p & 0x80) == 0) { + value = *p++ & 0x7f; + ret = 1; + } else if((*p & 0xe0) == 0xc0) { + if(len < 2) return -1; + if((p[1] & 0xc0) != 0x80) return -3; + value = (*p++ & 0x1f) << 6; + value |= *p++ & 0x3f; + if(value < 0x80) return -4; + ret = 2; + } else if((*p & 0xf0) == 0xe0) { + if(len < 3) return -1; + if( ((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) ) return -3; + value = (*p++ & 0xf) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if(value < 0x800) return -4; + ret = 3; + } else if((*p & 0xf8) == 0xf0) { + if(len < 4) return -1; + if( ((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) ) return -3; + value = ((unsigned long)(*p++ & 0x7)) << 18; + value |= (*p++ & 0x3f) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if(value < 0x10000) return -4; + ret = 4; + } else if((*p & 0xfc) == 0xf8) { + if(len < 5) return -1; + if( ((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80) ) return -3; + value = ((unsigned long)(*p++ & 0x3)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if(value < 0x200000) return -4; + ret = 5; + } else if((*p & 0xfe) == 0xfc) { + if(len < 6) return -1; + if( ((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80) + || ((p[5] & 0xc0) != 0x80) ) return -3; + value = ((unsigned long)(*p++ & 0x1)) << 30; + value |= ((unsigned long)(*p++ & 0x3f)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if(value < 0x4000000) return -4; + ret = 6; + } else return -2; + *val = value; + return ret; +} + +/* This takes a character 'value' and writes the UTF8 encoded value in + * 'str' where 'str' is a buffer containing 'len' characters. Returns + * the number of characters written or -1 if 'len' is too small. 'str' can + * be set to NULL in which case it just returns the number of characters. + * It will need at most 6 characters. + */ + +int UTF8_putc(unsigned char *str, int len, unsigned long value) +{ + if(!str) len = 6; /* Maximum we will need */ + else if(len <= 0) return -1; + if(value < 0x80) { + if(str) *str = (unsigned char)value; + return 1; + } + if(value < 0x800) { + if(len < 2) return -1; + if(str) { + *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); + *str = (unsigned char)((value & 0x3f) | 0x80); } - return(ret); + return 2; } - + if(value < 0x10000) { + if(len < 3) return -1; + if(str) { + *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 3; + } + if(value < 0x200000) { + if(len < 4) return -1; + if(str) { + *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 4; + } + if(value < 0x4000000) { + if(len < 5) return -1; + if(str) { + *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 5; + } + if(len < 6) return -1; + if(str) { + *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); + *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 6; +} diff --git a/src/lib/libcrypto/asn1/a_verify.c b/src/lib/libcrypto/asn1/a_verify.c index 03fc63dbef..bf41de5146 100644 --- a/src/lib/libcrypto/asn1/a_verify.c +++ b/src/lib/libcrypto/asn1/a_verify.c @@ -58,29 +58,30 @@ #include #include -#include -#include #include "cryptlib.h" -#include "bn.h" -#include "x509.h" -#include "objects.h" -#include "buffer.h" -#include "evp.h" -#include "pem.h" - -int ASN1_verify(i2d,a,signature,data,pkey) -int (*i2d)(); -X509_ALGOR *a; -ASN1_BIT_STRING *signature; -char *data; -EVP_PKEY *pkey; + +#ifndef NO_SYS_TYPES_H +# include +#endif + +#include +#include +#include +#include +#include + +#ifndef NO_ASN1_OLD + +int ASN1_verify(int (*i2d)(), X509_ALGOR *a, ASN1_BIT_STRING *signature, + char *data, EVP_PKEY *pkey) { EVP_MD_CTX ctx; - EVP_MD *type; + const EVP_MD *type; unsigned char *p,*buf_in=NULL; int ret= -1,i,inl; + EVP_MD_CTX_init(&ctx); i=OBJ_obj2nid(a->algorithm); type=EVP_get_digestbyname(OBJ_nid2sn(i)); if (type == NULL) @@ -90,7 +91,7 @@ EVP_PKEY *pkey; } inl=i2d(data,NULL); - buf_in=(unsigned char *)Malloc((unsigned int)inl); + buf_in=OPENSSL_malloc((unsigned int)inl); if (buf_in == NULL) { ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_MALLOC_FAILURE); @@ -99,11 +100,61 @@ EVP_PKEY *pkey; p=buf_in; i2d(data,&p); - EVP_VerifyInit(&ctx,type); + EVP_VerifyInit_ex(&ctx,type, NULL); + EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl); + + memset(buf_in,0,(unsigned int)inl); + OPENSSL_free(buf_in); + + if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data, + (unsigned int)signature->length,pkey) <= 0) + { + ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB); + ret=0; + goto err; + } + /* we don't need to zero the 'ctx' because we just checked + * public information */ + /* memset(&ctx,0,sizeof(ctx)); */ + ret=1; +err: + EVP_MD_CTX_cleanup(&ctx); + return(ret); + } + +#endif + + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature, + void *asn, EVP_PKEY *pkey) + { + EVP_MD_CTX ctx; + const EVP_MD *type; + unsigned char *buf_in=NULL; + int ret= -1,i,inl; + + EVP_MD_CTX_init(&ctx); + i=OBJ_obj2nid(a->algorithm); + type=EVP_get_digestbyname(OBJ_nid2sn(i)); + if (type == NULL) + { + ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + goto err; + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + + if (buf_in == NULL) + { + ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_MALLOC_FAILURE); + goto err; + } + + EVP_VerifyInit_ex(&ctx,type, NULL); EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl); memset(buf_in,0,(unsigned int)inl); - Free((char *)buf_in); + OPENSSL_free(buf_in); if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data, (unsigned int)signature->length,pkey) <= 0) @@ -117,5 +168,8 @@ EVP_PKEY *pkey; /* memset(&ctx,0,sizeof(ctx)); */ ret=1; err: + EVP_MD_CTX_cleanup(&ctx); return(ret); } + + diff --git a/src/lib/libcrypto/asn1/asn1.h b/src/lib/libcrypto/asn1/asn1.h index 9793db365d..0d1713f8dd 100644 --- a/src/lib/libcrypto/asn1/asn1.h +++ b/src/lib/libcrypto/asn1/asn1.h @@ -59,29 +59,49 @@ #ifndef HEADER_ASN1_H #define HEADER_ASN1_H +#include +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include +#include + +#include + +#include +#include + +#ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + #ifdef __cplusplus extern "C" { #endif -#include -#include "bn.h" -#include "stack.h" - #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 recipent choose */ +#define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */ +#define V_ASN1_OTHER -3 /* used in ASN1_TYPE */ +#define V_ASN1_ANY -4 /* used in ASN1 template code */ + +#define V_ASN1_NEG 0x100 /* negative flag */ #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_NEG_INTEGER (2 | V_ASN1_NEG) #define V_ASN1_BIT_STRING 3 #define V_ASN1_OCTET_STRING 4 #define V_ASN1_NULL 5 @@ -89,7 +109,9 @@ extern "C" { #define V_ASN1_OBJECT_DESCRIPTOR 7 #define V_ASN1_EXTERNAL 8 #define V_ASN1_REAL 9 -#define V_ASN1_ENUMERATED 10 /* microsoft weirdness */ +#define V_ASN1_ENUMERATED 10 +#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) +#define V_ASN1_UTF8STRING 12 #define V_ASN1_SEQUENCE 16 #define V_ASN1_SET 17 #define V_ASN1_NUMERICSTRING 18 /**/ @@ -111,111 +133,33 @@ extern "C" { #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 +#define B_ASN1_UTCTIME 0x4000 +#define B_ASN1_GENERALIZEDTIME 0x8000 -#ifndef DEBUG - -#define ASN1_INTEGER 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_GENERALSTRING ASN1_STRING -#define ASN1_UNIVERSALSTRING ASN1_STRING -#define ASN1_BMPSTRING ASN1_STRING - -#else - -typedef struct asn1_integer_st - { - int length; - int type; - unsigned char *data; - } ASN1_INTEGER; - -typedef struct asn1_bit_string_st - { - int length; - int type; - unsigned char *data; - } ASN1_BIT_STRING; - -typedef struct asn1_octet_string_st - { - int length; - int type; - unsigned char *data; - } ASN1_OCTET_STRING; - -typedef struct asn1_printablestring_st - { - int length; - int type; - unsigned char *data; - } ASN1_PRINTABLESTRING; +/* 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) -typedef struct asn1_t61string_st - { - int length; - int type; - unsigned char *data; - } ASN1_T61STRING; +struct X509_algor_st; -typedef struct asn1_ia5string_st - { - int length; - int type; - unsigned char *data; - } ASN1_IA5STRING; - -typedef struct asn1_generalstring_st - { - int length; - int type; - unsigned char *data; - } ASN1_GENERALSTRING; - -typedef struct asn1_universalstring_st - { - int length; - int type; - unsigned char *data; - } ASN1_UNIVERSALSTRING; - -typedef struct asn1_bmpstring_st - { - int length; - int type; - unsigned char *data; - } ASN1_BMPSTRING; - -typedef struct asn1_utctime_st - { - int length; - int type; - unsigned char *data; - } ASN1_UTCTIME; - -typedef struct asn1_generalizedtime_st - { - int length; - int type; - unsigned char *data; - } ASN1_GENERALIZEDTIME; - -#endif +#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */ +#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */ typedef struct asn1_ctx_st { @@ -226,9 +170,10 @@ typedef struct asn1_ctx_st 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 alowed */ + 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 @@ -239,29 +184,274 @@ typedef struct asn1_ctx_st #define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */ typedef struct asn1_object_st { - char *sn,*ln; + 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; +/* ASN1_ENCODING structure: this is used to save the received + * encoding of an ASN1 type. This is useful to get round + * problems with invalid encodings which can break signatures. + */ + +typedef struct ASN1_ENCODING_st + { + unsigned char *enc; /* DER encoding */ + long len; /* Length of encoding */ + int modified; /* set to 1 if 'enc' is invalid */ + } ASN1_ENCODING; + +/* Used with ASN1 LONG type: if a long is set to this it is omitted */ +#define ASN1_LONG_UNDEF 0x7fffffffL + +#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 + +/* Declarations for template structures: for full definitions + * see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; + +/* Declare ASN1 functions: the implement macro in in asn1t.h */ + +#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + type *name##_new(void); \ + void name##_free(type *a); \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + type *name##_new(void); \ + void name##_free(type *a); \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + type *d2i_##name(type **a, unsigned char **in, long len); \ + int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +#define DECLARE_ASN1_FUNCTIONS_const(name) \ + name *name##_new(void); \ + void name##_free(name *a); + + +/* The following macros and typedefs allow an ASN1_ITEM + * to be embedded in a structure and referenced. Since + * the ASN1_ITEM pointers need to be globally accessible + * (possibly from shared libraries) they may exist in + * different forms. On platforms that support it the + * ASN1_ITEM structure itself will be globally exported. + * Other platforms will export a function that returns + * an ASN1_ITEM pointer. + * + * To handle both cases transparently the macros below + * should be used instead of hard coding an ASN1_ITEM + * pointer in a structure. + * + * The structure will look like this: + * + * typedef struct SOMETHING_st { + * ... + * ASN1_ITEM_EXP *iptr; + * ... + * } SOMETHING; + * + * It would be initialised as e.g.: + * + * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...}; + * + * and the actual pointer extracted with: + * + * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr); + * + * Finally an ASN1_ITEM pointer can be extracted from an + * appropriate reference with: ASN1_ITEM_rptr(X509). This + * would be used when a function takes an ASN1_ITEM * argument. + * + */ + +#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +#define ASN1_ITEM_ptr(iptr) (iptr) + +/* Macro to include ASN1_ITEM pointer from base type */ +#define ASN1_ITEM_ref(iptr) (&(iptr##_it)) + +#define ASN1_ITEM_rptr(ref) (&(ref##_it)) + +#define DECLARE_ASN1_ITEM(name) \ + OPENSSL_EXTERN const ASN1_ITEM name##_it; + +#else + +/* Platforms that can't easily handle shared global variables are declared + * as functions returning ASN1_ITEM pointers. + */ + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM * ASN1_ITEM_EXP(void); + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +#define ASN1_ITEM_ptr(iptr) (iptr()) + +/* Macro to include ASN1_ITEM pointer from base type */ +#define ASN1_ITEM_ref(iptr) (iptr##_it) + +#define ASN1_ITEM_rptr(ref) (ref##_it()) + +#define DECLARE_ASN1_ITEM(name) \ + const ASN1_ITEM * name##_it(void); + +#endif + +/* Parameters used by ASN1_STRING_print_ex() */ + +/* These determine which characters to escape: + * RFC2253 special characters, control characters and + * MSB set characters + */ + +#define ASN1_STRFLGS_ESC_2253 1 +#define ASN1_STRFLGS_ESC_CTRL 2 +#define ASN1_STRFLGS_ESC_MSB 4 + + +/* This flag determines how we do escaping: normally + * RC2253 backslash only, set this to use backslash and + * quote. + */ + +#define ASN1_STRFLGS_ESC_QUOTE 8 + + +/* These three flags are internal use only. */ + +/* Character is a valid PrintableString character */ +#define CHARTYPE_PRINTABLESTRING 0x10 +/* Character needs escaping if it is the first character */ +#define CHARTYPE_FIRST_ESC_2253 0x20 +/* Character needs escaping if it is the last character */ +#define CHARTYPE_LAST_ESC_2253 0x40 + +/* NB the internal flags are safely reused below by flags + * handled at the top level. + */ + +/* If this is set we convert all character strings + * to UTF8 first + */ + +#define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +/* If this is set we don't attempt to interpret content: + * just assume all strings are 1 byte per character. This + * will produce some pretty odd looking output! + */ + +#define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +/* If this is set we include the string type in the output */ +#define ASN1_STRFLGS_SHOW_TYPE 0x40 + +/* This determines which strings to display and which to + * 'dump' (hex dump of content octets or DER encoding). We can + * only dump non character strings or everything. If we + * don't dump 'unknown' they are interpreted as character + * strings with 1 octet per character and are subject to + * the usual escaping options. + */ + +#define ASN1_STRFLGS_DUMP_ALL 0x80 +#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +/* These determine what 'dumping' does, we can dump the + * content octets or the DER encoding: both use the + * RFC2253 #XXXXX notation. + */ + +#define ASN1_STRFLGS_DUMP_DER 0x200 + +/* All the string flags consistent with RFC2253, + * escaping control characters isn't essential in + * RFC2253 but it is advisable anyway. + */ + +#define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +DECLARE_STACK_OF(ASN1_INTEGER) +DECLARE_ASN1_SET_OF(ASN1_INTEGER) + +DECLARE_STACK_OF(ASN1_GENERALSTRING) + typedef struct asn1_type_st { int type; union { char *ptr; + ASN1_BOOLEAN boolean; 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; @@ -272,6 +462,8 @@ typedef struct asn1_type_st 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; @@ -279,6 +471,9 @@ typedef struct asn1_type_st } value; } ASN1_TYPE; +DECLARE_STACK_OF(ASN1_TYPE) +DECLARE_ASN1_SET_OF(ASN1_TYPE) + typedef struct asn1_method_st { int (*i2d)(); @@ -295,64 +490,110 @@ typedef struct asn1_header_st ASN1_METHOD *meth; } ASN1_HEADER; -#define ASN1_STRING_length(x) ((x)->length) -#define ASN1_STRING_type(x) ((x)->type) -#define ASN1_STRING_data(x) ((x)->data) +/* 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 ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\ +#define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\ ASN1_STRING_type_new(V_ASN1_BIT_STRING) -#define ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) -#define ASN1_BIT_STRING_dup(a) (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 ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\ +#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\ (ASN1_STRING *)a,(ASN1_STRING *)b) -#define ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) -/* i2d_ASN1_BIT_STRING() is a function */ -/* d2i_ASN1_BIT_STRING() is a function */ +#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) -#define ASN1_INTEGER_new() (ASN1_INTEGER *)\ +#define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\ ASN1_STRING_type_new(V_ASN1_INTEGER) -#define ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a) -#define ASN1_INTEGER_dup(a) (ASN1_INTEGER *)ASN1_STRING_dup((ASN1_STRING *)a) -#define ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\ +#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) -/* ASN1_INTEGER_set() is a function, also see BN_to_ASN1_INTEGER() */ -/* ASN1_INTEGER_get() is a function, also see ASN1_INTEGER_to_BN() */ -/* i2d_ASN1_INTEGER() is a function */ -/* d2i_ASN1_INTEGER() is a function */ -#define ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\ +#define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\ ASN1_STRING_type_new(V_ASN1_OCTET_STRING) -#define ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) -#define ASN1_OCTET_STRING_dup(a) (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 ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\ +#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\ (ASN1_STRING *)a,(ASN1_STRING *)b) -#define ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) -#define ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(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_OCTET_STRING) -/* d2i_ASN1_OCTET_STRING() is a function */ + V_ASN1_UNIVERSAL) -#define ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING) -#define 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, \ +#define B_ASN1_TIME \ + B_ASN1_UTCTIME | \ + B_ASN1_GENERALIZEDTIME + +#define B_ASN1_PRINTABLE \ B_ASN1_PRINTABLESTRING| \ B_ASN1_T61STRING| \ B_ASN1_IA5STRING| \ B_ASN1_BIT_STRING| \ B_ASN1_UNIVERSALSTRING|\ B_ASN1_BMPSTRING|\ - B_ASN1_UNKNOWN) + B_ASN1_UTF8STRING|\ + B_ASN1_UNKNOWN -#define ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING_STRING *)\ +#define B_ASN1_DIRECTORYSTRING \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING + +#define B_ASN1_DISPLAYTEXT \ + B_ASN1_IA5STRING| \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING + +#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_PRINTABLE) + +#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_DIRECTORYSTRING) + +#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_DISPLAYTEXT) + +#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\ ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) -#define ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#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) @@ -360,9 +601,9 @@ typedef struct asn1_header_st (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\ ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING) -#define ASN1_T61STRING_new() (ASN1_T61STRING_STRING *)\ +#define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\ ASN1_STRING_type_new(V_ASN1_T61STRING) -#define ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#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) @@ -370,9 +611,11 @@ typedef struct asn1_header_st (ASN1_T61STRING *)d2i_ASN1_type_bytes\ ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING) -#define ASN1_IA5STRING_new() (ASN1_IA5STRING *)\ +#define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\ ASN1_STRING_type_new(V_ASN1_IA5STRING) -#define ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#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) @@ -380,28 +623,25 @@ typedef struct asn1_header_st (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\ B_ASN1_IA5STRING) -#define ASN1_UTCTIME_new() (ASN1_UTCTIME *)\ +#define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\ ASN1_STRING_type_new(V_ASN1_UTCTIME) -#define ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) -#define ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)ASN1_STRING_dup((ASN1_STRING *)a) -/* i2d_ASN1_UTCTIME() is a function */ -/* d2i_ASN1_UTCTIME() is a function */ -/* ASN1_UTCTIME_set() is a function */ -/* ASN1_UTCTIME_check() is a function */ - -#define ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\ +#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 ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) -#define ASN1_GENERALIZEDTIME_dup(a) (ASN1_UTCTIME *)ASN1_STRING_dup(\ +#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) -/* DOES NOT EXIST YET i2d_ASN1_GENERALIZEDTIME() is a function */ -/* DOES NOT EXIST YET d2i_ASN1_GENERALIZEDTIME() is a function */ -/* DOES NOT EXIST YET ASN1_GENERALIZEDTIME_set() is a function */ -/* DOES NOT EXIST YET ASN1_GENERALIZEDTIME_check() is a function */ -#define ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\ +#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 ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#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) @@ -409,9 +649,9 @@ typedef struct asn1_header_st (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\ ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING) -#define ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\ +#define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\ ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING) -#define ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#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) @@ -419,9 +659,9 @@ typedef struct asn1_header_st (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\ ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING) -#define ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\ +#define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\ ASN1_STRING_type_new(V_ASN1_BMPSTRING) -#define ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +#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) @@ -429,88 +669,164 @@ typedef struct asn1_header_st (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\ ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING) -#ifndef NOPROTO -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); +#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 + +DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + int ASN1_TYPE_get(ASN1_TYPE *a); -void ASN1_TYPE_set(ASN1_TYPE *a, int type, char *value); +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 * c2i_ASN1_OBJECT(ASN1_OBJECT **a,unsigned char **pp, + long length); ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,unsigned char **pp, long length); -ASN1_STRING * ASN1_STRING_new(void ); +DECLARE_ASN1_ITEM(ASN1_OBJECT) + +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); -int ASN1_STRING_set(ASN1_STRING *str,unsigned char *data, int len); - -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, + /* 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); + +DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING) +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp); +ASN1_BIT_STRING *c2i_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); +#ifndef OPENSSL_NO_BIO +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); -int i2d_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp); -ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **a,unsigned char **pp, +DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER) +int i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp); +ASN1_INTEGER *c2i_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); + +DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED) 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_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); +#if 0 +time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s); +#endif -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); +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); -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 *d2i_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING **a, - unsigned char **pp, long l); +DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING) +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_T61STRING *d2i_ASN1_T61STRING(ASN1_T61STRING **a, - unsigned char **pp, long l); -int i2d_ASN1_IA5STRING(ASN1_IA5STRING *a,unsigned char **pp); -ASN1_IA5STRING *d2i_ASN1_IA5STRING(ASN1_IA5STRING **a, - unsigned char **pp, long l); +DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_NULL) +DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) -int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a,unsigned char **pp); -ASN1_UTCTIME * d2i_ASN1_UTCTIME(ASN1_UTCTIME **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); + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) +DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_TIME) + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t); +int ASN1_TIME_check(ASN1_TIME *t); +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out); int i2d_ASN1_SET(STACK *a, unsigned char **pp, - int (*func)(), int ex_tag, int ex_class); + int (*func)(), int ex_tag, int ex_class, int is_set); STACK * d2i_ASN1_SET(STACK **a, unsigned char **pp, long length, - char *(*func)(), int ex_tag, int ex_class); + char *(*func)(), void (*free_func)(void *), + int ex_tag, int ex_class); -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO 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, char *buf, int num); +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); + const char *sn, const 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); @@ -518,6 +834,7 @@ 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); +unsigned long ASN1_tag2bit(int tag); /* 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); @@ -536,18 +853,32 @@ 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 +void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +#ifndef OPENSSL_NO_FP_API char *ASN1_d2i_fp(char *(*xnew)(),char *(*d2i)(),FILE *fp,unsigned char **x); +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); int ASN1_i2d_fp(int (*i2d)(),FILE *out,unsigned char *x); +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); +int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags); #endif -#ifdef HEADER_BIO_H +int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); + +#ifndef OPENSSL_NO_BIO char *ASN1_d2i_bio(char *(*xnew)(),char *(*d2i)(),BIO *bp,unsigned char **x); +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); int ASN1_i2d_bio(int (*i2d)(),BIO *out,unsigned char *x); +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *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_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags); int ASN1_parse(BIO *bp,unsigned char *pp,long len,int indent); +int ASN1_parse_dump(BIO *bp,unsigned char *pp,long len,int indent,int dump); #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); @@ -557,8 +888,6 @@ 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); @@ -574,286 +903,201 @@ int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a,long *num, unsigned char *data, int max_len); -#else - -ASN1_TYPE * ASN1_TYPE_new(); -void ASN1_TYPE_free(); -int i2d_ASN1_TYPE(); -ASN1_TYPE * d2i_ASN1_TYPE(); -int ASN1_TYPE_get(); -void ASN1_TYPE_set(); - -ASN1_OBJECT * ASN1_OBJECT_new(); -void ASN1_OBJECT_free(); -int i2d_ASN1_OBJECT(); -ASN1_OBJECT * d2i_ASN1_OBJECT(); -ASN1_STRING * ASN1_STRING_new(); -void ASN1_STRING_free(); -ASN1_STRING * ASN1_STRING_dup(); -ASN1_STRING * ASN1_STRING_type_new(); -int ASN1_STRING_cmp(); -int ASN1_STRING_set(); -int i2d_ASN1_BIT_STRING(); -ASN1_BIT_STRING *d2i_ASN1_BIT_STRING(); -int ASN1_BIT_STRING_set_bit(); -int ASN1_BIT_STRING_get_bit(); -int i2d_ASN1_BOOLEAN(); -int d2i_ASN1_BOOLEAN(); -int i2d_ASN1_INTEGER(); -ASN1_INTEGER *d2i_ASN1_INTEGER(); -int ASN1_UTCTIME_check(); -ASN1_UTCTIME *ASN1_UTCTIME_set(); -int ASN1_UTCTIME_set_string(); -int i2d_ASN1_OCTET_STRING(); -ASN1_OCTET_STRING *d2i_ASN1_OCTET_STRING(); -int i2d_ASN1_PRINTABLE(); -ASN1_STRING *d2i_ASN1_PRINTABLE(); -ASN1_PRINTABLESTRING *d2i_ASN1_PRINTABLESTRING(); -ASN1_T61STRING *d2i_ASN1_T61STRING(); -int i2d_ASN1_IA5STRING(); -ASN1_IA5STRING *d2i_ASN1_IA5STRING(); -int i2d_ASN1_UTCTIME(); -ASN1_UTCTIME * d2i_ASN1_UTCTIME(); -int i2d_ASN1_SET(); -STACK * d2i_ASN1_SET(); -int a2d_ASN1_OBJECT(); -ASN1_OBJECT *ASN1_OBJECT_create(); -int ASN1_INTEGER_set(); -long ASN1_INTEGER_get(); -ASN1_INTEGER *BN_to_ASN1_INTEGER(); -BIGNUM *ASN1_INTEGER_to_BN(); -int ASN1_PRINTABLE_type(); -int i2d_ASN1_bytes(); -ASN1_STRING *d2i_ASN1_bytes(); -ASN1_STRING *d2i_ASN1_type_bytes(); -int asn1_Finish(); -int ASN1_get_object(); -int ASN1_check_infinite_end(); -void ASN1_put_object(); -int ASN1_object_size(); -char *ASN1_dup(); -#ifndef NO_FP_API -char *ASN1_d2i_fp(); -int ASN1_i2d_fp(); -#endif - -char *ASN1_d2i_bio(); -int ASN1_i2d_bio(); -int ASN1_UTCTIME_print(); -int ASN1_STRING_print(); -int ASN1_parse(); -int i2a_ASN1_INTEGER(); -int a2i_ASN1_INTEGER(); -int i2a_ASN1_OBJECT(); -int i2t_ASN1_OBJECT(); -int a2i_ASN1_STRING(); -int i2a_ASN1_STRING(); - -int i2d_ASN1_HEADER(); -ASN1_HEADER *d2i_ASN1_HEADER(); -ASN1_HEADER *ASN1_HEADER_new(); -void ASN1_HEADER_free(); -void ERR_load_ASN1_strings(); -ASN1_METHOD *X509_asn1_meth(); -ASN1_METHOD *RSAPrivateKey_asn1_meth(); -ASN1_METHOD *ASN1_IA5STRING_asn1_meth(); -ASN1_METHOD *ASN1_BIT_STRING_asn1_meth(); - -int ASN1_UNIVERSALSTRING_to_string(); - -int ASN1_TYPE_set_octetstring(); -int ASN1_TYPE_get_octetstring(); -int ASN1_TYPE_set_int_octetstring(); -int ASN1_TYPE_get_int_octetstring(); - -#endif +STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(), + void (*free_func)(void *) ); +unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, + int *len ); +void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)()); +void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it); +ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, 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); + +/* ASN1 template functions */ + +/* Old API compatible functions */ +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it); +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); + +void ASN1_add_oid_module(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. + */ +void ERR_load_ASN1_strings(void); + /* Error codes for the ASN1 functions. */ /* Function codes. */ #define ASN1_F_A2D_ASN1_OBJECT 100 -#define ASN1_F_A2I_ASN1_INTEGER 101 -#define ASN1_F_A2I_ASN1_STRING 102 -#define ASN1_F_ASN1_COLLATE_PRIMATIVE 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_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_OBJECT_NEW 113 -#define ASN1_F_ASN1_SIGN 114 -#define ASN1_F_ASN1_STRING_NEW 115 -#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_UTCTIME_NEW 120 -#define ASN1_F_ASN1_VERIFY 121 -#define ASN1_F_BN_TO_ASN1_INTEGER 122 -#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_HEADER 127 -#define ASN1_F_D2I_ASN1_INTEGER 128 -#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_TYPE 133 -#define ASN1_F_D2I_ASN1_TYPE_BYTES 134 -#define ASN1_F_D2I_ASN1_UTCTIME 135 -#define ASN1_F_D2I_DHPARAMS 136 -#define ASN1_F_D2I_DSAPARAMS 137 -#define ASN1_F_D2I_DSAPRIVATEKEY 138 -#define ASN1_F_D2I_DSAPUBLICKEY 139 -#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_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_PRIVATEKEY 155 -#define ASN1_F_D2I_PUBLICKEY 156 -#define ASN1_F_D2I_RSAPRIVATEKEY 157 -#define ASN1_F_D2I_RSAPUBLICKEY 158 -#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_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_I2D_ASN1_HEADER 176 -#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_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_X509_ATTRIBUTE 187 -#define ASN1_F_I2T_ASN1_OBJECT 188 -#define ASN1_F_NETSCAPE_PKEY_NEW 189 -#define ASN1_F_NETSCAPE_SPKAC_NEW 190 -#define ASN1_F_NETSCAPE_SPKI_NEW 191 -#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_X509_ALGOR_NEW 202 -#define ASN1_F_X509_ATTRIBUTE_NEW 203 -#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 +#define ASN1_F_A2I_ASN1_ENUMERATED 101 +#define ASN1_F_A2I_ASN1_INTEGER 102 +#define ASN1_F_A2I_ASN1_STRING 103 +#define ASN1_F_ASN1_CHECK_TLEN 104 +#define ASN1_F_ASN1_COLLATE_PRIMITIVE 105 +#define ASN1_F_ASN1_COLLECT 106 +#define ASN1_F_ASN1_D2I_BIO 107 +#define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108 +#define ASN1_F_ASN1_D2I_FP 109 +#define ASN1_F_ASN1_DO_ADB 110 +#define ASN1_F_ASN1_DUP 111 +#define ASN1_F_ASN1_ENUMERATED_SET 112 +#define ASN1_F_ASN1_ENUMERATED_TO_BN 113 +#define ASN1_F_ASN1_GET_OBJECT 114 +#define ASN1_F_ASN1_HEADER_NEW 115 +#define ASN1_F_ASN1_I2D_BIO 116 +#define ASN1_F_ASN1_I2D_FP 117 +#define ASN1_F_ASN1_INTEGER_SET 118 +#define ASN1_F_ASN1_INTEGER_TO_BN 119 +#define ASN1_F_ASN1_ITEM_EX_D2I 120 +#define ASN1_F_ASN1_ITEM_NEW 121 +#define ASN1_F_ASN1_MBSTRING_COPY 122 +#define ASN1_F_ASN1_OBJECT_NEW 123 +#define ASN1_F_ASN1_PACK_STRING 124 +#define ASN1_F_ASN1_PBE_SET 125 +#define ASN1_F_ASN1_SEQ_PACK 126 +#define ASN1_F_ASN1_SEQ_UNPACK 127 +#define ASN1_F_ASN1_SIGN 128 +#define ASN1_F_ASN1_STRING_TABLE_ADD 129 +#define ASN1_F_ASN1_STRING_TYPE_NEW 130 +#define ASN1_F_ASN1_TEMPLATE_D2I 131 +#define ASN1_F_ASN1_TEMPLATE_EX_D2I 132 +#define ASN1_F_ASN1_TEMPLATE_NEW 133 +#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134 +#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135 +#define ASN1_F_ASN1_UNPACK_STRING 136 +#define ASN1_F_ASN1_VERIFY 137 +#define ASN1_F_BN_TO_ASN1_ENUMERATED 138 +#define ASN1_F_BN_TO_ASN1_INTEGER 139 +#define ASN1_F_COLLECT_DATA 140 +#define ASN1_F_D2I_ASN1_BIT_STRING 141 +#define ASN1_F_D2I_ASN1_BOOLEAN 142 +#define ASN1_F_D2I_ASN1_BYTES 143 +#define ASN1_F_D2I_ASN1_GENERALIZEDTIME 144 +#define ASN1_F_D2I_ASN1_HEADER 145 +#define ASN1_F_D2I_ASN1_INTEGER 146 +#define ASN1_F_D2I_ASN1_OBJECT 147 +#define ASN1_F_D2I_ASN1_SET 148 +#define ASN1_F_D2I_ASN1_TYPE_BYTES 149 +#define ASN1_F_D2I_ASN1_UINTEGER 150 +#define ASN1_F_D2I_ASN1_UTCTIME 151 +#define ASN1_F_D2I_NETSCAPE_RSA 152 +#define ASN1_F_D2I_NETSCAPE_RSA_2 153 +#define ASN1_F_D2I_PRIVATEKEY 154 +#define ASN1_F_D2I_PUBLICKEY 155 +#define ASN1_F_D2I_X509 156 +#define ASN1_F_D2I_X509_CINF 157 +#define ASN1_F_D2I_X509_NAME 158 +#define ASN1_F_D2I_X509_PKEY 159 +#define ASN1_F_I2D_ASN1_TIME 160 +#define ASN1_F_I2D_DSA_PUBKEY 161 +#define ASN1_F_I2D_NETSCAPE_RSA 162 +#define ASN1_F_I2D_PRIVATEKEY 163 +#define ASN1_F_I2D_PUBLICKEY 164 +#define ASN1_F_I2D_RSA_PUBKEY 165 +#define ASN1_F_LONG_C2I 166 +#define ASN1_F_OID_MODULE_INIT 174 +#define ASN1_F_PKCS5_PBE2_SET 167 +#define ASN1_F_X509_CINF_NEW 168 +#define ASN1_F_X509_CRL_ADD0_REVOKED 169 +#define ASN1_F_X509_INFO_NEW 170 +#define ASN1_F_X509_NAME_NEW 171 +#define ASN1_F_X509_NEW 172 +#define ASN1_F_X509_PKEY_NEW 173 /* Reason codes. */ -#define ASN1_R_BAD_CLASS 100 -#define ASN1_R_BAD_GET_OBJECT 101 +#define ASN1_R_ADDING_OBJECT 171 +#define ASN1_R_AUX_ERROR 100 +#define ASN1_R_BAD_CLASS 101 #define ASN1_R_BAD_OBJECT_HEADER 102 #define ASN1_R_BAD_PASSWORD_READ 103 -#define ASN1_R_BAD_PKCS7_CONTENT 104 -#define ASN1_R_BAD_PKCS7_TYPE 105 -#define ASN1_R_BAD_TAG 106 -#define ASN1_R_BAD_TYPE 107 -#define ASN1_R_BN_LIB 108 -#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 109 -#define ASN1_R_BUFFER_TOO_SMALL 110 -#define ASN1_R_DATA_IS_WRONG 111 -#define ASN1_R_DECODING_ERROR 112 -#define ASN1_R_ERROR_STACK 113 -#define ASN1_R_EXPECTING_AN_INTEGER 114 -#define ASN1_R_EXPECTING_AN_OBJECT 115 -#define ASN1_R_EXPECTING_AN_OCTET_STRING 116 -#define ASN1_R_EXPECTING_A_BIT_STRING 117 -#define ASN1_R_EXPECTING_A_BOOLEAN 118 -#define ASN1_R_EXPECTING_A_SEQUENCE 119 -#define ASN1_R_EXPECTING_A_UTCTIME 120 -#define ASN1_R_FIRST_NUM_TOO_LARGE 121 -#define ASN1_R_HEADER_TOO_LONG 122 -#define ASN1_R_INVALID_DIGIT 123 -#define ASN1_R_INVALID_SEPARATOR 124 -#define ASN1_R_INVALID_TIME_FORMAT 125 -#define ASN1_R_IV_TOO_LARGE 126 -#define ASN1_R_LENGTH_ERROR 127 -#define ASN1_R_LENGTH_MISMATCH 128 -#define ASN1_R_MISSING_EOS 129 -#define ASN1_R_MISSING_SECOND_NUMBER 130 -#define ASN1_R_NON_HEX_CHARACTERS 131 -#define ASN1_R_NOT_ENOUGH_DATA 132 -#define ASN1_R_ODD_NUMBER_OF_CHARS 133 -#define ASN1_R_PARSING 134 -#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 135 -#define ASN1_R_SECOND_NUMBER_TOO_LARGE 136 -#define ASN1_R_SHORT_LINE 137 -#define ASN1_R_STRING_TOO_SHORT 138 -#define ASN1_R_TAG_VALUE_TOO_HIGH 139 -#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 140 -#define ASN1_R_TOO_LONG 141 -#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 142 -#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 143 -#define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE 144 -#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 145 -#define ASN1_R_UNKNOWN_OBJECT_TYPE 146 -#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 147 -#define ASN1_R_UNSUPPORTED_CIPHER 148 -#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 149 -#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 150 -#define ASN1_R_UTCTIME_TOO_LONG 151 -#define ASN1_R_WRONG_PRINTABLE_TYPE 152 -#define ASN1_R_WRONG_TAG 153 -#define ASN1_R_WRONG_TYPE 154 - +#define ASN1_R_BAD_TAG 104 +#define ASN1_R_BN_LIB 105 +#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +#define ASN1_R_BUFFER_TOO_SMALL 107 +#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108 +#define ASN1_R_DATA_IS_WRONG 109 +#define ASN1_R_DECODE_ERROR 110 +#define ASN1_R_DECODING_ERROR 111 +#define ASN1_R_ENCODE_ERROR 112 +#define ASN1_R_ERROR_LOADING_SECTION 172 +#define ASN1_R_ERROR_PARSING_SET_ELEMENT 113 +#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114 +#define ASN1_R_EXPECTING_AN_INTEGER 115 +#define ASN1_R_EXPECTING_AN_OBJECT 116 +#define ASN1_R_EXPECTING_A_BOOLEAN 117 +#define ASN1_R_EXPECTING_A_TIME 118 +#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +#define ASN1_R_FIELD_MISSING 121 +#define ASN1_R_FIRST_NUM_TOO_LARGE 122 +#define ASN1_R_HEADER_TOO_LONG 123 +#define ASN1_R_ILLEGAL_CHARACTERS 124 +#define ASN1_R_ILLEGAL_NULL 125 +#define ASN1_R_ILLEGAL_OPTIONAL_ANY 126 +#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170 +#define ASN1_R_ILLEGAL_TAGGED_ANY 127 +#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 +#define ASN1_R_INVALID_BMPSTRING_LENGTH 129 +#define ASN1_R_INVALID_DIGIT 130 +#define ASN1_R_INVALID_SEPARATOR 131 +#define ASN1_R_INVALID_TIME_FORMAT 132 +#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133 +#define ASN1_R_INVALID_UTF8STRING 134 +#define ASN1_R_IV_TOO_LARGE 135 +#define ASN1_R_LENGTH_ERROR 136 +#define ASN1_R_MISSING_EOC 137 +#define ASN1_R_MISSING_SECOND_NUMBER 138 +#define ASN1_R_MSTRING_NOT_UNIVERSAL 139 +#define ASN1_R_MSTRING_WRONG_TAG 140 +#define ASN1_R_NON_HEX_CHARACTERS 141 +#define ASN1_R_NOT_ENOUGH_DATA 142 +#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 +#define ASN1_R_NULL_IS_WRONG_LENGTH 144 +#define ASN1_R_ODD_NUMBER_OF_CHARS 145 +#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 146 +#define ASN1_R_SECOND_NUMBER_TOO_LARGE 147 +#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148 +#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 +#define ASN1_R_SHORT_LINE 150 +#define ASN1_R_STRING_TOO_LONG 151 +#define ASN1_R_STRING_TOO_SHORT 152 +#define ASN1_R_TAG_VALUE_TOO_HIGH 153 +#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 +#define ASN1_R_TOO_LONG 155 +#define ASN1_R_TYPE_NOT_CONSTRUCTED 156 +#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157 +#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158 +#define ASN1_R_UNEXPECTED_EOC 159 +#define ASN1_R_UNKNOWN_FORMAT 160 +#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161 +#define ASN1_R_UNKNOWN_OBJECT_TYPE 162 +#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163 +#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164 +#define ASN1_R_UNSUPPORTED_CIPHER 165 +#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166 +#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 +#define ASN1_R_WRONG_TAG 168 +#define ASN1_R_WRONG_TYPE 169 + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/asn1/asn1_err.c b/src/lib/libcrypto/asn1/asn1_err.c index 03c2858e7d..c4c3d2a91d 100644 --- a/src/lib/libcrypto/asn1/asn1_err.c +++ b/src/lib/libcrypto/asn1/asn1_err.c @@ -1,263 +1,237 @@ -/* lib/asn1/asn1_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/asn1/asn1_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "asn1.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA ASN1_str_functs[]= { {ERR_PACK(0,ASN1_F_A2D_ASN1_OBJECT,0), "a2d_ASN1_OBJECT"}, +{ERR_PACK(0,ASN1_F_A2I_ASN1_ENUMERATED,0), "a2i_ASN1_ENUMERATED"}, {ERR_PACK(0,ASN1_F_A2I_ASN1_INTEGER,0), "a2i_ASN1_INTEGER"}, {ERR_PACK(0,ASN1_F_A2I_ASN1_STRING,0), "a2i_ASN1_STRING"}, -{ERR_PACK(0,ASN1_F_ASN1_COLLATE_PRIMATIVE,0), "ASN1_COLLATE_PRIMATIVE"}, +{ERR_PACK(0,ASN1_F_ASN1_CHECK_TLEN,0), "ASN1_CHECK_TLEN"}, +{ERR_PACK(0,ASN1_F_ASN1_COLLATE_PRIMITIVE,0), "ASN1_COLLATE_PRIMITIVE"}, +{ERR_PACK(0,ASN1_F_ASN1_COLLECT,0), "ASN1_COLLECT"}, {ERR_PACK(0,ASN1_F_ASN1_D2I_BIO,0), "ASN1_d2i_bio"}, +{ERR_PACK(0,ASN1_F_ASN1_D2I_EX_PRIMITIVE,0), "ASN1_D2I_EX_PRIMITIVE"}, {ERR_PACK(0,ASN1_F_ASN1_D2I_FP,0), "ASN1_d2i_fp"}, +{ERR_PACK(0,ASN1_F_ASN1_DO_ADB,0), "ASN1_DO_ADB"}, {ERR_PACK(0,ASN1_F_ASN1_DUP,0), "ASN1_dup"}, +{ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_SET,0), "ASN1_ENUMERATED_set"}, +{ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_TO_BN,0), "ASN1_ENUMERATED_to_BN"}, {ERR_PACK(0,ASN1_F_ASN1_GET_OBJECT,0), "ASN1_get_object"}, {ERR_PACK(0,ASN1_F_ASN1_HEADER_NEW,0), "ASN1_HEADER_new"}, {ERR_PACK(0,ASN1_F_ASN1_I2D_BIO,0), "ASN1_i2d_bio"}, {ERR_PACK(0,ASN1_F_ASN1_I2D_FP,0), "ASN1_i2d_fp"}, {ERR_PACK(0,ASN1_F_ASN1_INTEGER_SET,0), "ASN1_INTEGER_set"}, {ERR_PACK(0,ASN1_F_ASN1_INTEGER_TO_BN,0), "ASN1_INTEGER_to_BN"}, +{ERR_PACK(0,ASN1_F_ASN1_ITEM_EX_D2I,0), "ASN1_ITEM_EX_D2I"}, +{ERR_PACK(0,ASN1_F_ASN1_ITEM_NEW,0), "ASN1_item_new"}, +{ERR_PACK(0,ASN1_F_ASN1_MBSTRING_COPY,0), "ASN1_mbstring_copy"}, {ERR_PACK(0,ASN1_F_ASN1_OBJECT_NEW,0), "ASN1_OBJECT_new"}, -{ERR_PACK(0,ASN1_F_ASN1_SIGN,0), "ASN1_SIGN"}, -{ERR_PACK(0,ASN1_F_ASN1_STRING_NEW,0), "ASN1_STRING_new"}, +{ERR_PACK(0,ASN1_F_ASN1_PACK_STRING,0), "ASN1_pack_string"}, +{ERR_PACK(0,ASN1_F_ASN1_PBE_SET,0), "ASN1_PBE_SET"}, +{ERR_PACK(0,ASN1_F_ASN1_SEQ_PACK,0), "ASN1_seq_pack"}, +{ERR_PACK(0,ASN1_F_ASN1_SEQ_UNPACK,0), "ASN1_seq_unpack"}, +{ERR_PACK(0,ASN1_F_ASN1_SIGN,0), "ASN1_sign"}, +{ERR_PACK(0,ASN1_F_ASN1_STRING_TABLE_ADD,0), "ASN1_STRING_TABLE_add"}, {ERR_PACK(0,ASN1_F_ASN1_STRING_TYPE_NEW,0), "ASN1_STRING_type_new"}, +{ERR_PACK(0,ASN1_F_ASN1_TEMPLATE_D2I,0), "ASN1_TEMPLATE_D2I"}, +{ERR_PACK(0,ASN1_F_ASN1_TEMPLATE_EX_D2I,0), "ASN1_TEMPLATE_EX_D2I"}, +{ERR_PACK(0,ASN1_F_ASN1_TEMPLATE_NEW,0), "ASN1_TEMPLATE_NEW"}, {ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING,0), "ASN1_TYPE_get_int_octetstring"}, {ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_OCTETSTRING,0), "ASN1_TYPE_get_octetstring"}, -{ERR_PACK(0,ASN1_F_ASN1_TYPE_NEW,0), "ASN1_TYPE_new"}, -{ERR_PACK(0,ASN1_F_ASN1_UTCTIME_NEW,0), "ASN1_UTCTIME_NEW"}, -{ERR_PACK(0,ASN1_F_ASN1_VERIFY,0), "ASN1_VERIFY"}, +{ERR_PACK(0,ASN1_F_ASN1_UNPACK_STRING,0), "ASN1_unpack_string"}, +{ERR_PACK(0,ASN1_F_ASN1_VERIFY,0), "ASN1_verify"}, +{ERR_PACK(0,ASN1_F_BN_TO_ASN1_ENUMERATED,0), "BN_to_ASN1_ENUMERATED"}, {ERR_PACK(0,ASN1_F_BN_TO_ASN1_INTEGER,0), "BN_to_ASN1_INTEGER"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_BIT_STRING,0), "d2i_ASN1_BIT_STRING"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_BMPSTRING,0), "D2I_ASN1_BMPSTRING"}, +{ERR_PACK(0,ASN1_F_COLLECT_DATA,0), "COLLECT_DATA"}, +{ERR_PACK(0,ASN1_F_D2I_ASN1_BIT_STRING,0), "D2I_ASN1_BIT_STRING"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_BOOLEAN,0), "d2i_ASN1_BOOLEAN"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_BYTES,0), "d2i_ASN1_bytes"}, +{ERR_PACK(0,ASN1_F_D2I_ASN1_GENERALIZEDTIME,0), "D2I_ASN1_GENERALIZEDTIME"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_HEADER,0), "d2i_ASN1_HEADER"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_INTEGER,0), "d2i_ASN1_INTEGER"}, +{ERR_PACK(0,ASN1_F_D2I_ASN1_INTEGER,0), "D2I_ASN1_INTEGER"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_OBJECT,0), "d2i_ASN1_OBJECT"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_OCTET_STRING,0), "d2i_ASN1_OCTET_STRING"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_PRINT_TYPE,0), "D2I_ASN1_PRINT_TYPE"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_SET,0), "d2i_ASN1_SET"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_TYPE,0), "d2i_ASN1_TYPE"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_TYPE_BYTES,0), "d2i_ASN1_type_bytes"}, -{ERR_PACK(0,ASN1_F_D2I_ASN1_UTCTIME,0), "d2i_ASN1_UTCTIME"}, -{ERR_PACK(0,ASN1_F_D2I_DHPARAMS,0), "D2I_DHPARAMS"}, -{ERR_PACK(0,ASN1_F_D2I_DSAPARAMS,0), "D2I_DSAPARAMS"}, -{ERR_PACK(0,ASN1_F_D2I_DSAPRIVATEKEY,0), "D2I_DSAPRIVATEKEY"}, -{ERR_PACK(0,ASN1_F_D2I_DSAPUBLICKEY,0), "D2I_DSAPUBLICKEY"}, -{ERR_PACK(0,ASN1_F_D2I_NETSCAPE_PKEY,0), "D2I_NETSCAPE_PKEY"}, -{ERR_PACK(0,ASN1_F_D2I_NETSCAPE_RSA,0), "D2I_NETSCAPE_RSA"}, +{ERR_PACK(0,ASN1_F_D2I_ASN1_UINTEGER,0), "d2i_ASN1_UINTEGER"}, +{ERR_PACK(0,ASN1_F_D2I_ASN1_UTCTIME,0), "D2I_ASN1_UTCTIME"}, +{ERR_PACK(0,ASN1_F_D2I_NETSCAPE_RSA,0), "d2i_Netscape_RSA"}, {ERR_PACK(0,ASN1_F_D2I_NETSCAPE_RSA_2,0), "D2I_NETSCAPE_RSA_2"}, -{ERR_PACK(0,ASN1_F_D2I_NETSCAPE_SPKAC,0), "D2I_NETSCAPE_SPKAC"}, -{ERR_PACK(0,ASN1_F_D2I_NETSCAPE_SPKI,0), "D2I_NETSCAPE_SPKI"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7,0), "D2I_PKCS7"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_DIGEST,0), "D2I_PKCS7_DIGEST"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_ENCRYPT,0), "D2I_PKCS7_ENCRYPT"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_ENC_CONTENT,0), "D2I_PKCS7_ENC_CONTENT"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_ENVELOPE,0), "D2I_PKCS7_ENVELOPE"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_ISSUER_AND_SERIAL,0), "D2I_PKCS7_ISSUER_AND_SERIAL"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_RECIP_INFO,0), "D2I_PKCS7_RECIP_INFO"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_SIGNED,0), "D2I_PKCS7_SIGNED"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_SIGNER_INFO,0), "D2I_PKCS7_SIGNER_INFO"}, -{ERR_PACK(0,ASN1_F_D2I_PKCS7_SIGN_ENVELOPE,0), "D2I_PKCS7_SIGN_ENVELOPE"}, -{ERR_PACK(0,ASN1_F_D2I_PRIVATEKEY,0), "D2I_PRIVATEKEY"}, -{ERR_PACK(0,ASN1_F_D2I_PUBLICKEY,0), "D2I_PUBLICKEY"}, -{ERR_PACK(0,ASN1_F_D2I_RSAPRIVATEKEY,0), "D2I_RSAPRIVATEKEY"}, -{ERR_PACK(0,ASN1_F_D2I_RSAPUBLICKEY,0), "D2I_RSAPUBLICKEY"}, +{ERR_PACK(0,ASN1_F_D2I_PRIVATEKEY,0), "d2i_PrivateKey"}, +{ERR_PACK(0,ASN1_F_D2I_PUBLICKEY,0), "d2i_PublicKey"}, {ERR_PACK(0,ASN1_F_D2I_X509,0), "D2I_X509"}, -{ERR_PACK(0,ASN1_F_D2I_X509_ALGOR,0), "D2I_X509_ALGOR"}, -{ERR_PACK(0,ASN1_F_D2I_X509_ATTRIBUTE,0), "D2I_X509_ATTRIBUTE"}, {ERR_PACK(0,ASN1_F_D2I_X509_CINF,0), "D2I_X509_CINF"}, -{ERR_PACK(0,ASN1_F_D2I_X509_CRL,0), "D2I_X509_CRL"}, -{ERR_PACK(0,ASN1_F_D2I_X509_CRL_INFO,0), "D2I_X509_CRL_INFO"}, -{ERR_PACK(0,ASN1_F_D2I_X509_EXTENSION,0), "D2I_X509_EXTENSION"}, -{ERR_PACK(0,ASN1_F_D2I_X509_KEY,0), "D2I_X509_KEY"}, {ERR_PACK(0,ASN1_F_D2I_X509_NAME,0), "D2I_X509_NAME"}, -{ERR_PACK(0,ASN1_F_D2I_X509_NAME_ENTRY,0), "D2I_X509_NAME_ENTRY"}, -{ERR_PACK(0,ASN1_F_D2I_X509_PKEY,0), "D2I_X509_PKEY"}, -{ERR_PACK(0,ASN1_F_D2I_X509_PUBKEY,0), "D2I_X509_PUBKEY"}, -{ERR_PACK(0,ASN1_F_D2I_X509_REQ,0), "D2I_X509_REQ"}, -{ERR_PACK(0,ASN1_F_D2I_X509_REQ_INFO,0), "D2I_X509_REQ_INFO"}, -{ERR_PACK(0,ASN1_F_D2I_X509_REVOKED,0), "D2I_X509_REVOKED"}, -{ERR_PACK(0,ASN1_F_D2I_X509_SIG,0), "D2I_X509_SIG"}, -{ERR_PACK(0,ASN1_F_D2I_X509_VAL,0), "D2I_X509_VAL"}, -{ERR_PACK(0,ASN1_F_I2D_ASN1_HEADER,0), "i2d_ASN1_HEADER"}, -{ERR_PACK(0,ASN1_F_I2D_DHPARAMS,0), "I2D_DHPARAMS"}, -{ERR_PACK(0,ASN1_F_I2D_DSAPARAMS,0), "I2D_DSAPARAMS"}, -{ERR_PACK(0,ASN1_F_I2D_DSAPRIVATEKEY,0), "I2D_DSAPRIVATEKEY"}, -{ERR_PACK(0,ASN1_F_I2D_DSAPUBLICKEY,0), "I2D_DSAPUBLICKEY"}, -{ERR_PACK(0,ASN1_F_I2D_NETSCAPE_RSA,0), "I2D_NETSCAPE_RSA"}, -{ERR_PACK(0,ASN1_F_I2D_PKCS7,0), "I2D_PKCS7"}, -{ERR_PACK(0,ASN1_F_I2D_PRIVATEKEY,0), "I2D_PRIVATEKEY"}, -{ERR_PACK(0,ASN1_F_I2D_PUBLICKEY,0), "I2D_PUBLICKEY"}, -{ERR_PACK(0,ASN1_F_I2D_RSAPRIVATEKEY,0), "I2D_RSAPRIVATEKEY"}, -{ERR_PACK(0,ASN1_F_I2D_RSAPUBLICKEY,0), "I2D_RSAPUBLICKEY"}, -{ERR_PACK(0,ASN1_F_I2D_X509_ATTRIBUTE,0), "I2D_X509_ATTRIBUTE"}, -{ERR_PACK(0,ASN1_F_I2T_ASN1_OBJECT,0), "i2t_ASN1_OBJECT"}, -{ERR_PACK(0,ASN1_F_NETSCAPE_PKEY_NEW,0), "NETSCAPE_PKEY_NEW"}, -{ERR_PACK(0,ASN1_F_NETSCAPE_SPKAC_NEW,0), "NETSCAPE_SPKAC_NEW"}, -{ERR_PACK(0,ASN1_F_NETSCAPE_SPKI_NEW,0), "NETSCAPE_SPKI_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_DIGEST_NEW,0), "PKCS7_DIGEST_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_ENCRYPT_NEW,0), "PKCS7_ENCRYPT_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_ENC_CONTENT_NEW,0), "PKCS7_ENC_CONTENT_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_ENVELOPE_NEW,0), "PKCS7_ENVELOPE_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_ISSUER_AND_SERIAL_NEW,0), "PKCS7_ISSUER_AND_SERIAL_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_NEW,0), "PKCS7_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_RECIP_INFO_NEW,0), "PKCS7_RECIP_INFO_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_SIGNED_NEW,0), "PKCS7_SIGNED_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_SIGNER_INFO_NEW,0), "PKCS7_SIGNER_INFO_NEW"}, -{ERR_PACK(0,ASN1_F_PKCS7_SIGN_ENVELOPE_NEW,0), "PKCS7_SIGN_ENVELOPE_NEW"}, -{ERR_PACK(0,ASN1_F_X509_ALGOR_NEW,0), "X509_ALGOR_NEW"}, -{ERR_PACK(0,ASN1_F_X509_ATTRIBUTE_NEW,0), "X509_ATTRIBUTE_NEW"}, +{ERR_PACK(0,ASN1_F_D2I_X509_PKEY,0), "d2i_X509_PKEY"}, +{ERR_PACK(0,ASN1_F_I2D_ASN1_TIME,0), "I2D_ASN1_TIME"}, +{ERR_PACK(0,ASN1_F_I2D_DSA_PUBKEY,0), "i2d_DSA_PUBKEY"}, +{ERR_PACK(0,ASN1_F_I2D_NETSCAPE_RSA,0), "i2d_Netscape_RSA"}, +{ERR_PACK(0,ASN1_F_I2D_PRIVATEKEY,0), "i2d_PrivateKey"}, +{ERR_PACK(0,ASN1_F_I2D_PUBLICKEY,0), "i2d_PublicKey"}, +{ERR_PACK(0,ASN1_F_I2D_RSA_PUBKEY,0), "i2d_RSA_PUBKEY"}, +{ERR_PACK(0,ASN1_F_LONG_C2I,0), "LONG_C2I"}, +{ERR_PACK(0,ASN1_F_OID_MODULE_INIT,0), "OID_MODULE_INIT"}, +{ERR_PACK(0,ASN1_F_PKCS5_PBE2_SET,0), "PKCS5_pbe2_set"}, {ERR_PACK(0,ASN1_F_X509_CINF_NEW,0), "X509_CINF_NEW"}, -{ERR_PACK(0,ASN1_F_X509_CRL_INFO_NEW,0), "X509_CRL_INFO_NEW"}, -{ERR_PACK(0,ASN1_F_X509_CRL_NEW,0), "X509_CRL_NEW"}, -{ERR_PACK(0,ASN1_F_X509_DHPARAMS_NEW,0), "X509_DHPARAMS_NEW"}, -{ERR_PACK(0,ASN1_F_X509_EXTENSION_NEW,0), "X509_EXTENSION_NEW"}, -{ERR_PACK(0,ASN1_F_X509_INFO_NEW,0), "X509_INFO_NEW"}, -{ERR_PACK(0,ASN1_F_X509_KEY_NEW,0), "X509_KEY_NEW"}, -{ERR_PACK(0,ASN1_F_X509_NAME_ENTRY_NEW,0), "X509_NAME_ENTRY_NEW"}, +{ERR_PACK(0,ASN1_F_X509_CRL_ADD0_REVOKED,0), "X509_CRL_add0_revoked"}, +{ERR_PACK(0,ASN1_F_X509_INFO_NEW,0), "X509_INFO_new"}, {ERR_PACK(0,ASN1_F_X509_NAME_NEW,0), "X509_NAME_NEW"}, {ERR_PACK(0,ASN1_F_X509_NEW,0), "X509_NEW"}, -{ERR_PACK(0,ASN1_F_X509_PKEY_NEW,0), "X509_PKEY_NEW"}, -{ERR_PACK(0,ASN1_F_X509_PUBKEY_NEW,0), "X509_PUBKEY_NEW"}, -{ERR_PACK(0,ASN1_F_X509_REQ_INFO_NEW,0), "X509_REQ_INFO_NEW"}, -{ERR_PACK(0,ASN1_F_X509_REQ_NEW,0), "X509_REQ_NEW"}, -{ERR_PACK(0,ASN1_F_X509_REVOKED_NEW,0), "X509_REVOKED_NEW"}, -{ERR_PACK(0,ASN1_F_X509_SIG_NEW,0), "X509_SIG_NEW"}, -{ERR_PACK(0,ASN1_F_X509_VAL_FREE,0), "X509_VAL_FREE"}, -{ERR_PACK(0,ASN1_F_X509_VAL_NEW,0), "X509_VAL_NEW"}, -{0,NULL}, +{ERR_PACK(0,ASN1_F_X509_PKEY_NEW,0), "X509_PKEY_new"}, +{0,NULL} }; static ERR_STRING_DATA ASN1_str_reasons[]= { +{ASN1_R_ADDING_OBJECT ,"adding object"}, +{ASN1_R_AUX_ERROR ,"aux error"}, {ASN1_R_BAD_CLASS ,"bad class"}, -{ASN1_R_BAD_GET_OBJECT ,"bad get object"}, {ASN1_R_BAD_OBJECT_HEADER ,"bad object header"}, {ASN1_R_BAD_PASSWORD_READ ,"bad password read"}, -{ASN1_R_BAD_PKCS7_CONTENT ,"bad pkcs7 content"}, -{ASN1_R_BAD_PKCS7_TYPE ,"bad pkcs7 type"}, {ASN1_R_BAD_TAG ,"bad tag"}, -{ASN1_R_BAD_TYPE ,"bad type"}, {ASN1_R_BN_LIB ,"bn lib"}, {ASN1_R_BOOLEAN_IS_WRONG_LENGTH ,"boolean is wrong length"}, {ASN1_R_BUFFER_TOO_SMALL ,"buffer too small"}, +{ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER ,"cipher has no object identifier"}, {ASN1_R_DATA_IS_WRONG ,"data is wrong"}, +{ASN1_R_DECODE_ERROR ,"decode error"}, {ASN1_R_DECODING_ERROR ,"decoding error"}, -{ASN1_R_ERROR_STACK ,"error stack"}, +{ASN1_R_ENCODE_ERROR ,"encode error"}, +{ASN1_R_ERROR_LOADING_SECTION ,"error loading section"}, +{ASN1_R_ERROR_PARSING_SET_ELEMENT ,"error parsing set element"}, +{ASN1_R_ERROR_SETTING_CIPHER_PARAMS ,"error setting cipher params"}, {ASN1_R_EXPECTING_AN_INTEGER ,"expecting an integer"}, {ASN1_R_EXPECTING_AN_OBJECT ,"expecting an object"}, -{ASN1_R_EXPECTING_AN_OCTET_STRING ,"expecting an octet string"}, -{ASN1_R_EXPECTING_A_BIT_STRING ,"expecting a bit string"}, {ASN1_R_EXPECTING_A_BOOLEAN ,"expecting a boolean"}, -{ASN1_R_EXPECTING_A_SEQUENCE ,"expecting a sequence"}, -{ASN1_R_EXPECTING_A_UTCTIME ,"expecting a utctime"}, +{ASN1_R_EXPECTING_A_TIME ,"expecting a time"}, +{ASN1_R_EXPLICIT_LENGTH_MISMATCH ,"explicit length mismatch"}, +{ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED ,"explicit tag not constructed"}, +{ASN1_R_FIELD_MISSING ,"field missing"}, {ASN1_R_FIRST_NUM_TOO_LARGE ,"first num too large"}, {ASN1_R_HEADER_TOO_LONG ,"header too long"}, +{ASN1_R_ILLEGAL_CHARACTERS ,"illegal characters"}, +{ASN1_R_ILLEGAL_NULL ,"illegal null"}, +{ASN1_R_ILLEGAL_OPTIONAL_ANY ,"illegal optional any"}, +{ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE ,"illegal options on item template"}, +{ASN1_R_ILLEGAL_TAGGED_ANY ,"illegal tagged any"}, +{ASN1_R_INTEGER_TOO_LARGE_FOR_LONG ,"integer too large for long"}, +{ASN1_R_INVALID_BMPSTRING_LENGTH ,"invalid bmpstring length"}, {ASN1_R_INVALID_DIGIT ,"invalid digit"}, {ASN1_R_INVALID_SEPARATOR ,"invalid separator"}, {ASN1_R_INVALID_TIME_FORMAT ,"invalid time format"}, +{ASN1_R_INVALID_UNIVERSALSTRING_LENGTH ,"invalid universalstring length"}, +{ASN1_R_INVALID_UTF8STRING ,"invalid utf8string"}, {ASN1_R_IV_TOO_LARGE ,"iv too large"}, {ASN1_R_LENGTH_ERROR ,"length error"}, -{ASN1_R_LENGTH_MISMATCH ,"length mismatch"}, -{ASN1_R_MISSING_EOS ,"missing eos"}, +{ASN1_R_MISSING_EOC ,"missing eoc"}, {ASN1_R_MISSING_SECOND_NUMBER ,"missing second number"}, +{ASN1_R_MSTRING_NOT_UNIVERSAL ,"mstring not universal"}, +{ASN1_R_MSTRING_WRONG_TAG ,"mstring wrong tag"}, {ASN1_R_NON_HEX_CHARACTERS ,"non hex characters"}, {ASN1_R_NOT_ENOUGH_DATA ,"not enough data"}, +{ASN1_R_NO_MATCHING_CHOICE_TYPE ,"no matching choice type"}, +{ASN1_R_NULL_IS_WRONG_LENGTH ,"null is wrong length"}, {ASN1_R_ODD_NUMBER_OF_CHARS ,"odd number of chars"}, -{ASN1_R_PARSING ,"parsing"}, {ASN1_R_PRIVATE_KEY_HEADER_MISSING ,"private key header missing"}, {ASN1_R_SECOND_NUMBER_TOO_LARGE ,"second number too large"}, +{ASN1_R_SEQUENCE_LENGTH_MISMATCH ,"sequence length mismatch"}, +{ASN1_R_SEQUENCE_NOT_CONSTRUCTED ,"sequence not constructed"}, {ASN1_R_SHORT_LINE ,"short line"}, +{ASN1_R_STRING_TOO_LONG ,"string too long"}, {ASN1_R_STRING_TOO_SHORT ,"string too short"}, {ASN1_R_TAG_VALUE_TOO_HIGH ,"tag value too high"}, {ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD,"the asn1 object identifier is not known for this md"}, {ASN1_R_TOO_LONG ,"too long"}, +{ASN1_R_TYPE_NOT_CONSTRUCTED ,"type not constructed"}, {ASN1_R_UNABLE_TO_DECODE_RSA_KEY ,"unable to decode rsa key"}, {ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY ,"unable to decode rsa private key"}, -{ASN1_R_UNKNOWN_ATTRIBUTE_TYPE ,"unknown attribute type"}, +{ASN1_R_UNEXPECTED_EOC ,"unexpected eoc"}, +{ASN1_R_UNKNOWN_FORMAT ,"unknown format"}, {ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM ,"unknown message digest algorithm"}, {ASN1_R_UNKNOWN_OBJECT_TYPE ,"unknown object type"}, {ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE ,"unknown public key type"}, +{ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE ,"unsupported any defined by type"}, {ASN1_R_UNSUPPORTED_CIPHER ,"unsupported cipher"}, {ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM ,"unsupported encryption algorithm"}, {ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE ,"unsupported public key type"}, -{ASN1_R_UTCTIME_TOO_LONG ,"utctime too long"}, -{ASN1_R_WRONG_PRINTABLE_TYPE ,"wrong printable type"}, {ASN1_R_WRONG_TAG ,"wrong tag"}, {ASN1_R_WRONG_TYPE ,"wrong type"}, -{0,NULL}, +{0,NULL} }; #endif -void ERR_load_ASN1_strings() +void ERR_load_ASN1_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_ASN1,ASN1_str_functs); ERR_load_strings(ERR_LIB_ASN1,ASN1_str_reasons); #endif diff --git a/src/lib/libcrypto/asn1/asn1_lib.c b/src/lib/libcrypto/asn1/asn1_lib.c index ff30b25836..830ff2af3c 100644 --- a/src/lib/libcrypto/asn1/asn1_lib.c +++ b/src/lib/libcrypto/asn1/asn1_lib.c @@ -58,22 +58,13 @@ #include #include "cryptlib.h" -#include "asn1.h" -#include "asn1_mac.h" +#include -#ifndef NOPROTO static int asn1_get_length(unsigned char **pp,int *inf,long *rl,int max); static void asn1_put_length(unsigned char **pp, int length); -#else -static int asn1_get_length(); -static void asn1_put_length(); -#endif - -char *ASN1_version="ASN1 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *ASN1_version="ASN.1" OPENSSL_VERSION_PTEXT; -int ASN1_check_infinite_end(p,len) -unsigned char **p; -long len; +int ASN1_check_infinite_end(unsigned char **p, long len) { /* If there is 0 or 1 byte left, the length check should pick * things up */ @@ -88,12 +79,8 @@ long len; } -int ASN1_get_object(pp, plength, ptag, pclass, omax) -unsigned char **pp; -long *plength; -int *ptag; -int *pclass; -long omax; +int ASN1_get_object(unsigned char **pp, long *plength, int *ptag, int *pclass, + long omax) { int i,ret; long l; @@ -104,8 +91,8 @@ long omax; if (!max) goto err; ret=(*p&V_ASN1_CONSTRUCTED); xclass=(*p&V_ASN1_PRIVATE); - i= *p&V_ASN1_PRIMATIVE_TAG; - if (i == V_ASN1_PRIMATIVE_TAG) + i= *p&V_ASN1_PRIMITIVE_TAG; + if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ p++; if (--max == 0) goto err; @@ -130,11 +117,13 @@ long omax; *pclass=xclass; if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err; -#ifdef undef - fprintf(stderr,"p=%d + *plength=%d > omax=%d + *pp=%d (%d > %d)\n", - p,*plength,omax,*pp,(p+ *plength),omax+ *pp); +#if 0 + fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n", + (int)p,*plength,omax,(int)*pp,(int)(p+ *plength), + (int)(omax+ *pp)); #endif +#if 0 if ((p+ *plength) > (omax+ *pp)) { ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG); @@ -142,18 +131,15 @@ long omax; * the values are set correctly */ ret|=0x80; } +#endif *pp=p; - return(ret+inf); + return(ret|inf); err: ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG); return(0x80); } -static int asn1_get_length(pp,inf,rl,max) -unsigned char **pp; -int *inf; -long *rl; -int max; +static int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) { unsigned char *p= *pp; long ret=0; @@ -189,30 +175,29 @@ int max; } /* class 0 is constructed - * constructed == 2 for indefinitle length constructed */ -void ASN1_put_object(pp,constructed,length,tag,xclass) -unsigned char **pp; -int constructed; -int length; -int tag; -int xclass; + * constructed == 2 for indefinite length constructed */ +void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, + int xclass) { unsigned char *p= *pp; - int i; + int i, ttag; i=(constructed)?V_ASN1_CONSTRUCTED:0; i|=(xclass&V_ASN1_PRIVATE); if (tag < 31) - *(p++)=i|(tag&V_ASN1_PRIMATIVE_TAG); + *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG); else { - *(p++)=i|V_ASN1_PRIMATIVE_TAG; - while (tag > 0x7f) + *(p++)=i|V_ASN1_PRIMITIVE_TAG; + for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7; + ttag = i; + while(i-- > 0) { - *(p++)=(tag&0x7f)|0x80; - tag>>=7; + p[i] = tag & 0x7f; + if(i != (ttag - 1)) p[i] |= 0x80; + tag >>= 7; } - *(p++)=(tag&0x7f); + p += ttag; } if ((constructed == 2) && (length == 0)) *(p++)=0x80; /* der_put_length would output 0 instead */ @@ -221,9 +206,7 @@ int xclass; *pp=p; } -static void asn1_put_length(pp, length) -unsigned char **pp; -int length; +static void asn1_put_length(unsigned char **pp, int length) { unsigned char *p= *pp; int i,l; @@ -246,10 +229,7 @@ int length; *pp=p; } -int ASN1_object_size(constructed, length, tag) -int constructed; -int length; -int tag; +int ASN1_object_size(int constructed, int length, int tag) { int ret; @@ -277,29 +257,26 @@ int tag; return(ret); } -int asn1_Finish(c) -ASN1_CTX *c; +int asn1_Finish(ASN1_CTX *c) { if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos)) { if (!ASN1_check_infinite_end(&c->p,c->slen)) { - c->error=ASN1_R_MISSING_EOS; + c->error=ERR_R_MISSING_ASN1_EOS; return(0); } } if ( ((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) { - c->error=ASN1_R_LENGTH_MISMATCH; + c->error=ERR_R_ASN1_LENGTH_MISMATCH; return(0); } return(1); } -int asn1_GetSequence(c,length) -ASN1_CTX *c; -long *length; +int asn1_GetSequence(ASN1_CTX *c, long *length) { unsigned char *q; @@ -308,18 +285,18 @@ long *length; *length); if (c->inf & 0x80) { - c->error=ASN1_R_BAD_GET_OBJECT; + c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL; return(0); } if (c->tag != V_ASN1_SEQUENCE) { - c->error=ASN1_R_EXPECTING_A_SEQUENCE; + c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE; return(0); } (*length)-=(c->p-q); if (c->max && (*length < 0)) { - c->error=ASN1_R_LENGTH_MISMATCH; + c->error=ERR_R_ASN1_LENGTH_MISMATCH; return(0); } if (c->inf == (1|V_ASN1_CONSTRUCTED)) @@ -328,8 +305,7 @@ long *length; return(1); } -ASN1_STRING *ASN1_STRING_dup(str) -ASN1_STRING *str; +ASN1_STRING *ASN1_STRING_dup(ASN1_STRING *str) { ASN1_STRING *ret; @@ -341,34 +317,33 @@ ASN1_STRING *str; ASN1_STRING_free(ret); return(NULL); } + ret->flags = str->flags; return(ret); } -int ASN1_STRING_set(str,data,len) -ASN1_STRING *str; -unsigned char *data; -int len; +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) { - char *c; + unsigned char *c; + const char *data=_data; if (len < 0) { if (data == NULL) return(0); else - len=strlen((char *)data); + len=strlen(data); } if ((str->length < len) || (str->data == NULL)) { - c=(char *)str->data; + c=str->data; if (c == NULL) - str->data=(unsigned char *)Malloc(len+1); + str->data=OPENSSL_malloc(len+1); else - str->data=(unsigned char *)Realloc(c,len+1); + str->data=OPENSSL_realloc(c,len+1); if (str->data == NULL) { - str->data=(unsigned char *)c; + str->data=c; return(0); } } @@ -376,24 +351,23 @@ int len; if (data != NULL) { memcpy(str->data,data,len); - /* an alowance for strings :-) */ + /* an allowance for strings :-) */ str->data[len]='\0'; } return(1); } -ASN1_STRING *ASN1_STRING_new() +ASN1_STRING *ASN1_STRING_new(void) { return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); } -ASN1_STRING *ASN1_STRING_type_new(type) -int type; +ASN1_STRING *ASN1_STRING_type_new(int type) { ASN1_STRING *ret; - ret=(ASN1_STRING *)Malloc(sizeof(ASN1_STRING)); + ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); if (ret == NULL) { ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW,ERR_R_MALLOC_FAILURE); @@ -402,19 +376,18 @@ int type; ret->length=0; ret->type=type; ret->data=NULL; + ret->flags=0; return(ret); } -void ASN1_STRING_free(a) -ASN1_STRING *a; +void ASN1_STRING_free(ASN1_STRING *a) { if (a == NULL) return; - if (a->data != NULL) Free((char *)a->data); - Free((char *)a); + if (a->data != NULL) OPENSSL_free(a->data); + OPENSSL_free(a); } -int ASN1_STRING_cmp(a,b) -ASN1_STRING *a,*b; +int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b) { int i; @@ -431,9 +404,7 @@ ASN1_STRING *a,*b; return(i); } -void asn1_add_error(address,offset) -unsigned char *address; -int offset; +void asn1_add_error(unsigned char *address, int offset) { char buf1[16],buf2[16]; @@ -442,3 +413,14 @@ int offset; ERR_add_error_data(4,"address=",buf1," offset=",buf2); } +int ASN1_STRING_length(ASN1_STRING *x) +{ return M_ASN1_STRING_length(x); } + +void ASN1_STRING_length_set(ASN1_STRING *x, int len) +{ M_ASN1_STRING_length_set(x, len); return; } + +int ASN1_STRING_type(ASN1_STRING *x) +{ return M_ASN1_STRING_type(x); } + +unsigned char * ASN1_STRING_data(ASN1_STRING *x) +{ return M_ASN1_STRING_data(x); } diff --git a/src/lib/libcrypto/asn1/asn1_mac.h b/src/lib/libcrypto/asn1/asn1_mac.h index 4fba70e4bb..a48649ceeb 100644 --- a/src/lib/libcrypto/asn1/asn1_mac.h +++ b/src/lib/libcrypto/asn1/asn1_mac.h @@ -59,52 +59,84 @@ #ifndef HEADER_ASN1_MAC_H #define HEADER_ASN1_MAC_H +#include + #ifdef __cplusplus extern "C" { #endif -#include "asn1.h" -#include "x509.h" -#include "pkcs7.h" +#ifndef ASN1_MAC_ERR_LIB +#define ASN1_MAC_ERR_LIB ERR_LIB_ASN1 +#endif + +#define ASN1_MAC_H_err(f,r,line) \ + ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line)) #define M_ASN1_D2I_vars(a,type,func) \ ASN1_CTX c; \ type ret=NULL; \ \ - c.pp=pp; \ - c.error=ASN1_R_ERROR_STACK; \ + c.pp=(unsigned char **)pp; \ + c.q= *(unsigned char **)pp; \ + c.error=ERR_R_NESTED_ASN1_ERROR; \ if ((a == NULL) || ((*a) == NULL)) \ - { if ((ret=(type)func()) == NULL) goto err; } \ + { if ((ret=(type)func()) == NULL) \ + { c.line=__LINE__; goto err; } } \ else ret=(*a); #define M_ASN1_D2I_Init() \ - c.p= *pp; \ + c.p= *(unsigned char **)pp; \ c.max=(length == 0)?0:(c.p+length); #define M_ASN1_D2I_Finish_2(a) \ - if (!asn1_Finish(&c)) goto err; \ - *pp=c.p; \ + if (!asn1_Finish(&c)) \ + { c.line=__LINE__; goto err; } \ + *(unsigned char **)pp=c.p; \ if (a != NULL) (*a)=ret; \ return(ret); #define M_ASN1_D2I_Finish(a,func,e) \ M_ASN1_D2I_Finish_2(a); \ err:\ - ASN1err((e),c.error); \ - asn1_add_error(*pp,(int)(c.q- *pp)); \ + ASN1_MAC_H_err((e),c.error,c.line); \ + asn1_add_error(*(unsigned char **)pp,(int)(c.q- *pp)); \ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \ return(NULL) #define M_ASN1_D2I_start_sequence() \ - if (!asn1_GetSequence(&c,&length)) goto err; + if (!asn1_GetSequence(&c,&length)) \ + { c.line=__LINE__; goto err; } +/* Begin reading ASN1 without a surrounding sequence */ +#define M_ASN1_D2I_begin() \ + c.slen = length; + +/* End reading ASN1 with no check on length */ +#define M_ASN1_D2I_Finish_nolen(a, func, e) \ + *pp=c.p; \ + if (a != NULL) (*a)=ret; \ + return(ret); \ +err:\ + ASN1_MAC_H_err((e),c.error,c.line); \ + asn1_add_error(*pp,(int)(c.q- *pp)); \ + if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \ + return(NULL) #define M_ASN1_D2I_end_sequence() \ (((c.inf&1) == 0)?(c.slen <= 0): \ (c.eos=ASN1_check_infinite_end(&c.p,c.slen))) +/* Don't use this with d2i_ASN1_BOOLEAN() */ #define M_ASN1_D2I_get(b,func) \ c.q=c.p; \ - if (func(&(b),&c.p,c.slen) == NULL) goto err; \ + if (func(&(b),&c.p,c.slen) == NULL) \ + {c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +/* use this instead () */ +#define M_ASN1_D2I_get_int(b,func) \ + c.q=c.p; \ + if (func(&(b),&c.p,c.slen) < 0) \ + {c.line=__LINE__; goto err; } \ c.slen-=(c.p-c.q); #define M_ASN1_D2I_get_opt(b,func,type) \ @@ -114,49 +146,118 @@ err:\ M_ASN1_D2I_get(b,func); \ } +#define M_ASN1_D2I_get_imp(b,func, type) \ + M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \ + c.q=c.p; \ + if (func(&(b),&c.p,c.slen) == NULL) \ + {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \ + c.slen-=(c.p-c.q);\ + M_ASN1_next_prev=_tmp; + #define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \ (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \ { \ - unsigned char tmp; \ - tmp=M_ASN1_next; \ - M_ASN1_next=(tmp& ~V_ASN1_PRIMATIVE_TAG)|type; \ - M_ASN1_D2I_get(b,func); \ - M_ASN1_next_prev=tmp; \ + unsigned char _tmp = M_ASN1_next; \ + M_ASN1_D2I_get_imp(b,func, type);\ } -#define M_ASN1_D2I_get_set(r,func) \ - M_ASN1_D2I_get_imp_set(r,func,V_ASN1_SET,V_ASN1_UNIVERSAL); +#define M_ASN1_D2I_get_set(r,func,free_func) \ + M_ASN1_D2I_get_imp_set(r,func,free_func, \ + V_ASN1_SET,V_ASN1_UNIVERSAL); + +#define M_ASN1_D2I_get_set_type(type,r,func,free_func) \ + M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \ + V_ASN1_SET,V_ASN1_UNIVERSAL); + +#define M_ASN1_D2I_get_set_opt(r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SET)))\ + { M_ASN1_D2I_get_set(r,func,free_func); } + +#define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SET)))\ + { M_ASN1_D2I_get_set_type(type,r,func,free_func); } + +#define M_ASN1_I2D_len_SET_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_len_SET(a,f); + +#define M_ASN1_I2D_put_SET_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_put_SET(a,f); + +#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_put_SEQUENCE(a,f); -#define M_ASN1_D2I_get_IMP_set_opt(b,func,tag) \ +#define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + M_ASN1_I2D_put_SEQUENCE_type(type,a,f); + +#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \ if ((c.slen != 0) && \ (M_ASN1_next == \ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\ { \ - M_ASN1_D2I_get_imp_set(b,func,tag,V_ASN1_CONTEXT_SPECIFIC); \ + M_ASN1_D2I_get_imp_set(b,func,free_func,\ + tag,V_ASN1_CONTEXT_SPECIFIC); \ } -#define M_ASN1_D2I_get_seq(r,func) \ - M_ASN1_D2I_get_imp_set(r,func,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); +#define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \ + if ((c.slen != 0) && \ + (M_ASN1_next == \ + (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\ + { \ + M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\ + tag,V_ASN1_CONTEXT_SPECIFIC); \ + } + +#define M_ASN1_D2I_get_seq(r,func,free_func) \ + M_ASN1_D2I_get_imp_set(r,func,free_func,\ + V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); + +#define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \ + M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\ + V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL) -#define M_ASN1_D2I_get_seq_opt(r,func) \ +#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\ - { M_ASN1_D2I_get_seq(r,func); } + { M_ASN1_D2I_get_seq(r,func,free_func); } -#define M_ASN1_D2I_get_IMP_set(r,func,x) \ - M_ASN1_D2I_get_imp_set(r,func,x,V_ASN1_CONTEXT_SPECIFIC); +#define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\ + { M_ASN1_D2I_get_seq_type(type,r,func,free_func); } + +#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \ + M_ASN1_D2I_get_imp_set(r,func,free_func,\ + x,V_ASN1_CONTEXT_SPECIFIC); + +#define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \ + M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\ + x,V_ASN1_CONTEXT_SPECIFIC); + +#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \ + c.q=c.p; \ + if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\ + (void (*)())free_func,a,b) == NULL) \ + { c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); -#define M_ASN1_D2I_get_imp_set(r,func,a,b) \ +#define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \ c.q=c.p; \ - if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,a,b) == NULL) \ - goto err; \ + if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\ + free_func,a,b) == NULL) \ + { c.line=__LINE__; goto err; } \ c.slen-=(c.p-c.q); #define M_ASN1_D2I_get_set_strings(r,func,a,b) \ c.q=c.p; \ if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \ - goto err; \ + { c.line=__LINE__; goto err; } \ c.slen-=(c.p-c.q); #define M_ASN1_D2I_get_EXP_opt(r,func,tag) \ @@ -169,13 +270,22 @@ err:\ c.q=c.p; \ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \ if (Tinf & 0x80) \ - { c.error=ASN1_R_BAD_OBJECT_HEADER; goto err; } \ + { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \ + c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) \ + Tlen = c.slen - (c.p - c.q) - 2; \ if (func(&(r),&c.p,Tlen) == NULL) \ - goto err; \ + { c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \ + Tlen = c.slen - (c.p - c.q); \ + if(!ASN1_check_infinite_end(&c.p, Tlen)) \ + { c.error=ERR_R_MISSING_ASN1_EOS; \ + c.line=__LINE__; goto err; } \ + }\ c.slen-=(c.p-c.q); \ } -#define M_ASN1_D2I_get_EXP_set_opt(r,func,tag,b) \ +#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \ if ((c.slen != 0) && (M_ASN1_next == \ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \ { \ @@ -185,24 +295,61 @@ err:\ c.q=c.p; \ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \ if (Tinf & 0x80) \ - { c.error=ASN1_R_BAD_OBJECT_HEADER; goto err; } \ + { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \ + c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) \ + Tlen = c.slen - (c.p - c.q) - 2; \ if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \ + (void (*)())free_func, \ b,V_ASN1_UNIVERSAL) == NULL) \ - goto err; \ + { c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \ + Tlen = c.slen - (c.p - c.q); \ + if(!ASN1_check_infinite_end(&c.p, Tlen)) \ + { c.error=ERR_R_MISSING_ASN1_EOS; \ + c.line=__LINE__; goto err; } \ + }\ + c.slen-=(c.p-c.q); \ + } + +#define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \ + if ((c.slen != 0) && (M_ASN1_next == \ + (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \ + { \ + int Tinf,Ttag,Tclass; \ + long Tlen; \ + \ + c.q=c.p; \ + Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \ + if (Tinf & 0x80) \ + { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \ + c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) \ + Tlen = c.slen - (c.p - c.q) - 2; \ + if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \ + free_func,b,V_ASN1_UNIVERSAL) == NULL) \ + { c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \ + Tlen = c.slen - (c.p - c.q); \ + if(!ASN1_check_infinite_end(&c.p, Tlen)) \ + { c.error=ERR_R_MISSING_ASN1_EOS; \ + c.line=__LINE__; goto err; } \ + }\ c.slen-=(c.p-c.q); \ } /* New macros */ #define M_ASN1_New_Malloc(ret,type) \ - if ((ret=(type *)Malloc(sizeof(type))) == NULL) goto err2; + if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \ + { c.line=__LINE__; goto err2; } #define M_ASN1_New(arg,func) \ if (((arg)=func()) == NULL) return(NULL) #define M_ASN1_New_Error(a) \ -/* err: ASN1err((a),ASN1_R_ERROR_STACK); \ +/* err: ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \ return(NULL);*/ \ - err2: ASN1err((a),ERR_R_MALLOC_FAILURE); \ + err2: ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \ return(NULL) @@ -220,21 +367,59 @@ err:\ #define M_ASN1_I2D_len_IMP_opt(a,f) if (a != NULL) M_ASN1_I2D_len(a,f) #define M_ASN1_I2D_len_SET(a,f) \ - ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL); + ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); + +#define M_ASN1_I2D_len_SET_type(type,a,f) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \ + V_ASN1_UNIVERSAL,IS_SET); + +#define M_ASN1_I2D_len_SEQUENCE(a,f) \ + ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); -#define M_ASN1_I2D_len_SEQ(a,f) \ - ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); +#define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \ + V_ASN1_UNIVERSAL,IS_SEQUENCE) -#define M_ASN1_I2D_len_SEQ_opt(a,f) \ +#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \ if ((a != NULL) && (sk_num(a) != 0)) \ - M_ASN1_I2D_len_SEQ(a,f); + M_ASN1_I2D_len_SEQUENCE(a,f); -#define M_ASN1_I2D_len_IMP_set(a,f,x) \ - ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC); +#define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + M_ASN1_I2D_len_SEQUENCE_type(type,a,f); -#define M_ASN1_I2D_len_IMP_set_opt(a,f,x) \ +#define M_ASN1_I2D_len_IMP_SET(a,f,x) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET); + +#define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \ + V_ASN1_CONTEXT_SPECIFIC,IS_SET); + +#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SET); + +#define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \ + V_ASN1_CONTEXT_SPECIFIC,IS_SET); + +#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); + +#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \ if ((a != NULL) && (sk_num(a) != 0)) \ - ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC); + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); + +#define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \ + V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); #define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \ if (a != NULL)\ @@ -243,10 +428,27 @@ err:\ ret+=ASN1_object_size(1,v,mtag); \ } -#define M_ASN1_I2D_len_EXP_set_opt(a,f,mtag,tag,v) \ +#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_num(a) != 0))\ + { \ + v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \ + ret+=ASN1_object_size(1,v,mtag); \ + } + +#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \ if ((a != NULL) && (sk_num(a) != 0))\ { \ - v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL); \ + v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); \ + ret+=ASN1_object_size(1,v,mtag); \ + } + +#define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_##type##_num(a) != 0))\ + { \ + v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \ + V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); \ ret+=ASN1_object_size(1,v,mtag); \ } @@ -262,20 +464,48 @@ err:\ } #define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\ - V_ASN1_UNIVERSAL) -#define M_ASN1_I2D_put_IMP_set(a,f,x) i2d_ASN1_SET(a,&p,f,x,\ - V_ASN1_CONTEXT_SPECIFIC) - -#define M_ASN1_I2D_put_SEQ(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\ - V_ASN1_UNIVERSAL) + V_ASN1_UNIVERSAL,IS_SET) +#define M_ASN1_I2D_put_SET_type(type,a,f) \ + i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET) +#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\ + V_ASN1_CONTEXT_SPECIFIC,IS_SET) +#define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \ + i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET) +#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\ + V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE) + +#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\ + V_ASN1_UNIVERSAL,IS_SEQUENCE) + +#define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \ + i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE) + +#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_put_SEQUENCE(a,f); -#define M_ASN1_I2D_put_SEQ_opt(a,f) \ +#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \ if ((a != NULL) && (sk_num(a) != 0)) \ - M_ASN1_I2D_put_SEQ(a,f); + { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SET); } + +#define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + { i2d_ASN1_SET_OF_##type(a,&p,f,x, \ + V_ASN1_CONTEXT_SPECIFIC, \ + IS_SET); } -#define M_ASN1_I2D_put_IMP_set_opt(a,f,x) \ +#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \ if ((a != NULL) && (sk_num(a) != 0)) \ - { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC); } + { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); } + +#define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + { i2d_ASN1_SET_OF_##type(a,&p,f,x, \ + V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); } #define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \ if (a != NULL) \ @@ -284,11 +514,26 @@ err:\ f(a,&p); \ } -#define M_ASN1_I2D_put_EXP_set_opt(a,f,mtag,tag,v) \ +#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \ if ((a != NULL) && (sk_num(a) != 0)) \ { \ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \ - i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL); \ + i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \ + } + +#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + { \ + ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \ + i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \ + } + +#define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + { \ + ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \ + i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); \ } #define M_ASN1_I2D_seq_total() \ @@ -306,14 +551,8 @@ err:\ #define M_ASN1_I2D_finish() *pp=p; \ return(r); -#ifndef NOPROTO int asn1_GetSequence(ASN1_CTX *c, long *length); void asn1_add_error(unsigned char *address,int offset); -#else -int asn1_GetSequence(); -void asn1_add_error(); -#endif - #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/asn1/asn1_par.c b/src/lib/libcrypto/asn1/asn1_par.c index 3906227d21..facfdd27fc 100644 --- a/src/lib/libcrypto/asn1/asn1_par.c +++ b/src/lib/libcrypto/asn1/asn1_par.c @@ -58,30 +58,21 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -#ifndef NOPROTO static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed, int indent); static int asn1_parse2(BIO *bp, unsigned char **pp, long length, - int offset, int depth, int indent); -#else -static int asn1_print_info(); -static int asn1_parse2(); -#endif - -static int asn1_print_info(bp, tag, xclass, constructed,indent) -BIO *bp; -int tag; -int xclass; -int constructed; -int indent; + int offset, int depth, int indent, int dump); +static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, + int indent) { - static char *fmt="%-18s"; - static char *fmt2="%2d %-15s"; - char *p,str[128],*p2=NULL; + static const char fmt[]="%-18s"; + static const char fmt2[]="%2d %-15s"; + char str[128]; + const char *p,*p2=NULL; if (constructed & V_ASN1_CONSTRUCTED) p="cons: "; @@ -102,53 +93,8 @@ int indent; sprintf(str,"cont [ %d ]",tag); else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) sprintf(str,"appl [ %d ]",tag); - else if ((tag == V_ASN1_EOC) /* && (xclass == V_ASN1_UNIVERSAL) */) - p="EOC"; - else if (tag == V_ASN1_BOOLEAN) - p="BOOLEAN"; - else if (tag == V_ASN1_INTEGER) - p="INTEGER"; - else if (tag == V_ASN1_BIT_STRING) - p="BIT STRING"; - else if (tag == V_ASN1_OCTET_STRING) - p="OCTET STRING"; - else if (tag == V_ASN1_NULL) - p="NULL"; - else if (tag == V_ASN1_OBJECT) - p="OBJECT"; - else if (tag == V_ASN1_SEQUENCE) - p="SEQUENCE"; - else if (tag == V_ASN1_SET) - p="SET"; - else if (tag == V_ASN1_PRINTABLESTRING) - p="PRINTABLESTRING"; - else if (tag == V_ASN1_T61STRING) - p="T61STRING"; - else if (tag == V_ASN1_IA5STRING) - p="IA5STRING"; - else if (tag == V_ASN1_UTCTIME) - p="UTCTIME"; + else p = ASN1_tag2str(tag); - /* extras */ - else if (tag == V_ASN1_NUMERICSTRING) - p="NUMERICSTRING"; - else if (tag == V_ASN1_VIDEOTEXSTRING) - p="VIDEOTEXSTRING"; - else if (tag == V_ASN1_GENERALIZEDTIME) - p="GENERALIZEDTIME"; - else if (tag == V_ASN1_GRAPHICSTRING) - p="GRAPHICSTRING"; - else if (tag == V_ASN1_ISO64STRING) - p="ISO64STRING"; - else if (tag == V_ASN1_GENERALSTRING) - p="GENERALSTRING"; - else if (tag == V_ASN1_UNIVERSALSTRING) - p="UNIVERSALSTRING"; - else if (tag == V_ASN1_BMPSTRING) - p="BMPSTRING"; - else - p2="(unknown)"; - if (p2 != NULL) { if (BIO_printf(bp,fmt2,tag,p2) <= 0) goto err; @@ -162,22 +108,18 @@ err: return(0); } -int ASN1_parse(bp, pp, len, indent) -BIO *bp; -unsigned char *pp; -long len; -int indent; +int ASN1_parse(BIO *bp, unsigned char *pp, long len, int indent) + { + return(asn1_parse2(bp,&pp,len,0,0,indent,0)); + } + +int ASN1_parse_dump(BIO *bp, unsigned char *pp, long len, int indent, int dump) { - return(asn1_parse2(bp,&pp,len,0,0,indent)); + return(asn1_parse2(bp,&pp,len,0,0,indent,dump)); } -static int asn1_parse2(bp, pp, length, offset, depth, indent) -BIO *bp; -unsigned char **pp; -long length; -int offset; -int depth; -int indent; +static int asn1_parse2(BIO *bp, unsigned char **pp, long length, int offset, + int depth, int indent, int dump) { unsigned char *p,*ep,*tot,*op,*opp; long len; @@ -186,7 +128,13 @@ int indent; ASN1_OBJECT *o=NULL; ASN1_OCTET_STRING *os=NULL; /* ASN1_BMPSTRING *bmp=NULL;*/ + int dump_indent; +#if 0 + dump_indent = indent; +#else + dump_indent = 6; /* Because we know BIO_dump_indent() */ +#endif p= *pp; tot=p+length; op=p-1; @@ -241,7 +189,7 @@ int indent; { r=asn1_parse2(bp,&p,(long)(tot-p), offset+(p - *pp),depth+1, - indent); + indent,dump); if (r == 0) { ret=0; goto end; } if ((r == 2) || (p >= tot)) break; } @@ -251,7 +199,7 @@ int indent; { r=asn1_parse2(bp,&p,(long)len, offset+(p - *pp),depth+1, - indent); + indent,dump); if (r == 0) { ret=0; goto end; } } } @@ -266,7 +214,9 @@ int indent; if ( (tag == V_ASN1_PRINTABLESTRING) || (tag == V_ASN1_T61STRING) || (tag == V_ASN1_IA5STRING) || - (tag == V_ASN1_UTCTIME)) + (tag == V_ASN1_VISIBLESTRING) || + (tag == V_ASN1_UTCTIME) || + (tag == V_ASN1_GENERALIZEDTIME)) { if (BIO_write(bp,":",1) <= 0) goto end; if ((len > 0) && @@ -334,7 +284,21 @@ int indent; os->length) <= 0) goto end; } - ASN1_OCTET_STRING_free(os); + if (!printable && (os->length > 0) + && dump) + { + if (!nl) + { + if (BIO_write(bp,"\n",1) <= 0) + goto end; + } + if (BIO_dump_indent(bp,(char *)opp, + ((dump == -1 || dump > os->length)?os->length:dump), + dump_indent) <= 0) + goto end; + nl=1; + } + M_ASN1_OCTET_STRING_free(os); os=NULL; } } @@ -368,7 +332,52 @@ int indent; if (BIO_write(bp,"BAD INTEGER",11) <= 0) goto end; } - ASN1_INTEGER_free(bs); + M_ASN1_INTEGER_free(bs); + } + else if (tag == V_ASN1_ENUMERATED) + { + ASN1_ENUMERATED *bs; + int i; + + opp=op; + bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl); + if (bs != NULL) + { + if (BIO_write(bp,":",1) <= 0) goto end; + if (bs->type == V_ASN1_NEG_ENUMERATED) + if (BIO_write(bp,"-",1) <= 0) + goto end; + for (i=0; ilength; i++) + { + if (BIO_printf(bp,"%02X", + bs->data[i]) <= 0) + goto end; + } + if (bs->length == 0) + { + if (BIO_write(bp,"00",2) <= 0) + goto end; + } + } + else + { + if (BIO_write(bp,"BAD ENUMERATED",11) <= 0) + goto end; + } + M_ASN1_ENUMERATED_free(bs); + } + else if (len > 0 && dump) + { + if (!nl) + { + if (BIO_write(bp,"\n",1) <= 0) + goto end; + } + if (BIO_dump_indent(bp,(char *)p, + ((dump == -1 || dump > len)?len:dump), + dump_indent) <= 0) + goto end; + nl=1; } if (!nl) @@ -387,7 +396,28 @@ int indent; ret=1; end: if (o != NULL) ASN1_OBJECT_free(o); - if (os != NULL) ASN1_OCTET_STRING_free(os); + if (os != NULL) M_ASN1_OCTET_STRING_free(os); *pp=p; return(ret); } + +const char *ASN1_tag2str(int tag) +{ + const static char *tag2str[] = { + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ + "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ + "ENUMERATED", "", "UTF8STRING", "", /* 10-13 */ + "", "", "SEQUENCE", "SET", /* 15-17 */ + "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ + "VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */ + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ + "UNIVERSALSTRING", "", "BMPSTRING" /* 28-30 */ + }; + + if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) + tag &= ~0x100; + + if(tag < 0 || tag > 30) return "(unknown)"; + return tag2str[tag]; +} + diff --git a/src/lib/libcrypto/asn1/asn_pack.c b/src/lib/libcrypto/asn1/asn_pack.c index 662a2626a1..e6051db2dc 100644 --- a/src/lib/libcrypto/asn1/asn_pack.c +++ b/src/lib/libcrypto/asn1/asn_pack.c @@ -60,12 +60,14 @@ #include "cryptlib.h" #include +#ifndef NO_ASN1_OLD + /* ASN1 packing and unpacking functions */ /* Turn an ASN1 encoded SEQUENCE OF into a STACK of structures */ STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(), - void (*free_func)()) + void (*free_func)(void *)) { STACK *sk; unsigned char *pbuf; @@ -77,7 +79,7 @@ STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(), } /* Turn a STACK structures into an ASN1 encoded SEQUENCE OF structure in a - * Malloc'ed buffer + * OPENSSL_malloc'ed buffer */ unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, @@ -90,7 +92,7 @@ unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, ASN1err(ASN1_F_ASN1_SEQ_PACK,ASN1_R_ENCODE_ERROR); return NULL; } - if (!(safe = Malloc (safelen))) { + if (!(safe = OPENSSL_malloc (safelen))) { ASN1err(ASN1_F_ASN1_SEQ_PACK,ERR_R_MALLOC_FAILURE); return NULL; } @@ -117,7 +119,7 @@ void *ASN1_unpack_string (ASN1_STRING *oct, char *(*d2i)()) /* Pack an ASN1 object into an ASN1_STRING */ -ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct) +ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_STRING **oct) { unsigned char *p; ASN1_STRING *octmp; @@ -134,7 +136,7 @@ ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct) ASN1err(ASN1_F_ASN1_PACK_STRING,ASN1_R_ENCODE_ERROR); return NULL; } - if (!(p = Malloc (octmp->length))) { + if (!(p = OPENSSL_malloc (octmp->length))) { ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); return NULL; } @@ -143,3 +145,47 @@ ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct) return octmp; } +#endif + +/* ASN1_ITEM versions of the above */ + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +{ + ASN1_STRING *octmp; + + if (!oct || !*oct) { + if (!(octmp = ASN1_STRING_new ())) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + if (oct) *oct = octmp; + } else octmp = *oct; + + if(octmp->data) { + OPENSSL_free(octmp->data); + octmp->data = NULL; + } + + if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ASN1_R_ENCODE_ERROR); + return NULL; + } + if (!octmp->data) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + return octmp; +} + +/* Extract an ASN1 object from an ASN1_STRING */ + +void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it) +{ + unsigned char *p; + void *ret; + + p = oct->data; + if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it))) + ASN1err(ASN1_F_ASN1_UNPACK_STRING,ASN1_R_DECODE_ERROR); + return ret; +} diff --git a/src/lib/libcrypto/asn1/d2i_pr.c b/src/lib/libcrypto/asn1/d2i_pr.c index b9eaa9629b..2e7d96af90 100644 --- a/src/lib/libcrypto/asn1/d2i_pr.c +++ b/src/lib/libcrypto/asn1/d2i_pr.c @@ -58,16 +58,19 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif -EVP_PKEY *d2i_PrivateKey(type,a,pp,length) -int type; -EVP_PKEY **a; -unsigned char **pp; -long length; +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, unsigned char **pp, + long length) { EVP_PKEY *ret; @@ -85,18 +88,20 @@ long length; ret->type=EVP_PKEY_type(type); switch (ret->type) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: - if ((ret->pkey.rsa=d2i_RSAPrivateKey(NULL,pp,length)) == NULL) + if ((ret->pkey.rsa=d2i_RSAPrivateKey(NULL, + (const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */ { ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB); goto err; } break; #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: - if ((ret->pkey.dsa=d2i_DSAPrivateKey(NULL,pp,length)) == NULL) + if ((ret->pkey.dsa=d2i_DSAPrivateKey(NULL, + (const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */ { ASN1err(ASN1_F_D2I_PRIVATEKEY,ERR_R_ASN1_LIB); goto err; @@ -106,7 +111,7 @@ long length; default: ASN1err(ASN1_F_D2I_PRIVATEKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; - break; + /* break; */ } if (a != NULL) (*a)=ret; return(ret); @@ -115,3 +120,26 @@ err: return(NULL); } +/* This works like d2i_PrivateKey() except it automatically works out the type */ + +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, unsigned char **pp, + long length) +{ + STACK_OF(ASN1_TYPE) *inkey; + unsigned char *p; + int keytype; + p = *pp; + /* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): + * by analyzing it we can determine the passed structure: this + * assumes the input is surrounded by an ASN1 SEQUENCE. + */ + inkey = d2i_ASN1_SET_OF_ASN1_TYPE(NULL, &p, length, d2i_ASN1_TYPE, + ASN1_TYPE_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); + /* Since we only need to discern "traditional format" RSA and DSA + * keys we can just count the elements. + */ + if(sk_ASN1_TYPE_num(inkey) == 6) keytype = EVP_PKEY_DSA; + else keytype = EVP_PKEY_RSA; + sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); + return d2i_PrivateKey(keytype, a, pp, length); +} diff --git a/src/lib/libcrypto/asn1/d2i_pu.c b/src/lib/libcrypto/asn1/d2i_pu.c index 5d6192f1e5..71f2eb361b 100644 --- a/src/lib/libcrypto/asn1/d2i_pu.c +++ b/src/lib/libcrypto/asn1/d2i_pu.c @@ -58,16 +58,19 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif -EVP_PKEY *d2i_PublicKey(type,a,pp,length) -int type; -EVP_PKEY **a; -unsigned char **pp; -long length; +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, unsigned char **pp, + long length) { EVP_PKEY *ret; @@ -85,18 +88,20 @@ long length; ret->type=EVP_PKEY_type(type); switch (ret->type) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: - if ((ret->pkey.rsa=d2i_RSAPublicKey(NULL,pp,length)) == NULL) + if ((ret->pkey.rsa=d2i_RSAPublicKey(NULL, + (const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */ { ASN1err(ASN1_F_D2I_PUBLICKEY,ERR_R_ASN1_LIB); goto err; } break; #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: - if ((ret->pkey.dsa=d2i_DSAPublicKey(NULL,pp,length)) == NULL) + if ((ret->pkey.dsa=d2i_DSAPublicKey(NULL, + (const unsigned char **)pp,length)) == NULL) /* TMP UGLY CAST */ { ASN1err(ASN1_F_D2I_PUBLICKEY,ERR_R_ASN1_LIB); goto err; @@ -106,7 +111,7 @@ long length; default: ASN1err(ASN1_F_D2I_PUBLICKEY,ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); goto err; - break; + /* break; */ } if (a != NULL) (*a)=ret; return(ret); diff --git a/src/lib/libcrypto/asn1/evp_asn1.c b/src/lib/libcrypto/asn1/evp_asn1.c index ebe34a3362..3506005a71 100644 --- a/src/lib/libcrypto/asn1/evp_asn1.c +++ b/src/lib/libcrypto/asn1/evp_asn1.c @@ -58,26 +58,22 @@ #include #include "cryptlib.h" -#include "asn1.h" -#include "asn1_mac.h" +#include +#include -int ASN1_TYPE_set_octetstring(a,data,len) -ASN1_TYPE *a; -unsigned char *data; -int len; +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len) { ASN1_STRING *os; - if ((os=ASN1_OCTET_STRING_new()) == NULL) return(0); - if (!ASN1_OCTET_STRING_set(os,data,len)) return(0); - ASN1_TYPE_set(a,V_ASN1_OCTET_STRING,(char *)os); + if ((os=M_ASN1_OCTET_STRING_new()) == NULL) return(0); + if (!M_ASN1_OCTET_STRING_set(os,data,len)) return(0); + ASN1_TYPE_set(a,V_ASN1_OCTET_STRING,os); return(1); } -int ASN1_TYPE_get_octetstring(a,data,max_len) -ASN1_TYPE *a; -unsigned char *data; -int max_len; /* for returned value */ +/* int max_len: for returned value */ +int ASN1_TYPE_get_octetstring(ASN1_TYPE *a, unsigned char *data, + int max_len) { int ret,num; unsigned char *p; @@ -87,8 +83,8 @@ int max_len; /* for returned value */ ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING,ASN1_R_DATA_IS_WRONG); return(-1); } - p=ASN1_STRING_data(a->value.octet_string); - ret=ASN1_STRING_length(a->value.octet_string); + p=M_ASN1_STRING_data(a->value.octet_string); + ret=M_ASN1_STRING_length(a->value.octet_string); if (ret < max_len) num=ret; else @@ -97,11 +93,8 @@ int max_len; /* for returned value */ return(ret); } -int ASN1_TYPE_set_int_octetstring(a,num,data,len) -ASN1_TYPE *a; -long num; -unsigned char *data; -int len; +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data, + int len) { int n,size; ASN1_OCTET_STRING os,*osp; @@ -124,23 +117,22 @@ int len; /* Grow the 'string' */ ASN1_STRING_set(osp,NULL,size); - ASN1_STRING_length(osp)=size; - p=ASN1_STRING_data(osp); + M_ASN1_STRING_length_set(osp, size); + p=M_ASN1_STRING_data(osp); ASN1_put_object(&p,1,n,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); i2d_ASN1_INTEGER(&in,&p); M_i2d_ASN1_OCTET_STRING(&os,&p); - ASN1_TYPE_set(a,V_ASN1_SEQUENCE,(char *)osp); + ASN1_TYPE_set(a,V_ASN1_SEQUENCE,osp); return(1); } -/* we return the actual length... */ -int ASN1_TYPE_get_int_octetstring(a,num,data,max_len) -ASN1_TYPE *a; -long *num; -unsigned char *data; -int max_len; /* for returned value */ +/* we return the actual length..., num may be missing, in which + * case, set it to zero */ +/* int max_len: for returned value */ +int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a, long *num, unsigned char *data, + int max_len) { int ret= -1,n; ASN1_INTEGER *ai=NULL; @@ -153,8 +145,8 @@ int max_len; /* for returned value */ { goto err; } - p=ASN1_STRING_data(a->value.sequence); - length=ASN1_STRING_length(a->value.sequence); + p=M_ASN1_STRING_data(a->value.sequence); + length=M_ASN1_STRING_length(a->value.sequence); c.pp= &p; c.p=p; @@ -173,21 +165,21 @@ int max_len; /* for returned value */ if (num != NULL) *num=ASN1_INTEGER_get(ai); - ret=ASN1_STRING_length(os); + ret=M_ASN1_STRING_length(os); if (max_len > ret) n=ret; else n=max_len; if (data != NULL) - memcpy(data,ASN1_STRING_data(os),n); + memcpy(data,M_ASN1_STRING_data(os),n); if (0) { err: ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING,ASN1_R_DATA_IS_WRONG); } - if (os != NULL) ASN1_OCTET_STRING_free(os); - if (ai != NULL) ASN1_INTEGER_free(ai); + if (os != NULL) M_ASN1_OCTET_STRING_free(os); + if (ai != NULL) M_ASN1_INTEGER_free(ai); return(ret); } diff --git a/src/lib/libcrypto/asn1/f_enum.c b/src/lib/libcrypto/asn1/f_enum.c index 3bcceecdb8..56e3cc8df2 100644 --- a/src/lib/libcrypto/asn1/f_enum.c +++ b/src/lib/libcrypto/asn1/f_enum.c @@ -153,15 +153,15 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) if (num+i > slen) { if (s == NULL) - sp=(unsigned char *)Malloc( + sp=(unsigned char *)OPENSSL_malloc( (unsigned int)num+i*2); else - sp=(unsigned char *)Realloc(s, + sp=(unsigned char *)OPENSSL_realloc(s, (unsigned int)num+i*2); if (sp == NULL) { ASN1err(ASN1_F_A2I_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE); - if (s != NULL) Free((char *)s); + if (s != NULL) OPENSSL_free(s); goto err; } s=sp; diff --git a/src/lib/libcrypto/asn1/f_int.c b/src/lib/libcrypto/asn1/f_int.c index 4817c45cb7..48cc3bfb90 100644 --- a/src/lib/libcrypto/asn1/f_int.c +++ b/src/lib/libcrypto/asn1/f_int.c @@ -58,23 +58,27 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "x509.h" +#include +#include -int i2a_ASN1_INTEGER(bp, a) -BIO *bp; -ASN1_INTEGER *a; +int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a) { int i,n=0; - static char *h="0123456789ABCDEF"; + static const char *h="0123456789ABCDEF"; char buf[2]; if (a == NULL) return(0); + if (a->type & V_ASN1_NEG) + { + if (BIO_write(bp, "-", 1) != 1) goto err; + n = 1; + } + if (a->length == 0) { if (BIO_write(bp,"00",2) != 2) goto err; - n=2; + n += 2; } else { @@ -96,11 +100,7 @@ err: return(-1); } -int a2i_ASN1_INTEGER(bp,bs,buf,size) -BIO *bp; -ASN1_INTEGER *bs; -char *buf; -int size; +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) { int ret=0; int i,j,k,m,n,again,bufsize; @@ -123,9 +123,18 @@ int size; for (j=0; j= '0') && (buf[j] <= '9')) || ((buf[j] >= 'a') && (buf[j] <= 'f')) || ((buf[j] >= 'A') && (buf[j] <= 'F')))) +#else + /* This #ifdef is not strictly necessary, since + * the characters A...F a...f 0...9 are contiguous + * (yes, even in EBCDIC - but not the whole alphabet). + * Nevertheless, isxdigit() is faster. + */ + if (!isxdigit(buf[j])) +#endif { i=j; break; @@ -157,15 +166,15 @@ int size; if (num+i > slen) { if (s == NULL) - sp=(unsigned char *)Malloc( + sp=(unsigned char *)OPENSSL_malloc( (unsigned int)num+i*2); else - sp=(unsigned char *)Realloc(s, + sp=(unsigned char *)OPENSSL_realloc(s, (unsigned int)num+i*2); if (sp == NULL) { ASN1err(ASN1_F_A2I_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); - if (s != NULL) Free((char *)s); + if (s != NULL) OPENSSL_free(s); goto err; } s=sp; diff --git a/src/lib/libcrypto/asn1/f_string.c b/src/lib/libcrypto/asn1/f_string.c index ab2837824e..968698a798 100644 --- a/src/lib/libcrypto/asn1/f_string.c +++ b/src/lib/libcrypto/asn1/f_string.c @@ -58,16 +58,13 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "x509.h" +#include +#include -int i2a_ASN1_STRING(bp, a, type) -BIO *bp; -ASN1_STRING *a; -int type; +int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type) { int i,n=0; - static char *h="0123456789ABCDEF"; + static const char *h="0123456789ABCDEF"; char buf[2]; if (a == NULL) return(0); @@ -97,11 +94,7 @@ err: return(-1); } -int a2i_ASN1_STRING(bp,bs,buf,size) -BIO *bp; -ASN1_STRING *bs; -char *buf; -int size; +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) { int ret=0; int i,j,k,m,n,again,bufsize; @@ -130,9 +123,18 @@ int size; for (j=i-1; j>0; j--) { +#ifndef CHARSET_EBCDIC if (!( ((buf[j] >= '0') && (buf[j] <= '9')) || ((buf[j] >= 'a') && (buf[j] <= 'f')) || ((buf[j] >= 'A') && (buf[j] <= 'F')))) +#else + /* This #ifdef is not strictly necessary, since + * the characters A...F a...f 0...9 are contiguous + * (yes, even in EBCDIC - but not the whole alphabet). + * Nevertheless, isxdigit() is faster. + */ + if (!isxdigit(buf[j])) +#endif { i=j; break; @@ -156,15 +158,15 @@ int size; if (num+i > slen) { if (s == NULL) - sp=(unsigned char *)Malloc( + sp=(unsigned char *)OPENSSL_malloc( (unsigned int)num+i*2); else - sp=(unsigned char *)Realloc(s, + sp=(unsigned char *)OPENSSL_realloc(s, (unsigned int)num+i*2); if (sp == NULL) { ASN1err(ASN1_F_A2I_ASN1_STRING,ERR_R_MALLOC_FAILURE); - if (s != NULL) Free((char *)s); + if (s != NULL) OPENSSL_free(s); goto err; } s=sp; diff --git a/src/lib/libcrypto/asn1/i2d_pr.c b/src/lib/libcrypto/asn1/i2d_pr.c index b6b821d73c..1e951ae01d 100644 --- a/src/lib/libcrypto/asn1/i2d_pr.c +++ b/src/lib/libcrypto/asn1/i2d_pr.c @@ -58,22 +58,26 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "objects.h" +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif -int i2d_PrivateKey(a,pp) -EVP_PKEY *a; -unsigned char **pp; +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (a->type == EVP_PKEY_RSA) { return(i2d_RSAPrivateKey(a->pkey.rsa,pp)); } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (a->type == EVP_PKEY_DSA) { return(i2d_DSAPrivateKey(a->pkey.dsa,pp)); diff --git a/src/lib/libcrypto/asn1/i2d_pu.c b/src/lib/libcrypto/asn1/i2d_pu.c index 1b854252b7..013d19bbf4 100644 --- a/src/lib/libcrypto/asn1/i2d_pu.c +++ b/src/lib/libcrypto/asn1/i2d_pu.c @@ -58,21 +58,25 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "objects.h" +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif -int i2d_PublicKey(a,pp) -EVP_PKEY *a; -unsigned char **pp; +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) { switch (a->type) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: return(i2d_RSAPublicKey(a->pkey.rsa,pp)); #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: return(i2d_DSAPublicKey(a->pkey.dsa,pp)); #endif diff --git a/src/lib/libcrypto/asn1/n_pkey.c b/src/lib/libcrypto/asn1/n_pkey.c index 5110c91bec..49f80fffd2 100644 --- a/src/lib/libcrypto/asn1/n_pkey.c +++ b/src/lib/libcrypto/asn1/n_pkey.c @@ -56,118 +56,134 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_RSA #include #include "cryptlib.h" -#include "rsa.h" -#include "objects.h" -#include "asn1_mac.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include +#include -#ifndef NO_RC4 +#ifndef OPENSSL_NO_RC4 typedef struct netscape_pkey_st { - ASN1_INTEGER *version; + long version; X509_ALGOR *algor; ASN1_OCTET_STRING *private_key; } NETSCAPE_PKEY; -/* - * ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ASN1_R_DECODING_ERROR); - * ASN1err(ASN1_F_D2I_NETSCAPE_PKEY,ASN1_R_DECODING_ERROR); - * ASN1err(ASN1_F_NETSCAPE_PKEY_NEW,ASN1_R_DECODING_ERROR); - */ -#ifndef NOPROTO -static int i2d_NETSCAPE_PKEY(NETSCAPE_PKEY *a, unsigned char **pp); -static NETSCAPE_PKEY *d2i_NETSCAPE_PKEY(NETSCAPE_PKEY **a,unsigned char **pp, long length); -static NETSCAPE_PKEY *NETSCAPE_PKEY_new(void); -static void NETSCAPE_PKEY_free(NETSCAPE_PKEY *); -#else -static int i2d_NETSCAPE_PKEY(); -static NETSCAPE_PKEY *d2i_NETSCAPE_PKEY(); -static NETSCAPE_PKEY *NETSCAPE_PKEY_new(); -static void NETSCAPE_PKEY_free(); -#endif +typedef struct netscape_encrypted_pkey_st + { + ASN1_OCTET_STRING *os; + /* This is the same structure as DigestInfo so use it: + * although this isn't really anything to do with + * digests. + */ + X509_SIG *enckey; + } NETSCAPE_ENCRYPTED_PKEY; + + +ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = { + ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING), + ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG) +} ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY) + +IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) + +ASN1_SEQUENCE(NETSCAPE_PKEY) = { + ASN1_SIMPLE(NETSCAPE_PKEY, version, LONG), + ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR), + ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(NETSCAPE_PKEY) + +IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) + +static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, + int (*cb)(), int sgckey); -int i2d_Netscape_RSA(a,pp,cb) -RSA *a; -unsigned char **pp; -int (*cb)(); +int i2d_Netscape_RSA(const RSA *a, unsigned char **pp, int (*cb)()) +{ + return i2d_RSA_NET(a, pp, cb, 0); +} + +int i2d_RSA_NET(const RSA *a, unsigned char **pp, int (*cb)(), int sgckey) { - int i,j,l[6]; - NETSCAPE_PKEY *pkey; + int i, j, ret = 0; + int rsalen, pkeylen, olen; + NETSCAPE_PKEY *pkey = NULL; + NETSCAPE_ENCRYPTED_PKEY *enckey = NULL; unsigned char buf[256],*zz; unsigned char key[EVP_MAX_KEY_LENGTH]; EVP_CIPHER_CTX ctx; - X509_ALGOR *alg=NULL; - ASN1_OCTET_STRING os,os2; - M_ASN1_I2D_vars(a); if (a == NULL) return(0); -#ifdef WIN32 - r=r; /* shut the damn compiler up :-) */ -#endif - - os.data=os2.data=NULL; if ((pkey=NETSCAPE_PKEY_new()) == NULL) goto err; - if (!ASN1_INTEGER_set(pkey->version,0)) goto err; + if ((enckey=NETSCAPE_ENCRYPTED_PKEY_new()) == NULL) goto err; + pkey->version = 0; - if (pkey->algor->algorithm != NULL) - ASN1_OBJECT_free(pkey->algor->algorithm); pkey->algor->algorithm=OBJ_nid2obj(NID_rsaEncryption); if ((pkey->algor->parameter=ASN1_TYPE_new()) == NULL) goto err; pkey->algor->parameter->type=V_ASN1_NULL; - l[0]=i2d_RSAPrivateKey(a,NULL); - pkey->private_key->length=l[0]; + rsalen = i2d_RSAPrivateKey(a, NULL); + + /* Fake some octet strings just for the initial length + * calculation. + */ - os2.length=i2d_NETSCAPE_PKEY(pkey,NULL); - l[1]=i2d_ASN1_OCTET_STRING(&os2,NULL); + pkey->private_key->length=rsalen; - if ((alg=X509_ALGOR_new()) == NULL) goto err; - if (alg->algorithm != NULL) - ASN1_OBJECT_free(alg->algorithm); - alg->algorithm=OBJ_nid2obj(NID_rc4); - if ((alg->parameter=ASN1_TYPE_new()) == NULL) goto err; - alg->parameter->type=V_ASN1_NULL; + pkeylen=i2d_NETSCAPE_PKEY(pkey,NULL); - l[2]=i2d_X509_ALGOR(alg,NULL); - l[3]=ASN1_object_size(1,l[2]+l[1],V_ASN1_SEQUENCE); + enckey->enckey->digest->length = pkeylen; - os.data=(unsigned char *)"private-key"; - os.length=11; - l[4]=i2d_ASN1_OCTET_STRING(&os,NULL); + enckey->os->length = 11; /* "private-key" */ - l[5]=ASN1_object_size(1,l[4]+l[3],V_ASN1_SEQUENCE); + enckey->enckey->algor->algorithm=OBJ_nid2obj(NID_rc4); + if ((enckey->enckey->algor->parameter=ASN1_TYPE_new()) == NULL) goto err; + enckey->enckey->algor->parameter->type=V_ASN1_NULL; if (pp == NULL) { - if (pkey != NULL) NETSCAPE_PKEY_free(pkey); - if (alg != NULL) X509_ALGOR_free(alg); - return(l[5]); + olen = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, NULL); + NETSCAPE_PKEY_free(pkey); + NETSCAPE_ENCRYPTED_PKEY_free(enckey); + return olen; } - if (pkey->private_key->data != NULL) - Free((char *)pkey->private_key->data); - if ((pkey->private_key->data=(unsigned char *)Malloc(l[0])) == NULL) + + /* Since its RC4 encrypted length is actual length */ + if ((zz=(unsigned char *)OPENSSL_malloc(rsalen)) == NULL) { ASN1err(ASN1_F_I2D_NETSCAPE_RSA,ERR_R_MALLOC_FAILURE); goto err; } - zz=pkey->private_key->data; + + pkey->private_key->data = zz; + /* Write out private key encoding */ i2d_RSAPrivateKey(a,&zz); - if ((os2.data=(unsigned char *)Malloc(os2.length)) == NULL) + if ((zz=OPENSSL_malloc(pkeylen)) == NULL) { ASN1err(ASN1_F_I2D_NETSCAPE_RSA,ERR_R_MALLOC_FAILURE); goto err; } - zz=os2.data; + + if (!ASN1_STRING_set(enckey->os, "private-key", -1)) + { + ASN1err(ASN1_F_I2D_NETSCAPE_RSA,ERR_R_MALLOC_FAILURE); + goto err; + } + enckey->enckey->digest->data = zz; i2d_NETSCAPE_PKEY(pkey,&zz); + + /* Wipe the private key encoding */ + memset(pkey->private_key->data, 0, rsalen); if (cb == NULL) cb=EVP_read_pw_string; @@ -177,92 +193,88 @@ int (*cb)(); ASN1err(ASN1_F_I2D_NETSCAPE_RSA,ASN1_R_BAD_PASSWORD_READ); goto err; } - EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf, - strlen((char *)buf),1,key,NULL); + i = strlen((char *)buf); + /* If the key is used for SGC the algorithm is modified a little. */ + if(sgckey) { + EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL); + memcpy(buf + 16, "SGCKEYSALT", 10); + i = 26; + } + + EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL); memset(buf,0,256); + /* Encrypt private key in place */ + zz = enckey->enckey->digest->data; EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit(&ctx,EVP_rc4(),key,NULL); - EVP_EncryptUpdate(&ctx,os2.data,&i,os2.data,os2.length); - EVP_EncryptFinal(&ctx,&(os2.data[i]),&j); + EVP_EncryptInit_ex(&ctx,EVP_rc4(),NULL,key,NULL); + EVP_EncryptUpdate(&ctx,zz,&i,zz,pkeylen); + EVP_EncryptFinal_ex(&ctx,zz + i,&j); EVP_CIPHER_CTX_cleanup(&ctx); - p= *pp; - ASN1_put_object(&p,1,l[4]+l[3],V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); - i2d_ASN1_OCTET_STRING(&os,&p); - ASN1_put_object(&p,1,l[2]+l[1],V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); - i2d_X509_ALGOR(alg,&p); - i2d_ASN1_OCTET_STRING(&os2,&p); - ret=l[5]; + ret = i2d_NETSCAPE_ENCRYPTED_PKEY(enckey, pp); err: - if (os2.data != NULL) Free((char *)os2.data); - if (alg != NULL) X509_ALGOR_free(alg); - if (pkey != NULL) NETSCAPE_PKEY_free(pkey); - r=r; + NETSCAPE_ENCRYPTED_PKEY_free(enckey); + NETSCAPE_PKEY_free(pkey); return(ret); } -RSA *d2i_Netscape_RSA(a,pp,length,cb) -RSA **a; -unsigned char **pp; -long length; -int (*cb)(); + +RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length, int (*cb)()) +{ + return d2i_RSA_NET(a, pp, length, cb, 0); +} + +RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length, int (*cb)(), int sgckey) { RSA *ret=NULL; - ASN1_OCTET_STRING *os=NULL; - ASN1_CTX c; + const unsigned char *p, *kp; + NETSCAPE_ENCRYPTED_PKEY *enckey = NULL; + + p = *pp; - c.pp=pp; - c.error=ASN1_R_DECODING_ERROR; + enckey = d2i_NETSCAPE_ENCRYPTED_PKEY(NULL, &p, length); + if(!enckey) { + ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ASN1_R_DECODING_ERROR); + return NULL; + } - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(os,d2i_ASN1_OCTET_STRING); - if ((os->length != 11) || (strncmp("private-key", - (char *)os->data,os->length) != 0)) + if ((enckey->os->length != 11) || (strncmp("private-key", + (char *)enckey->os->data,11) != 0)) { ASN1err(ASN1_F_D2I_NETSCAPE_RSA,ASN1_R_PRIVATE_KEY_HEADER_MISSING); - ASN1_BIT_STRING_free(os); - goto err; + NETSCAPE_ENCRYPTED_PKEY_free(enckey); + return NULL; } - ASN1_BIT_STRING_free(os); - c.q=c.p; - if ((ret=d2i_Netscape_RSA_2(a,&c.p,c.slen,cb)) == NULL) goto err; - c.slen-=(c.p-c.q); + if (OBJ_obj2nid(enckey->enckey->algor->algorithm) != NID_rc4) + { + ASN1err(ASN1_F_D2I_NETSCAPE_RSA_2,ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM); + goto err; + } + kp = enckey->enckey->digest->data; + if (cb == NULL) + cb=EVP_read_pw_string; + if ((ret=d2i_RSA_NET_2(a, enckey->enckey->digest,cb, sgckey)) == NULL) goto err; + + *pp = p; + + err: + NETSCAPE_ENCRYPTED_PKEY_free(enckey); + return ret; - M_ASN1_D2I_Finish(a,RSA_free,ASN1_F_D2I_NETSCAPE_RSA); } -RSA *d2i_Netscape_RSA_2(a,pp,length,cb) -RSA **a; -unsigned char **pp; -long length; -int (*cb)(); +static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, + int (*cb)(), int sgckey) { NETSCAPE_PKEY *pkey=NULL; RSA *ret=NULL; int i,j; - unsigned char buf[256],*zz; + unsigned char buf[256]; + const unsigned char *zz; unsigned char key[EVP_MAX_KEY_LENGTH]; EVP_CIPHER_CTX ctx; - X509_ALGOR *alg=NULL; - ASN1_OCTET_STRING *os=NULL; - ASN1_CTX c; - - c.error=ASN1_R_ERROR_STACK; - c.pp=pp; - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(alg,d2i_X509_ALGOR); - if (OBJ_obj2nid(alg->algorithm) != NID_rc4) - { - ASN1err(ASN1_F_D2I_NETSCAPE_RSA_2,ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM); - goto err; - } - M_ASN1_D2I_get(os,d2i_ASN1_OCTET_STRING); - if (cb == NULL) - cb=EVP_read_pw_string; i=cb(buf,256,"Enter Private Key password:",0); if (i != 0) { @@ -270,14 +282,20 @@ int (*cb)(); goto err; } - EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf, - strlen((char *)buf),1,key,NULL); + i = strlen((char *)buf); + if(sgckey){ + EVP_Digest(buf, i, buf, NULL, EVP_md5(), NULL); + memcpy(buf + 16, "SGCKEYSALT", 10); + i = 26; + } + + EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL); memset(buf,0,256); EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit(&ctx,EVP_rc4(),key,NULL); + EVP_DecryptInit_ex(&ctx,EVP_rc4(),NULL, key,NULL); EVP_DecryptUpdate(&ctx,os->data,&i,os->data,os->length); - EVP_DecryptFinal(&ctx,&(os->data[i]),&j); + EVP_DecryptFinal_ex(&ctx,&(os->data[i]),&j); EVP_CIPHER_CTX_cleanup(&ctx); os->length=i+j; @@ -295,71 +313,17 @@ int (*cb)(); ASN1err(ASN1_F_D2I_NETSCAPE_RSA_2,ASN1_R_UNABLE_TO_DECODE_RSA_KEY); goto err; } - if (!asn1_Finish(&c)) goto err; - *pp=c.p; err: - if (pkey != NULL) NETSCAPE_PKEY_free(pkey); - if (os != NULL) ASN1_BIT_STRING_free(os); - if (alg != NULL) X509_ALGOR_free(alg); + NETSCAPE_PKEY_free(pkey); return(ret); } -static int i2d_NETSCAPE_PKEY(a,pp) -NETSCAPE_PKEY *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - - M_ASN1_I2D_len(a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_len(a->algor, i2d_X509_ALGOR); - M_ASN1_I2D_len(a->private_key, i2d_ASN1_OCTET_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_put(a->algor, i2d_X509_ALGOR); - M_ASN1_I2D_put(a->private_key, i2d_ASN1_OCTET_STRING); - - M_ASN1_I2D_finish(); - } - -static NETSCAPE_PKEY *d2i_NETSCAPE_PKEY(a,pp,length) -NETSCAPE_PKEY **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,NETSCAPE_PKEY *,NETSCAPE_PKEY_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->version,d2i_ASN1_INTEGER); - M_ASN1_D2I_get(ret->algor,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->private_key,d2i_ASN1_OCTET_STRING); - M_ASN1_D2I_Finish(a,NETSCAPE_PKEY_free,ASN1_F_D2I_NETSCAPE_PKEY); - } - -static NETSCAPE_PKEY *NETSCAPE_PKEY_new() - { - NETSCAPE_PKEY *ret=NULL; - - M_ASN1_New_Malloc(ret,NETSCAPE_PKEY); - M_ASN1_New(ret->version,ASN1_INTEGER_new); - M_ASN1_New(ret->algor,X509_ALGOR_new); - M_ASN1_New(ret->private_key,ASN1_OCTET_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_NETSCAPE_PKEY_NEW); - } +#endif /* OPENSSL_NO_RC4 */ -static void NETSCAPE_PKEY_free(a) -NETSCAPE_PKEY *a; - { - if (a == NULL) return; - ASN1_INTEGER_free(a->version); - X509_ALGOR_free(a->algor); - ASN1_OCTET_STRING_free(a->private_key); - Free((char *)a); - } +#else /* !OPENSSL_NO_RSA */ -#endif /* NO_RC4 */ +# if PEDANTIC +static void *dummy=&dummy; +# endif +#endif diff --git a/src/lib/libcrypto/asn1/nsseq.c b/src/lib/libcrypto/asn1/nsseq.c index 417d024b81..50e2d4d07a 100644 --- a/src/lib/libcrypto/asn1/nsseq.c +++ b/src/lib/libcrypto/asn1/nsseq.c @@ -58,61 +58,25 @@ #include #include -#include -#include +#include #include #include -/* Netscape certificate sequence structure */ - -int i2d_NETSCAPE_CERT_SEQUENCE(NETSCAPE_CERT_SEQUENCE *a, unsigned char **pp) +static int nsseq_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) { - int v = 0; - M_ASN1_I2D_vars(a); - M_ASN1_I2D_len (a->type, i2d_ASN1_OBJECT); - M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(X509,a->certs,i2d_X509,0, - V_ASN1_SEQUENCE,v); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->type, i2d_ASN1_OBJECT); - M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(X509,a->certs,i2d_X509,0, - V_ASN1_SEQUENCE,v); - - M_ASN1_I2D_finish(); + if(operation == ASN1_OP_NEW_POST) { + NETSCAPE_CERT_SEQUENCE *nsseq; + nsseq = (NETSCAPE_CERT_SEQUENCE *)*pval; + nsseq->type = OBJ_nid2obj(NID_netscape_cert_sequence); + } + return 1; } -NETSCAPE_CERT_SEQUENCE *NETSCAPE_CERT_SEQUENCE_new(void) -{ - NETSCAPE_CERT_SEQUENCE *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, NETSCAPE_CERT_SEQUENCE); - /* Note hardcoded object type */ - ret->type = OBJ_nid2obj(NID_netscape_cert_sequence); - ret->certs = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_NETSCAPE_CERT_SEQUENCE_NEW); -} +/* Netscape certificate sequence structure */ -NETSCAPE_CERT_SEQUENCE *d2i_NETSCAPE_CERT_SEQUENCE(NETSCAPE_CERT_SEQUENCE **a, - unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,NETSCAPE_CERT_SEQUENCE *, - NETSCAPE_CERT_SEQUENCE_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->type, d2i_ASN1_OBJECT); - M_ASN1_D2I_get_EXP_set_opt_type(X509,ret->certs,d2i_X509,X509_free,0, - V_ASN1_SEQUENCE); - M_ASN1_D2I_Finish(a, NETSCAPE_CERT_SEQUENCE_free, - ASN1_F_D2I_NETSCAPE_CERT_SEQUENCE); -} +ASN1_SEQUENCE_cb(NETSCAPE_CERT_SEQUENCE, nsseq_cb) = { + ASN1_SIMPLE(NETSCAPE_CERT_SEQUENCE, type, ASN1_OBJECT), + ASN1_EXP_SEQUENCE_OF_OPT(NETSCAPE_CERT_SEQUENCE, certs, X509, 0) +} ASN1_SEQUENCE_END_cb(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) -void NETSCAPE_CERT_SEQUENCE_free (NETSCAPE_CERT_SEQUENCE *a) -{ - if (a == NULL) return; - ASN1_OBJECT_free(a->type); - if(a->certs) - sk_X509_pop_free(a->certs, X509_free); - Free (a); -} +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) diff --git a/src/lib/libcrypto/asn1/p5_pbe.c b/src/lib/libcrypto/asn1/p5_pbe.c index b831836e7b..891150638e 100644 --- a/src/lib/libcrypto/asn1/p5_pbe.c +++ b/src/lib/libcrypto/asn1/p5_pbe.c @@ -58,53 +58,18 @@ #include #include "cryptlib.h" -#include +#include #include #include /* PKCS#5 password based encryption structure */ -int i2d_PBEPARAM(PBEPARAM *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - M_ASN1_I2D_len (a->salt, i2d_ASN1_OCTET_STRING); - M_ASN1_I2D_len (a->iter, i2d_ASN1_INTEGER); - - M_ASN1_I2D_seq_total (); +ASN1_SEQUENCE(PBEPARAM) = { + ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING), + ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PBEPARAM) - M_ASN1_I2D_put (a->salt, i2d_ASN1_OCTET_STRING); - M_ASN1_I2D_put (a->iter, i2d_ASN1_INTEGER); - M_ASN1_I2D_finish(); -} - -PBEPARAM *PBEPARAM_new(void) -{ - PBEPARAM *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, PBEPARAM); - M_ASN1_New(ret->iter,ASN1_INTEGER_new); - M_ASN1_New(ret->salt,ASN1_OCTET_STRING_new); - return (ret); - M_ASN1_New_Error(ASN1_F_PBEPARAM_NEW); -} - -PBEPARAM *d2i_PBEPARAM(PBEPARAM **a, unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,PBEPARAM *,PBEPARAM_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->salt, d2i_ASN1_OCTET_STRING); - M_ASN1_D2I_get (ret->iter, d2i_ASN1_INTEGER); - M_ASN1_D2I_Finish(a, PBEPARAM_free, ASN1_F_D2I_PBEPARAM); -} - -void PBEPARAM_free (PBEPARAM *a) -{ - if(a==NULL) return; - ASN1_OCTET_STRING_free(a->salt); - ASN1_INTEGER_free (a->iter); - Free ((char *)a); -} +IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM) /* Return an algorithm identifier for a PKCS#5 PBE algorithm */ @@ -123,13 +88,14 @@ X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, if(iter <= 0) iter = PKCS5_DEFAULT_ITER; ASN1_INTEGER_set (pbe->iter, iter); if (!saltlen) saltlen = PKCS5_SALT_LEN; - if (!(pbe->salt->data = Malloc (saltlen))) { + if (!(pbe->salt->data = OPENSSL_malloc (saltlen))) { ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); return NULL; } pbe->salt->length = saltlen; if (salt) memcpy (pbe->salt->data, salt, saltlen); - else RAND_bytes (pbe->salt->data, saltlen); + else if (RAND_pseudo_bytes (pbe->salt->data, saltlen) < 0) + return NULL; if (!(astype = ASN1_TYPE_new())) { ASN1err(ASN1_F_ASN1_PBE_SET,ERR_R_MALLOC_FAILURE); diff --git a/src/lib/libcrypto/asn1/p5_pbev2.c b/src/lib/libcrypto/asn1/p5_pbev2.c index 09f4bf6112..91e1c8987d 100644 --- a/src/lib/libcrypto/asn1/p5_pbev2.c +++ b/src/lib/libcrypto/asn1/p5_pbev2.c @@ -58,108 +58,27 @@ #include #include "cryptlib.h" -#include +#include #include #include /* PKCS#5 v2.0 password based encryption structures */ -int i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - M_ASN1_I2D_len (a->keyfunc, i2d_X509_ALGOR); - M_ASN1_I2D_len (a->encryption, i2d_X509_ALGOR); - - M_ASN1_I2D_seq_total (); - - M_ASN1_I2D_put (a->keyfunc, i2d_X509_ALGOR); - M_ASN1_I2D_put (a->encryption, i2d_X509_ALGOR); - - M_ASN1_I2D_finish(); -} - -PBE2PARAM *PBE2PARAM_new(void) -{ - PBE2PARAM *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, PBE2PARAM); - M_ASN1_New(ret->keyfunc,X509_ALGOR_new); - M_ASN1_New(ret->encryption,X509_ALGOR_new); - return (ret); - M_ASN1_New_Error(ASN1_F_PBE2PARAM_NEW); -} - -PBE2PARAM *d2i_PBE2PARAM(PBE2PARAM **a, unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,PBE2PARAM *,PBE2PARAM_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->keyfunc, d2i_X509_ALGOR); - M_ASN1_D2I_get (ret->encryption, d2i_X509_ALGOR); - M_ASN1_D2I_Finish(a, PBE2PARAM_free, ASN1_F_D2I_PBE2PARAM); -} +ASN1_SEQUENCE(PBE2PARAM) = { + ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR), + ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR) +} ASN1_SEQUENCE_END(PBE2PARAM) -void PBE2PARAM_free (PBE2PARAM *a) -{ - if(a==NULL) return; - X509_ALGOR_free(a->keyfunc); - X509_ALGOR_free(a->encryption); - Free ((char *)a); -} +IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM) -int i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - M_ASN1_I2D_len (a->salt, i2d_ASN1_TYPE); - M_ASN1_I2D_len (a->iter, i2d_ASN1_INTEGER); - M_ASN1_I2D_len (a->keylength, i2d_ASN1_INTEGER); - M_ASN1_I2D_len (a->prf, i2d_X509_ALGOR); +ASN1_SEQUENCE(PBKDF2PARAM) = { + ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY), + ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER), + ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER), + ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR) +} ASN1_SEQUENCE_END(PBKDF2PARAM) - M_ASN1_I2D_seq_total (); - - M_ASN1_I2D_put (a->salt, i2d_ASN1_TYPE); - M_ASN1_I2D_put (a->iter, i2d_ASN1_INTEGER); - M_ASN1_I2D_put (a->keylength, i2d_ASN1_INTEGER); - M_ASN1_I2D_put (a->prf, i2d_X509_ALGOR); - - M_ASN1_I2D_finish(); -} - -PBKDF2PARAM *PBKDF2PARAM_new(void) -{ - PBKDF2PARAM *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, PBKDF2PARAM); - M_ASN1_New(ret->salt, ASN1_TYPE_new); - M_ASN1_New(ret->iter, ASN1_INTEGER_new); - ret->keylength = NULL; - ret->prf = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_PBKDF2PARAM_NEW); -} - -PBKDF2PARAM *d2i_PBKDF2PARAM(PBKDF2PARAM **a, unsigned char **pp, - long length) -{ - M_ASN1_D2I_vars(a,PBKDF2PARAM *,PBKDF2PARAM_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->salt, d2i_ASN1_TYPE); - M_ASN1_D2I_get (ret->iter, d2i_ASN1_INTEGER); - M_ASN1_D2I_get_opt (ret->keylength, d2i_ASN1_INTEGER, V_ASN1_INTEGER); - M_ASN1_D2I_get_opt (ret->prf, d2i_X509_ALGOR, V_ASN1_SEQUENCE); - M_ASN1_D2I_Finish(a, PBKDF2PARAM_free, ASN1_F_D2I_PBKDF2PARAM); -} - -void PBKDF2PARAM_free (PBKDF2PARAM *a) -{ - if(a==NULL) return; - ASN1_TYPE_free(a->salt); - ASN1_INTEGER_free(a->iter); - ASN1_INTEGER_free(a->keylength); - X509_ALGOR_free(a->prf); - Free ((char *)a); -} +IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM) /* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: * yes I know this is horrible! @@ -175,22 +94,32 @@ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, PBKDF2PARAM *kdf = NULL; PBE2PARAM *pbe2 = NULL; ASN1_OCTET_STRING *osalt = NULL; + ASN1_OBJECT *obj; + + alg_nid = EVP_CIPHER_type(cipher); + if(alg_nid == NID_undef) { + ASN1err(ASN1_F_PKCS5_PBE2_SET, + ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + goto err; + } + obj = OBJ_nid2obj(alg_nid); if(!(pbe2 = PBE2PARAM_new())) goto merr; /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; - alg_nid = EVP_CIPHER_type(cipher); - - scheme->algorithm = OBJ_nid2obj(alg_nid); + scheme->algorithm = obj; if(!(scheme->parameter = ASN1_TYPE_new())) goto merr; /* Create random IV */ - RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)); + if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) + goto err; + + EVP_CIPHER_CTX_init(&ctx); /* Dummy cipherinit to just setup the IV */ - EVP_CipherInit(&ctx, cipher, NULL, iv, 0); + EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0); if(EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { ASN1err(ASN1_F_PKCS5_PBE2_SET, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); @@ -199,13 +128,13 @@ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, EVP_CIPHER_CTX_cleanup(&ctx); if(!(kdf = PBKDF2PARAM_new())) goto merr; - if(!(osalt = ASN1_OCTET_STRING_new())) goto merr; + if(!(osalt = M_ASN1_OCTET_STRING_new())) goto merr; if (!saltlen) saltlen = PKCS5_SALT_LEN; - if (!(osalt->data = Malloc (saltlen))) goto merr; + if (!(osalt->data = OPENSSL_malloc (saltlen))) goto merr; osalt->length = saltlen; if (salt) memcpy (osalt->data, salt, saltlen); - else RAND_bytes (osalt->data, saltlen); + else if (RAND_pseudo_bytes (osalt->data, saltlen) < 0) goto merr; if(iter <= 0) iter = PKCS5_DEFAULT_ITER; if(!ASN1_INTEGER_set(kdf->iter, iter)) goto merr; @@ -218,7 +147,7 @@ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, /* If its RC2 then we'd better setup the key length */ if(alg_nid == NID_rc2_cbc) { - if(!(kdf->keylength = ASN1_INTEGER_new())) goto merr; + if(!(kdf->keylength = M_ASN1_INTEGER_new())) goto merr; if(!ASN1_INTEGER_set (kdf->keylength, EVP_CIPHER_key_length(cipher))) goto merr; } @@ -264,7 +193,7 @@ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, err: PBE2PARAM_free(pbe2); /* Note 'scheme' is freed as part of pbe2 */ - ASN1_OCTET_STRING_free(osalt); + M_ASN1_OCTET_STRING_free(osalt); PBKDF2PARAM_free(kdf); X509_ALGOR_free(kalg); X509_ALGOR_free(ret); diff --git a/src/lib/libcrypto/asn1/p8_pkey.c b/src/lib/libcrypto/asn1/p8_pkey.c index aa9a4f6c96..b634d5bc85 100644 --- a/src/lib/libcrypto/asn1/p8_pkey.c +++ b/src/lib/libcrypto/asn1/p8_pkey.c @@ -58,72 +58,27 @@ #include #include "cryptlib.h" -#include +#include #include -int i2d_PKCS8_PRIV_KEY_INFO (PKCS8_PRIV_KEY_INFO *a, unsigned char **pp) +/* Minor tweak to operation: zero private key data */ +static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) { - - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_len (a->pkeyalg, i2d_X509_ALGOR); - M_ASN1_I2D_len (a->pkey, i2d_ASN1_TYPE); - M_ASN1_I2D_len_IMP_SET_opt_type (X509_ATTRIBUTE, a->attributes, - i2d_X509_ATTRIBUTE, 0); - - M_ASN1_I2D_seq_total (); - - M_ASN1_I2D_put (a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_put (a->pkeyalg, i2d_X509_ALGOR); - M_ASN1_I2D_put (a->pkey, i2d_ASN1_TYPE); - M_ASN1_I2D_put_IMP_SET_opt_type (X509_ATTRIBUTE, a->attributes, - i2d_X509_ATTRIBUTE, 0); - - M_ASN1_I2D_finish(); + /* Since the structure must still be valid use ASN1_OP_FREE_PRE */ + if(operation == ASN1_OP_FREE_PRE) { + PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval; + if (key->pkey->value.octet_string) + memset(key->pkey->value.octet_string->data, + 0, key->pkey->value.octet_string->length); + } + return 1; } -PKCS8_PRIV_KEY_INFO *PKCS8_PRIV_KEY_INFO_new(void) -{ - PKCS8_PRIV_KEY_INFO *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, PKCS8_PRIV_KEY_INFO); - M_ASN1_New (ret->version, ASN1_INTEGER_new); - M_ASN1_New (ret->pkeyalg, X509_ALGOR_new); - M_ASN1_New (ret->pkey, ASN1_TYPE_new); - ret->attributes = NULL; - ret->broken = PKCS8_OK; - return (ret); - M_ASN1_New_Error(ASN1_F_PKCS8_PRIV_KEY_INFO_NEW); -} +ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = { + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR), + ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY), + ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) -PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a, - unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,PKCS8_PRIV_KEY_INFO *,PKCS8_PRIV_KEY_INFO_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->version, d2i_ASN1_INTEGER); - M_ASN1_D2I_get (ret->pkeyalg, d2i_X509_ALGOR); - M_ASN1_D2I_get (ret->pkey, d2i_ASN1_TYPE); - M_ASN1_D2I_get_IMP_set_opt_type(X509_ATTRIBUTE, ret->attributes, - d2i_X509_ATTRIBUTE, - X509_ATTRIBUTE_free, 0); - if (ASN1_TYPE_get(ret->pkey) == V_ASN1_SEQUENCE) - ret->broken = PKCS8_NO_OCTET; - M_ASN1_D2I_Finish(a, PKCS8_PRIV_KEY_INFO_free, ASN1_F_D2I_PKCS8_PRIV_KEY_INFO); -} - -void PKCS8_PRIV_KEY_INFO_free (PKCS8_PRIV_KEY_INFO *a) -{ - if (a == NULL) return; - ASN1_INTEGER_free (a->version); - X509_ALGOR_free(a->pkeyalg); - /* Clear sensitive data */ - if (a->pkey->value.octet_string) - memset (a->pkey->value.octet_string->data, - 0, a->pkey->value.octet_string->length); - ASN1_TYPE_free (a->pkey); - sk_X509_ATTRIBUTE_pop_free (a->attributes, X509_ATTRIBUTE_free); - Free (a); -} +IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) diff --git a/src/lib/libcrypto/asn1/t_crl.c b/src/lib/libcrypto/asn1/t_crl.c index c2e447ce6f..60db305756 100644 --- a/src/lib/libcrypto/asn1/t_crl.c +++ b/src/lib/libcrypto/asn1/t_crl.c @@ -64,8 +64,7 @@ #include #include -static void ext_print(BIO *out, X509_EXTENSION *ex); -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API int X509_CRL_print_fp(FILE *fp, X509_CRL *x) { BIO *b; @@ -86,11 +85,10 @@ int X509_CRL_print_fp(FILE *fp, X509_CRL *x) int X509_CRL_print(BIO *out, X509_CRL *x) { char buf[256]; - unsigned char *s; STACK_OF(X509_REVOKED) *rev; X509_REVOKED *r; long l; - int i, j, n; + int i, n; BIO_printf(out, "Certificate Revocation List (CRL):\n"); l = X509_CRL_get_version(x); @@ -109,15 +107,12 @@ int X509_CRL_print(BIO *out, X509_CRL *x) BIO_printf(out,"\n"); n=X509_CRL_get_ext_count(x); - if (n > 0) { - BIO_printf(out,"%8sCRL extensions:\n",""); - for (i=0; icrl->extensions, 0, 8); rev = X509_CRL_get_REVOKED(x); - if(sk_X509_REVOKED_num(rev)) + if(sk_X509_REVOKED_num(rev) > 0) BIO_printf(out, "Revoked Certificates:\n"); else BIO_printf(out, "No Revoked Certificates.\n"); @@ -128,39 +123,11 @@ int X509_CRL_print(BIO *out, X509_CRL *x) BIO_printf(out,"\n Revocation Date: ",""); ASN1_TIME_print(out,r->revocationDate); BIO_printf(out,"\n"); - for(j = 0; j < X509_REVOKED_get_ext_count(r); j++) - ext_print(out, X509_REVOKED_get_ext(r, j)); - } - - i=OBJ_obj2nid(x->sig_alg->algorithm); - BIO_printf(out," Signature Algorithm: %s", - (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)); - - s = x->signature->data; - n = x->signature->length; - for (i=0; iextensions, 0, 8); } - BIO_write(out,"\n",1); + X509_signature_print(out, x->sig_alg, x->signature); return 1; } - -static void ext_print(BIO *out, X509_EXTENSION *ex) -{ - ASN1_OBJECT *obj; - int j; - BIO_printf(out,"%12s",""); - obj=X509_EXTENSION_get_object(ex); - i2a_ASN1_OBJECT(out,obj); - j=X509_EXTENSION_get_critical(ex); - BIO_printf(out, ": %s\n", j ? "critical":"",""); - if(!X509V3_EXT_print(out, ex, 0, 16)) { - BIO_printf(out, "%16s", ""); - ASN1_OCTET_STRING_print(out,ex->value); - } - BIO_write(out,"\n",1); -} diff --git a/src/lib/libcrypto/asn1/t_pkey.c b/src/lib/libcrypto/asn1/t_pkey.c index bc518d59a2..8060115202 100644 --- a/src/lib/libcrypto/asn1/t_pkey.c +++ b/src/lib/libcrypto/asn1/t_pkey.c @@ -58,35 +58,23 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "bn.h" -#ifndef NO_RSA -#include "rsa.h" +#include +#include +#ifndef OPENSSL_NO_RSA +#include #endif -#ifndef NO_DH -#include "dh.h" +#ifndef OPENSSL_NO_DH +#include #endif -#ifndef NO_DSA -#include "dsa.h" +#ifndef OPENSSL_NO_DSA +#include #endif -/* DHerr(DH_F_DHPARAMS_PRINT,ERR_R_MALLOC_FAILURE); - * DSAerr(DSA_F_DSAPARAMS_PRINT,ERR_R_MALLOC_FAILURE); - */ - -#ifndef NOPROTO -static int print(BIO *fp,char *str,BIGNUM *num, +static int print(BIO *fp,const char *str,BIGNUM *num, unsigned char *buf,int off); -#else -static int print(); -#endif - -#ifndef NO_RSA -#ifndef NO_FP_API -int RSA_print_fp(fp,x,off) -FILE *fp; -RSA *x; -int off; +#ifndef OPENSSL_NO_RSA +#ifndef OPENSSL_NO_FP_API +int RSA_print_fp(FILE *fp, const RSA *x, int off) { BIO *b; int ret; @@ -103,17 +91,15 @@ int off; } #endif -int RSA_print(bp,x,off) -BIO *bp; -RSA *x; -int off; +int RSA_print(BIO *bp, const RSA *x, int off) { - char str[128],*s; + char str[128]; + const char *s; unsigned char *m=NULL; int i,ret=0; i=RSA_size(x); - m=(unsigned char *)Malloc((unsigned int)i+10); + m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); if (m == NULL) { RSAerr(RSA_F_RSA_PRINT,ERR_R_MALLOC_FAILURE); @@ -147,17 +133,14 @@ int off; if (!print(bp,"coefficient:",x->iqmp,m,off)) goto err; ret=1; err: - if (m != NULL) Free((char *)m); + if (m != NULL) OPENSSL_free(m); return(ret); } -#endif /* NO_RSA */ +#endif /* OPENSSL_NO_RSA */ -#ifndef NO_DSA -#ifndef NO_FP_API -int DSA_print_fp(fp,x,off) -FILE *fp; -DSA *x; -int off; +#ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_FP_API +int DSA_print_fp(FILE *fp, const DSA *x, int off) { BIO *b; int ret; @@ -174,10 +157,7 @@ int off; } #endif -int DSA_print(bp,x,off) -BIO *bp; -DSA *x; -int off; +int DSA_print(BIO *bp, const DSA *x, int off) { char str[128]; unsigned char *m=NULL; @@ -196,7 +176,7 @@ int off; i=BN_num_bytes(bn)*2; else i=256; - m=(unsigned char *)Malloc((unsigned int)i+10); + m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); if (m == NULL) { DSAerr(DSA_F_DSA_PRINT,ERR_R_MALLOC_FAILURE); @@ -224,20 +204,17 @@ int off; if ((x->g != NULL) && !print(bp,"G: ",x->g,m,off)) goto err; ret=1; err: - if (m != NULL) Free((char *)m); + if (m != NULL) OPENSSL_free(m); return(ret); } -#endif /* !NO_DSA */ +#endif /* !OPENSSL_NO_DSA */ -static int print(bp,number,num,buf,off) -BIO *bp; -char *number; -BIGNUM *num; -unsigned char *buf; -int off; +static int print(BIO *bp, const char *number, BIGNUM *num, unsigned char *buf, + int off) { int n,i; - char str[128],*neg; + char str[128]; + const char *neg; if (num == NULL) return(1); neg=(num->neg)?"-":""; @@ -282,11 +259,9 @@ int off; return(1); } -#ifndef NO_DH -#ifndef NO_FP_API -int DHparams_print_fp(fp,x) -FILE *fp; -DH *x; +#ifndef OPENSSL_NO_DH +#ifndef OPENSSL_NO_FP_API +int DHparams_print_fp(FILE *fp, const DH *x) { BIO *b; int ret; @@ -303,15 +278,13 @@ DH *x; } #endif -int DHparams_print(bp,x) -BIO *bp; -DH *x; +int DHparams_print(BIO *bp, const DH *x) { unsigned char *m=NULL; int reason=ERR_R_BUF_LIB,i,ret=0; i=BN_num_bytes(x->p); - m=(unsigned char *)Malloc((unsigned int)i+10); + m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); if (m == NULL) { reason=ERR_R_MALLOC_FAILURE; @@ -325,7 +298,7 @@ DH *x; if (!print(bp,"generator:",x->g,m,4)) goto err; if (x->length != 0) { - if (BIO_printf(bp," recomented-private-length: %d bits\n", + if (BIO_printf(bp," recommended-private-length: %d bits\n", (int)x->length) <= 0) goto err; } ret=1; @@ -334,16 +307,14 @@ DH *x; err: DHerr(DH_F_DHPARAMS_PRINT,reason); } - if (m != NULL) Free((char *)m); + if (m != NULL) OPENSSL_free(m); return(ret); } #endif -#ifndef NO_DSA -#ifndef NO_FP_API -int DSAparams_print_fp(fp,x) -FILE *fp; -DSA *x; +#ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_FP_API +int DSAparams_print_fp(FILE *fp, const DSA *x) { BIO *b; int ret; @@ -360,15 +331,13 @@ DSA *x; } #endif -int DSAparams_print(bp,x) -BIO *bp; -DSA *x; +int DSAparams_print(BIO *bp, const DSA *x) { unsigned char *m=NULL; int reason=ERR_R_BUF_LIB,i,ret=0; i=BN_num_bytes(x->p); - m=(unsigned char *)Malloc((unsigned int)i+10); + m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); if (m == NULL) { reason=ERR_R_MALLOC_FAILURE; @@ -383,10 +352,10 @@ DSA *x; if (!print(bp,"g:",x->g,m,4)) goto err; ret=1; err: - if (m != NULL) Free((char *)m); + if (m != NULL) OPENSSL_free(m); DSAerr(DSA_F_DSAPARAMS_PRINT,reason); return(ret); } -#endif /* !NO_DSA */ +#endif /* !OPENSSL_NO_DSA */ diff --git a/src/lib/libcrypto/asn1/t_req.c b/src/lib/libcrypto/asn1/t_req.c index 7df749a48f..848c29a2dd 100644 --- a/src/lib/libcrypto/asn1/t_req.c +++ b/src/lib/libcrypto/asn1/t_req.c @@ -58,15 +58,14 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "bn.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include +#include -#ifndef NO_FP_API -int X509_REQ_print_fp(fp,x) -FILE *fp; -X509_REQ *x; +#ifndef OPENSSL_NO_FP_API +int X509_REQ_print_fp(FILE *fp, X509_REQ *x) { BIO *b; int ret; @@ -83,16 +82,15 @@ X509_REQ *x; } #endif -int X509_REQ_print(bp,x) -BIO *bp; -X509_REQ *x; +int X509_REQ_print(BIO *bp, X509_REQ *x) { unsigned long l; - int i,n; - char *s,*neg; + int i; + const char *neg; X509_REQ_INFO *ri; EVP_PKEY *pkey; - STACK *sk; + STACK_OF(X509_ATTRIBUTE) *sk; + STACK_OF(X509_EXTENSION) *exts; char str[128]; ri=x->req_info; @@ -119,8 +117,8 @@ X509_REQ *x; if (BIO_puts(bp,str) <= 0) goto err; pkey=X509_REQ_get_pubkey(x); -#ifndef NO_RSA - if (pkey->type == EVP_PKEY_RSA) +#ifndef OPENSSL_NO_RSA + if (pkey != NULL && pkey->type == EVP_PKEY_RSA) { BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", BN_num_bits(pkey->pkey.rsa->n)); @@ -128,8 +126,8 @@ X509_REQ *x; } else #endif -#ifndef NO_DSA - if (pkey->type == EVP_PKEY_DSA) +#ifndef OPENSSL_NO_DSA + if (pkey != NULL && pkey->type == EVP_PKEY_DSA) { BIO_printf(bp,"%12sDSA Public Key:\n",""); DSA_print(bp,pkey->pkey.dsa,16); @@ -138,22 +136,22 @@ X509_REQ *x; #endif BIO_printf(bp,"%12sUnknown Public Key:\n",""); + if (pkey != NULL) + EVP_PKEY_free(pkey); + /* may not be */ sprintf(str,"%8sAttributes:\n",""); if (BIO_puts(bp,str) <= 0) goto err; sk=x->req_info->attributes; - if ((sk == NULL) || (sk_num(sk) == 0)) + if (sk_X509_ATTRIBUTE_num(sk) == 0) { - if (!x->req_info->req_kludge) - { - sprintf(str,"%12sa0:00\n",""); - if (BIO_puts(bp,str) <= 0) goto err; - } + sprintf(str,"%12sa0:00\n",""); + if (BIO_puts(bp,str) <= 0) goto err; } else { - for (i=0; iobject))) + continue; sprintf(str,"%12s",""); if (BIO_puts(bp,str) <= 0) goto err; if ((j=i2a_ASN1_OBJECT(bp,a->object)) > 0) - - if (a->set) + { + if (a->single) + { + t=a->value.single; + type=t->type; + bs=t->value.bit_string; + } + else { ii=0; - count=sk_num(a->value.set); + count=sk_ASN1_TYPE_num(a->value.set); get_next: - at=(ASN1_TYPE *)sk_value(a->value.set,ii); + at=sk_ASN1_TYPE_value(a->value.set,ii); type=at->type; bs=at->value.asn1_string; } - else - { - t=a->value.single; - type=t->type; - bs=t->value.bit_string; - } + } for (j=25-j; j>0; j--) if (BIO_write(bp," ",1) != 1) goto err; if (BIO_puts(bp,":") <= 0) goto err; @@ -201,24 +202,31 @@ get_next: } } - i=OBJ_obj2nid(x->sig_alg->algorithm); - sprintf(str,"%4sSignature Algorithm: %s","", - (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)); - if (BIO_puts(bp,str) <= 0) goto err; - - n=x->signature->length; - s=(char *)x->signature->data; - for (i=0; ivalue); } - sprintf(str,"%02x%s",(unsigned char)s[i],((i+1) == n)?"":":"); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_write(bp,"\n",1) <= 0) goto err; } - if (BIO_puts(bp,"\n") <= 0) goto err; + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + } + + if(!X509_signature_print(bp, x->sig_alg, x->signature)) goto err; + return(1); err: X509err(X509_F_X509_REQ_PRINT,ERR_R_BUF_LIB); diff --git a/src/lib/libcrypto/asn1/t_spki.c b/src/lib/libcrypto/asn1/t_spki.c index d708434fca..5abfbc815e 100644 --- a/src/lib/libcrypto/asn1/t_spki.c +++ b/src/lib/libcrypto/asn1/t_spki.c @@ -59,7 +59,7 @@ #include #include "cryptlib.h" #include -#include +#include /* Print out an SPKI */ @@ -76,7 +76,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) pkey = X509_PUBKEY_get(spki->spkac->pubkey); if(!pkey) BIO_printf(out, " Unable to load public key\n"); else { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { BIO_printf(out," RSA Public Key: (%d bit)\n", @@ -85,7 +85,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { BIO_printf(out," DSA Public Key:\n"); diff --git a/src/lib/libcrypto/asn1/t_x509.c b/src/lib/libcrypto/asn1/t_x509.c index b10fbbb992..5de4833ed0 100644 --- a/src/lib/libcrypto/asn1/t_x509.c +++ b/src/lib/libcrypto/asn1/t_x509.c @@ -58,21 +58,25 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "bn.h" -#ifndef NO_RSA -#include "rsa.h" +#include +#include +#ifndef OPENSSL_NO_RSA +#include #endif -#ifndef NO_DSA -#include "dsa.h" +#ifndef OPENSSL_NO_DSA +#include #endif -#include "objects.h" -#include "x509.h" +#include +#include +#include -#ifndef NO_FP_API -int X509_print_fp(fp,x) -FILE *fp; -X509 *x; +#ifndef OPENSSL_NO_FP_API +int X509_print_fp(FILE *fp, X509 *x) + { + return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); + } + +int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag) { BIO *b; int ret; @@ -83,179 +87,238 @@ X509 *x; return(0); } BIO_set_fp(b,fp,BIO_NOCLOSE); - ret=X509_print(b, x); + ret=X509_print_ex(b, x, nmflag, cflag); BIO_free(b); return(ret); } #endif -int X509_print(bp,x) -BIO *bp; -X509 *x; +int X509_print(BIO *bp, X509 *x) +{ + return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag) { long l; - int ret=0,i,j,n; - char *m=NULL,*s; + int ret=0,i; + char *m=NULL,mlch = ' '; + int nmindent = 0; X509_CINF *ci; ASN1_INTEGER *bs; EVP_PKEY *pkey=NULL; - char *neg; - X509_EXTENSION *ex; + const char *neg; ASN1_STRING *str=NULL; + if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if(nmflags == X509_FLAG_COMPAT) + nmindent = 16; + ci=x->cert_info; - if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err; - if (BIO_write(bp," Data:\n",10) <= 0) goto err; - l=X509_get_version(x); - if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err; - if (BIO_write(bp," Serial Number:",22) <= 0) goto err; - - bs=X509_get_serialNumber(x); - if (bs->length <= 4) + if(!(cflag & X509_FLAG_NO_HEADER)) { - l=ASN1_INTEGER_get(bs); - if (l < 0) - { - l= -l; - neg="-"; - } - else - neg=""; - if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0) - goto err; + if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err; + if (BIO_write(bp," Data:\n",10) <= 0) goto err; } - else + if(!(cflag & X509_FLAG_NO_VERSION)) + { + l=X509_get_version(x); + if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err; + } + if(!(cflag & X509_FLAG_NO_SERIAL)) { - neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":""; - if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err; - for (i=0; ilength; i++) + if (BIO_write(bp," Serial Number:",22) <= 0) goto err; + + bs=X509_get_serialNumber(x); + if (bs->length <= 4) { - if (BIO_printf(bp,"%02x%c",bs->data[i], - ((i+1 == bs->length)?'\n':':')) <= 0) + l=ASN1_INTEGER_get(bs); + if (l < 0) + { + l= -l; + neg="-"; + } + else + neg=""; + if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0) goto err; } - } + else + { + neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":""; + if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err; - i=OBJ_obj2nid(ci->signature->algorithm); - if (BIO_printf(bp,"%8sSignature Algorithm: %s\n","", - (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)) <= 0) - goto err; + for (i=0; ilength; i++) + { + if (BIO_printf(bp,"%02x%c",bs->data[i], + ((i+1 == bs->length)?'\n':':')) <= 0) + goto err; + } + } - if (BIO_write(bp," Issuer: ",16) <= 0) goto err; - if (!X509_NAME_print(bp,X509_get_issuer_name(x),16)) goto err; - if (BIO_write(bp,"\n Validity\n",18) <= 0) goto err; - if (BIO_write(bp," Not Before: ",24) <= 0) goto err; - if (!ASN1_UTCTIME_print(bp,X509_get_notBefore(x))) goto err; - if (BIO_write(bp,"\n Not After : ",25) <= 0) goto err; - if (!ASN1_UTCTIME_print(bp,X509_get_notAfter(x))) goto err; - if (BIO_write(bp,"\n Subject: ",18) <= 0) goto err; - if (!X509_NAME_print(bp,X509_get_subject_name(x),16)) goto err; - if (BIO_write(bp,"\n Subject Public Key Info:\n",34) <= 0) - goto err; - i=OBJ_obj2nid(ci->key->algor->algorithm); - if (BIO_printf(bp,"%12sPublic Key Algorithm: %s\n","", - (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)) <= 0) goto err; + } - pkey=X509_get_pubkey(x); -#ifndef NO_RSA - if (pkey->type == EVP_PKEY_RSA) + if(!(cflag & X509_FLAG_NO_SIGNAME)) { - BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", - BN_num_bits(pkey->pkey.rsa->n)); - RSA_print(bp,pkey->pkey.rsa,16); + if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; } - else -#endif -#ifndef NO_DSA - if (pkey->type == EVP_PKEY_DSA) + + if(!(cflag & X509_FLAG_NO_ISSUER)) { - BIO_printf(bp,"%12sDSA Public Key:\n",""); - DSA_print(bp,pkey->pkey.dsa,16); + if (BIO_printf(bp," Issuer:%c",mlch) <= 0) goto err; + if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err; + if (BIO_write(bp,"\n",1) <= 0) goto err; } - else -#endif - BIO_printf(bp,"%12sDSA Public Key:\n",""); - - n=X509_get_ext_count(x); - if (n > 0) + if(!(cflag & X509_FLAG_NO_VALIDITY)) { - BIO_printf(bp,"%8sX509v3 extensions:\n",""); - for (i=0; ikey->algor->algorithm) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; - pack_type=X509v3_pack_type_by_OBJ(obj); - data_type=X509v3_data_type_by_OBJ(obj); - - if (pack_type == X509_EXT_PACK_STRING) - { - if (X509v3_unpack_string( - &str,data_type, - X509_EXTENSION_get_data(ex)) == NULL) - { - /* hmm... */ - goto err; - } - if ( (data_type == V_ASN1_IA5STRING) || - (data_type == V_ASN1_PRINTABLESTRING) || - (data_type == V_ASN1_T61STRING)) - { - if (BIO_write(bp,(char *)str->data, - str->length) <= 0) - goto err; - } - else if (data_type == V_ASN1_BIT_STRING) - { - BIO_printf(bp,"0x"); - for (j=0; jlength; j++) - { - BIO_printf(bp,"%02X", - str->data[j]); - } - } - } - else - { - ASN1_OCTET_STRING_print(bp,ex->value); - } - if (BIO_write(bp,"\n",1) <= 0) goto err; + pkey=X509_get_pubkey(x); + if (pkey == NULL) + { + BIO_printf(bp,"%12sUnable to load Public Key\n",""); + ERR_print_errors(bp); + } + else +#ifndef OPENSSL_NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", + BN_num_bits(pkey->pkey.rsa->n)); + RSA_print(bp,pkey->pkey.rsa,16); + } + else +#endif +#ifndef OPENSSL_NO_DSA + if (pkey->type == EVP_PKEY_DSA) + { + BIO_printf(bp,"%12sDSA Public Key:\n",""); + DSA_print(bp,pkey->pkey.dsa,16); } + else +#endif + BIO_printf(bp,"%12sUnknown Public Key:\n",""); + + EVP_PKEY_free(pkey); } - i=OBJ_obj2nid(x->sig_alg->algorithm); - if (BIO_printf(bp,"%4sSignature Algorithm: %s","", - (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)) <= 0) goto err; + if (!(cflag & X509_FLAG_NO_EXTENSIONS)) + X509V3_extensions_print(bp, "X509v3 extensions", + ci->extensions, cflag, 8); - n=x->signature->length; - s=(char *)x->signature->data; - for (i=0; isig_alg, x->signature) <= 0) goto err; + } + if(!(cflag & X509_FLAG_NO_AUX)) + { + if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err; } - if (BIO_write(bp,"\n",1) != 1) goto err; ret=1; err: if (str != NULL) ASN1_STRING_free(str); - if (m != NULL) Free((char *)m); + if (m != NULL) OPENSSL_free(m); return(ret); } -int ASN1_STRING_print(bp,v) -BIO *bp; -ASN1_STRING *v; +int X509_ocspid_print (BIO *bp, X509 *x) + { + unsigned char *der=NULL ; + unsigned char *dertmp; + int derlen; + int i; + unsigned char SHA1md[SHA_DIGEST_LENGTH]; + + /* display the hash of the subject as it would appear + in OCSP requests */ + if (BIO_printf(bp," Subject OCSP hash: ") <= 0) + goto err; + derlen = i2d_X509_NAME(x->cert_info->subject, NULL); + if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL) + goto err; + i2d_X509_NAME(x->cert_info->subject, &dertmp); + + EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL); + for (i=0; i < SHA_DIGEST_LENGTH; i++) + { + if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err; + } + OPENSSL_free (der); + der=NULL; + + /* display the hash of the public key as it would appear + in OCSP requests */ + if (BIO_printf(bp,"\n Public key OCSP hash: ") <= 0) + goto err; + + EVP_Digest(x->cert_info->key->public_key->data, + x->cert_info->key->public_key->length, SHA1md, NULL, EVP_sha1(), NULL); + for (i=0; i < SHA_DIGEST_LENGTH; i++) + { + if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) + goto err; + } + BIO_printf(bp,"\n"); + + return (1); +err: + if (der != NULL) OPENSSL_free(der); + return(0); + } + +int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig) +{ + unsigned char *s; + int i, n; + if (BIO_puts(bp," Signature Algorithm: ") <= 0) return 0; + if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0; + + n=sig->length; + s=sig->data; + for (i=0; itype == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm); + if(tm->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_print(bp, tm); + BIO_write(bp,"Bad time value",14); + return(0); +} + +static const char *mon[12]= + { + "Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec" + }; + +int ASN1_GENERALIZEDTIME_print(BIO *bp, ASN1_GENERALIZEDTIME *tm) + { + char *v; + int gmt=0; + int i; + int y=0,M=0,d=0,h=0,m=0,s=0; + + i=tm->length; + v=(char *)tm->data; + + if (i < 12) goto err; + if (v[i-1] == 'Z') gmt=1; + for (i=0; i<12; i++) + if ((v[i] > '9') || (v[i] < '0')) goto err; + y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0'); + M= (v[4]-'0')*10+(v[5]-'0'); + if ((M > 12) || (M < 1)) goto err; + d= (v[6]-'0')*10+(v[7]-'0'); + h= (v[8]-'0')*10+(v[9]-'0'); + m= (v[10]-'0')*10+(v[11]-'0'); + if ( (v[12] >= '0') && (v[12] <= '9') && + (v[13] >= '0') && (v[13] <= '9')) + s= (v[12]-'0')*10+(v[13]-'0'); + + if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s", + mon[M-1],d,h,m,s,y,(gmt)?" GMT":"") <= 0) + return(0); + else + return(1); +err: + BIO_write(bp,"Bad time value",14); + return(0); + } + +int ASN1_UTCTIME_print(BIO *bp, ASN1_UTCTIME *tm) { char *v; int gmt=0; - static char *mon[12]={ - "Jan","Feb","Mar","Apr","May","Jun", - "Jul","Aug","Sep","Oct","Nov","Dec"}; int i; int y=0,M=0,d=0,h=0,m=0,s=0; @@ -324,10 +431,7 @@ err: return(0); } -int X509_NAME_print(bp,name,obase) -BIO *bp; -X509_NAME *name; -int obase; +int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) { char *s,*c; int ret=0,l,ll,i,first=1; @@ -336,12 +440,15 @@ int obase; ll=80-2-obase; s=X509_NAME_oneline(name,buf,256); + if (!*s) + return 1; s++; /* skip the first slash */ l=ll; c=s; for (;;) { +#ifndef CHARSET_EBCDIC if ( ((*s == '/') && ((s[1] >= 'A') && (s[1] <= 'Z') && ( (s[2] == '=') || @@ -349,6 +456,15 @@ int obase; (s[3] == '=')) ))) || (*s == '\0')) +#else + if ( ((*s == '/') && + (isupper(s[1]) && ( + (s[2] == '=') || + (isupper(s[2]) && + (s[3] == '=')) + ))) || + (*s == '\0')) +#endif { if ((l <= 0) && !first) { diff --git a/src/lib/libcrypto/asn1/t_x509a.c b/src/lib/libcrypto/asn1/t_x509a.c index a18ebb586c..7d4a6e6084 100644 --- a/src/lib/libcrypto/asn1/t_x509a.c +++ b/src/lib/libcrypto/asn1/t_x509a.c @@ -59,7 +59,7 @@ #include #include "cryptlib.h" #include -#include +#include #include /* X509_CERT_AUX and string set routines @@ -98,5 +98,13 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) } else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "", aux->alias->data); + if(aux->keyid) { + BIO_printf(out, "%*sKey Id: ", indent, ""); + for(i = 0; i < aux->keyid->length; i++) + BIO_printf(out, "%s%02X", + i ? ":" : "", + aux->keyid->data[i]); + BIO_write(out,"\n",1); + } return 1; } diff --git a/src/lib/libcrypto/asn1/x_algor.c b/src/lib/libcrypto/asn1/x_algor.c index 0ed2c87b64..00b9ea54a1 100644 --- a/src/lib/libcrypto/asn1/x_algor.c +++ b/src/lib/libcrypto/asn1/x_algor.c @@ -1,126 +1,73 @@ -/* crypto/asn1/x_algor.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* x_algor.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. 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. + * + * 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 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 "asn1_mac.h" - -/* - * ASN1err(ASN1_F_D2I_X509_ALGOR,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_ALGOR_NEW,ASN1_R_EXPECTING_A_SEQUENCE); - * ASN1err(ASN1_F_D2I_X509_ALGOR,ASN1_R_LENGTH_MISMATCH); + * 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). + * */ -int i2d_X509_ALGOR(a,pp) -X509_ALGOR *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->algorithm,i2d_ASN1_OBJECT); - if (a->parameter != NULL) - { M_ASN1_I2D_len(a->parameter,i2d_ASN1_TYPE); } - - M_ASN1_I2D_seq_total(); - M_ASN1_I2D_put(a->algorithm,i2d_ASN1_OBJECT); - if (a->parameter != NULL) - { M_ASN1_I2D_put(a->parameter,i2d_ASN1_TYPE); } - - M_ASN1_I2D_finish(); - } - -X509_ALGOR *d2i_X509_ALGOR(a,pp,length) -X509_ALGOR **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_ALGOR *,X509_ALGOR_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->algorithm,d2i_ASN1_OBJECT); - if (!M_ASN1_D2I_end_sequence()) - { M_ASN1_D2I_get(ret->parameter,d2i_ASN1_TYPE); } - else - { - ASN1_TYPE_free(ret->parameter); - ret->parameter=NULL; - } - M_ASN1_D2I_Finish(a,X509_ALGOR_free,ASN1_F_D2I_X509_ALGOR); - } - -X509_ALGOR *X509_ALGOR_new() - { - X509_ALGOR *ret=NULL; +#include +#include +#include +#include - M_ASN1_New_Malloc(ret,X509_ALGOR); - M_ASN1_New(ret->algorithm,ASN1_OBJECT_new); - ret->parameter=NULL; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_ALGOR_NEW); - } +ASN1_SEQUENCE(X509_ALGOR) = { + ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), + ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY) +} ASN1_SEQUENCE_END(X509_ALGOR) -void X509_ALGOR_free(a) -X509_ALGOR *a; - { - if (a == NULL) return; - ASN1_OBJECT_free(a->algorithm); - ASN1_TYPE_free(a->parameter); - Free((char *)a); - } +IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) +IMPLEMENT_STACK_OF(X509_ALGOR) +IMPLEMENT_ASN1_SET_OF(X509_ALGOR) diff --git a/src/lib/libcrypto/asn1/x_attrib.c b/src/lib/libcrypto/asn1/x_attrib.c index e52ced8627..1e3713f18f 100644 --- a/src/lib/libcrypto/asn1/x_attrib.c +++ b/src/lib/libcrypto/asn1/x_attrib.c @@ -58,95 +58,61 @@ #include #include "cryptlib.h" -#include "objects.h" -#include "asn1_mac.h" +#include +#include +#include -/* - * ASN1err(ASN1_F_D2I_X509_ATTRIBUTE,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_ATTRIBUTE_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE); - * ASN1err(ASN1_F_I2D_X509_ATTRIBUTE,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE); +/* X509_ATTRIBUTE: this has the following form: + * + * typedef struct x509_attributes_st + * { + * ASN1_OBJECT *object; + * int single; + * union { + * char *ptr; + * STACK_OF(ASN1_TYPE) *set; + * ASN1_TYPE *single; + * } value; + * } X509_ATTRIBUTE; + * + * this needs some extra thought because the CHOICE type is + * merged with the main structure and because the value can + * be anything at all we *must* try the SET OF first because + * the ASN1_ANY type will swallow anything including the whole + * SET OF structure. */ -/* sequence */ -int i2d_X509_ATTRIBUTE(a,pp) -X509_ATTRIBUTE *a; -unsigned char **pp; - { - int k=0; - int r=0,ret=0; - unsigned char **p=NULL; - - if (a == NULL) return(0); +ASN1_CHOICE(X509_ATTRIBUTE_SET) = { + ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY), + ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY) +} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single) - p=NULL; - for (;;) - { - if (k) - { - r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); - if (pp == NULL) return(r); - p=pp; - ASN1_put_object(p,1,ret,V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL); - } +ASN1_SEQUENCE(X509_ATTRIBUTE) = { + ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), + /* CHOICE type merged with parent */ + ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET) +} ASN1_SEQUENCE_END(X509_ATTRIBUTE) - ret+=i2d_ASN1_OBJECT(a->object,p); - if (a->set) - ret+=i2d_ASN1_SET(a->value.set,p,i2d_ASN1_TYPE, - V_ASN1_SET,V_ASN1_UNIVERSAL); - else - ret+=i2d_ASN1_TYPE(a->value.single,p); - if (k++) return(r); - } - } +IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE) -X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(a,pp,length) -X509_ATTRIBUTE **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_ATTRIBUTE *,X509_ATTRIBUTE_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->object,d2i_ASN1_OBJECT); - - if ((c.slen != 0) && - (M_ASN1_next == (V_ASN1_CONSTRUCTED|V_ASN1_UNIVERSAL|V_ASN1_SET))) - { - ret->set=1; - M_ASN1_D2I_get_set(ret->value.set,d2i_ASN1_TYPE); - } - else - { - ret->set=0; - M_ASN1_D2I_get(ret->value.single,d2i_ASN1_TYPE); - } - - M_ASN1_D2I_Finish(a,X509_ATTRIBUTE_free,ASN1_F_D2I_X509_ATTRIBUTE); - } - -X509_ATTRIBUTE *X509_ATTRIBUTE_new() +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) { X509_ATTRIBUTE *ret=NULL; + ASN1_TYPE *val=NULL; + + if ((ret=X509_ATTRIBUTE_new()) == NULL) + return(NULL); + ret->object=OBJ_nid2obj(nid); + ret->single=0; + if ((ret->value.set=sk_ASN1_TYPE_new_null()) == NULL) goto err; + if ((val=ASN1_TYPE_new()) == NULL) goto err; + if (!sk_ASN1_TYPE_push(ret->value.set,val)) goto err; - M_ASN1_New_Malloc(ret,X509_ATTRIBUTE); - M_ASN1_New(ret->object,ASN1_OBJECT_new); - ret->set=0; - ret->value.ptr=NULL; + ASN1_TYPE_set(val,atrtype,value); return(ret); - M_ASN1_New_Error(ASN1_F_X509_ATTRIBUTE_NEW); +err: + if (ret != NULL) X509_ATTRIBUTE_free(ret); + if (val != NULL) ASN1_TYPE_free(val); + return(NULL); } - -void X509_ATTRIBUTE_free(a) -X509_ATTRIBUTE *a; - { - if (a == NULL) return; - ASN1_OBJECT_free(a->object); - if (a->set) - sk_pop_free(a->value.set,ASN1_TYPE_free); - else - ASN1_TYPE_free(a->value.single); - Free((char *)a); - } - diff --git a/src/lib/libcrypto/asn1/x_crl.c b/src/lib/libcrypto/asn1/x_crl.c index 13acdab427..11fce96825 100644 --- a/src/lib/libcrypto/asn1/x_crl.c +++ b/src/lib/libcrypto/asn1/x_crl.c @@ -58,296 +58,105 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" -#include "x509.h" - -/* - * ASN1err(ASN1_F_D2I_X509_CRL,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_D2I_X509_CRL_INFO,ASN1_R_EXPECTING_A_SEQUENCE); - * ASN1err(ASN1_F_D2I_X509_REVOKED,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_CRL_NEW,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_CRL_INFO_NEW,ASN1_R_EXPECTING_A_SEQUENCE); - * ASN1err(ASN1_F_X509_REVOKED_NEW,ASN1_R_LENGTH_MISMATCH); +#include +#include + +static int X509_REVOKED_cmp(const X509_REVOKED * const *a, + const X509_REVOKED * const *b); +static int X509_REVOKED_seq_cmp(const X509_REVOKED * const *a, + const X509_REVOKED * const *b); + +ASN1_SEQUENCE(X509_REVOKED) = { + ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION) +} ASN1_SEQUENCE_END(X509_REVOKED) + +/* The X509_CRL_INFO structure needs a bit of customisation. This is actually + * mirroring the old behaviour: its purpose is to allow the use of + * sk_X509_REVOKED_find to lookup revoked certificates. Unfortunately + * this will zap the original order and the signature so we keep a copy + * of the original positions and reorder appropriately before encoding. + * + * Might want to see if there's a better way of doing this later... */ - -#ifndef NOPROTO -static int X509_REVOKED_cmp(X509_REVOKED **a,X509_REVOKED **b); -static int X509_REVOKED_seq_cmp(X509_REVOKED **a,X509_REVOKED **b); -#else -static int X509_REVOKED_cmp(); -static int X509_REVOKED_seq_cmp(); -#endif - -int i2d_X509_REVOKED(a,pp) -X509_REVOKED *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->serialNumber,i2d_ASN1_INTEGER); - M_ASN1_I2D_len(a->revocationDate,i2d_ASN1_UTCTIME); - M_ASN1_I2D_len_SEQ_opt(a->extensions,i2d_X509_EXTENSION); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->serialNumber,i2d_ASN1_INTEGER); - M_ASN1_I2D_put(a->revocationDate,i2d_ASN1_UTCTIME); - M_ASN1_I2D_put_SEQ_opt(a->extensions,i2d_X509_EXTENSION); - - M_ASN1_I2D_finish(); - } - -X509_REVOKED *d2i_X509_REVOKED(a,pp,length) -X509_REVOKED **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_REVOKED *,X509_REVOKED_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->serialNumber,d2i_ASN1_INTEGER); - M_ASN1_D2I_get(ret->revocationDate,d2i_ASN1_UTCTIME); - M_ASN1_D2I_get_seq_opt(ret->extensions,d2i_X509_EXTENSION); - M_ASN1_D2I_Finish(a,X509_REVOKED_free,ASN1_F_D2I_X509_REVOKED); - } - -int i2d_X509_CRL_INFO(a,pp) -X509_CRL_INFO *a; -unsigned char **pp; - { - int v1=0; - long l=0; - M_ASN1_I2D_vars(a); - - if (sk_num(a->revoked) != 0) - qsort((char *)a->revoked->data,sk_num(a->revoked), - sizeof(X509_REVOKED *),(int (*)(P_CC_CC))X509_REVOKED_seq_cmp); - if ((a->version != NULL) && ((l=ASN1_INTEGER_get(a->version)) != 0)) - { - M_ASN1_I2D_len(a->version,i2d_ASN1_INTEGER); - } - M_ASN1_I2D_len(a->sig_alg,i2d_X509_ALGOR); - M_ASN1_I2D_len(a->issuer,i2d_X509_NAME); - M_ASN1_I2D_len(a->lastUpdate,i2d_ASN1_UTCTIME); - if (a->nextUpdate != NULL) - { M_ASN1_I2D_len(a->nextUpdate,i2d_ASN1_UTCTIME); } - M_ASN1_I2D_len_SEQ_opt(a->revoked,i2d_X509_REVOKED); - M_ASN1_I2D_len_EXP_set_opt(a->extensions,i2d_X509_EXTENSION,0, - V_ASN1_SEQUENCE,v1); - - M_ASN1_I2D_seq_total(); - - if ((a->version != NULL) && (l != 0)) - { - M_ASN1_I2D_put(a->version,i2d_ASN1_INTEGER); - } - M_ASN1_I2D_put(a->sig_alg,i2d_X509_ALGOR); - M_ASN1_I2D_put(a->issuer,i2d_X509_NAME); - M_ASN1_I2D_put(a->lastUpdate,i2d_ASN1_UTCTIME); - if (a->nextUpdate != NULL) - { M_ASN1_I2D_put(a->nextUpdate,i2d_ASN1_UTCTIME); } - M_ASN1_I2D_put_SEQ_opt(a->revoked,i2d_X509_REVOKED); - M_ASN1_I2D_put_EXP_set_opt(a->extensions,i2d_X509_EXTENSION,0, - V_ASN1_SEQUENCE,v1); - - M_ASN1_I2D_finish(); - } - -X509_CRL_INFO *d2i_X509_CRL_INFO(a,pp,length) -X509_CRL_INFO **a; -unsigned char **pp; -long length; - { - int i,ver=0; - M_ASN1_D2I_vars(a,X509_CRL_INFO *,X509_CRL_INFO_new); - - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get_opt(ret->version,d2i_ASN1_INTEGER,V_ASN1_INTEGER); - if (ret->version != NULL) - ver=ret->version->data[0]; - - if ((ver == 0) && (ret->version != NULL)) - { - ASN1_INTEGER_free(ret->version); - ret->version=NULL; - } - M_ASN1_D2I_get(ret->sig_alg,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->issuer,d2i_X509_NAME); - M_ASN1_D2I_get(ret->lastUpdate,d2i_ASN1_UTCTIME); - M_ASN1_D2I_get_opt(ret->nextUpdate,d2i_ASN1_UTCTIME,V_ASN1_UTCTIME); - if (ret->revoked != NULL) - { - while (sk_num(ret->revoked)) - X509_REVOKED_free((X509_REVOKED *)sk_pop(ret->revoked)); - } - M_ASN1_D2I_get_seq_opt(ret->revoked,d2i_X509_REVOKED); - - if (ret->revoked != NULL) - { - for (i=0; irevoked); i++) - { - ((X509_REVOKED *)sk_value(ret->revoked,i))->sequence=i; - } - } - - if (ver >= 1) - { - if (ret->extensions != NULL) - { - while (sk_num(ret->extensions)) - X509_EXTENSION_free((X509_EXTENSION *) - sk_pop(ret->extensions)); - } - - M_ASN1_D2I_get_EXP_set_opt(ret->extensions,d2i_X509_EXTENSION, - 0,V_ASN1_SEQUENCE); - } - - M_ASN1_D2I_Finish(a,X509_CRL_INFO_free,ASN1_F_D2I_X509_CRL_INFO); - } - -int i2d_X509_CRL(a,pp) -X509_CRL *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->crl,i2d_X509_CRL_INFO); - M_ASN1_I2D_len(a->sig_alg,i2d_X509_ALGOR); - M_ASN1_I2D_len(a->signature,i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->crl,i2d_X509_CRL_INFO); - M_ASN1_I2D_put(a->sig_alg,i2d_X509_ALGOR); - M_ASN1_I2D_put(a->signature,i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_finish(); - } - -X509_CRL *d2i_X509_CRL(a,pp,length) -X509_CRL **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_CRL *,X509_CRL_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->crl,d2i_X509_CRL_INFO); - M_ASN1_D2I_get(ret->sig_alg,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->signature,d2i_ASN1_BIT_STRING); - - M_ASN1_D2I_Finish(a,X509_CRL_free,ASN1_F_D2I_X509_CRL); - } - - -X509_REVOKED *X509_REVOKED_new() - { - X509_REVOKED *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_REVOKED); - M_ASN1_New(ret->serialNumber,ASN1_INTEGER_new); - M_ASN1_New(ret->revocationDate,ASN1_UTCTIME_new); - ret->extensions=NULL; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_REVOKED_NEW); - } - -X509_CRL_INFO *X509_CRL_INFO_new() - { - X509_CRL_INFO *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_CRL_INFO); - ret->version=NULL; - M_ASN1_New(ret->sig_alg,X509_ALGOR_new); - M_ASN1_New(ret->issuer,X509_NAME_new); - M_ASN1_New(ret->lastUpdate,ASN1_UTCTIME_new); - ret->nextUpdate=NULL; - M_ASN1_New(ret->revoked,sk_new_null); - M_ASN1_New(ret->extensions,sk_new_null); - ret->revoked->comp=(int (*)())X509_REVOKED_cmp; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_CRL_INFO_NEW); - } - -X509_CRL *X509_CRL_new() - { - X509_CRL *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_CRL); - ret->references=1; - M_ASN1_New(ret->crl,X509_CRL_INFO_new); - M_ASN1_New(ret->sig_alg,X509_ALGOR_new); - M_ASN1_New(ret->signature,ASN1_BIT_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_CRL_NEW); - } - -void X509_REVOKED_free(a) -X509_REVOKED *a; - { - if (a == NULL) return; - ASN1_INTEGER_free(a->serialNumber); - ASN1_UTCTIME_free(a->revocationDate); - sk_pop_free(a->extensions,X509_EXTENSION_free); - Free((char *)a); - } - -void X509_CRL_INFO_free(a) -X509_CRL_INFO *a; - { - if (a == NULL) return; - ASN1_INTEGER_free(a->version); - X509_ALGOR_free(a->sig_alg); - X509_NAME_free(a->issuer); - ASN1_UTCTIME_free(a->lastUpdate); - if (a->nextUpdate) - ASN1_UTCTIME_free(a->nextUpdate); - sk_pop_free(a->revoked,X509_REVOKED_free); - sk_pop_free(a->extensions,X509_EXTENSION_free); - Free((char *)a); - } - -void X509_CRL_free(a) -X509_CRL *a; - { +static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_CRL_INFO *a = (X509_CRL_INFO *)*pval; int i; - - if (a == NULL) return; - - i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_X509_CRL); -#ifdef REF_PRINT - REF_PRINT("X509_CRL",a); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"X509_CRL_free, bad reference count\n"); - abort(); - } -#endif - - X509_CRL_INFO_free(a->crl); - X509_ALGOR_free(a->sig_alg); - ASN1_BIT_STRING_free(a->signature); - Free((char *)a); + int (*old_cmp)(const X509_REVOKED * const *, + const X509_REVOKED * const *); + + if(!a || !a->revoked) return 1; + switch(operation) { + + /* Save original order */ + case ASN1_OP_D2I_POST: + for (i=0; irevoked); i++) + sk_X509_REVOKED_value(a->revoked,i)->sequence=i; + sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp); + break; + + /* Restore original order */ + case ASN1_OP_I2D_PRE: + old_cmp=sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_seq_cmp); + sk_X509_REVOKED_sort(a->revoked); + sk_X509_REVOKED_set_cmp_func(a->revoked,old_cmp); + break; } - -static int X509_REVOKED_cmp(a,b) -X509_REVOKED **a,**b; + return 1; +} + + +ASN1_SEQUENCE_cb(X509_CRL_INFO, crl_inf_cb) = { + ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME), + ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME), + ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0) +} ASN1_SEQUENCE_END_cb(X509_CRL_INFO, X509_CRL_INFO) + +ASN1_SEQUENCE_ref(X509_CRL, 0, CRYPTO_LOCK_X509_CRL) = { + ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO), + ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL) + +IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED) +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO) +IMPLEMENT_ASN1_FUNCTIONS(X509_CRL) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL) + +static int X509_REVOKED_cmp(const X509_REVOKED * const *a, + const X509_REVOKED * const *b) { return(ASN1_STRING_cmp( (ASN1_STRING *)(*a)->serialNumber, (ASN1_STRING *)(*b)->serialNumber)); } -static int X509_REVOKED_seq_cmp(a,b) -X509_REVOKED **a,**b; +static int X509_REVOKED_seq_cmp(const X509_REVOKED * const *a, + const X509_REVOKED * const *b) { return((*a)->sequence-(*b)->sequence); } + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) +{ + X509_CRL_INFO *inf; + inf = crl->crl; + if(!inf->revoked) + inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); + if(!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) { + ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +IMPLEMENT_STACK_OF(X509_REVOKED) +IMPLEMENT_ASN1_SET_OF(X509_REVOKED) +IMPLEMENT_STACK_OF(X509_CRL) +IMPLEMENT_ASN1_SET_OF(X509_CRL) diff --git a/src/lib/libcrypto/asn1/x_exten.c b/src/lib/libcrypto/asn1/x_exten.c index 54ffe2f00b..702421b6c8 100644 --- a/src/lib/libcrypto/asn1/x_exten.c +++ b/src/lib/libcrypto/asn1/x_exten.c @@ -1,156 +1,71 @@ -/* crypto/asn1/x_exten.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* x_exten.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. 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. + * + * 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 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 "objects.h" -#include "asn1_mac.h" - -/* - * ASN1err(ASN1_F_D2I_X509_EXTENSION,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_EXTENSION_NEW,ASN1_R_LENGTH_MISMATCH); + * 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). + * */ -int i2d_X509_EXTENSION(a,pp) -X509_EXTENSION *a; -unsigned char **pp; - { - int k=0; - int r=0,ret=0; - unsigned char **p=NULL; - - if (a == NULL) return(0); - - p=NULL; - for (;;) - { - if (k) - { - r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); - if (pp == NULL) return(r); - p=pp; - ASN1_put_object(p,1,ret,V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL); - } - - ret+=i2d_ASN1_OBJECT(a->object,p); - if ((a->critical) || a->netscape_hack) - ret+=i2d_ASN1_BOOLEAN(a->critical,p); - ret+=i2d_ASN1_OCTET_STRING(a->value,p); - if (k++) return(r); - } - } - -X509_EXTENSION *d2i_X509_EXTENSION(a,pp,length) -X509_EXTENSION **a; -unsigned char **pp; -long length; - { - int i; - M_ASN1_D2I_vars(a,X509_EXTENSION *,X509_EXTENSION_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->object,d2i_ASN1_OBJECT); - - if ((ret->argp != NULL) && (ret->ex_free != NULL)) - ret->ex_free(ret); - ret->argl=0; - ret->argp=NULL; - ret->netscape_hack=0; - if ((c.slen != 0) && - (M_ASN1_next == (V_ASN1_UNIVERSAL|V_ASN1_BOOLEAN))) - { - c.q=c.p; - if (d2i_ASN1_BOOLEAN(&i,&c.p,c.slen) < 0) goto err; - ret->critical=i; - c.slen-=(c.p-c.q); - if (ret->critical == 0) ret->netscape_hack=1; - } - M_ASN1_D2I_get(ret->value,d2i_ASN1_OCTET_STRING); - - M_ASN1_D2I_Finish(a,X509_EXTENSION_free,ASN1_F_D2I_X509_EXTENSION); - } - -X509_EXTENSION *X509_EXTENSION_new() - { - X509_EXTENSION *ret=NULL; +#include +#include +#include +#include - M_ASN1_New_Malloc(ret,X509_EXTENSION); - M_ASN1_New(ret->object,ASN1_OBJECT_new); - M_ASN1_New(ret->value,ASN1_OCTET_STRING_new); - ret->critical=0; - ret->netscape_hack=0; - ret->argl=0L; - ret->argp=NULL; - ret->ex_free=NULL; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_EXTENSION_NEW); - } - -void X509_EXTENSION_free(a) -X509_EXTENSION *a; - { - if (a == NULL) return; - if ((a->argp != NULL) && (a->ex_free != NULL)) - a->ex_free(a); - ASN1_OBJECT_free(a->object); - ASN1_OCTET_STRING_free(a->value); - Free((char *)a); - } +ASN1_SEQUENCE(X509_EXTENSION) = { + ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), + ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), + ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_EXTENSION) +IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION) diff --git a/src/lib/libcrypto/asn1/x_info.c b/src/lib/libcrypto/asn1/x_info.c index b55f0ce77a..d44f6cdb01 100644 --- a/src/lib/libcrypto/asn1/x_info.c +++ b/src/lib/libcrypto/asn1/x_info.c @@ -58,15 +58,15 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "asn1_mac.h" -#include "x509.h" +#include +#include +#include -X509_INFO *X509_INFO_new() +X509_INFO *X509_INFO_new(void) { X509_INFO *ret=NULL; - ret=(X509_INFO *)Malloc(sizeof(X509_INFO)); + ret=(X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO)); if (ret == NULL) { ASN1err(ASN1_F_X509_INFO_NEW,ERR_R_MALLOC_FAILURE); @@ -84,8 +84,7 @@ X509_INFO *X509_INFO_new() return(ret); } -void X509_INFO_free(x) -X509_INFO *x; +void X509_INFO_free(X509_INFO *x) { int i; @@ -107,5 +106,9 @@ X509_INFO *x; if (x->x509 != NULL) X509_free(x->x509); if (x->crl != NULL) X509_CRL_free(x->crl); if (x->x_pkey != NULL) X509_PKEY_free(x->x_pkey); - Free((char *)x); + if (x->enc_data != NULL) OPENSSL_free(x->enc_data); + OPENSSL_free(x); } + +IMPLEMENT_STACK_OF(X509_INFO) + diff --git a/src/lib/libcrypto/asn1/x_long.c b/src/lib/libcrypto/asn1/x_long.c index c5f25956cb..c04b192794 100644 --- a/src/lib/libcrypto/asn1/x_long.c +++ b/src/lib/libcrypto/asn1/x_long.c @@ -104,12 +104,7 @@ static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const A long ltmp; unsigned long utmp; int clen, pad, i; - /* this exists to bypass broken gcc optimization */ - char *cp = (char *)pval; - - /* use memcpy, because we may not be long aligned */ - memcpy(<mp, cp, sizeof(long)); - + ltmp = *(long *)pval; if(ltmp == it->size) return -1; /* Convert the long to positive: we subtract one if negative so * we can cleanly handle the padding if only the MSB of the leading @@ -141,7 +136,6 @@ static int long_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, int neg, i; long ltmp; unsigned long utmp = 0; - char *cp = (char *)pval; if(len > sizeof(long)) { ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); return 0; @@ -164,6 +158,6 @@ static int long_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); return 0; } - memcpy(cp, <mp, sizeof(long)); + *(long *)pval = ltmp; return 1; } diff --git a/src/lib/libcrypto/asn1/x_name.c b/src/lib/libcrypto/asn1/x_name.c index 28b9c34b58..caece0f158 100644 --- a/src/lib/libcrypto/asn1/x_name.c +++ b/src/lib/libcrypto/asn1/x_name.c @@ -58,228 +58,203 @@ #include #include "cryptlib.h" -#include "objects.h" -#include "asn1_mac.h" +#include +#include -/* - * ASN1err(ASN1_F_D2I_X509_NAME,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_NAME_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE); - * ASN1err(ASN1_F_D2I_X509_NAME_ENTRY,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_NAME_ENTRY_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE); - */ - -#ifndef NOPROTO -static int i2d_X509_NAME_entries(X509_NAME *a); -#else -static int i2d_X509_NAME_entries(); -#endif - -int i2d_X509_NAME_ENTRY(a,pp) -X509_NAME_ENTRY *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->object,i2d_ASN1_OBJECT); - M_ASN1_I2D_len(a->value,i2d_ASN1_PRINTABLE); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->object,i2d_ASN1_OBJECT); - M_ASN1_I2D_put(a->value,i2d_ASN1_PRINTABLE); - - M_ASN1_I2D_finish(); - } +static int x509_name_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); -X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(a,pp,length) -X509_NAME_ENTRY **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_NAME_ENTRY *,X509_NAME_ENTRY_new); +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); +static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->object,d2i_ASN1_OBJECT); - M_ASN1_D2I_get(ret->value,d2i_ASN1_PRINTABLE); - ret->set=0; - M_ASN1_D2I_Finish(a,X509_NAME_ENTRY_free,ASN1_F_D2I_X509_NAME_ENTRY); - } +static int x509_name_encode(X509_NAME *a); -int i2d_X509_NAME(a,pp) -X509_NAME *a; -unsigned char **pp; - { - int ret; +ASN1_SEQUENCE(X509_NAME_ENTRY) = { + ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), + ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) +} ASN1_SEQUENCE_END(X509_NAME_ENTRY) - if (a == NULL) return(0); - if (a->modified) - { - ret=i2d_X509_NAME_entries(a); - if (ret < 0) return(ret); - } +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) - ret=a->bytes->length; - if (pp != NULL) - { - memcpy(*pp,a->bytes->data,ret); - *pp+=ret; - } - return(ret); - } - -static int i2d_X509_NAME_entries(a) -X509_NAME *a; - { - X509_NAME_ENTRY *ne,*fe=NULL; - STACK *sk; - BUF_MEM *buf=NULL; - int set=0,r,ret=0; - int i; - unsigned char *p; - int size=0; - - sk=a->entries; - for (i=0; iset != set) - { - ret+=ASN1_object_size(1,size,V_ASN1_SET); - fe->size=size; - fe=ne; - size=0; - set=ne->set; - } - size+=i2d_X509_NAME_ENTRY(ne,NULL); - } +/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } + * so declare two template wrappers for this + */ - ret+=ASN1_object_size(1,size,V_ASN1_SET); - if (fe != NULL) - fe->size=size; +ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) +ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) - r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); +ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) +ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) - buf=a->bytes; - if (!BUF_MEM_grow(buf,r)) goto err; - p=(unsigned char *)buf->data; +/* Normally that's where it would end: we'd have two nested STACK structures + * representing the ASN1. Unfortunately X509_NAME uses a completely different + * form and caches encodings so we have to process the internal form and convert + * to the external form. + */ - ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); +const ASN1_EXTERN_FUNCS x509_name_ff = { + NULL, + x509_name_ex_new, + x509_name_ex_free, + 0, /* Default clear behaviour is OK */ + x509_name_ex_d2i, + x509_name_ex_i2d +}; + +IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) + +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) +{ + X509_NAME *ret = NULL; + ret = OPENSSL_malloc(sizeof(X509_NAME)); + if(!ret) goto memerr; + if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL) + goto memerr; + if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr; + ret->modified=1; + *val = (ASN1_VALUE *)ret; + return 1; - set= -1; - for (i=0; iset) - { - set=ne->set; - ASN1_put_object(&p,1,ne->size, - V_ASN1_SET,V_ASN1_UNIVERSAL); - } - i2d_X509_NAME_ENTRY(ne,&p); + if (ret->entries) + sk_X509_NAME_ENTRY_free(ret->entries); + OPENSSL_free(ret); } - a->modified=0; - return(r); -err: - return(-1); - } + return 0; +} -X509_NAME *d2i_X509_NAME(a,pp,length) -X509_NAME **a; -unsigned char **pp; -long length; - { - int set=0,i; - int idx=0; - unsigned char *orig; - M_ASN1_D2I_vars(a,X509_NAME *,X509_NAME_new); +static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_NAME *a; + if(!pval || !*pval) + return; + a = (X509_NAME *)*pval; - orig= *pp; - if (sk_num(ret->entries) > 0) - { - while (sk_num(ret->entries) > 0) - X509_NAME_ENTRY_free((X509_NAME_ENTRY *) - sk_pop(ret->entries)); - } + BUF_MEM_free(a->bytes); + sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free); + OPENSSL_free(a); + *pval = NULL; +} + +/* Used with sk_pop_free() to free up the internal representation. + * NB: we only free the STACK and not its contents because it is + * already present in the X509_NAME structure. + */ - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - for (;;) - { - if (M_ASN1_D2I_end_sequence()) break; - M_ASN1_D2I_get_set(ret->entries,d2i_X509_NAME_ENTRY); - for (; idx < sk_num(ret->entries); idx++) - { - ((X509_NAME_ENTRY *)sk_value(ret->entries,idx))->set= - set; - } - set++; +static void sk_internal_free(void *a) +{ + sk_free(a); +} + +static int x509_name_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + unsigned char *p = *in, *q; + STACK *intname = NULL; + int i, j, ret; + X509_NAME *nm = NULL; + STACK_OF(X509_NAME_ENTRY) *entries; + X509_NAME_ENTRY *entry; + q = p; + + /* Get internal representation of Name */ + ret = ASN1_item_ex_d2i((ASN1_VALUE **)&intname, &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + tag, aclass, opt, ctx); + + if(ret <= 0) return ret; + + if(*val) x509_name_ex_free(val, NULL); + if(!x509_name_ex_new((ASN1_VALUE **)&nm, NULL)) goto err; + /* We've decoded it: now cache encoding */ + if(!BUF_MEM_grow(nm->bytes, p - q)) goto err; + memcpy(nm->bytes->data, q, p - q); + + /* Convert internal representation to X509_NAME structure */ + for(i = 0; i < sk_num(intname); i++) { + entries = (STACK_OF(X509_NAME_ENTRY) *)sk_value(intname, i); + for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { + entry = sk_X509_NAME_ENTRY_value(entries, j); + entry->set = i; + if(!sk_X509_NAME_ENTRY_push(nm->entries, entry)) + goto err; } - - i=(int)(c.p-orig); - if (!BUF_MEM_grow(ret->bytes,i)) goto err; - memcpy(ret->bytes->data,orig,i); - ret->bytes->length=i; - ret->modified=0; - - M_ASN1_D2I_Finish(a,X509_NAME_free,ASN1_F_D2I_X509_NAME); + sk_X509_NAME_ENTRY_free(entries); } - -X509_NAME *X509_NAME_new() - { - X509_NAME *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_NAME); - if ((ret->entries=sk_new(NULL)) == NULL) goto err2; - M_ASN1_New(ret->bytes,BUF_MEM_new); - ret->modified=1; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_NAME_NEW); + sk_free(intname); + nm->modified = 0; + *val = (ASN1_VALUE *)nm; + *in = p; + return ret; + err: + ASN1err(ASN1_F_D2I_X509_NAME, ERR_R_NESTED_ASN1_ERROR); + return 0; +} + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) +{ + int ret; + X509_NAME *a = (X509_NAME *)*val; + if(a->modified) { + ret = x509_name_encode((X509_NAME *)a); + if(ret < 0) return ret; } - -X509_NAME_ENTRY *X509_NAME_ENTRY_new() - { - X509_NAME_ENTRY *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_NAME_ENTRY); -/* M_ASN1_New(ret->object,ASN1_OBJECT_new);*/ - ret->object=NULL; - ret->set=0; - M_ASN1_New(ret->value,ASN1_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_NAME_ENTRY_NEW); + ret = a->bytes->length; + if(out != NULL) { + memcpy(*out,a->bytes->data,ret); + *out+=ret; } + return ret; +} -void X509_NAME_free(a) -X509_NAME *a; - { - BUF_MEM_free(a->bytes); - sk_pop_free(a->entries,X509_NAME_ENTRY_free); - Free((char *)a); - } - -void X509_NAME_ENTRY_free(a) -X509_NAME_ENTRY *a; - { - if (a == NULL) return; - ASN1_OBJECT_free(a->object); - ASN1_BIT_STRING_free(a->value); - Free((char *)a); +static int x509_name_encode(X509_NAME *a) +{ + STACK *intname = NULL; + int len; + unsigned char *p; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry; + int i, set = -1; + intname = sk_new_null(); + if(!intname) goto memerr; + for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if(entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if(!entries) goto memerr; + if(!sk_push(intname, (char *)entries)) goto memerr; + set = entry->set; + } + if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; } - -int X509_NAME_set(xn,name) -X509_NAME **xn; -X509_NAME *name; + len = ASN1_item_ex_i2d((ASN1_VALUE **)&intname, NULL, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + if (!BUF_MEM_grow(a->bytes,len)) goto memerr; + p=(unsigned char *)a->bytes->data; + ASN1_item_ex_i2d((ASN1_VALUE **)&intname, &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + sk_pop_free(intname, sk_internal_free); + a->modified = 0; + return len; + memerr: + sk_pop_free(intname, sk_internal_free); + ASN1err(ASN1_F_D2I_X509_NAME, ERR_R_MALLOC_FAILURE); + return -1; +} + + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name) { X509_NAME *in; - if (*xn == NULL) return(0); + if (!xn || !name) return(0); if (*xn != name) { @@ -293,3 +268,5 @@ X509_NAME *name; return(*xn != NULL); } +IMPLEMENT_STACK_OF(X509_NAME_ENTRY) +IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY) diff --git a/src/lib/libcrypto/asn1/x_pkey.c b/src/lib/libcrypto/asn1/x_pkey.c index 1d4d926129..f1c6221ac3 100644 --- a/src/lib/libcrypto/asn1/x_pkey.c +++ b/src/lib/libcrypto/asn1/x_pkey.c @@ -58,25 +58,18 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "asn1_mac.h" - -/* ASN1err(ASN1_F_D2I_X509_PKEY,ASN1_R_UNSUPPORTED_CIPHER); */ -/* ASN1err(ASN1_F_X509_PKEY_NEW,ASN1_R_IV_TOO_LARGE); */ +#include +#include +#include +#include /* need to implement */ -int i2d_X509_PKEY(a,pp) -X509_PKEY *a; -unsigned char **pp; +int i2d_X509_PKEY(X509_PKEY *a, unsigned char **pp) { return(0); } -X509_PKEY *d2i_X509_PKEY(a,pp,length) -X509_PKEY **a; -unsigned char **pp; -long length; +X509_PKEY *d2i_X509_PKEY(X509_PKEY **a, unsigned char **pp, long length) { int i; M_ASN1_D2I_vars(a,X509_PKEY *,X509_PKEY_new); @@ -91,6 +84,7 @@ long length; if (ret->cipher.cipher == NULL) { c.error=ASN1_R_UNSUPPORTED_CIPHER; + c.line=__LINE__; goto err; } if (ret->enc_algor->parameter->type == V_ASN1_OCTET_STRING) @@ -99,6 +93,7 @@ long length; if (i > EVP_MAX_IV_LENGTH) { c.error=ASN1_R_IV_TOO_LARGE; + c.line=__LINE__; goto err; } memcpy(ret->cipher.iv, @@ -109,14 +104,15 @@ long length; M_ASN1_D2I_Finish(a,X509_PKEY_free,ASN1_F_D2I_X509_PKEY); } -X509_PKEY *X509_PKEY_new() +X509_PKEY *X509_PKEY_new(void) { X509_PKEY *ret=NULL; + ASN1_CTX c; M_ASN1_New_Malloc(ret,X509_PKEY); ret->version=0; M_ASN1_New(ret->enc_algor,X509_ALGOR_new); - M_ASN1_New(ret->enc_pkey,ASN1_OCTET_STRING_new); + M_ASN1_New(ret->enc_pkey,M_ASN1_OCTET_STRING_new); ret->dec_pkey=NULL; ret->key_length=0; ret->key_data=NULL; @@ -128,8 +124,7 @@ X509_PKEY *X509_PKEY_new() M_ASN1_New_Error(ASN1_F_X509_PKEY_NEW); } -void X509_PKEY_free(x) -X509_PKEY *x; +void X509_PKEY_free(X509_PKEY *x) { int i; @@ -149,8 +144,8 @@ X509_PKEY *x; #endif if (x->enc_algor != NULL) X509_ALGOR_free(x->enc_algor); - if (x->enc_pkey != NULL) ASN1_OCTET_STRING_free(x->enc_pkey); + if (x->enc_pkey != NULL) M_ASN1_OCTET_STRING_free(x->enc_pkey); if (x->dec_pkey != NULL)EVP_PKEY_free(x->dec_pkey); - if ((x->key_data != NULL) && (x->key_free)) Free((char *)x->key_data); - Free((char *)(char *)x); + if ((x->key_data != NULL) && (x->key_free)) OPENSSL_free(x->key_data); + OPENSSL_free(x); } diff --git a/src/lib/libcrypto/asn1/x_pubkey.c b/src/lib/libcrypto/asn1/x_pubkey.c index a309cf74a7..d958540120 100644 --- a/src/lib/libcrypto/asn1/x_pubkey.c +++ b/src/lib/libcrypto/asn1/x_pubkey.c @@ -58,80 +58,33 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" +#include +#include -/* - * ASN1err(ASN1_F_D2I_X509_PUBKEY,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_PUBKEY_NEW,ASN1_R_LENGTH_MISMATCH); - */ - -int i2d_X509_PUBKEY(a,pp) -X509_PUBKEY *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->algor, i2d_X509_ALGOR); - M_ASN1_I2D_len(a->public_key, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->algor, i2d_X509_ALGOR); - M_ASN1_I2D_put(a->public_key, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_finish(); - } - -X509_PUBKEY *d2i_X509_PUBKEY(a,pp,length) -X509_PUBKEY **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_PUBKEY *,X509_PUBKEY_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->algor,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->public_key,d2i_ASN1_BIT_STRING); - if (ret->pkey != NULL) - { - EVP_PKEY_free(ret->pkey); - ret->pkey=NULL; - } - M_ASN1_D2I_Finish(a,X509_PUBKEY_free,ASN1_F_D2I_X509_PUBKEY); +/* Minor tweak to operation: free up EVP_PKEY */ +static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + if(operation == ASN1_OP_FREE_POST) { + X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval; + EVP_PKEY_free(pubkey->pkey); } + return 1; +} -X509_PUBKEY *X509_PUBKEY_new() - { - X509_PUBKEY *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_PUBKEY); - M_ASN1_New(ret->algor,X509_ALGOR_new); - M_ASN1_New(ret->public_key,ASN1_BIT_STRING_new); - ret->pkey=NULL; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_PUBKEY_NEW); - } +ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = { + ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR), + ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY) -void X509_PUBKEY_free(a) -X509_PUBKEY *a; - { - if (a == NULL) return; - X509_ALGOR_free(a->algor); - ASN1_BIT_STRING_free(a->public_key); - if (a->pkey != NULL) EVP_PKEY_free(a->pkey); - Free((char *)a); - } +IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY) -int X509_PUBKEY_set(x,pkey) -X509_PUBKEY **x; -EVP_PKEY *pkey; +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) { int ok=0; X509_PUBKEY *pk; X509_ALGOR *a; ASN1_OBJECT *o; - unsigned char *s,*p; + unsigned char *s,*p = NULL; int i; if (x == NULL) return(0); @@ -156,7 +109,7 @@ EVP_PKEY *pkey; } } else -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { unsigned char *pp; @@ -166,14 +119,14 @@ EVP_PKEY *pkey; dsa->write_params=0; ASN1_TYPE_free(a->parameter); i=i2d_DSAparams(dsa,NULL); - p=(unsigned char *)Malloc(i); + if ((p=(unsigned char *)OPENSSL_malloc(i)) == NULL) goto err; pp=p; i2d_DSAparams(dsa,&pp); a->parameter=ASN1_TYPE_new(); a->parameter->type=V_ASN1_SEQUENCE; a->parameter->value.sequence=ASN1_STRING_new(); ASN1_STRING_set(a->parameter->value.sequence,p,i); - Free(p); + OPENSSL_free(p); } else #endif @@ -182,15 +135,25 @@ EVP_PKEY *pkey; goto err; } - i=i2d_PublicKey(pkey,NULL); - if ((s=(unsigned char *)Malloc(i+1)) == NULL) goto err; + if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err; + if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL) + { + X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE); + goto err; + } p=s; i2d_PublicKey(pkey,&p); - if (!ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err; - Free(s); + if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err; + /* Set number of unused bits to zero */ + pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); + pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT; + + OPENSSL_free(s); +#if 0 CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); pk->pkey=pkey; +#endif if (*x != NULL) X509_PUBKEY_free(*x); @@ -204,20 +167,24 @@ err: return(ok); } -EVP_PKEY *X509_PUBKEY_get(key) -X509_PUBKEY *key; +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; long j; int type; unsigned char *p; -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA + const unsigned char *cp; X509_ALGOR *a; #endif if (key == NULL) goto err; - if (key->pkey != NULL) return(key->pkey); + if (key->pkey != NULL) + { + CRYPTO_add(&key->pkey->references,1,CRYPTO_LOCK_EVP_PKEY); + return(key->pkey); + } if (key->public_key == NULL) goto err; @@ -231,22 +198,23 @@ X509_PUBKEY *key; } ret->save_parameters=0; -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA a=key->algor; if (ret->type == EVP_PKEY_DSA) { - if (a->parameter->type == V_ASN1_SEQUENCE) + if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) { ret->pkey.dsa->write_params=0; - p=a->parameter->value.sequence->data; + cp=p=a->parameter->value.sequence->data; j=a->parameter->value.sequence->length; - if (!d2i_DSAparams(&ret->pkey.dsa,&p,(long)j)) + if (!d2i_DSAparams(&ret->pkey.dsa,&cp,(long)j)) goto err; } ret->save_parameters=1; } #endif key->pkey=ret; + CRYPTO_add(&ret->references,1,CRYPTO_LOCK_EVP_PKEY); return(ret); err: if (ret != NULL) @@ -254,3 +222,113 @@ err: return(NULL); } +/* Now two pseudo ASN1 routines that take an EVP_PKEY structure + * and encode or decode as X509_PUBKEY + */ + +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, unsigned char **pp, + long length) +{ + X509_PUBKEY *xpk; + EVP_PKEY *pktmp; + xpk = d2i_X509_PUBKEY(NULL, pp, length); + if(!xpk) return NULL; + pktmp = X509_PUBKEY_get(xpk); + X509_PUBKEY_free(xpk); + if(!pktmp) return NULL; + if(a) { + EVP_PKEY_free(*a); + *a = pktmp; + } + return pktmp; +} + +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp) +{ + X509_PUBKEY *xpk=NULL; + int ret; + if(!a) return 0; + if(!X509_PUBKEY_set(&xpk, a)) return 0; + ret = i2d_X509_PUBKEY(xpk, pp); + X509_PUBKEY_free(xpk); + return ret; +} + +/* The following are equivalents but which return RSA and DSA + * keys + */ +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSA_PUBKEY(RSA **a, unsigned char **pp, + long length) +{ + EVP_PKEY *pkey; + RSA *key; + unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if(!pkey) return NULL; + key = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if(!key) return NULL; + *pp = q; + if(a) { + RSA_free(*a); + *a = key; + } + return key; +} + +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if(!a) return 0; + pktmp = EVP_PKEY_new(); + if(!pktmp) { + ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_set1_RSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif + +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY(DSA **a, unsigned char **pp, + long length) +{ + EVP_PKEY *pkey; + DSA *key; + unsigned char *q; + q = *pp; + pkey = d2i_PUBKEY(NULL, &q, length); + if(!pkey) return NULL; + key = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + if(!key) return NULL; + *pp = q; + if(a) { + DSA_free(*a); + *a = key; + } + return key; +} + +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp) +{ + EVP_PKEY *pktmp; + int ret; + if(!a) return 0; + pktmp = EVP_PKEY_new(); + if(!pktmp) { + ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + EVP_PKEY_set1_DSA(pktmp, a); + ret = i2d_PUBKEY(pktmp, pp); + EVP_PKEY_free(pktmp); + return ret; +} +#endif diff --git a/src/lib/libcrypto/asn1/x_req.c b/src/lib/libcrypto/asn1/x_req.c index ff0be13d37..b3f18ebc12 100644 --- a/src/lib/libcrypto/asn1/x_req.c +++ b/src/lib/libcrypto/asn1/x_req.c @@ -58,190 +58,55 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" -#include "x509.h" - -/* - * ASN1err(ASN1_F_D2I_X509_REQ,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_D2I_X509_REQ_INFO,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_REQ_NEW,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_REQ_INFO_NEW,ASN1_R_LENGTH_MISMATCH); +#include +#include + +/* X509_REQ_INFO is handled in an unusual way to get round + * invalid encodings. Some broken certificate requests don't + * encode the attributes field if it is empty. This is in + * violation of PKCS#10 but we need to tolerate it. We do + * this by making the attributes field OPTIONAL then using + * the callback to initialise it to an empty STACK. + * + * This means that the field will be correctly encoded unless + * we NULL out the field. + * + * As a result we no longer need the req_kludge field because + * the information is now contained in the attributes field: + * 1. If it is NULL then it's the invalid omission. + * 2. If it is empty it is the correct encoding. + * 3. If it is not empty then some attributes are present. + * */ -int i2d_X509_REQ_INFO(a,pp) -X509_REQ_INFO *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_len(a->subject, i2d_X509_NAME); - M_ASN1_I2D_len(a->pubkey, i2d_X509_PUBKEY); - - /* this is a *nasty* hack reported to be required to - * allow some CA Software to accept the cert request. - * It is not following the PKCS standards ... - * PKCS#10 pg 5 - * attributes [0] IMPLICIT Attibutes - * NOTE: no OPTIONAL ... so it *must* be there - */ - if (a->req_kludge) - { - M_ASN1_I2D_len_IMP_set_opt(a->attributes,i2d_X509_ATTRIBUTE,0); - } - else - { - M_ASN1_I2D_len_IMP_set(a->attributes, i2d_X509_ATTRIBUTE,0); - } - - M_ASN1_I2D_seq_total(); - M_ASN1_I2D_put(a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_put(a->subject, i2d_X509_NAME); - M_ASN1_I2D_put(a->pubkey, i2d_X509_PUBKEY); - - /* this is a *nasty* hack reported to be required by some CA's. - * It is not following the PKCS standards ... - * PKCS#10 pg 5 - * attributes [0] IMPLICIT Attibutes - * NOTE: no OPTIONAL ... so it *must* be there - */ - if (a->req_kludge) - { - M_ASN1_I2D_put_IMP_set_opt(a->attributes,i2d_X509_ATTRIBUTE,0); - } - else - { - M_ASN1_I2D_put_IMP_set(a->attributes,i2d_X509_ATTRIBUTE,0); - } +static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval; - M_ASN1_I2D_finish(); + if(operation == ASN1_OP_NEW_POST) { + rinf->attributes = sk_X509_ATTRIBUTE_new_null(); + if(!rinf->attributes) return 0; } - -X509_REQ_INFO *d2i_X509_REQ_INFO(a,pp,length) -X509_REQ_INFO **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_REQ_INFO *,X509_REQ_INFO_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->version,d2i_ASN1_INTEGER); - M_ASN1_D2I_get(ret->subject,d2i_X509_NAME); - M_ASN1_D2I_get(ret->pubkey,d2i_X509_PUBKEY); - - /* this is a *nasty* hack to allow for some CA's that - * have been reported as requiring it. - * It is not following the PKCS standards ... - * PKCS#10 pg 5 - * attributes [0] IMPLICIT Attibutes - * NOTE: no OPTIONAL ... so it *must* be there + return 1; +} + +ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), + ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY), + /* This isn't really OPTIONAL but it gets round invalid + * encodings */ - if (asn1_Finish(&c)) - ret->req_kludge=1; - else - { - M_ASN1_D2I_get_IMP_set(ret->attributes,d2i_X509_ATTRIBUTE,0); - } - - M_ASN1_D2I_Finish(a,X509_REQ_INFO_free,ASN1_F_D2I_X509_REQ_INFO); - } - -X509_REQ_INFO *X509_REQ_INFO_new() - { - X509_REQ_INFO *ret=NULL; + ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO) - M_ASN1_New_Malloc(ret,X509_REQ_INFO); - M_ASN1_New(ret->version,ASN1_INTEGER_new); - M_ASN1_New(ret->subject,X509_NAME_new); - M_ASN1_New(ret->pubkey,X509_PUBKEY_new); - M_ASN1_New(ret->attributes,sk_new_null); - ret->req_kludge=0; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_REQ_INFO_NEW); - } - -void X509_REQ_INFO_free(a) -X509_REQ_INFO *a; - { - if (a == NULL) return; - ASN1_INTEGER_free(a->version); - X509_NAME_free(a->subject); - X509_PUBKEY_free(a->pubkey); - sk_pop_free(a->attributes,X509_ATTRIBUTE_free); - Free((char *)a); - } - -int i2d_X509_REQ(a,pp) -X509_REQ *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - M_ASN1_I2D_len(a->req_info, i2d_X509_REQ_INFO); - M_ASN1_I2D_len(a->sig_alg, i2d_X509_ALGOR); - M_ASN1_I2D_len(a->signature, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->req_info, i2d_X509_REQ_INFO); - M_ASN1_I2D_put(a->sig_alg, i2d_X509_ALGOR); - M_ASN1_I2D_put(a->signature, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_finish(); - } - -X509_REQ *d2i_X509_REQ(a,pp,length) -X509_REQ **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_REQ *,X509_REQ_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->req_info,d2i_X509_REQ_INFO); - M_ASN1_D2I_get(ret->sig_alg,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->signature,d2i_ASN1_BIT_STRING); - M_ASN1_D2I_Finish(a,X509_REQ_free,ASN1_F_D2I_X509_REQ); - } - -X509_REQ *X509_REQ_new() - { - X509_REQ *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_REQ); - ret->references=1; - M_ASN1_New(ret->req_info,X509_REQ_INFO_new); - M_ASN1_New(ret->sig_alg,X509_ALGOR_new); - M_ASN1_New(ret->signature,ASN1_BIT_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_REQ_NEW); - } - -void X509_REQ_free(a) -X509_REQ *a; - { - int i; - - if (a == NULL) return; - - i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_X509_REQ); -#ifdef REF_PRINT - REF_PRINT("X509_REQ",a); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"X509_REQ_free, bad reference count\n"); - abort(); - } -#endif - - X509_REQ_INFO_free(a->req_info); - X509_ALGOR_free(a->sig_alg); - ASN1_BIT_STRING_free(a->signature); - Free((char *)a); - } +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) +ASN1_SEQUENCE_ref(X509_REQ, 0, CRYPTO_LOCK_X509_INFO) = { + ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO), + ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ) +IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) diff --git a/src/lib/libcrypto/asn1/x_sig.c b/src/lib/libcrypto/asn1/x_sig.c index f0a2e4c27a..42efa86c1c 100644 --- a/src/lib/libcrypto/asn1/x_sig.c +++ b/src/lib/libcrypto/asn1/x_sig.c @@ -58,62 +58,12 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" - -/* - * ASN1err(ASN1_F_D2I_X509_SIG,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_SIG_NEW,ASN1_R_LENGTH_MISMATCH); - */ - -int i2d_X509_SIG(a,pp) -X509_SIG *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->algor, i2d_X509_ALGOR); - M_ASN1_I2D_len(a->digest, i2d_ASN1_OCTET_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->algor, i2d_X509_ALGOR); - M_ASN1_I2D_put(a->digest, i2d_ASN1_OCTET_STRING); - - M_ASN1_I2D_finish(); - } - -X509_SIG *d2i_X509_SIG(a,pp,length) -X509_SIG **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_SIG *,X509_SIG_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->algor,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->digest,d2i_ASN1_OCTET_STRING); - M_ASN1_D2I_Finish(a,X509_SIG_free,ASN1_F_D2I_X509_SIG); - } - -X509_SIG *X509_SIG_new() - { - X509_SIG *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_SIG); - M_ASN1_New(ret->algor,X509_ALGOR_new); - M_ASN1_New(ret->digest,ASN1_OCTET_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_SIG_NEW); - } - -void X509_SIG_free(a) -X509_SIG *a; - { - if (a == NULL) return; - X509_ALGOR_free(a->algor); - ASN1_OCTET_STRING_free(a->digest); - Free((char *)a); - } +#include +#include +ASN1_SEQUENCE(X509_SIG) = { + ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR), + ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(X509_SIG) +IMPLEMENT_ASN1_FUNCTIONS(X509_SIG) diff --git a/src/lib/libcrypto/asn1/x_spki.c b/src/lib/libcrypto/asn1/x_spki.c index 4a80df44b8..2aece077c5 100644 --- a/src/lib/libcrypto/asn1/x_spki.c +++ b/src/lib/libcrypto/asn1/x_spki.c @@ -57,125 +57,25 @@ */ /* This module was send to me my Pat Richards who - * wrote it. It is under my Copyright with his permision + * wrote it. It is under my Copyright with his permission */ #include #include "cryptlib.h" -#include "x509.h" -#include "asn1_mac.h" +#include +#include -/* - * ASN1err(ASN1_F_D2I_NETSCAPE_SPKAC,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_NETSCAPE_SPKAC_NEW,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_D2I_NETSCAPE_SPKI,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_NETSCAPE_SPKI_NEW,ASN1_R_LENGTH_MISMATCH); - */ - -int i2d_NETSCAPE_SPKAC(a,pp) -NETSCAPE_SPKAC *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->pubkey, i2d_X509_PUBKEY); - M_ASN1_I2D_len(a->challenge, i2d_ASN1_IA5STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->pubkey, i2d_X509_PUBKEY); - M_ASN1_I2D_put(a->challenge, i2d_ASN1_IA5STRING); - - M_ASN1_I2D_finish(); - } - -NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(a,pp,length) -NETSCAPE_SPKAC **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,NETSCAPE_SPKAC *,NETSCAPE_SPKAC_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->pubkey,d2i_X509_PUBKEY); - M_ASN1_D2I_get(ret->challenge,d2i_ASN1_IA5STRING); - M_ASN1_D2I_Finish(a,NETSCAPE_SPKAC_free,ASN1_F_D2I_NETSCAPE_SPKAC); - } - -NETSCAPE_SPKAC *NETSCAPE_SPKAC_new() - { - NETSCAPE_SPKAC *ret=NULL; - - M_ASN1_New_Malloc(ret,NETSCAPE_SPKAC); - M_ASN1_New(ret->pubkey,X509_PUBKEY_new); - M_ASN1_New(ret->challenge,ASN1_IA5STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_NETSCAPE_SPKAC_NEW); - } - -void NETSCAPE_SPKAC_free(a) -NETSCAPE_SPKAC *a; - { - if (a == NULL) return; - X509_PUBKEY_free(a->pubkey); - ASN1_IA5STRING_free(a->challenge); - Free((char *)a); - } - -int i2d_NETSCAPE_SPKI(a,pp) -NETSCAPE_SPKI *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->spkac, i2d_NETSCAPE_SPKAC); - M_ASN1_I2D_len(a->sig_algor, i2d_X509_ALGOR); - M_ASN1_I2D_len(a->signature, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->spkac, i2d_NETSCAPE_SPKAC); - M_ASN1_I2D_put(a->sig_algor, i2d_X509_ALGOR); - M_ASN1_I2D_put(a->signature, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_finish(); - } - -NETSCAPE_SPKI *d2i_NETSCAPE_SPKI(a,pp,length) -NETSCAPE_SPKI **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,NETSCAPE_SPKI *,NETSCAPE_SPKI_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->spkac,d2i_NETSCAPE_SPKAC); - M_ASN1_D2I_get(ret->sig_algor,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->signature,d2i_ASN1_BIT_STRING); - M_ASN1_D2I_Finish(a,NETSCAPE_SPKI_free,ASN1_F_D2I_NETSCAPE_SPKI); - } - -NETSCAPE_SPKI *NETSCAPE_SPKI_new() - { - NETSCAPE_SPKI *ret=NULL; +ASN1_SEQUENCE(NETSCAPE_SPKAC) = { + ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY), + ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING) +} ASN1_SEQUENCE_END(NETSCAPE_SPKAC) - M_ASN1_New_Malloc(ret,NETSCAPE_SPKI); - M_ASN1_New(ret->spkac,NETSCAPE_SPKAC_new); - M_ASN1_New(ret->sig_algor,X509_ALGOR_new); - M_ASN1_New(ret->signature,ASN1_BIT_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_NETSCAPE_SPKI_NEW); - } +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC) -void NETSCAPE_SPKI_free(a) -NETSCAPE_SPKI *a; - { - if (a == NULL) return; - NETSCAPE_SPKAC_free(a->spkac); - X509_ALGOR_free(a->sig_algor); - ASN1_BIT_STRING_free(a->signature); - Free((char *)a); - } +ASN1_SEQUENCE(NETSCAPE_SPKI) = { + ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC), + ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR), + ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(NETSCAPE_SPKI) +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI) diff --git a/src/lib/libcrypto/asn1/x_val.c b/src/lib/libcrypto/asn1/x_val.c index a9c390f88c..dc17c67758 100644 --- a/src/lib/libcrypto/asn1/x_val.c +++ b/src/lib/libcrypto/asn1/x_val.c @@ -58,61 +58,12 @@ #include #include "cryptlib.h" -#include "asn1_mac.h" +#include +#include -/* ASN1err(ASN1_F_X509_VAL_NEW,ERR_R_MALLOC_FAILURE); - * ASN1err(ASN1_F_X509_VAL_FREE,ERR_R_MALLOC_FAILURE); - * ASN1err(ASN1_F_D2I_X509_VAL,ERR_R_MALLOC_FAILURE); - */ - -int i2d_X509_VAL(a,pp) -X509_VAL *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->notBefore,i2d_ASN1_UTCTIME); - M_ASN1_I2D_len(a->notAfter,i2d_ASN1_UTCTIME); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->notBefore,i2d_ASN1_UTCTIME); - M_ASN1_I2D_put(a->notAfter,i2d_ASN1_UTCTIME); - - M_ASN1_I2D_finish(); - } - -X509_VAL *d2i_X509_VAL(a,pp,length) -X509_VAL **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_VAL *,X509_VAL_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->notBefore,d2i_ASN1_UTCTIME); - M_ASN1_D2I_get(ret->notAfter,d2i_ASN1_UTCTIME); - M_ASN1_D2I_Finish(a,X509_VAL_free,ASN1_F_D2I_X509_VAL); - } - -X509_VAL *X509_VAL_new() - { - X509_VAL *ret=NULL; - - M_ASN1_New_Malloc(ret,X509_VAL); - M_ASN1_New(ret->notBefore,ASN1_UTCTIME_new); - M_ASN1_New(ret->notAfter,ASN1_UTCTIME_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_VAL_NEW); - } - -void X509_VAL_free(a) -X509_VAL *a; - { - if (a == NULL) return; - ASN1_UTCTIME_free(a->notBefore); - ASN1_UTCTIME_free(a->notAfter); - Free((char *)a); - } +ASN1_SEQUENCE(X509_VAL) = { + ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME), + ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME) +} ASN1_SEQUENCE_END(X509_VAL) +IMPLEMENT_ASN1_FUNCTIONS(X509_VAL) diff --git a/src/lib/libcrypto/asn1/x_x509.c b/src/lib/libcrypto/asn1/x_x509.c index bc466ce0f6..b50167ce43 100644 --- a/src/lib/libcrypto/asn1/x_x509.c +++ b/src/lib/libcrypto/asn1/x_x509.c @@ -58,13 +58,72 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "asn1_mac.h" +#include +#include +#include +#include + +ASN1_SEQUENCE(X509_CINF) = { + ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0), + ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR), + ASN1_SIMPLE(X509_CINF, issuer, X509_NAME), + ASN1_SIMPLE(X509_CINF, validity, X509_VAL), + ASN1_SIMPLE(X509_CINF, subject, X509_NAME), + ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY), + ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1), + ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2), + ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3) +} ASN1_SEQUENCE_END(X509_CINF) + +IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) +/* X509 top level structure needs a bit of customisation */ + +static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509 *ret = (X509 *)*pval; + + switch(operation) { + + case ASN1_OP_NEW_POST: + ret->valid=0; + ret->name = NULL; + ret->ex_flags = 0; + ret->ex_pathlen = -1; + ret->skid = NULL; + ret->akid = NULL; + ret->aux = NULL; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); + break; + + case ASN1_OP_D2I_POST: + if (ret->name != NULL) OPENSSL_free(ret->name); + ret->name=X509_NAME_oneline(ret->cert_info->subject,NULL,0); + break; + + case ASN1_OP_FREE_POST: + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data); + X509_CERT_AUX_free(ret->aux); + ASN1_OCTET_STRING_free(ret->skid); + AUTHORITY_KEYID_free(ret->akid); + + if (ret->name != NULL) OPENSSL_free(ret->name); + break; -/* - * ASN1err(ASN1_F_D2I_X509,ASN1_R_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_NEW,ASN1_R_BAD_GET_OBJECT); - */ + } + + return 1; + +} + +ASN1_SEQUENCE_ref(X509, x509_cb, CRYPTO_LOCK_X509) = { + ASN1_SIMPLE(X509, cert_info, X509_CINF), + ASN1_SIMPLE(X509, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END_ref(X509, X509) + +IMPLEMENT_ASN1_FUNCTIONS(X509) +IMPLEMENT_ASN1_DUP_FUNCTION(X509) static ASN1_METHOD meth={ (int (*)()) i2d_X509, @@ -72,87 +131,59 @@ static ASN1_METHOD meth={ (char *(*)())X509_new, (void (*)()) X509_free}; -ASN1_METHOD *X509_asn1_meth() +ASN1_METHOD *X509_asn1_meth(void) { return(&meth); } -int i2d_X509(a,pp) -X509 *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->cert_info, i2d_X509_CINF); - M_ASN1_I2D_len(a->sig_alg, i2d_X509_ALGOR); - M_ASN1_I2D_len(a->signature, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_seq_total(); +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) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, argl, argp, + new_func, dup_func, free_func); + } - M_ASN1_I2D_put(a->cert_info, i2d_X509_CINF); - M_ASN1_I2D_put(a->sig_alg, i2d_X509_ALGOR); - M_ASN1_I2D_put(a->signature, i2d_ASN1_BIT_STRING); - - M_ASN1_I2D_finish(); - } - -X509 *d2i_X509(a,pp,length) -X509 **a; -unsigned char **pp; -long length; +int X509_set_ex_data(X509 *r, int idx, void *arg) { - M_ASN1_D2I_vars(a,X509 *,X509_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->cert_info,d2i_X509_CINF); - M_ASN1_D2I_get(ret->sig_alg,d2i_X509_ALGOR); - M_ASN1_D2I_get(ret->signature,d2i_ASN1_BIT_STRING); -if (ret->name != NULL) Free(ret->name); -ret->name=X509_NAME_oneline(ret->cert_info->subject,NULL,0); - - M_ASN1_D2I_Finish(a,X509_free,ASN1_F_D2I_X509); + return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); } -X509 *X509_new() +void *X509_get_ex_data(X509 *r, int idx) { - X509 *ret=NULL; - - M_ASN1_New_Malloc(ret,X509); - ret->references=1; - ret->valid=0; - ret->name=NULL; - M_ASN1_New(ret->cert_info,X509_CINF_new); - M_ASN1_New(ret->sig_alg,X509_ALGOR_new); - M_ASN1_New(ret->signature,ASN1_BIT_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_NEW); + return(CRYPTO_get_ex_data(&r->ex_data,idx)); } -void X509_free(a) -X509 *a; - { - int i; - - if (a == NULL) return; - - i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_X509); -#ifdef REF_PRINT - REF_PRINT("X509",a); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"X509_free, bad reference count\n"); - abort(); - } -#endif - - X509_CINF_free(a->cert_info); - X509_ALGOR_free(a->sig_alg); - ASN1_BIT_STRING_free(a->signature); - if (a->name != NULL) Free(a->name); - Free((char *)a); - } +/* X509_AUX ASN1 routines. X509_AUX is the name given to + * a certificate with extra info tagged on the end. Since these + * functions set how a certificate is trusted they should only + * be used when the certificate comes from a reliable source + * such as local storage. + * + */ +X509 *d2i_X509_AUX(X509 **a, unsigned char **pp, long length) +{ + unsigned char *q; + X509 *ret; + /* Save start position */ + q = *pp; + ret = d2i_X509(a, pp, length); + /* If certificate unreadable then forget it */ + if(!ret) return NULL; + /* update length */ + length -= *pp - q; + if(!length) return ret; + if(!d2i_X509_CERT_AUX(&ret->aux, pp, length)) goto err; + return ret; + err: + X509_free(ret); + return NULL; +} + +int i2d_X509_AUX(X509 *a, unsigned char **pp) +{ + int length; + length = i2d_X509(a, pp); + if(a) length += i2d_X509_CERT_AUX(a->aux, pp); + return length; +} diff --git a/src/lib/libcrypto/asn1/x_x509a.c b/src/lib/libcrypto/asn1/x_x509a.c index b9987ea968..f244768b7e 100644 --- a/src/lib/libcrypto/asn1/x_x509a.c +++ b/src/lib/libcrypto/asn1/x_x509a.c @@ -59,7 +59,7 @@ #include #include "cryptlib.h" #include -#include +#include #include /* X509_CERT_AUX routines. These are used to encode additional @@ -71,72 +71,15 @@ static X509_CERT_AUX *aux_get(X509 *x); -X509_CERT_AUX *d2i_X509_CERT_AUX(X509_CERT_AUX **a, unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a, X509_CERT_AUX *, X509_CERT_AUX_new); - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - - M_ASN1_D2I_get_seq_opt_type(ASN1_OBJECT, ret->trust, - d2i_ASN1_OBJECT, ASN1_OBJECT_free); - M_ASN1_D2I_get_IMP_set_opt_type(ASN1_OBJECT, ret->reject, - d2i_ASN1_OBJECT, ASN1_OBJECT_free, 0); - M_ASN1_D2I_get_opt(ret->alias, d2i_ASN1_UTF8STRING, V_ASN1_UTF8STRING); - M_ASN1_D2I_get_opt(ret->keyid, d2i_ASN1_OCTET_STRING, V_ASN1_OCTET_STRING); - M_ASN1_D2I_get_IMP_set_opt_type(X509_ALGOR, ret->other, - d2i_X509_ALGOR, X509_ALGOR_free, 1); - - M_ASN1_D2I_Finish(a, X509_CERT_AUX_free, ASN1_F_D2I_X509_CERT_AUX); -} - -X509_CERT_AUX *X509_CERT_AUX_new() -{ - X509_CERT_AUX *ret = NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, X509_CERT_AUX); - ret->trust = NULL; - ret->reject = NULL; - ret->alias = NULL; - ret->keyid = NULL; - ret->other = NULL; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_CERT_AUX_NEW); -} - -void X509_CERT_AUX_free(X509_CERT_AUX *a) -{ - if(a == NULL) return; - sk_ASN1_OBJECT_pop_free(a->trust, ASN1_OBJECT_free); - sk_ASN1_OBJECT_pop_free(a->reject, ASN1_OBJECT_free); - ASN1_UTF8STRING_free(a->alias); - ASN1_OCTET_STRING_free(a->keyid); - sk_X509_ALGOR_pop_free(a->other, X509_ALGOR_free); - Free(a); -} - -int i2d_X509_CERT_AUX(X509_CERT_AUX *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); +ASN1_SEQUENCE(X509_CERT_AUX) = { + ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0), + ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING), + ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING), + ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1) +} ASN1_SEQUENCE_END(X509_CERT_AUX) - M_ASN1_I2D_len_SEQUENCE_opt_type(ASN1_OBJECT, a->trust, i2d_ASN1_OBJECT); - M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(ASN1_OBJECT, a->reject, i2d_ASN1_OBJECT, 0); - - M_ASN1_I2D_len(a->alias, i2d_ASN1_UTF8STRING); - M_ASN1_I2D_len(a->keyid, i2d_ASN1_OCTET_STRING); - M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(X509_ALGOR, a->other, i2d_X509_ALGOR, 1); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put_SEQUENCE_opt_type(ASN1_OBJECT, a->trust, i2d_ASN1_OBJECT); - M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(ASN1_OBJECT, a->reject, i2d_ASN1_OBJECT, 0); - - M_ASN1_I2D_put(a->alias, i2d_ASN1_UTF8STRING); - M_ASN1_I2D_put(a->keyid, i2d_ASN1_OCTET_STRING); - M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(X509_ALGOR, a->other, i2d_X509_ALGOR, 1); - - M_ASN1_I2D_finish(); -} +IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX) static X509_CERT_AUX *aux_get(X509 *x) { @@ -153,6 +96,14 @@ int X509_alias_set1(X509 *x, unsigned char *name, int len) return ASN1_STRING_set(aux->alias, name, len); } +int X509_keyid_set1(X509 *x, unsigned char *id, int len) +{ + X509_CERT_AUX *aux; + if(!(aux = aux_get(x))) return 0; + if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0; + return ASN1_STRING_set(aux->keyid, id, len); +} + unsigned char *X509_alias_get0(X509 *x, int *len) { if(!x->aux || !x->aux->alias) return NULL; diff --git a/src/lib/libcrypto/bf/asm/bf-586.pl b/src/lib/libcrypto/bf/asm/bf-586.pl index 5c7ab14ab0..b556642c94 100644 --- a/src/lib/libcrypto/bf/asm/bf-586.pl +++ b/src/lib/libcrypto/bf/asm/bf-586.pl @@ -1,10 +1,10 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl push(@INC,"perlasm","../../perlasm"); require "x86asm.pl"; require "cbc.pl"; -&asm_init($ARGV[0],"bf-586.pl"); +&asm_init($ARGV[0],"bf-586.pl",$ARGV[$#ARGV] eq "386"); $BF_ROUNDS=16; $BF_OFF=($BF_ROUNDS+2)*4; diff --git a/src/lib/libcrypto/bf/bf_cbc.c b/src/lib/libcrypto/bf/bf_cbc.c index e0fa9ad763..f949629dc6 100644 --- a/src/lib/libcrypto/bf/bf_cbc.c +++ b/src/lib/libcrypto/bf/bf_cbc.c @@ -56,16 +56,11 @@ * [including the GNU Public Licence.] */ -#include "blowfish.h" +#include #include "bf_locl.h" -void BF_cbc_encrypt(in, out, length, ks, iv, encrypt) -unsigned char *in; -unsigned char *out; -long length; -BF_KEY *ks; -unsigned char *iv; -int encrypt; +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; @@ -74,9 +69,9 @@ int encrypt; if (encrypt) { - n2l(iv,tout0); - n2l(iv,tout1); - iv-=8; + n2l(ivec,tout0); + n2l(ivec,tout1); + ivec-=8; for (l-=8; l>=0; l-=8) { n2l(in,tin0); @@ -85,7 +80,7 @@ int encrypt; tin1^=tout1; tin[0]=tin0; tin[1]=tin1; - BF_encrypt(tin,ks); + BF_encrypt(tin,schedule); tout0=tin[0]; tout1=tin[1]; l2n(tout0,out); @@ -98,27 +93,27 @@ int encrypt; tin1^=tout1; tin[0]=tin0; tin[1]=tin1; - BF_encrypt(tin,ks); + BF_encrypt(tin,schedule); tout0=tin[0]; tout1=tin[1]; l2n(tout0,out); l2n(tout1,out); } - l2n(tout0,iv); - l2n(tout1,iv); + l2n(tout0,ivec); + l2n(tout1,ivec); } else { - n2l(iv,xor0); - n2l(iv,xor1); - iv-=8; + 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,ks); + BF_decrypt(tin,schedule); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2n(tout0,out); @@ -132,15 +127,15 @@ int encrypt; n2l(in,tin1); tin[0]=tin0; tin[1]=tin1; - BF_decrypt(tin,ks); + BF_decrypt(tin,schedule); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2nn(tout0,tout1,out,l+8); xor0=tin0; xor1=tin1; } - l2n(xor0,iv); - l2n(xor1,iv); + l2n(xor0,ivec); + l2n(xor1,ivec); } tin0=tin1=tout0=tout1=xor0=xor1=0; tin[0]=tin[1]=0; diff --git a/src/lib/libcrypto/bf/bf_cfb64.c b/src/lib/libcrypto/bf/bf_cfb64.c index f9c66e7ced..6451c8d407 100644 --- a/src/lib/libcrypto/bf/bf_cfb64.c +++ b/src/lib/libcrypto/bf/bf_cfb64.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -#include "blowfish.h" +#include #include "bf_locl.h" /* The input and output encrypted as though 64bit cfb mode is being @@ -64,14 +64,8 @@ * 64bit block we have used is contained in *num; */ -void BF_cfb64_encrypt(in, out, length, schedule, ivec, num, encrypt) -unsigned char *in; -unsigned char *out; -long length; -BF_KEY *schedule; -unsigned char *ivec; -int *num; -int encrypt; +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num, int encrypt) { register BF_LONG v0,v1,t; register int n= *num; diff --git a/src/lib/libcrypto/bf/bf_ecb.c b/src/lib/libcrypto/bf/bf_ecb.c index 6d16360bd9..341991636f 100644 --- a/src/lib/libcrypto/bf/bf_ecb.c +++ b/src/lib/libcrypto/bf/bf_ecb.c @@ -56,17 +56,18 @@ * [including the GNU Public Licence.] */ -#include "blowfish.h" +#include #include "bf_locl.h" +#include /* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' - * (From LECTURE NOTES IN COIMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) */ -char *BF_version="BlowFish part of SSLeay 0.9.0b 29-Jun-1998"; +const char *BF_version="Blowfish" OPENSSL_VERSION_PTEXT; -char *BF_options() +const char *BF_options(void) { #ifdef BF_PTR return("blowfish(ptr)"); @@ -77,20 +78,17 @@ char *BF_options() #endif } -void BF_ecb_encrypt(in, out, ks, encrypt) -unsigned char *in; -unsigned char *out; -BF_KEY *ks; -int encrypt; +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,ks); + BF_encrypt(d,key); else - BF_decrypt(d,ks); + 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/src/lib/libcrypto/bf/bf_enc.c b/src/lib/libcrypto/bf/bf_enc.c index 66a8604c59..b380acf959 100644 --- a/src/lib/libcrypto/bf/bf_enc.c +++ b/src/lib/libcrypto/bf/bf_enc.c @@ -56,24 +56,24 @@ * [including the GNU Public Licence.] */ -#include "blowfish.h" +#include #include "bf_locl.h" /* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' - * (From LECTURE NOTES IN COIMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * (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) -If you set BF_ROUNDS to some value other than 16 or 20, you will have +#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(data,key) -BF_LONG *data; -BF_KEY *key; +void BF_encrypt(BF_LONG *data, const BF_KEY *key) { - register BF_LONG l,r,*p,*s; +#ifndef BF_PTR2 + register BF_LONG l,r; + const register BF_LONG *p,*s; p=key->P; s= &(key->S[0]); @@ -107,15 +107,50 @@ BF_KEY *key; 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(data,key) -BF_LONG *data; -BF_KEY *key; +void BF_decrypt(BF_LONG *data, const BF_KEY *key) { - register BF_LONG l,r,*p,*s; +#ifndef BF_PTR2 + register BF_LONG l,r; + const register BF_LONG *p,*s; p=key->P; s= &(key->S[0]); @@ -149,15 +184,45 @@ BF_KEY *key; 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(in, out, length, ks, iv, encrypt) -unsigned char *in; -unsigned char *out; -long length; -BF_KEY *ks; -unsigned char *iv; -int encrypt; +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; @@ -166,9 +231,9 @@ int encrypt; if (encrypt) { - n2l(iv,tout0); - n2l(iv,tout1); - iv-=8; + n2l(ivec,tout0); + n2l(ivec,tout1); + ivec-=8; for (l-=8; l>=0; l-=8) { n2l(in,tin0); @@ -177,7 +242,7 @@ int encrypt; tin1^=tout1; tin[0]=tin0; tin[1]=tin1; - BF_encrypt(tin,ks); + BF_encrypt(tin,schedule); tout0=tin[0]; tout1=tin[1]; l2n(tout0,out); @@ -190,27 +255,27 @@ int encrypt; tin1^=tout1; tin[0]=tin0; tin[1]=tin1; - BF_encrypt(tin,ks); + BF_encrypt(tin,schedule); tout0=tin[0]; tout1=tin[1]; l2n(tout0,out); l2n(tout1,out); } - l2n(tout0,iv); - l2n(tout1,iv); + l2n(tout0,ivec); + l2n(tout1,ivec); } else { - n2l(iv,xor0); - n2l(iv,xor1); - iv-=8; + 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,ks); + BF_decrypt(tin,schedule); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2n(tout0,out); @@ -224,15 +289,15 @@ int encrypt; n2l(in,tin1); tin[0]=tin0; tin[1]=tin1; - BF_decrypt(tin,ks); + BF_decrypt(tin,schedule); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2nn(tout0,tout1,out,l+8); xor0=tin0; xor1=tin1; } - l2n(xor0,iv); - l2n(xor1,iv); + l2n(xor0,ivec); + l2n(xor1,ivec); } tin0=tin1=tout0=tout1=xor0=xor1=0; tin[0]=tin[1]=0; diff --git a/src/lib/libcrypto/bf/bf_locl.h b/src/lib/libcrypto/bf/bf_locl.h index 05756b5d3b..cc7c3ec992 100644 --- a/src/lib/libcrypto/bf/bf_locl.h +++ b/src/lib/libcrypto/bf/bf_locl.h @@ -148,7 +148,7 @@ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff)) -/* This is actually a big endian algorithm, the most significate byte +/* This is actually a big endian algorithm, the most significant byte * is used to lookup array 0 */ #if defined(BF_PTR2) @@ -183,8 +183,8 @@ /* * This is normally very good on RISC platforms where normally you - * have to explicitely "multiplicate" array index by sizeof(BF_LONG) - * in order to caclulate the effective address. This implementation + * have to explicitly "multiply" array index by sizeof(BF_LONG) + * in order to calculate the effective address. This implementation * excuses CPU from this extra work. Power[PC] uses should have most * fun as (R>>BF_i)&BF_M gets folded into a single instruction, namely * rlwinm. So let'em double-check if their compiler does it. diff --git a/src/lib/libcrypto/bf/bf_ofb64.c b/src/lib/libcrypto/bf/bf_ofb64.c index 5d844ac760..f2a9ff6e41 100644 --- a/src/lib/libcrypto/bf/bf_ofb64.c +++ b/src/lib/libcrypto/bf/bf_ofb64.c @@ -56,20 +56,15 @@ * [including the GNU Public Licence.] */ -#include "blowfish.h" +#include #include "bf_locl.h" /* The input and output encrypted as though 64bit ofb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ -void BF_ofb64_encrypt(in, out, length, schedule, ivec, num) -unsigned char *in; -unsigned char *out; -long length; -BF_KEY *schedule; -unsigned char *ivec; -int *num; +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num) { register BF_LONG v0,v1,t; register int n= *num; diff --git a/src/lib/libcrypto/bf/bf_pi.h b/src/lib/libcrypto/bf/bf_pi.h index 417b935538..9949513c68 100644 --- a/src/lib/libcrypto/bf/bf_pi.h +++ b/src/lib/libcrypto/bf/bf_pi.h @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -static BF_KEY bf_init= { +static const BF_KEY bf_init= { { 0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, 0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, diff --git a/src/lib/libcrypto/bf/bf_skey.c b/src/lib/libcrypto/bf/bf_skey.c index 86574c0acc..3673cdee6e 100644 --- a/src/lib/libcrypto/bf/bf_skey.c +++ b/src/lib/libcrypto/bf/bf_skey.c @@ -58,21 +58,18 @@ #include #include -#include "blowfish.h" +#include #include "bf_locl.h" #include "bf_pi.h" -void BF_set_key(key,len,data) -BF_KEY *key; -int len; -unsigned char *data; +void BF_set_key(BF_KEY *key, int len, const unsigned char *data) { int i; BF_LONG *p,ri,in[2]; - unsigned char *d,*end; + const unsigned char *d,*end; - memcpy((char *)key,(char *)&bf_init,sizeof(BF_KEY)); + memcpy(key,&bf_init,sizeof(BF_KEY)); p=key->P; if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4; diff --git a/src/lib/libcrypto/bf/blowfish.h b/src/lib/libcrypto/bf/blowfish.h index c4a8085a29..cd49e85ab2 100644 --- a/src/lib/libcrypto/bf/blowfish.h +++ b/src/lib/libcrypto/bf/blowfish.h @@ -59,18 +59,41 @@ #ifndef HEADER_BLOWFISH_H #define HEADER_BLOWFISH_H +#include + #ifdef __cplusplus extern "C" { #endif +#ifdef OPENSSL_NO_BF +#error BF is disabled. +#endif + #define BF_ENCRYPT 1 #define BF_DECRYPT 0 -/* If you make this 'unsigned int' the pointer variants will work on - * the Alpha, otherwise they will not. Strangly using the '8 byte' - * BF_LONG and the default 'non-pointer' inner loop is the best configuration - * for the Alpha */ +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! 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(OPENSSL_SYS_WIN16) || defined(__LP32__) +#define BF_LONG unsigned long +#elif defined(OPENSSL_SYS_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... + * + */ +#else +#define BF_LONG unsigned int +#endif #define BF_ROUNDS 16 #define BF_BLOCK 8 @@ -81,33 +104,21 @@ typedef struct bf_key_st BF_LONG S[4*256]; } BF_KEY; -#ifndef NOPROTO -void BF_set_key(BF_KEY *key, int len, unsigned char *data); -void BF_ecb_encrypt(unsigned char *in,unsigned char *out,BF_KEY *key, - int enc); -void BF_encrypt(BF_LONG *data,BF_KEY *key); -void BF_decrypt(BF_LONG *data,BF_KEY *key); -void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length, - BF_KEY *ks, unsigned char *iv, int enc); -void BF_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, - BF_KEY *schedule, unsigned char *ivec, int *num, int enc); -void BF_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, - BF_KEY *schedule, unsigned char *ivec, int *num); -char *BF_options(void); +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); -#else - -void BF_set_key(); -void BF_ecb_encrypt(); -void BF_encrypt(); -void BF_decrypt(); -void BF_cbc_encrypt(); -void BF_cfb64_encrypt(); -void BF_ofb64_encrypt(); -char *BF_options(); +void BF_encrypt(BF_LONG *data,const BF_KEY *key); +void BF_decrypt(BF_LONG *data,const BF_KEY *key); -#endif +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 } diff --git a/src/lib/libcrypto/bio/b_dump.c b/src/lib/libcrypto/bio/b_dump.c index db84ad3d47..8397cfab6a 100644 --- a/src/lib/libcrypto/bio/b_dump.c +++ b/src/lib/libcrypto/bio/b_dump.c @@ -62,64 +62,91 @@ #include #include "cryptlib.h" -#include "bio.h" +#include #define TRUNCATE #define DUMP_WIDTH 16 +#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH-((i-(i>6?6:i)+3)/4)) -int BIO_dump(bio,s,len) -BIO *bio; -char *s; -int len; -{ - int ret=0; - char buf[160+1],tmp[20]; - int i,j,rows,trunc; - unsigned char ch; - - trunc=0; +int BIO_dump(BIO *bio, const char *s, int len) + { + return BIO_dump_indent(bio, s, len, 0); + } +int BIO_dump_indent(BIO *bio, const char *s, int len, int indent) + { + int ret=0; + char buf[288+1],tmp[20],str[128+1]; + int i,j,rows,trunc; + unsigned char ch; + int dump_width; + + trunc=0; + #ifdef TRUNCATE - for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--) - trunc++; + for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--) + trunc++; #endif - rows=(len/DUMP_WIDTH); - if ((rows*DUMP_WIDTH)=len) { - strcat(buf," "); - } else { - ch=((unsigned char)*((char *)(s)+i*DUMP_WIDTH+j)) & 0xff; - sprintf(tmp,"%02x%c",ch,j==7?'-':' '); - strcat(buf,tmp); - } - } - strcat(buf," "); - for(j=0;j=len) - break; - ch=((unsigned char)*((char *)(s)+i*DUMP_WIDTH+j)) & 0xff; - sprintf(tmp,"%c",((ch>=' ')&&(ch<='~'))?ch:'.'); - strcat(buf,tmp); - } - strcat(buf,"\n"); - /* if this is the last call then update the ddt_dump thing so that - * we will move the selection point in the debug window - */ - ret+=BIO_write(bio,(char *)buf,strlen(buf)); - } + if (indent < 0) + indent = 0; + if (indent) + { + if (indent > 128) indent=128; + memset(str,' ',indent); + } + str[indent]='\0'; + + dump_width=DUMP_WIDTH_LESS_INDENT(indent); + rows=(len/dump_width); + if ((rows*dump_width)=len) + { + strcat(buf," "); + } + else + { + ch=((unsigned char)*(s+i*dump_width+j)) & 0xff; + sprintf(tmp,"%02x%c",ch,j==7?'-':' '); + strcat(buf,tmp); + } + } + strcat(buf," "); + for(j=0;j=len) + break; + ch=((unsigned char)*(s+i*dump_width+j)) & 0xff; +#ifndef CHARSET_EBCDIC + sprintf(tmp,"%c",((ch>=' ')&&(ch<='~'))?ch:'.'); +#else + sprintf(tmp,"%c",((ch>=os_toascii[' '])&&(ch<=os_toascii['~'])) + ? os_toebcdic[ch] + : '.'); +#endif + strcat(buf,tmp); + } + strcat(buf,"\n"); + /* if this is the last call then update the ddt_dump thing so that + * we will move the selection point in the debug window + */ + ret+=BIO_write(bio,(char *)buf,strlen(buf)); + } #ifdef TRUNCATE - if (trunc > 0) { - sprintf(buf,"%04x - \n",len+trunc); - ret+=BIO_write(bio,(char *)buf,strlen(buf)); - } + if (trunc > 0) + { + sprintf(buf,"%s%04x - \n",str,len+trunc); + ret+=BIO_write(bio,(char *)buf,strlen(buf)); + } #endif - return(ret); -} - + return(ret); + } diff --git a/src/lib/libcrypto/bio/b_print.c b/src/lib/libcrypto/bio/b_print.c index cdadeb839a..3ce1290772 100644 --- a/src/lib/libcrypto/bio/b_print.c +++ b/src/lib/libcrypto/bio/b_print.c @@ -56,37 +56,774 @@ * [including the GNU Public Licence.] */ +/* disable assert() unless BIO_DEBUG has been defined */ +#ifndef BIO_DEBUG +# ifndef NDEBUG +# define NDEBUG +# endif +#endif + /* * Stolen from tjh's ssl/ssl_trc.c stuff. */ #include +#include +#include +#include +#include #include "cryptlib.h" -#include "bio.h" +#ifndef NO_SYS_TYPES_H +#include +#endif +#include /* To get BN_LLONG properly defined */ +#include + +#ifdef BN_LLONG +# ifndef HAVE_LONG_LONG +# define HAVE_LONG_LONG 1 +# endif +#endif + +/***************************************************************************/ + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions. + */ + +/* + * This code contains numerious changes and enhancements which were + * made by lots of contributors over the last years to Patrick Powell's + * original code: + * + * o Patrick Powell (1995) + * o Brandon Long (1996, for Mutt) + * o Thomas Roessler (1998, for Mutt) + * o Michael Elkins (1998, for Mutt) + * o Andrew Tridgell (1998, for Samba) + * o Luke Mewburn (1999, for LukemFTP) + * o Ralf S. Engelschall (1999, for Pth) + * o ... (for OpenSSL) + */ + +#if HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#if HAVE_LONG_LONG +# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) +# define LLONG _int64 +# else +# define LLONG long long +# endif +#else +#define LLONG long +#endif + +static void fmtstr (char **, char **, size_t *, size_t *, + const char *, int, int, int); +static void fmtint (char **, char **, size_t *, size_t *, + LLONG, int, int, int, int); +static void fmtfp (char **, char **, size_t *, size_t *, + LDOUBLE, int, int, int); +static void doapr_outch (char **, char **, size_t *, size_t *, int); +static void _dopr(char **sbuffer, char **buffer, + size_t *maxlen, size_t *retlen, int *truncated, + const char *format, va_list args); + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* conversion flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +/* some handy macros */ +#define char_to_int(p) (p - '0') +#define OSSL_MAX(p,q) ((p >= q) ? p : q) + +static void +_dopr( + char **sbuffer, + char **buffer, + size_t *maxlen, + size_t *retlen, + int *truncated, + const char *format, + va_list args) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + flags = currlen = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) + state = DP_S_DONE; + + switch (state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + doapr_outch(sbuffer,buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10 * min + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg(args, int); + ch = *format++; + state = DP_S_DOT; + } else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10 * max + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg(args, int); + ch = *format++; + state = DP_S_MOD; + } else + state = DP_S_MOD; + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + if (*format == 'l') { + cflags = DP_C_LLONG; + format++; + } else + cflags = DP_C_LONG; + ch = *format++; + break; + case 'q': + cflags = DP_C_LLONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + switch (cflags) { + case DP_C_SHORT: + value = (short int)va_arg(args, int); + break; + case DP_C_LONG: + value = va_arg(args, long int); + break; + case DP_C_LLONG: + value = va_arg(args, LLONG); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(sbuffer, buffer, &currlen, maxlen, + value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + /* FALLTHROUGH */ + case 'x': + case 'o': + case 'u': + flags |= DP_F_UNSIGNED; + switch (cflags) { + case DP_C_SHORT: + value = (unsigned short int)va_arg(args, unsigned int); + break; + case DP_C_LONG: + value = (LLONG) va_arg(args, + unsigned long int); + break; + case DP_C_LLONG: + value = va_arg(args, unsigned LLONG); + break; + default: + value = (LLONG) va_arg(args, + unsigned int); + break; + } + fmtint(sbuffer, buffer, &currlen, maxlen, value, + ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), + min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtfp(sbuffer, buffer, &currlen, maxlen, + fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + break; + case 'c': + doapr_outch(sbuffer, buffer, &currlen, maxlen, + va_arg(args, int)); + break; + case 's': + strvalue = va_arg(args, char *); + if (max < 0) { + if (buffer) + max = INT_MAX; + else + max = *maxlen; + } + fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, + flags, min, max); + break; + case 'p': + value = (long)va_arg(args, void *); + fmtint(sbuffer, buffer, &currlen, maxlen, + value, 16, min, max, flags); + break; + case 'n': /* XXX */ + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg(args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { /* XXX */ + long int *num; + num = va_arg(args, long int *); + *num = (long int) currlen; + } else if (cflags == DP_C_LLONG) { /* XXX */ + LLONG *num; + num = va_arg(args, LLONG *); + *num = (LLONG) currlen; + } else { + int *num; + num = va_arg(args, int *); + *num = currlen; + } + break; + case '%': + doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + break; + } + } + *truncated = (currlen > *maxlen - 1); + if (*truncated) + currlen = *maxlen - 1; + doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); + *retlen = currlen - 1; + return; +} + +static void +fmtstr( + char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, + const char *value, + int flags, + int min, + int max) +{ + int padlen, strln; + int cnt = 0; + + if (value == 0) + value = ""; + for (strln = 0; value[strln]; ++strln) + ; + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + while ((padlen > 0) && (cnt < max)) { + doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +static void +fmtint( + char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, + LLONG value, + int base, + int min, + int max, + int flags) +{ + int signvalue = 0; + unsigned LLONG uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; + int zpadlen = 0; + int caps = 0; + + if (max < 0) + max = 0; + uvalue = value; + if (!(flags & DP_F_UNSIGNED)) { + if (value < 0) { + signvalue = '-'; + uvalue = -value; + } else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + if (flags & DP_F_UP) + caps = 1; + do { + convert[place++] = + (caps ? "0123456789ABCDEF" : "0123456789abcdef") + [uvalue % (unsigned) base]; + uvalue = (uvalue / (unsigned) base); + } while (uvalue && (place < 20)); + if (place == 20) + place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = OSSL_MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; + + /* spaces */ + while (spadlen > 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* sign */ + if (signvalue) + doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); + + /* zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + /* digits */ + while (place > 0) + doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); + + /* left justified spaces */ + while (spadlen < 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + ++spadlen; + } + return; +} + +static LDOUBLE +abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + if (value < 0) + result = -value; + return result; +} + +static LDOUBLE +pow10(int exp) +{ + LDOUBLE result = 1; + while (exp) { + result *= 10; + exp--; + } + return result; +} + +static long +roundv(LDOUBLE value) +{ + long intpart; + intpart = (long) value; + value = value - intpart; + if (value >= 0.5) + intpart++; + return intpart; +} + +static void +fmtfp( + char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, + LDOUBLE fvalue, + int min, + int max, + int flags) +{ + int signvalue = 0; + LDOUBLE ufvalue; + char iconvert[20]; + char fconvert[20]; + int iplace = 0; + int fplace = 0; + int padlen = 0; + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + + if (max < 0) + max = 6; + ufvalue = abs_val(fvalue); + if (fvalue < 0) + signvalue = '-'; + else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; -int BIO_printf ( VAR_PLIST( BIO *, bio ) ) -VAR_ALIST + intpart = (long)ufvalue; + + /* sorry, we only support 9 digits past the decimal because of our + conversion method */ + if (max > 9) + max = 9; + + /* we "cheat" by converting the fractional part to integer by + multiplying by a factor of 10 */ + fracpart = roundv((pow10(max)) * (ufvalue - intpart)); + + if (fracpart >= pow10(max)) { + intpart++; + fracpart -= (long)pow10(max); + } + + /* convert integer part */ + do { + iconvert[iplace++] = + (caps ? "0123456789ABCDEF" + : "0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while (intpart && (iplace < 20)); + if (iplace == 20) + iplace--; + iconvert[iplace] = 0; + + /* convert fractional part */ + do { + fconvert[fplace++] = + (caps ? "0123456789ABCDEF" + : "0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + } while (fplace < max); + if (fplace == 20) + fplace--; + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); + + while (fplace > 0) + doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); + } + while (zpadlen > 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (padlen < 0) { + doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void +doapr_outch( + char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, + int c) +{ + /* If we haven't at least one buffer, someone has doe a big booboo */ + assert(*sbuffer != NULL || buffer != NULL); + + if (buffer) { + while (*currlen >= *maxlen) { + if (*buffer == NULL) { + if (*maxlen == 0) + *maxlen = 1024; + *buffer = OPENSSL_malloc(*maxlen); + if (*currlen > 0) { + assert(*sbuffer != NULL); + memcpy(*buffer, *sbuffer, *currlen); + } + *sbuffer = NULL; + } else { + *maxlen += 1024; + *buffer = OPENSSL_realloc(*buffer, *maxlen); + } + } + /* What to do if *buffer is NULL? */ + assert(*sbuffer != NULL || *buffer != NULL); + } + + if (*currlen < *maxlen) { + if (*sbuffer) + (*sbuffer)[(*currlen)++] = (char)c; + else + (*buffer)[(*currlen)++] = (char)c; + } + + return; +} + +/***************************************************************************/ + +int BIO_printf (BIO *bio, const char *format, ...) { - VAR_BDEFN(args, BIO *, bio); - char *format; + va_list args; int ret; - MS_STATIC char hugebuf[1024*2]; /* 10k in one chunk is the limit */ - VAR_INIT(args, BIO *, bio); - VAR_ARG(args, char *, format); + va_start(args, format); - hugebuf[0]='\0'; + ret = BIO_vprintf(bio, format, args); -/* no-one uses _doprnt anymore and it appears to be broken under SunOS 4.1.4 */ -#if 0 && defined(sun) && !defined(VAR_ANSI) /**/ - _doprnt(hugebuf,format,args); -#else /* !sun */ - vsprintf(hugebuf,format,args); -#endif /* sun */ + va_end(args); + return(ret); + } - ret=BIO_write(bio,hugebuf,strlen(hugebuf)); +int BIO_vprintf (BIO *bio, const char *format, va_list args) + { + int ret; + size_t retlen; + char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable + in small-stack environments, like threads + or DOS programs. */ + char *hugebufp = hugebuf; + size_t hugebufsize = sizeof(hugebuf); + char *dynbuf = NULL; + int ignored; - VAR_END( args ); + dynbuf = NULL; + CRYPTO_push_info("doapr()"); + _dopr(&hugebufp, &dynbuf, &hugebufsize, + &retlen, &ignored, format, args); + if (dynbuf) + { + ret=BIO_write(bio, dynbuf, (int)retlen); + OPENSSL_free(dynbuf); + } + else + { + ret=BIO_write(bio, hugebuf, (int)retlen); + } + CRYPTO_pop_info(); return(ret); } +/* As snprintf is not available everywhere, we provide our own implementation. + * This function has nothing to do with BIOs, but it's closely related + * to BIO_printf, and we need *some* name prefix ... + * (XXX the function should be renamed, but to what?) */ +int BIO_snprintf(char *buf, size_t n, const char *format, ...) + { + va_list args; + int ret; + + va_start(args, format); + + ret = BIO_vsnprintf(buf, n, format, args); + + va_end(args); + return(ret); + } + +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) + { + size_t retlen; + int truncated; + + _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); + + if (truncated) + /* In case of truncation, return -1 like traditional snprintf. + * (Current drafts for ISO/IEC 9899 say snprintf should return + * the number of characters that would have been written, + * had the buffer been large enough.) */ + return -1; + else + return (retlen <= INT_MAX) ? retlen : -1; + } diff --git a/src/lib/libcrypto/bio/b_sock.c b/src/lib/libcrypto/bio/b_sock.c index a45909527c..dcaef68ea7 100644 --- a/src/lib/libcrypto/bio/b_sock.c +++ b/src/lib/libcrypto/bio/b_sock.c @@ -56,32 +56,30 @@ * [including the GNU Public Licence.] */ -#ifndef NO_SOCK +#ifndef OPENSSL_NO_SOCK #include #include #include #define USE_SOCKETS #include "cryptlib.h" -#include "bio.h" +#include -/* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */ - -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ #else #define SOCKET_PROTOCOL IPPROTO_TCP #endif #ifdef SO_MAXCONN -#define MAX_LISTEN SOMAXCONN -#elif defined(SO_MAXCONN) #define MAX_LISTEN SO_MAXCONN +#elif defined(SOMAXCONN) +#define MAX_LISTEN SOMAXCONN #else #define MAX_LISTEN 32 #endif -#ifdef WINDOWS +#ifdef OPENSSL_SYS_WINDOWS static int wsa_init_done=0; #endif @@ -96,59 +94,67 @@ static struct ghbn_cache_st unsigned long order; } ghbn_cache[GHBN_NUM]; -#ifndef NOPROTO -static int get_ip(char *str,unsigned char *ip); +static int get_ip(const char *str,unsigned char *ip); +#if 0 static void ghbn_free(struct hostent *a); static struct hostent *ghbn_dup(struct hostent *a); -#else -static int get_ip(); -static void ghbn_free(); -static struct hostent *ghbn_dup(); #endif - -int BIO_get_host_ip(str,ip) -char *str; -unsigned char *ip; +int BIO_get_host_ip(const char *str, unsigned char *ip) { int i; + int err = 1; + int locked = 0; struct hostent *he; i=get_ip(str,ip); - if (i > 0) return(1); if (i < 0) { BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); - ERR_add_error_data(2,"host=",str); - return(0); + goto err; } - else - { /* do a gethostbyname */ - if (!BIO_sock_init()) return(0); - he=BIO_gethostbyname(str); - if (he == NULL) - { - BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); - ERR_add_error_data(2,"host=",str); - return(0); - } + /* At this point, we have something that is most probably correct + in some way, so let's init the socket. */ + if (BIO_sock_init() != 1) + return 0; /* don't generate another error code here */ - /* cast to short because of win16 winsock definition */ - if ((short)he->h_addrtype != AF_INET) - { - BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); - ERR_add_error_data(2,"host=",str); - return(0); - } - for (i=0; i<4; i++) - ip[i]=he->h_addr_list[0][i]; + /* If the string actually contained an IP address, we need not do + anything more */ + if (i > 0) return(1); + + /* do a gethostbyname */ + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); + locked = 1; + he=BIO_gethostbyname(str); + if (he == NULL) + { + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); + goto err; } - return(1); + + /* cast to short because of win16 winsock definition */ + if ((short)he->h_addrtype != AF_INET) + { + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); + goto err; + } + for (i=0; i<4; i++) + ip[i]=he->h_addr_list[0][i]; + err = 0; + + err: + if (locked) + CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); + if (err) + { + ERR_add_error_data(2,"host=",str); + return 0; + } + else + return 1; } -int BIO_get_port(str,port_ptr) -char *str; -short *port_ptr; +int BIO_get_port(const char *str, unsigned short *port_ptr) { int i; struct servent *s; @@ -163,8 +169,19 @@ short *port_ptr; *port_ptr=(unsigned short)i; else { - s=getservbyname(str,"tcp"); - if (s == NULL) + CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); + /* Note: under VMS with SOCKETSHR, it seems like the first + * parameter is 'char *', instead of 'const char *' + */ + s=getservbyname( +#ifndef CONST_STRICT + (char *) +#endif + str,"tcp"); + if(s != NULL) + *port_ptr=ntohs((unsigned short)s->s_port); + CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); + if(s == NULL) { if (strcmp(str,"http") == 0) *port_ptr=80; @@ -190,31 +207,30 @@ short *port_ptr; ERR_add_error_data(3,"service='",str,"'"); return(0); } - return(1); } - *port_ptr=htons((unsigned short)s->s_port); } return(1); } -int BIO_sock_error(sock) -int sock; +int BIO_sock_error(int sock) { - int j,i,size; + int j,i; + int size; size=sizeof(int); - - i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size); + /* Note: under Windows the third parameter is of type (char *) + * whereas under other systems it is (void *) if you don't have + * a cast it will choke the compiler: if you do have a cast then + * you can either go for (char *) or (void *). + */ + i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); if (i < 0) return(1); else return(j); } -long BIO_ghbn_ctrl(cmd,iarg,parg) -int cmd; -int iarg; -char *parg; +long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) { int i; char **p; @@ -223,13 +239,13 @@ char *parg; { case BIO_GHBN_CTRL_HITS: return(BIO_ghbn_hits); - break; + /* break; */ case BIO_GHBN_CTRL_MISSES: return(BIO_ghbn_miss); - break; + /* break; */ case BIO_GHBN_CTRL_CACHE_SIZE: return(GHBN_NUM); - break; + /* break; */ case BIO_GHBN_CTRL_GET_ENTRY: if ((iarg >= 0) && (iarg 0)) @@ -241,7 +257,7 @@ char *parg; return(1); } return(0); - break; + /* break; */ case BIO_GHBN_CTRL_FLUSH: for (i=0; ih_aliases[i] != NULL; i++) ; i++; - ret->h_aliases=(char **)malloc(sizeof(char *)*i); - memset(ret->h_aliases,0,sizeof(char *)*i); - if (ret == NULL) goto err; + ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *)); + if (ret->h_aliases == NULL) + goto err; + memset(ret->h_aliases, 0, i*sizeof(char *)); for (i=0; a->h_addr_list[i] != NULL; i++) ; i++; - ret->h_addr_list=(char **)malloc(sizeof(char *)*i); - memset(ret->h_addr_list,0,sizeof(char *)*i); - if (ret->h_addr_list == NULL) goto err; + ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *)); + if (ret->h_addr_list == NULL) + goto err; + memset(ret->h_addr_list, 0, i*sizeof(char *)); j=strlen(a->h_name)+1; - if ((ret->h_name=malloc(j)) == NULL) goto err; + if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err; memcpy((char *)ret->h_name,a->h_name,j); for (i=0; a->h_aliases[i] != NULL; i++) { j=strlen(a->h_aliases[i])+1; - if ((ret->h_aliases[i]=malloc(j)) == NULL) goto err; + if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err; memcpy(ret->h_aliases[i],a->h_aliases[i],j); } ret->h_length=a->h_length; ret->h_addrtype=a->h_addrtype; for (i=0; a->h_addr_list[i] != NULL; i++) { - if ((ret->h_addr_list[i]=malloc(a->h_length)) == NULL) + if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL) goto err; memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); } - return(ret); + if (0) + { err: - if (ret != NULL) - ghbn_free(ret); - return(NULL); + if (ret != NULL) + ghbn_free(ret); + ret=NULL; + } + MemCheck_on(); + return(ret); } -static void ghbn_free(a) -struct hostent *a; +static void ghbn_free(struct hostent *a) { int i; + if(a == NULL) + return; + if (a->h_aliases != NULL) { for (i=0; a->h_aliases[i] != NULL; i++) - free(a->h_aliases[i]); - free(a->h_aliases); + OPENSSL_free(a->h_aliases[i]); + OPENSSL_free(a->h_aliases); } if (a->h_addr_list != NULL) { for (i=0; a->h_addr_list[i] != NULL; i++) - free(a->h_addr_list[i]); - free(a->h_addr_list); + OPENSSL_free(a->h_addr_list[i]); + OPENSSL_free(a->h_addr_list); } - if (a->h_name != NULL) free((char *)a->h_name); - free(a); + if (a->h_name != NULL) OPENSSL_free(a->h_name); + OPENSSL_free(a); } -struct hostent *BIO_gethostbyname(name) -char *name; +#endif + +struct hostent *BIO_gethostbyname(const char *name) { +#if 1 + /* Caching gethostbyname() results forever is wrong, + * so we have to let the true gethostbyname() worry about this */ + return gethostbyname(name); +#else struct hostent *ret; int i,lowi=0,j; unsigned long low= (unsigned long)-1; -/* return(gethostbyname(name)); */ - CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); +# if 0 + /* It doesn't make sense to use locking here: The function interface + * is not thread-safe, because threads can never be sure when + * some other thread destroys the data they were given a pointer to. + */ + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); +# endif j=strlen(name); if (j < 128) { @@ -354,17 +390,39 @@ char *name; if (i == GHBN_NUM) /* no hit*/ { BIO_ghbn_miss++; - ret=gethostbyname(name); - - if (ret == NULL) return(NULL); - if (j > 128) return(ret); /* too big to cache */ + /* Note: under VMS with SOCKETSHR, it seems like the first + * parameter is 'char *', instead of 'const char *' + */ + ret=gethostbyname( +# ifndef CONST_STRICT + (char *) +# endif + name); + + if (ret == NULL) + goto end; + if (j > 128) /* too big to cache */ + { +# if 0 + /* If we were trying to make this function thread-safe (which + * is bound to fail), we'd have to give up in this case + * (or allocate more memory). */ + ret = NULL; +# endif + goto end; + } /* else add to cache */ if (ghbn_cache[lowi].ent != NULL) - ghbn_free(ghbn_cache[lowi].ent); + ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ + ghbn_cache[lowi].name[0] = '\0'; + if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL) + { + BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE); + goto end; + } strncpy(ghbn_cache[lowi].name,name,128); - ghbn_cache[lowi].ent=ghbn_dup(ret); ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; } else @@ -373,13 +431,18 @@ char *name; ret= ghbn_cache[i].ent; ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; } - CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); +end: +# if 0 + CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); +# endif return(ret); +#endif } -int BIO_sock_init() + +int BIO_sock_init(void) { -#ifdef WINDOWS +#ifdef OPENSSL_SYS_WINDOWS static struct WSAData wsa_state; if (!wsa_init_done) @@ -399,13 +462,13 @@ int BIO_sock_init() return(-1); } } -#endif /* WINDOWS */ +#endif /* OPENSSL_SYS_WINDOWS */ return(1); } -void BIO_sock_cleanup() +void BIO_sock_cleanup(void) { -#ifdef WINDOWS +#ifdef OPENSSL_SYS_WINDOWS if (wsa_init_done) { wsa_init_done=0; @@ -415,10 +478,9 @@ void BIO_sock_cleanup() #endif } -int BIO_socket_ioctl(fd,type,arg) -int fd; -long type; -unsigned long *arg; +#if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 + +int BIO_socket_ioctl(int fd, long type, unsigned long *arg) { int i; @@ -427,12 +489,11 @@ unsigned long *arg; SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); return(i); } +#endif /* __VMS_VER */ /* The reason I have implemented this instead of using sscanf is because * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ -static int get_ip(str,ip) -char *str; -unsigned char ip[4]; +static int get_ip(const char *str, unsigned char ip[4]) { unsigned int tmp[4]; int num=0,c,ok=0; @@ -446,16 +507,16 @@ unsigned char ip[4]; { ok=1; tmp[num]=tmp[num]*10+c-'0'; - if (tmp[num] > 255) return(-1); + if (tmp[num] > 255) return(0); } else if (c == '.') { if (!ok) return(-1); - if (num == 3) break; + if (num == 3) return(0); num++; ok=0; } - else if ((num == 3) && ok) + else if (c == '\0' && (num == 3) && ok) break; else return(0); @@ -467,18 +528,19 @@ unsigned char ip[4]; return(1); } -int BIO_get_accept_socket(host) -char *host; +int BIO_get_accept_socket(char *host, int bind_mode) { int ret=0; - struct sockaddr_in server; - int s= -1; + struct sockaddr_in server,client; + int s=INVALID_SOCKET,cs; unsigned char ip[4]; - short port; - char *str,*h,*p,*e; + unsigned short port; + char *str=NULL,*e; + const char *h,*p; unsigned long l; + int err_num; - if (!BIO_sock_init()) return(INVALID_SOCKET); + if (BIO_sock_init() != 1) return(INVALID_SOCKET); if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); @@ -504,25 +566,26 @@ char *host; h="*"; } - if (!BIO_get_port(p,&port)) return(INVALID_SOCKET); + if (!BIO_get_port(p,&port)) goto err; memset((char *)&server,0,sizeof(server)); server.sin_family=AF_INET; - server.sin_port=htons((unsigned short)port); + server.sin_port=htons(port); if (strcmp(h,"*") == 0) server.sin_addr.s_addr=INADDR_ANY; else { - if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET); + if (!BIO_get_host_ip(h,&(ip[0]))) goto err; l=(unsigned long) ((unsigned long)ip[0]<<24L)| - ((unsigned long)ip[0]<<16L)| - ((unsigned long)ip[0]<< 8L)| - ((unsigned long)ip[0]); + ((unsigned long)ip[1]<<16L)| + ((unsigned long)ip[2]<< 8L)| + ((unsigned long)ip[3]); server.sin_addr.s_addr=htonl(l); } +again: s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); if (s == INVALID_SOCKET) { @@ -531,9 +594,45 @@ char *host; BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); goto err; } + +#ifdef SO_REUSEADDR + if (bind_mode == BIO_BIND_REUSEADDR) + { + int i=1; + + ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); + bind_mode=BIO_BIND_NORMAL; + } +#endif if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) { - SYSerr(SYS_F_BIND,get_last_socket_error()); +#ifdef SO_REUSEADDR + err_num=get_last_socket_error(); + if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && + (err_num == EADDRINUSE)) + { + memcpy((char *)&client,(char *)&server,sizeof(server)); + if (strcmp(h,"*") == 0) + client.sin_addr.s_addr=htonl(0x7F000001); + cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + if (cs != INVALID_SOCKET) + { + int ii; + ii=connect(cs,(struct sockaddr *)&client, + sizeof(client)); + closesocket(cs); + if (ii == INVALID_SOCKET) + { + bind_mode=BIO_BIND_REUSEADDR; + closesocket(s); + goto again; + } + /* else error */ + } + /* else error */ + } +#endif + SYSerr(SYS_F_BIND,err_num); ERR_add_error_data(3,"port='",host,"'"); BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); goto err; @@ -547,35 +646,35 @@ char *host; } ret=1; err: - if (str != NULL) Free(str); + if (str != NULL) OPENSSL_free(str); if ((ret == 0) && (s != INVALID_SOCKET)) { -#ifdef WINDOWS closesocket(s); -#else - close(s); -#endif s= INVALID_SOCKET; } return(s); } -int BIO_accept(sock,addr) -int sock; -char **addr; +int BIO_accept(int sock, char **addr) { int ret=INVALID_SOCKET; static struct sockaddr_in from; unsigned long l; - short port; + unsigned short port; int len; char *p; memset((char *)&from,0,sizeof(from)); len=sizeof(from); - ret=accept(sock,(struct sockaddr *)&from,&len); + /* Note: under VMS with SOCKETSHR the fourth parameter is currently + * of type (int *) whereas under other systems it is (void *) if + * you don't have a cast it will choke the compiler: if you do + * have a cast then you can either go for (int *) or (void *). + */ + ret=accept(sock,(struct sockaddr *)&from,(void *)&len); if (ret == INVALID_SOCKET) { + if(BIO_sock_should_retry(ret)) return -2; SYSerr(SYS_F_ACCEPT,get_last_socket_error()); BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); goto end; @@ -587,7 +686,7 @@ char **addr; port=ntohs(from.sin_port); if (*addr == NULL) { - if ((p=Malloc(24)) == NULL) + if ((p=OPENSSL_malloc(24)) == NULL) { BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); goto end; @@ -604,9 +703,7 @@ end: return(ret); } -int BIO_set_tcp_ndelay(s,on) -int s; -int on; +int BIO_set_tcp_ndelay(int s, int on) { int ret=0; #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) @@ -626,3 +723,14 @@ int on; } #endif +int BIO_socket_nbio(int s, int mode) + { + int ret= -1; + unsigned long l; + + l=mode; +#ifdef FIONBIO + ret=BIO_socket_ioctl(s,FIONBIO,&l); +#endif + return(ret == 0); + } diff --git a/src/lib/libcrypto/bio/bf_buff.c b/src/lib/libcrypto/bio/bf_buff.c index 7912b88473..6ccda06596 100644 --- a/src/lib/libcrypto/bio/bf_buff.c +++ b/src/lib/libcrypto/bio/bf_buff.c @@ -59,28 +59,17 @@ #include #include #include "cryptlib.h" -#include "bio.h" -#include "evp.h" - -#ifndef NOPROTO -static int buffer_write(BIO *h,char *buf,int num); -static int buffer_read(BIO *h,char *buf,int size); -static int buffer_puts(BIO *h,char *str); -static int buffer_gets(BIO *h,char *str,int size); -static long buffer_ctrl(BIO *h,int cmd,long arg1,char *arg2); +#include + +static int buffer_write(BIO *h, const char *buf,int num); +static int buffer_read(BIO *h, char *buf, int size); +static int buffer_puts(BIO *h, const char *str); +static int buffer_gets(BIO *h, char *str, int size); +static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int buffer_new(BIO *h); static int buffer_free(BIO *data); -#else -static int buffer_write(); -static int buffer_read(); -static int buffer_puts(); -static int buffer_gets(); -static long buffer_ctrl(); -static int buffer_new(); -static int buffer_free(); -#endif - -#define DEFAULT_BUFFER_SIZE 1024 +static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +#define DEFAULT_BUFFER_SIZE 4096 static BIO_METHOD methods_buffer= { @@ -93,24 +82,24 @@ static BIO_METHOD methods_buffer= buffer_ctrl, buffer_new, buffer_free, + buffer_callback_ctrl, }; -BIO_METHOD *BIO_f_buffer() +BIO_METHOD *BIO_f_buffer(void) { return(&methods_buffer); } -static int buffer_new(bi) -BIO *bi; +static int buffer_new(BIO *bi) { BIO_F_BUFFER_CTX *ctx; - ctx=(BIO_F_BUFFER_CTX *)Malloc(sizeof(BIO_F_BUFFER_CTX)); + ctx=(BIO_F_BUFFER_CTX *)OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX)); if (ctx == NULL) return(0); - ctx->ibuf=(char *)Malloc(DEFAULT_BUFFER_SIZE); - if (ctx->ibuf == NULL) { Free(ctx); return(0); } - ctx->obuf=(char *)Malloc(DEFAULT_BUFFER_SIZE); - if (ctx->obuf == NULL) { Free(ctx->ibuf); Free(ctx); return(0); } + ctx->ibuf=(char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE); + if (ctx->ibuf == NULL) { OPENSSL_free(ctx); return(0); } + ctx->obuf=(char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE); + if (ctx->obuf == NULL) { OPENSSL_free(ctx->ibuf); OPENSSL_free(ctx); return(0); } ctx->ibuf_size=DEFAULT_BUFFER_SIZE; ctx->obuf_size=DEFAULT_BUFFER_SIZE; ctx->ibuf_len=0; @@ -124,26 +113,22 @@ BIO *bi; return(1); } -static int buffer_free(a) -BIO *a; +static int buffer_free(BIO *a) { BIO_F_BUFFER_CTX *b; if (a == NULL) return(0); b=(BIO_F_BUFFER_CTX *)a->ptr; - if (b->ibuf != NULL) Free(b->ibuf); - if (b->obuf != NULL) Free(b->obuf); - Free(a->ptr); + if (b->ibuf != NULL) OPENSSL_free(b->ibuf); + if (b->obuf != NULL) OPENSSL_free(b->obuf); + OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } -static int buffer_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int buffer_read(BIO *b, char *out, int outl) { int i,num=0; BIO_F_BUFFER_CTX *ctx; @@ -209,10 +194,7 @@ start: goto start; } -static int buffer_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int buffer_write(BIO *b, const char *in, int inl) { int i,num=0; BIO_F_BUFFER_CTX *ctx; @@ -285,11 +267,7 @@ start: goto start; } -static long buffer_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; BIO_F_BUFFER_CTX *ctx; @@ -307,6 +285,7 @@ char *ptr; ctx->ibuf_len=0; ctx->obuf_off=0; ctx->obuf_len=0; + if (b->next_bio == NULL) return(0); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_CTRL_INFO: @@ -323,19 +302,25 @@ char *ptr; case BIO_CTRL_WPENDING: ret=(long)ctx->obuf_len; if (ret == 0) + { + if (b->next_bio == NULL) return(0); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + } break; case BIO_CTRL_PENDING: ret=(long)ctx->ibuf_len; if (ret == 0) + { + if (b->next_bio == NULL) return(0); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); + } break; case BIO_C_SET_BUFF_READ_DATA: if (num > ctx->ibuf_size) { - p1=Malloc((int)num); + p1=OPENSSL_malloc((int)num); if (p1 == NULL) goto malloc_error; - if (ctx->ibuf != NULL) Free(ctx->ibuf); + if (ctx->ibuf != NULL) OPENSSL_free(ctx->ibuf); ctx->ibuf=p1; } ctx->ibuf_off=0; @@ -367,21 +352,21 @@ char *ptr; p2=ctx->obuf; if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) { - p1=(char *)Malloc((int)num); + p1=(char *)OPENSSL_malloc((int)num); if (p1 == NULL) goto malloc_error; } if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { - p2=(char *)Malloc((int)num); + p2=(char *)OPENSSL_malloc((int)num); if (p2 == NULL) { - if (p1 != ctx->ibuf) Free(p1); + if (p1 != ctx->ibuf) OPENSSL_free(p1); goto malloc_error; } } if (ctx->ibuf != p1) { - Free(ctx->ibuf); + OPENSSL_free(ctx->ibuf); ctx->ibuf=p1; ctx->ibuf_off=0; ctx->ibuf_len=0; @@ -389,7 +374,7 @@ char *ptr; } if (ctx->obuf != p2) { - Free(ctx->obuf); + OPENSSL_free(ctx->obuf); ctx->obuf=p2; ctx->obuf_off=0; ctx->obuf_len=0; @@ -397,12 +382,14 @@ char *ptr; } break; case BIO_C_DO_STATE_MACHINE: + if (b->next_bio == NULL) return(0); BIO_clear_retry_flags(b); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); BIO_copy_next_retry(b); break; case BIO_CTRL_FLUSH: + if (b->next_bio == NULL) return(0); if (ctx->obuf_len <= 0) { ret=BIO_ctrl(b->next_bio,cmd,num,ptr); @@ -432,6 +419,7 @@ fprintf(stderr,"FLUSH [%3d] %3d -> %3d\n",ctx->obuf_off,ctx->obuf_len-ctx->obuf_ break; } } + ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_CTRL_DUP: dbio=(BIO *)ptr; @@ -440,6 +428,7 @@ fprintf(stderr,"FLUSH [%3d] %3d -> %3d\n",ctx->obuf_off,ctx->obuf_len-ctx->obuf_ ret=0; break; default: + if (b->next_bio == NULL) return(0); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; } @@ -449,10 +438,21 @@ malloc_error: return(0); } -static int buffer_gets(b,buf,size) -BIO *b; -char *buf; -int size; +static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + +static int buffer_gets(BIO *b, char *buf, int size) { BIO_F_BUFFER_CTX *ctx; int num=0,i,flag; @@ -503,10 +503,8 @@ int size; } } -static int buffer_puts(b,str) -BIO *b; -char *str; +static int buffer_puts(BIO *b, const char *str) { - return(BIO_write(b,str,strlen(str))); + return(buffer_write(b,str,strlen(str))); } diff --git a/src/lib/libcrypto/bio/bf_lbuf.c b/src/lib/libcrypto/bio/bf_lbuf.c index 7bcf8ed941..ec0f7eb0b7 100644 --- a/src/lib/libcrypto/bio/bf_lbuf.c +++ b/src/lib/libcrypto/bio/bf_lbuf.c @@ -200,7 +200,7 @@ static int linebuffer_write(BIO *b, const char *in, int inl) } } -#ifdef DEBUG +#if 0 BIO_write(b->next_bio, "<*<", 3); #endif i=BIO_write(b->next_bio, @@ -210,13 +210,13 @@ BIO_write(b->next_bio, "<*<", 3); ctx->obuf_len = orig_olen; BIO_copy_next_retry(b); -#ifdef DEBUG +#if 0 BIO_write(b->next_bio, ">*>", 3); #endif if (i < 0) return((num > 0)?num:i); if (i == 0) return(num); } -#ifdef DEBUG +#if 0 BIO_write(b->next_bio, ">*>", 3); #endif if (i < ctx->obuf_len) @@ -229,20 +229,20 @@ BIO_write(b->next_bio, ">*>", 3); buffer if a NL was found and there is anything to write. */ if ((foundnl || p - in > ctx->obuf_size) && p - in > 0) { -#ifdef DEBUG +#if 0 BIO_write(b->next_bio, "<*<", 3); #endif i=BIO_write(b->next_bio,in,p - in); if (i <= 0) { BIO_copy_next_retry(b); -#ifdef DEBUG +#if 0 BIO_write(b->next_bio, ">*>", 3); #endif if (i < 0) return((num > 0)?num:i); if (i == 0) return(num); } -#ifdef DEBUG +#if 0 BIO_write(b->next_bio, ">*>", 3); #endif num+=i; diff --git a/src/lib/libcrypto/bio/bf_nbio.c b/src/lib/libcrypto/bio/bf_nbio.c index 034b3024df..1ce2bfacc0 100644 --- a/src/lib/libcrypto/bio/bf_nbio.c +++ b/src/lib/libcrypto/bio/bf_nbio.c @@ -59,31 +59,20 @@ #include #include #include "cryptlib.h" -#include "rand.h" -#include "bio.h" -#include "evp.h" +#include +#include /* BIO_put and BIO_get both add to the digest, * BIO_gets returns the digest */ -#ifndef NOPROTO -static int nbiof_write(BIO *h,char *buf,int num); +static int nbiof_write(BIO *h,const char *buf,int num); static int nbiof_read(BIO *h,char *buf,int size); -static int nbiof_puts(BIO *h,char *str); +static int nbiof_puts(BIO *h,const char *str); static int nbiof_gets(BIO *h,char *str,int size); -static long nbiof_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static long nbiof_ctrl(BIO *h,int cmd,long arg1,void *arg2); static int nbiof_new(BIO *h); static int nbiof_free(BIO *data); -#else -static int nbiof_write(); -static int nbiof_read(); -static int nbiof_puts(); -static int nbiof_gets(); -static long nbiof_ctrl(); -static int nbiof_new(); -static int nbiof_free(); -#endif - +static long nbiof_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp); typedef struct nbio_test_st { /* only set if we sent a 'should retry' error */ @@ -102,19 +91,19 @@ static BIO_METHOD methods_nbiof= nbiof_ctrl, nbiof_new, nbiof_free, + nbiof_callback_ctrl, }; -BIO_METHOD *BIO_f_nbio_test() +BIO_METHOD *BIO_f_nbio_test(void) { return(&methods_nbiof); } -static int nbiof_new(bi) -BIO *bi; +static int nbiof_new(BIO *bi) { NBIO_TEST *nt; - nt=(NBIO_TEST *)Malloc(sizeof(NBIO_TEST)); + if (!(nt=(NBIO_TEST *)OPENSSL_malloc(sizeof(NBIO_TEST)))) return(0); nt->lrn= -1; nt->lwn= -1; bi->ptr=(char *)nt; @@ -123,22 +112,18 @@ BIO *bi; return(1); } -static int nbiof_free(a) -BIO *a; +static int nbiof_free(BIO *a) { if (a == NULL) return(0); if (a->ptr != NULL) - Free(a->ptr); + OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } -static int nbiof_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int nbiof_read(BIO *b, char *out, int outl) { NBIO_TEST *nt; int ret=0; @@ -153,7 +138,7 @@ int outl; BIO_clear_retry_flags(b); #if 0 - RAND_bytes(&n,1); + RAND_pseudo_bytes(&n,1); num=(n&0x07); if (outl > num) outl=num; @@ -173,10 +158,7 @@ int outl; return(ret); } -static int nbiof_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int nbiof_write(BIO *b, const char *in, int inl) { NBIO_TEST *nt; int ret=0; @@ -197,7 +179,7 @@ int inl; } else { - RAND_bytes(&n,1); + RAND_pseudo_bytes(&n,1); num=(n&7); } @@ -221,11 +203,7 @@ int inl; return(ret); } -static long nbiof_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long nbiof_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret; @@ -247,19 +225,28 @@ char *ptr; return(ret); } -static int nbiof_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; +static long nbiof_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + +static int nbiof_gets(BIO *bp, char *buf, int size) { if (bp->next_bio == NULL) return(0); return(BIO_gets(bp->next_bio,buf,size)); } -static int nbiof_puts(bp,str) -BIO *bp; -char *str; +static int nbiof_puts(BIO *bp, const char *str) { if (bp->next_bio == NULL) return(0); return(BIO_puts(bp->next_bio,str)); diff --git a/src/lib/libcrypto/bio/bf_null.c b/src/lib/libcrypto/bio/bf_null.c index a47a65741a..c1bf39a904 100644 --- a/src/lib/libcrypto/bio/bf_null.c +++ b/src/lib/libcrypto/bio/bf_null.c @@ -59,30 +59,19 @@ #include #include #include "cryptlib.h" -#include "bio.h" -#include "evp.h" +#include /* BIO_put and BIO_get both add to the digest, * BIO_gets returns the digest */ -#ifndef NOPROTO -static int nullf_write(BIO *h,char *buf,int num); -static int nullf_read(BIO *h,char *buf,int size); -static int nullf_puts(BIO *h,char *str); -static int nullf_gets(BIO *h,char *str,int size); -static long nullf_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int nullf_write(BIO *h, const char *buf, int num); +static int nullf_read(BIO *h, char *buf, int size); +static int nullf_puts(BIO *h, const char *str); +static int nullf_gets(BIO *h, char *str, int size); +static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int nullf_new(BIO *h); static int nullf_free(BIO *data); -#else -static int nullf_write(); -static int nullf_read(); -static int nullf_puts(); -static int nullf_gets(); -static long nullf_ctrl(); -static int nullf_new(); -static int nullf_free(); -#endif - +static long nullf_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); static BIO_METHOD methods_nullf= { BIO_TYPE_NULL_FILTER, @@ -94,15 +83,15 @@ static BIO_METHOD methods_nullf= nullf_ctrl, nullf_new, nullf_free, + nullf_callback_ctrl, }; -BIO_METHOD *BIO_f_null() +BIO_METHOD *BIO_f_null(void) { return(&methods_nullf); } -static int nullf_new(bi) -BIO *bi; +static int nullf_new(BIO *bi) { bi->init=1; bi->ptr=NULL; @@ -110,8 +99,7 @@ BIO *bi; return(1); } -static int nullf_free(a) -BIO *a; +static int nullf_free(BIO *a) { if (a == NULL) return(0); /* a->ptr=NULL; @@ -120,10 +108,7 @@ BIO *a; return(1); } -static int nullf_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int nullf_read(BIO *b, char *out, int outl) { int ret=0; @@ -135,10 +120,7 @@ int outl; return(ret); } -static int nullf_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int nullf_write(BIO *b, const char *in, int inl) { int ret=0; @@ -150,11 +132,7 @@ int inl; return(ret); } -static long nullf_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long nullf_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret; @@ -175,19 +153,28 @@ char *ptr; return(ret); } -static int nullf_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; +static long nullf_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + +static int nullf_gets(BIO *bp, char *buf, int size) { if (bp->next_bio == NULL) return(0); return(BIO_gets(bp->next_bio,buf,size)); } -static int nullf_puts(bp,str) -BIO *bp; -char *str; +static int nullf_puts(BIO *bp, const char *str) { if (bp->next_bio == NULL) return(0); return(BIO_puts(bp->next_bio,str)); diff --git a/src/lib/libcrypto/bio/bio.h b/src/lib/libcrypto/bio/bio.h index 300b330e00..b122c7069d 100644 --- a/src/lib/libcrypto/bio/bio.h +++ b/src/lib/libcrypto/bio/bio.h @@ -59,12 +59,18 @@ #ifndef HEADER_BIO_H #define HEADER_BIO_H +#ifndef OPENSSL_NO_FP_API +# include +#endif +#include + +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include "crypto.h" - /* These are the 'types' of BIOs */ #define BIO_TYPE_NONE 0 #define BIO_TYPE_MEM (1|0x0400) @@ -74,7 +80,7 @@ extern "C" { #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) /* pasive filter */ +#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 */ @@ -84,6 +90,9 @@ extern "C" { #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_LINEBUFFER (20|0x0200) /* filter */ #define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ #define BIO_TYPE_FILTER 0x0200 @@ -143,6 +152,11 @@ extern "C" { #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) \ @@ -159,14 +173,14 @@ extern "C" { #define BIO_get_retry_flags(b) \ ((b)->flags&(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) -/* These shouldbe used by the application to tell why we 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 +/* The next three 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. @@ -175,6 +189,8 @@ extern "C" { #define BIO_RR_SSL_X509_LOOKUP 0x01 /* Returned from the connect BIO when a connect would have blocked */ #define BIO_RR_CONNECT 0x02 +/* Returned from the accept BIO when an accept would have blocked */ +#define BIO_RR_ACCEPT 0x03 /* These are passed by the BIO callback */ #define BIO_CB_FREE 0x01 @@ -198,24 +214,29 @@ extern "C" { #define BIO_method_name(b) ((b)->method->name) #define BIO_method_type(b) ((b)->method->type) -#ifndef WIN16 +typedef struct bio_st BIO; + +typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long); + +#ifndef OPENSSL_SYS_WIN16 typedef struct bio_method_st { int type; - char *name; - int (*bwrite)(); - int (*bread)(); - int (*bputs)(); - int (*bgets)(); - long (*ctrl)(); - int (*create)(); - int (*destroy)(); + const char *name; + int (*bwrite)(BIO *, const char *, int); + int (*bread)(BIO *, char *, int); + int (*bputs)(BIO *, const char *); + int (*bgets)(BIO *, char *, int); + long (*ctrl)(BIO *, int, long, void *); + int (*create)(BIO *); + int (*destroy)(BIO *); + long (*callback_ctrl)(BIO *, int, bio_info_cb *); } BIO_METHOD; #else typedef struct bio_method_st { int type; - char *name; + const char *name; int (_far *bwrite)(); int (_far *bread)(); int (_far *bputs)(); @@ -223,18 +244,15 @@ typedef struct bio_method_st long (_far *ctrl)(); int (_far *create)(); int (_far *destroy)(); + long (_fat *callback_ctrl)(); } BIO_METHOD; #endif -typedef struct bio_st +struct bio_st { BIO_METHOD *method; -#ifndef NOPROTO /* bio, mode, argp, argi, argl, ret */ - long (*callback)(struct bio_st *,int,char *,int, long,long); -#else - long (*callback)(); -#endif + long (*callback)(struct bio_st *,int,const char *,int, long,long); char *cb_arg; /* first argument for the callback */ int init; @@ -242,7 +260,7 @@ typedef struct bio_st int flags; /* extra storage */ int retry_reason; int num; - char *ptr; + void *ptr; struct bio_st *next_bio; /* used by filter BIOs */ struct bio_st *prev_bio; /* used by filter BIOs */ int references; @@ -250,7 +268,9 @@ typedef struct bio_st unsigned long num_write; CRYPTO_EX_DATA ex_data; - } BIO; + }; + +DECLARE_STACK_OF(BIO) typedef struct bio_f_buffer_ctx_struct { @@ -276,10 +296,7 @@ typedef struct bio_f_buffer_ctx_struct #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_number_read(b) ((b)->num_read) -#define BIO_number_written(b) ((b)->num_write) +/*#define BIO_CONN_get_param_hostname BIO_ctrl */ #define BIO_C_SET_CONNECT 100 #define BIO_C_DO_STATE_MACHINE 101 @@ -309,26 +326,42 @@ typedef struct bio_f_buffer_ctx_struct #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_set_app_data(s,arg) BIO_set_ex_data(s,0,(char *)arg) +#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) -int BIO_get_ex_num(BIO *bio); -int BIO_set_ex_data(BIO *bio,int idx,char *data); -char *BIO_get_ex_data(BIO *bio,int idx); -void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); -int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); - -/* BIO_s_connect_socket() */ +/* 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_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2) +#define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3) + #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) @@ -339,6 +372,12 @@ int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), #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) @@ -349,7 +388,7 @@ int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), /* 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_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(char *)(cb)) +#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) @@ -364,12 +403,26 @@ int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), #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,name) + 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 @@ -381,15 +434,18 @@ int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), #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); + BIO_ctrl(b,BIO_C_GET_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) @@ -407,19 +463,42 @@ int BIO_get_ex_new_index(long argl, char *argp, int (*new_func)(), #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,(char *)cbp) -#define BIO_set_info_callback(b,cb) (int)BIO_ctrl(b,BIO_CTRL_SET_CALLBACK,0,(char *)cb) +#define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \ + cbp) +#define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb) /* For the BIO_f_buffer() type */ #define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) -#ifdef NO_STDIO -#define NO_FP_API -#endif - -#ifndef NOPROTO -# if defined(WIN16) && defined(_WINDLL) +/* 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) +#define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 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); + +/* 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); + +# ifndef OPENSSL_NO_FP_API +# if defined(OPENSSL_SYS_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); @@ -428,261 +507,184 @@ BIO *BIO_new_fp_internal(FILE *stream, int close_flag); # define BIO_new_fp BIO_new_fp_internal # else /* FP_API */ BIO_METHOD *BIO_s_file(void ); -BIO *BIO_new_file(char *filename, char *mode); +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 */ -#else -# if defined(WIN16) && defined(_WINDLL) -BIO_METHOD *BIO_s_file_internal(); -BIO *BIO_new_file_internal(); -BIO *BIO_new_fp_internal(); -# 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 */ -BIO_METHOD *BIO_s_file(); -BIO *BIO_new_file(); -BIO *BIO_new_fp(); -# 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 */ -#endif - -#ifndef NOPROTO +# endif BIO * BIO_new(BIO_METHOD *type); int BIO_set(BIO *a,BIO_METHOD *type); int BIO_free(BIO *a); -int BIO_read(BIO *b, char *data, int len); +void BIO_vfree(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, char *data, int len); -int BIO_puts(BIO *bp,char *buf); -long BIO_ctrl(BIO *bp,int cmd,long larg,char *parg); +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 *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long)); 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_next(BIO *b); BIO * BIO_get_retry_BIO(BIO *bio, int *reason); int BIO_get_retry_reason(BIO *bio); BIO * BIO_dup_chain(BIO *in); -#ifndef WIN16 -long BIO_debug_callback(BIO *bio,int cmd,char *argp,int argi, +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 OPENSSL_SYS_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,char *argp,int argi, +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_nbio_test(void); BIO_METHOD *BIO_f_buffer(void); +#ifdef OPENSSL_SYS_VMS +BIO_METHOD *BIO_f_linebuffer(void); +#endif +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,char *bytes,int len); - -struct hostent *BIO_gethostbyname(char *name); +int BIO_dump(BIO *b,const char *bytes,int len); +int BIO_dump_indent(BIO *b,const char *bytes,int len,int indent); + +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_get_port(char *str, short *port_ptr); -int BIO_get_host_ip(char *str, unsigned char *ip); -int BIO_get_accept_socket(char *host_port); +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); -#else - -BIO * BIO_new(); -int BIO_set(); -int BIO_free(); -int BIO_read(); -int BIO_gets(); -int BIO_write(); -int BIO_puts(); -char * BIO_ptr_ctrl(); -long BIO_ctrl(); -long BIO_int_ctrl(); -BIO * BIO_push(); -BIO * BIO_pop(); -void BIO_free_all(); -BIO * BIO_find_type(); -BIO * BIO_get_retry_BIO(); -int BIO_get_retry_reason(); -BIO * BIO_dup_chain(); - -#ifndef WIN16 -long BIO_debug_callback(); -#else -long _far _loadds BIO_debug_callback(); -#endif - -BIO_METHOD *BIO_s_mem(); -BIO_METHOD *BIO_s_socket(); -BIO_METHOD *BIO_s_connect(); -BIO_METHOD *BIO_s_accept(); -BIO_METHOD *BIO_s_fd(); -BIO_METHOD *BIO_s_null(); -BIO_METHOD *BIO_f_null(); -BIO_METHOD *BIO_f_buffer(); -BIO_METHOD *BIO_f_nbio_test(); - -int BIO_sock_should_retry(); -int BIO_sock_non_fatal_error(); -int BIO_fd_should_retry(); -int BIO_fd_non_fatal_error(); -int BIO_dump(); - -struct hostent *BIO_gethostbyname(); -int BIO_sock_error(); -int BIO_socket_ioctl(); -int BIO_get_port(); -int BIO_get_host_ip(); -int BIO_get_accept_socket(); -int BIO_accept(); -int BIO_sock_init(); -void BIO_sock_cleanup(); -int BIO_set_tcp_ndelay(); - -void ERR_load_BIO_strings(); - -BIO *BIO_new_socket(); -BIO *BIO_new_fd(); -BIO *BIO_new_connect(); -BIO *BIO_new_accept(); - -void BIO_copy_next_retry(); - -int BIO_ghbn_ctrl(); - -#endif - -/* Tim Hudson's portable varargs stuff */ - -#ifndef NOPROTO -#define VAR_ANSI /* select ANSI version by default */ -#endif - -#ifdef VAR_ANSI -/* ANSI version of a "portable" macro set for variable length args */ -#ifndef __STDARG_H__ /**/ -#include -#endif /**/ - -#define VAR_PLIST(arg1type,arg1) arg1type arg1, ... -#define VAR_PLIST2(arg1type,arg1,arg2type,arg2) arg1type arg1,arg2type arg2,... -#define VAR_ALIST -#define VAR_BDEFN(args,arg1type,arg1) va_list args -#define VAR_BDEFN2(args,arg1type,arg1,arg2type,arg2) va_list args -#define VAR_INIT(args,arg1type,arg1) va_start(args,arg1); -#define VAR_INIT2(args,arg1type,arg1,arg2type,arg2) va_start(args,arg2); -#define VAR_ARG(args,type,arg) arg=va_arg(args,type) -#define VAR_END(args) va_end(args); - -#else - -/* K&R version of a "portable" macro set for variable length args */ -#ifndef __VARARGS_H__ -#include -#endif - -#define VAR_PLIST(arg1type,arg1) va_alist -#define VAR_PLIST2(arg1type,arg1,arg2type,arg2) va_alist -#define VAR_ALIST va_dcl -#define VAR_BDEFN(args,arg1type,arg1) va_list args; arg1type arg1 -#define VAR_BDEFN2(args,arg1type,arg1,arg2type,arg2) va_list args; \ - arg1type arg1; arg2type arg2 -#define VAR_INIT(args,arg1type,arg1) va_start(args); \ - arg1=va_arg(args,arg1type); -#define VAR_INIT2(args,arg1type,arg1,arg2type,arg2) va_start(args); \ - arg1=va_arg(args,arg1type); arg2=va_arg(args,arg2type); -#define VAR_ARG(args,type,arg) arg=va_arg(args,type) -#define VAR_END(args) va_end(args); - -#endif - -#ifndef NOPROTO -int BIO_printf( VAR_PLIST( BIO *, bio ) ); -#else -int BIO_printf(); -#endif +int BIO_printf(BIO *bio, const char *format, ...); +int BIO_vprintf(BIO *bio, const char *format, va_list args); +int BIO_snprintf(char *buf, size_t n, const char *format, ...); +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args); /* 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. + */ +void ERR_load_BIO_strings(void); + /* Error codes for the BIO functions. */ /* Function codes. */ #define BIO_F_ACPT_STATE 100 #define BIO_F_BIO_ACCEPT 101 -#define BIO_F_BIO_CTRL 102 -#define BIO_F_BIO_GETS 103 -#define BIO_F_BIO_GET_ACCEPT_SOCKET 104 -#define BIO_F_BIO_GET_HOST_IP 105 -#define BIO_F_BIO_GET_PORT 106 -#define BIO_F_BIO_NEW 107 -#define BIO_F_BIO_NEW_FILE 108 -#define BIO_F_BIO_PUTS 109 -#define BIO_F_BIO_READ 110 -#define BIO_F_BIO_SOCK_INIT 111 -#define BIO_F_BIO_WRITE 112 -#define BIO_F_BUFFER_CTRL 113 -#define BIO_F_CONN_STATE 114 -#define BIO_F_FILE_CTRL 115 -#define BIO_F_MEM_WRITE 116 -#define BIO_F_SSL_NEW 117 -#define BIO_F_WSASTARTUP 118 +#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_LINEBUFFER_CTRL 129 +#define BIO_F_MEM_READ 128 +#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_EOF_ON_MEMORY_BIO 127 #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_HOSTHNAME_SPECIFIED 112 +#define BIO_R_NO_HOSTNAME_SPECIFIED 112 #define BIO_R_NO_PORT_DEFINED 113 #define BIO_R_NO_PORT_SPECIFIED 114 +#define BIO_R_NO_SUCH_FILE 128 #define BIO_R_NULL_PARAMETER 115 -#define BIO_R_UNABLE_TO_BIND_SOCKET 116 -#define BIO_R_UNABLE_TO_CREATE_SOCKET 117 -#define BIO_R_UNABLE_TO_LISTEN_SOCKET 118 -#define BIO_R_UNINITALISED 119 -#define BIO_R_UNSUPPORTED_METHOD 120 -#define BIO_R_WSASTARTUP 121 - +#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/src/lib/libcrypto/bio/bio_cb.c b/src/lib/libcrypto/bio/bio_cb.c index bc6ed9eda1..0ffa4d2136 100644 --- a/src/lib/libcrypto/bio/bio_cb.c +++ b/src/lib/libcrypto/bio/bio_cb.c @@ -60,16 +60,11 @@ #include #include #include "cryptlib.h" -#include "bio.h" -#include "err.h" +#include +#include -long MS_CALLBACK BIO_debug_callback(bio,cmd,argp,argi,argl,ret) -BIO *bio; -int cmd; -char *argp; -int argi; -long argl; -long ret; +long MS_CALLBACK BIO_debug_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret) { BIO *b; MS_STATIC char buf[256]; @@ -130,7 +125,7 @@ long ret; b=(BIO *)bio->cb_arg; if (b != NULL) BIO_write(b,buf,strlen(buf)); -#if !defined(NO_STDIO) && !defined(WIN16) +#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) else fputs(buf,stderr); #endif diff --git a/src/lib/libcrypto/bio/bio_err.c b/src/lib/libcrypto/bio/bio_err.c index 37e14ca107..99ca3cd0da 100644 --- a/src/lib/libcrypto/bio/bio_err.c +++ b/src/lib/libcrypto/bio/bio_err.c @@ -1,88 +1,102 @@ -/* lib/bio/bio_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/bio/bio_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "bio.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA BIO_str_functs[]= { {ERR_PACK(0,BIO_F_ACPT_STATE,0), "ACPT_STATE"}, {ERR_PACK(0,BIO_F_BIO_ACCEPT,0), "BIO_accept"}, +{ERR_PACK(0,BIO_F_BIO_BER_GET_HEADER,0), "BIO_BER_GET_HEADER"}, {ERR_PACK(0,BIO_F_BIO_CTRL,0), "BIO_ctrl"}, +{ERR_PACK(0,BIO_F_BIO_GETHOSTBYNAME,0), "BIO_gethostbyname"}, {ERR_PACK(0,BIO_F_BIO_GETS,0), "BIO_gets"}, {ERR_PACK(0,BIO_F_BIO_GET_ACCEPT_SOCKET,0), "BIO_get_accept_socket"}, {ERR_PACK(0,BIO_F_BIO_GET_HOST_IP,0), "BIO_get_host_ip"}, {ERR_PACK(0,BIO_F_BIO_GET_PORT,0), "BIO_get_port"}, +{ERR_PACK(0,BIO_F_BIO_MAKE_PAIR,0), "BIO_MAKE_PAIR"}, {ERR_PACK(0,BIO_F_BIO_NEW,0), "BIO_new"}, {ERR_PACK(0,BIO_F_BIO_NEW_FILE,0), "BIO_new_file"}, +{ERR_PACK(0,BIO_F_BIO_NEW_MEM_BUF,0), "BIO_new_mem_buf"}, +{ERR_PACK(0,BIO_F_BIO_NREAD,0), "BIO_nread"}, +{ERR_PACK(0,BIO_F_BIO_NREAD0,0), "BIO_nread0"}, +{ERR_PACK(0,BIO_F_BIO_NWRITE,0), "BIO_nwrite"}, +{ERR_PACK(0,BIO_F_BIO_NWRITE0,0), "BIO_nwrite0"}, {ERR_PACK(0,BIO_F_BIO_PUTS,0), "BIO_puts"}, {ERR_PACK(0,BIO_F_BIO_READ,0), "BIO_read"}, {ERR_PACK(0,BIO_F_BIO_SOCK_INIT,0), "BIO_sock_init"}, {ERR_PACK(0,BIO_F_BIO_WRITE,0), "BIO_write"}, {ERR_PACK(0,BIO_F_BUFFER_CTRL,0), "BUFFER_CTRL"}, +{ERR_PACK(0,BIO_F_CONN_CTRL,0), "CONN_CTRL"}, {ERR_PACK(0,BIO_F_CONN_STATE,0), "CONN_STATE"}, {ERR_PACK(0,BIO_F_FILE_CTRL,0), "FILE_CTRL"}, +{ERR_PACK(0,BIO_F_LINEBUFFER_CTRL,0), "LINEBUFFER_CTRL"}, +{ERR_PACK(0,BIO_F_MEM_READ,0), "MEM_READ"}, {ERR_PACK(0,BIO_F_MEM_WRITE,0), "MEM_WRITE"}, -{ERR_PACK(0,BIO_F_SSL_NEW,0), "SSL_NEW"}, +{ERR_PACK(0,BIO_F_SSL_NEW,0), "SSL_new"}, {ERR_PACK(0,BIO_F_WSASTARTUP,0), "WSASTARTUP"}, -{0,NULL}, +{0,NULL} }; static ERR_STRING_DATA BIO_str_reasons[]= @@ -90,38 +104,45 @@ static ERR_STRING_DATA BIO_str_reasons[]= {BIO_R_ACCEPT_ERROR ,"accept error"}, {BIO_R_BAD_FOPEN_MODE ,"bad fopen mode"}, {BIO_R_BAD_HOSTNAME_LOOKUP ,"bad hostname lookup"}, +{BIO_R_BROKEN_PIPE ,"broken pipe"}, {BIO_R_CONNECT_ERROR ,"connect error"}, +{BIO_R_EOF_ON_MEMORY_BIO ,"EOF on memory BIO"}, {BIO_R_ERROR_SETTING_NBIO ,"error setting nbio"}, {BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET,"error setting nbio on accepted socket"}, {BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET,"error setting nbio on accept socket"}, {BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET ,"gethostbyname addr is not af inet"}, +{BIO_R_INVALID_ARGUMENT ,"invalid argument"}, {BIO_R_INVALID_IP_ADDRESS ,"invalid ip address"}, +{BIO_R_IN_USE ,"in use"}, {BIO_R_KEEPALIVE ,"keepalive"}, {BIO_R_NBIO_CONNECT_ERROR ,"nbio connect error"}, {BIO_R_NO_ACCEPT_PORT_SPECIFIED ,"no accept port specified"}, -{BIO_R_NO_HOSTHNAME_SPECIFIED ,"no hosthname specified"}, +{BIO_R_NO_HOSTNAME_SPECIFIED ,"no hostname specified"}, {BIO_R_NO_PORT_DEFINED ,"no port defined"}, {BIO_R_NO_PORT_SPECIFIED ,"no port specified"}, +{BIO_R_NO_SUCH_FILE ,"no such file"}, {BIO_R_NULL_PARAMETER ,"null parameter"}, +{BIO_R_TAG_MISMATCH ,"tag mismatch"}, {BIO_R_UNABLE_TO_BIND_SOCKET ,"unable to bind socket"}, {BIO_R_UNABLE_TO_CREATE_SOCKET ,"unable to create socket"}, {BIO_R_UNABLE_TO_LISTEN_SOCKET ,"unable to listen socket"}, -{BIO_R_UNINITALISED ,"uninitalised"}, +{BIO_R_UNINITIALIZED ,"uninitialized"}, {BIO_R_UNSUPPORTED_METHOD ,"unsupported method"}, -{BIO_R_WSASTARTUP ,"wsastartup"}, -{0,NULL}, +{BIO_R_WRITE_TO_READ_ONLY_BIO ,"write to read only BIO"}, +{BIO_R_WSASTARTUP ,"WSAStartup"}, +{0,NULL} }; #endif -void ERR_load_BIO_strings() +void ERR_load_BIO_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_BIO,BIO_str_functs); ERR_load_strings(ERR_LIB_BIO,BIO_str_reasons); #endif diff --git a/src/lib/libcrypto/bio/bio_lib.c b/src/lib/libcrypto/bio/bio_lib.c index 7a66b0892e..50df2238fa 100644 --- a/src/lib/libcrypto/bio/bio_lib.c +++ b/src/lib/libcrypto/bio/bio_lib.c @@ -58,20 +58,16 @@ #include #include -#include "crypto.h" +#include #include "cryptlib.h" -#include "bio.h" -#include "stack.h" +#include +#include -static STACK *bio_meth=NULL; -static int bio_meth_num=0; - -BIO *BIO_new(method) -BIO_METHOD *method; +BIO *BIO_new(BIO_METHOD *method) { BIO *ret=NULL; - ret=(BIO *)Malloc(sizeof(BIO)); + ret=(BIO *)OPENSSL_malloc(sizeof(BIO)); if (ret == NULL) { BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE); @@ -79,15 +75,13 @@ BIO_METHOD *method; } if (!BIO_set(ret,method)) { - Free(ret); + OPENSSL_free(ret); ret=NULL; } return(ret); } -int BIO_set(bio,method) -BIO *bio; -BIO_METHOD *method; +int BIO_set(BIO *bio, BIO_METHOD *method) { bio->method=method; bio->callback=NULL; @@ -103,15 +97,18 @@ BIO_METHOD *method; bio->references=1; bio->num_read=0L; bio->num_write=0L; - CRYPTO_new_ex_data(bio_meth,(char *)bio,&bio->ex_data); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); if (method->create != NULL) if (!method->create(bio)) + { + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, + &bio->ex_data); return(0); + } return(1); } -int BIO_free(a) -BIO *a; +int BIO_free(BIO *a) { int ret=0,i; @@ -121,7 +118,7 @@ BIO *a; #ifdef REF_PRINT REF_PRINT("BIO",a); #endif - if (i > 0) return(1); + if (i > 0) return(1); #ifdef REF_CHECK if (i < 0) { @@ -133,18 +130,18 @@ BIO *a; ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0)) return(i); - CRYPTO_free_ex_data(bio_meth,(char *)a,&a->ex_data); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); if ((a->method == NULL) || (a->method->destroy == NULL)) return(1); ret=a->method->destroy(a); - Free(a); + OPENSSL_free(a); return(1); } -int BIO_read(b,out,outl) -BIO *b; -char *out; -int outl; +void BIO_vfree(BIO *a) + { BIO_free(a); } + +int BIO_read(BIO *b, void *out, int outl) { int i; long (*cb)(); @@ -162,11 +159,12 @@ int outl; if (!b->init) { - BIOerr(BIO_F_BIO_READ,BIO_R_UNINITALISED); + 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) @@ -175,10 +173,7 @@ int outl; return(i); } -int BIO_write(b,in,inl) -BIO *b; -char *in; -int inl; +int BIO_write(BIO *b, const void *in, int inl) { int i; long (*cb)(); @@ -199,11 +194,12 @@ int inl; if (!b->init) { - BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITALISED); + 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; if (cb != NULL) @@ -212,9 +208,7 @@ int inl; return(i); } -int BIO_puts(b,in) -BIO *b; -char *in; +int BIO_puts(BIO *b, const char *in) { int i; long (*cb)(); @@ -233,22 +227,21 @@ char *in; if (!b->init) { - BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITALISED); + BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED); return(-2); } i=b->method->bputs(b,in); + if (i > 0) b->num_write+=(unsigned long)i; + if (cb != NULL) i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0, 0L,(long)i); return(i); } -int BIO_gets(b,in,inl) -BIO *b; -char *in; -int inl; +int BIO_gets(BIO *b, char *in, int inl) { int i; long (*cb)(); @@ -267,7 +260,7 @@ int inl; if (!b->init) { - BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITALISED); + BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED); return(-2); } @@ -279,11 +272,7 @@ int inl; return(i); } -long BIO_int_ctrl(b,cmd,larg,iarg) -BIO *b; -int cmd; -long larg; -int iarg; +long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) { int i; @@ -291,10 +280,7 @@ int iarg; return(BIO_ctrl(b,cmd,larg,(char *)&i)); } -char *BIO_ptr_ctrl(b,cmd,larg) -BIO *b; -int cmd; -long larg; +char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) { char *p=NULL; @@ -304,11 +290,7 @@ long larg; return(p); } -long BIO_ctrl(b,cmd,larg,parg) -BIO *b; -int cmd; -long larg; -char *parg; +long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) { long ret; long (*cb)(); @@ -335,9 +317,49 @@ char *parg; return(ret); } +long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long)) + { + 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(b,bio) -BIO *b,*bio; +BIO *BIO_push(BIO *b, BIO *bio) { BIO *lb; @@ -354,8 +376,7 @@ BIO *b,*bio; } /* Remove the first and return the rest */ -BIO *BIO_pop(b) -BIO *b; +BIO *BIO_pop(BIO *b) { BIO *ret; @@ -373,9 +394,7 @@ BIO *b; return(ret); } -BIO *BIO_get_retry_BIO(bio,reason) -BIO *bio; -int *reason; +BIO *BIO_get_retry_BIO(BIO *bio, int *reason) { BIO *b,*last; @@ -391,18 +410,16 @@ int *reason; return(last); } -int BIO_get_retry_reason(bio) -BIO *bio; +int BIO_get_retry_reason(BIO *bio) { return(bio->retry_reason); } -BIO *BIO_find_type(bio,type) -BIO *bio; -int type; +BIO *BIO_find_type(BIO *bio, int type) { int mt,mask; + if(!bio) return NULL; mask=type&0xff; do { if (bio->method != NULL) @@ -421,8 +438,13 @@ int type; return(NULL); } -void BIO_free_all(bio) -BIO *bio; +BIO *BIO_next(BIO *b) + { + if(!b) return NULL; + return b->next_bio; + } + +void BIO_free_all(BIO *bio) { BIO *b; int ref; @@ -438,8 +460,7 @@ BIO *bio; } } -BIO *BIO_dup_chain(in) -BIO *in; +BIO *BIO_dup_chain(BIO *in) { BIO *ret=NULL,*eoc=NULL,*bio,*new; @@ -461,9 +482,10 @@ BIO *in; goto err; } - /* copy app data */ - if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data)) - goto err; + /* copy app data */ + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data, + &bio->ex_data)) + goto err; if (ret == NULL) { @@ -483,37 +505,39 @@ err: return(NULL); } -void BIO_copy_next_retry(b) -BIO *b; +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(argl,argp,new_func,dup_func,free_func) -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*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,idx,data) -BIO *bio; -int idx; -char *data; +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) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, 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)); } -char *BIO_get_ex_data(bio,idx) -BIO *bio; -int idx; +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; +} + +IMPLEMENT_STACK_OF(BIO) diff --git a/src/lib/libcrypto/bio/bss_acpt.c b/src/lib/libcrypto/bio/bss_acpt.c index e49902fa9f..8ea1db158b 100644 --- a/src/lib/libcrypto/bio/bss_acpt.c +++ b/src/lib/libcrypto/bio/bss_acpt.c @@ -56,22 +56,25 @@ * [including the GNU Public Licence.] */ -#ifndef NO_SOCK +#ifndef OPENSSL_NO_SOCK #include #include #define USE_SOCKETS #include "cryptlib.h" -#include "bio.h" +#include -/* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */ - -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ #else #define SOCKET_PROTOCOL IPPROTO_TCP #endif +#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) +/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ +#undef FIONBIO +#endif + typedef struct bio_accept_st { int state; @@ -82,39 +85,24 @@ typedef struct bio_accept_st char *addr; int nbio; + /* If 0, it means normal, if 1, do a connect on bind failure, + * and if there is no-one listening, bind with SO_REUSEADDR. + * If 2, always use SO_REUSEADDR. */ + int bind_mode; BIO *bio_chain; } BIO_ACCEPT; -#ifndef NOPROTO -static int acpt_write(BIO *h,char *buf,int num); -static int acpt_read(BIO *h,char *buf,int size); -static int acpt_puts(BIO *h,char *str); -static long acpt_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int acpt_write(BIO *h, const char *buf, int num); +static int acpt_read(BIO *h, char *buf, int size); +static int acpt_puts(BIO *h, const char *str); +static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int acpt_new(BIO *h); static int acpt_free(BIO *data); -#else -static int acpt_write(); -static int acpt_read(); -static int acpt_puts(); -static long acpt_ctrl(); -static int acpt_new(); -static int acpt_free(); -#endif - -#ifndef NOPROTO static int acpt_state(BIO *b, BIO_ACCEPT *c); static void acpt_close_socket(BIO *data); BIO_ACCEPT *BIO_ACCEPT_new(void ); void BIO_ACCEPT_free(BIO_ACCEPT *a); -#else - -static int acpt_state(); -static void acpt_close_socket(); -BIO_ACCEPT *BIO_ACCEPT_new(); -void BIO_ACCEPT_free(); -#endif - #define ACPT_S_BEFORE 1 #define ACPT_S_GET_ACCEPT_SOCKET 2 #define ACPT_S_OK 3 @@ -130,15 +118,15 @@ static BIO_METHOD methods_acceptp= acpt_ctrl, acpt_new, acpt_free, + NULL, }; -BIO_METHOD *BIO_s_accept() +BIO_METHOD *BIO_s_accept(void) { return(&methods_acceptp); } -static int acpt_new(bi) -BIO *bi; +static int acpt_new(BIO *bi) { BIO_ACCEPT *ba; @@ -153,29 +141,31 @@ BIO *bi; return(1); } -BIO_ACCEPT *BIO_ACCEPT_new() +BIO_ACCEPT *BIO_ACCEPT_new(void) { BIO_ACCEPT *ret; - if ((ret=(BIO_ACCEPT *)Malloc(sizeof(BIO_ACCEPT))) == NULL) + if ((ret=(BIO_ACCEPT *)OPENSSL_malloc(sizeof(BIO_ACCEPT))) == NULL) return(NULL); memset(ret,0,sizeof(BIO_ACCEPT)); ret->accept_sock=INVALID_SOCKET; + ret->bind_mode=BIO_BIND_NORMAL; return(ret); } -void BIO_ACCEPT_free(a) -BIO_ACCEPT *a; +void BIO_ACCEPT_free(BIO_ACCEPT *a) { - if (a->param_addr != NULL) Free(a->param_addr); - if (a->addr != NULL) Free(a->addr); + if(a == NULL) + return; + + if (a->param_addr != NULL) OPENSSL_free(a->param_addr); + if (a->addr != NULL) OPENSSL_free(a->addr); if (a->bio_chain != NULL) BIO_free(a->bio_chain); - Free(a); + OPENSSL_free(a); } -static void acpt_close_socket(bio) -BIO *bio; +static void acpt_close_socket(BIO *bio) { BIO_ACCEPT *c; @@ -183,18 +173,13 @@ BIO *bio; if (c->accept_sock != INVALID_SOCKET) { shutdown(c->accept_sock,2); -# ifdef WINDOWS closesocket(c->accept_sock); -# else - close(c->accept_sock); -# endif c->accept_sock=INVALID_SOCKET; bio->num=INVALID_SOCKET; } } -static int acpt_free(a) -BIO *a; +static int acpt_free(BIO *a) { BIO_ACCEPT *data; @@ -212,12 +197,9 @@ BIO *a; return(1); } -static int acpt_state(b,c) -BIO *b; -BIO_ACCEPT *c; +static int acpt_state(BIO *b, BIO_ACCEPT *c) { BIO *bio=NULL,*dbio; - unsigned long l=1; int s= -1; int i; @@ -230,56 +212,58 @@ again: BIOerr(BIO_F_ACPT_STATE,BIO_R_NO_ACCEPT_PORT_SPECIFIED); return(-1); } - s=BIO_get_accept_socket(c->param_addr); + s=BIO_get_accept_socket(c->param_addr,c->bind_mode); if (s == INVALID_SOCKET) return(-1); -#ifdef FIONBIO if (c->accept_nbio) { - i=BIO_socket_ioctl(b->num,FIONBIO,&l); - if (i < 0) + if (!BIO_socket_nbio(s,1)) { -#ifdef WINDOWS closesocket(s); -#else - close(s); -# endif BIOerr(BIO_F_ACPT_STATE,BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET); return(-1); } } -#endif c->accept_sock=s; b->num=s; c->state=ACPT_S_GET_ACCEPT_SOCKET; return(1); - break; + /* break; */ case ACPT_S_GET_ACCEPT_SOCKET: if (b->next_bio != NULL) { c->state=ACPT_S_OK; goto again; } + BIO_clear_retry_flags(b); + b->retry_reason=0; i=BIO_accept(c->accept_sock,&(c->addr)); + + /* -2 return means we should retry */ + if(i == -2) + { + BIO_set_retry_special(b); + b->retry_reason=BIO_RR_ACCEPT; + return -1; + } + if (i < 0) return(i); + bio=BIO_new_socket(i,BIO_CLOSE); if (bio == NULL) goto err; BIO_set_callback(bio,BIO_get_callback(b)); BIO_set_callback_arg(bio,BIO_get_callback_arg(b)); -#ifdef FIONBIO if (c->nbio) { - i=BIO_socket_ioctl(i,FIONBIO,&l); - if (i < 0) + if (!BIO_socket_nbio(i,1)) { BIOerr(BIO_F_ACPT_STATE,BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET); goto err; } } -#endif /* If the accept BIO has an bio_chain, we dup it and * put the new socket at the end. */ @@ -298,15 +282,9 @@ err: if (bio != NULL) BIO_free(bio); else if (s >= 0) - { -#ifdef WINDOWS closesocket(s); -#else - close(s); -# endif - } return(0); - break; + /* break; */ case ACPT_S_OK: if (b->next_bio == NULL) { @@ -314,23 +292,20 @@ err: goto again; } return(1); - break; + /* break; */ default: return(0); - break; + /* break; */ } } -static int acpt_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int acpt_read(BIO *b, char *out, int outl) { int ret=0; BIO_ACCEPT *data; - BIO_clear_retry_flags(b); + BIO_clear_retry_flags(b); data=(BIO_ACCEPT *)b->ptr; while (b->next_bio == NULL) @@ -344,10 +319,7 @@ int outl; return(ret); } -static int acpt_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int acpt_write(BIO *b, const char *in, int inl) { int ret; BIO_ACCEPT *data; @@ -366,11 +338,7 @@ int inl; return(ret); } -static long acpt_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; int *ip; @@ -399,7 +367,7 @@ char *ptr; { b->init=1; if (data->param_addr != NULL) - Free(data->param_addr); + OPENSSL_free(data->param_addr); data->param_addr=BUF_strdup(ptr); } else if (num == 1) @@ -417,13 +385,21 @@ char *ptr; case BIO_C_SET_NBIO: data->nbio=(int)num; break; + case BIO_C_SET_FD: + b->init=1; + b->num= *((int *)ptr); + data->accept_sock=b->num; + data->state=ACPT_S_GET_ACCEPT_SOCKET; + b->shutdown=(int)num; + b->init=1; + break; case BIO_C_GET_FD: if (b->init) { ip=(int *)ptr; if (ip != NULL) *ip=data->accept_sock; - ret=b->num; + ret=data->accept_sock; } else ret= -1; @@ -454,6 +430,12 @@ char *ptr; break; case BIO_CTRL_FLUSH: break; + case BIO_C_SET_BIND_MODE: + data->bind_mode=(int)num; + break; + case BIO_C_GET_BIND_MODE: + ret=(long)data->bind_mode; + break; case BIO_CTRL_DUP: dbio=(BIO *)ptr; /* if (data->param_port) EAY EAY @@ -470,9 +452,7 @@ char *ptr; return(ret); } -static int acpt_puts(bp,str) -BIO *bp; -char *str; +static int acpt_puts(BIO *bp, const char *str) { int n,ret; @@ -481,8 +461,7 @@ char *str; return(ret); } -BIO *BIO_new_accept(str) -char *str; +BIO *BIO_new_accept(char *str) { BIO *ret; diff --git a/src/lib/libcrypto/bio/bss_bio.c b/src/lib/libcrypto/bio/bss_bio.c index 562e9d8de2..1c485a4479 100644 --- a/src/lib/libcrypto/bio/bss_bio.c +++ b/src/lib/libcrypto/bio/bss_bio.c @@ -7,25 +7,46 @@ * for which no specific BIO method is available. * See ssl/ssltest.c for some hints on how this can be used. */ +/* BIO_DEBUG implies BIO_PAIR_DEBUG */ +#ifdef BIO_DEBUG +# ifndef BIO_PAIR_DEBUG +# define BIO_PAIR_DEBUG +# endif +#endif + +/* disable assert() unless BIO_PAIR_DEBUG has been defined */ #ifndef BIO_PAIR_DEBUG -# undef NDEBUG /* avoid conflicting definitions */ -# define NDEBUG +# ifndef NDEBUG +# define NDEBUG +# endif #endif #include +#include #include #include #include #include +#include #include +#include "e_os.h" + +/* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ +#if defined(OPENSSL_SYS_VSWORKS) +# undef SSIZE_MAX +#endif +#ifndef SSIZE_MAX +# define SSIZE_MAX INT_MAX +#endif + static int bio_new(BIO *bio); static int bio_free(BIO *bio); static int bio_read(BIO *bio, char *buf, int size); -static int bio_write(BIO *bio, char *buf, int num); +static int bio_write(BIO *bio, const char *buf, int num); static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); -static int bio_puts(BIO *bio, char *str); +static int bio_puts(BIO *bio, const char *str); static int bio_make_pair(BIO *bio1, BIO *bio2); static void bio_destroy_pair(BIO *bio); @@ -40,7 +61,8 @@ static BIO_METHOD methods_biop = NULL /* no bio_gets */, bio_ctrl, bio_new, - bio_free + bio_free, + NULL /* no bio_callback_ctrl */ }; BIO_METHOD *BIO_s_bio(void) @@ -64,7 +86,7 @@ struct bio_bio_st size_t request; /* valid iff peer != NULL; 0 if len != 0, * otherwise set by peer to number of bytes - * it (unsuccesfully) tried to read, + * it (unsuccessfully) tried to read, * never more than buffer space (size-len) warrants. */ }; @@ -72,7 +94,7 @@ static int bio_new(BIO *bio) { struct bio_bio_st *b; - b = Malloc(sizeof *b); + b = OPENSSL_malloc(sizeof *b); if (b == NULL) return 0; @@ -100,10 +122,10 @@ static int bio_free(BIO *bio) if (b->buf != NULL) { - Free(b->buf); + OPENSSL_free(b->buf); } - Free(b); + OPENSSL_free(b); return 1; } @@ -195,7 +217,87 @@ static int bio_read(BIO *bio, char *buf, int size_) return size; } -static int bio_write(BIO *bio, char *buf, int num_) +/* non-copying interface: provide pointer to available data in buffer + * bio_nread0: return number of available bytes + * bio_nread: also advance index + * (example usage: bio_nread0(), read from buffer, bio_nread() + * or just bio_nread(), read from buffer) + */ +/* WARNING: The non-copying interface is largely untested as of yet + * and may contain bugs. */ +static ssize_t bio_nread0(BIO *bio, char **buf) + { + struct bio_bio_st *b, *peer_b; + ssize_t num; + + BIO_clear_retry_flags(bio); + + if (!bio->init) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + peer_b = b->peer->ptr; + assert(peer_b != NULL); + assert(peer_b->buf != NULL); + + peer_b->request = 0; + + if (peer_b->len == 0) + { + char dummy; + + /* avoid code duplication -- nothing available for reading */ + return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ + } + + num = peer_b->len; + if (peer_b->size < peer_b->offset + num) + /* no ring buffer wrap-around for non-copying interface */ + num = peer_b->size - peer_b->offset; + assert(num > 0); + + if (buf != NULL) + *buf = peer_b->buf + peer_b->offset; + return num; + } + +static ssize_t bio_nread(BIO *bio, char **buf, size_t num_) + { + struct bio_bio_st *b, *peer_b; + ssize_t num, available; + + if (num_ > SSIZE_MAX) + num = SSIZE_MAX; + else + num = (ssize_t)num_; + + available = bio_nread0(bio, buf); + if (num > available) + num = available; + if (num <= 0) + return num; + + b = bio->ptr; + peer_b = b->peer->ptr; + + peer_b->len -= num; + if (peer_b->len) + { + peer_b->offset += num; + assert(peer_b->offset <= peer_b->size); + if (peer_b->offset == peer_b->size) + peer_b->offset = 0; + } + else + peer_b->offset = 0; + + return num; + } + + +static int bio_write(BIO *bio, const char *buf, int num_) { size_t num = num_; size_t rest; @@ -268,6 +370,83 @@ static int bio_write(BIO *bio, char *buf, int num_) return num; } +/* non-copying interface: provide pointer to region to write to + * bio_nwrite0: check how much space is available + * bio_nwrite: also increase length + * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() + * or just bio_nwrite(), write to buffer) + */ +static ssize_t bio_nwrite0(BIO *bio, char **buf) + { + struct bio_bio_st *b; + size_t num; + size_t write_offset; + + BIO_clear_retry_flags(bio); + + if (!bio->init) + return 0; + + b = bio->ptr; + assert(b != NULL); + assert(b->peer != NULL); + assert(b->buf != NULL); + + b->request = 0; + if (b->closed) + { + BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); + return -1; + } + + assert(b->len <= b->size); + + if (b->len == b->size) + { + BIO_set_retry_write(bio); + return -1; + } + + num = b->size - b->len; + write_offset = b->offset + b->len; + if (write_offset >= b->size) + write_offset -= b->size; + if (write_offset + num > b->size) + /* no ring buffer wrap-around for non-copying interface + * (to fulfil the promise by BIO_ctrl_get_write_guarantee, + * BIO_nwrite may have to be called twice) */ + num = b->size - write_offset; + + if (buf != NULL) + *buf = b->buf + write_offset; + assert(write_offset + num <= b->size); + + return num; + } + +static ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) + { + struct bio_bio_st *b; + ssize_t num, space; + + if (num_ > SSIZE_MAX) + num = SSIZE_MAX; + else + num = (ssize_t)num_; + + space = bio_nwrite0(bio, buf); + if (num > space) + num = space; + if (num <= 0) + return num; + b = bio->ptr; + assert(b != NULL); + b->len += num; + assert(b->len <= b->size); + + return num; + } + static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { @@ -299,7 +478,7 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { if (b->buf) { - Free(b->buf); + OPENSSL_free(b->buf); b->buf = NULL; } b->size = new_size; @@ -309,7 +488,8 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) break; case BIO_C_GET_WRITE_BUF_SIZE: - num = (long) b->size; + ret = (long) b->size; + break; case BIO_C_MAKE_BIO_PAIR: { @@ -331,7 +511,7 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) case BIO_C_GET_WRITE_GUARANTEE: /* How many bytes can the caller feed to the next write - * withouth having to keep any? */ + * without having to keep any? */ if (b->peer == NULL || b->closed) ret = 0; else @@ -339,18 +519,47 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) break; case BIO_C_GET_READ_REQUEST: - /* If the peer unsuccesfully tried to read, how many bytes + /* If the peer unsuccessfully tried to read, how many bytes * were requested? (As with BIO_CTRL_PENDING, that number * can usually be treated as boolean.) */ ret = (long) b->request; break; + case BIO_C_RESET_READ_REQUEST: + /* Reset request. (Can be useful after read attempts + * at the other side that are meant to be non-blocking, + * e.g. when probing SSL_read to see if any data is + * available.) */ + b->request = 0; + ret = 1; + break; + case BIO_C_SHUTDOWN_WR: /* similar to shutdown(..., SHUT_WR) */ b->closed = 1; ret = 1; break; + case BIO_C_NREAD0: + /* prepare for non-copying read */ + ret = (long) bio_nread0(bio, ptr); + break; + + case BIO_C_NREAD: + /* non-copying read */ + ret = (long) bio_nread(bio, ptr, (size_t) num); + break; + + case BIO_C_NWRITE0: + /* prepare for non-copying write */ + ret = (long) bio_nwrite0(bio, ptr); + break; + + case BIO_C_NWRITE: + /* non-copying write */ + ret = (long) bio_nwrite(bio, ptr, (size_t) num); + break; + /* standard CTRL codes follow */ @@ -434,7 +643,7 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) return ret; } -static int bio_puts(BIO *bio, char *str) +static int bio_puts(BIO *bio, const char *str) { return bio_write(bio, str, strlen(str)); } @@ -458,7 +667,7 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) if (b1->buf == NULL) { - b1->buf = Malloc(b1->size); + b1->buf = OPENSSL_malloc(b1->size); if (b1->buf == NULL) { BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); @@ -470,7 +679,7 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) if (b2->buf == NULL) { - b2->buf = Malloc(b2->size); + b2->buf = OPENSSL_malloc(b2->size); if (b2->buf == NULL) { BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); @@ -586,3 +795,78 @@ size_t BIO_ctrl_get_read_request(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); } + +int BIO_ctrl_reset_read_request(BIO *bio) + { + return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); + } + + +/* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now + * (conceivably some other BIOs could allow non-copying reads and writes too.) + */ +int BIO_nread0(BIO *bio, char **buf) + { + long ret; + + if (!bio->init) + { + BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); + return -2; + } + + ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); + if (ret > INT_MAX) + return INT_MAX; + else + return (int) ret; + } + +int BIO_nread(BIO *bio, char **buf, int num) + { + int ret; + + if (!bio->init) + { + BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); + return -2; + } + + ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); + if (ret > 0) + bio->num_read += ret; + return ret; + } + +int BIO_nwrite0(BIO *bio, char **buf) + { + long ret; + + if (!bio->init) + { + BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); + return -2; + } + + ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); + if (ret > INT_MAX) + return INT_MAX; + else + return (int) ret; + } + +int BIO_nwrite(BIO *bio, char **buf, int num) + { + int ret; + + if (!bio->init) + { + BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); + return -2; + } + + ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); + if (ret > 0) + bio->num_read += ret; + return ret; + } diff --git a/src/lib/libcrypto/bio/bss_conn.c b/src/lib/libcrypto/bio/bss_conn.c index 6e547bf866..f91ae4c8c6 100644 --- a/src/lib/libcrypto/bio/bss_conn.c +++ b/src/lib/libcrypto/bio/bss_conn.c @@ -56,22 +56,26 @@ * [including the GNU Public Licence.] */ -#ifndef NO_SOCK +#ifndef OPENSSL_NO_SOCK #include #include #define USE_SOCKETS #include "cryptlib.h" -#include "bio.h" +#include -/* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */ - -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ #else #define SOCKET_PROTOCOL IPPROTO_TCP #endif +#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) +/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ +#undef FIONBIO +#endif + + typedef struct bio_connect_st { int state; @@ -81,52 +85,32 @@ typedef struct bio_connect_st int nbio; unsigned char ip[4]; - short port; + unsigned short port; struct sockaddr_in them; /* int socket; this will be kept in bio->num so that it is - * compatable with the bss_sock bio */ - int error; + * compatible with the bss_sock bio */ /* called when the connection is initially made * callback(BIO,state,ret); The callback should return - * 'ret'. state is for compatablity with the ssl info_callback */ - int (*info_callback)(); + * 'ret'. state is for compatibility with the ssl info_callback */ + int (*info_callback)(const BIO *bio,int state,int ret); } BIO_CONNECT; -#ifndef NOPROTO -static int conn_write(BIO *h,char *buf,int num); -static int conn_read(BIO *h,char *buf,int size); -static int conn_puts(BIO *h,char *str); -static long conn_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int conn_write(BIO *h, const char *buf, int num); +static int conn_read(BIO *h, char *buf, int size); +static int conn_puts(BIO *h, const char *str); +static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int conn_new(BIO *h); static int conn_free(BIO *data); -#else -static int conn_write(); -static int conn_read(); -static int conn_puts(); -static long conn_ctrl(); -static int conn_new(); -static int conn_free(); -#endif - -#ifndef NOPROTO +static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *); static int conn_state(BIO *b, BIO_CONNECT *c); static void conn_close_socket(BIO *data); BIO_CONNECT *BIO_CONNECT_new(void ); void BIO_CONNECT_free(BIO_CONNECT *a); -#else - -static int conn_state(); -static void conn_close_socket(); -BIO_CONNECT *BIO_CONNECT_new(); -void BIO_CONNECT_free(); - -#endif - static BIO_METHOD methods_connectp= { BIO_TYPE_CONNECT, @@ -138,11 +122,10 @@ static BIO_METHOD methods_connectp= conn_ctrl, conn_new, conn_free, + conn_callback_ctrl, }; -static int conn_state(b,c) -BIO *b; -BIO_CONNECT *c; +static int conn_state(BIO *b, BIO_CONNECT *c) { int ret= -1,i; unsigned long l; @@ -160,7 +143,7 @@ BIO_CONNECT *c; p=c->param_hostname; if (p == NULL) { - BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTHNAME_SPECIFIED); + BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED); goto exit_loop; } for ( ; *p != '\0'; p++) @@ -182,12 +165,12 @@ BIO_CONNECT *c; break; } if (c->param_port != NULL) - Free(c->param_port); + OPENSSL_free(c->param_port); c->param_port=BUF_strdup(p); } } - if (p == NULL) + if (c->param_port == NULL) { BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED); ERR_add_error_data(2,"host=",c->param_hostname); @@ -203,7 +186,12 @@ BIO_CONNECT *c; break; case BIO_CONN_S_GET_PORT: - if (BIO_get_port(c->param_port,&c->port) <= 0) + if (c->param_port == NULL) + { + /* abort(); */ + goto exit_loop; + } + else if (BIO_get_port(c->param_port,&c->port) <= 0) goto exit_loop; c->state=BIO_CONN_S_CREATE_SOCKET; break; @@ -235,12 +223,9 @@ BIO_CONNECT *c; break; case BIO_CONN_S_NBIO: -#ifdef FIONBIO if (c->nbio) { - l=1; - ret=BIO_socket_ioctl(b->num,FIONBIO,&l); - if (ret < 0) + if (!BIO_socket_nbio(b->num,1)) { BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO); ERR_add_error_data(4,"host=", @@ -249,10 +234,9 @@ BIO_CONNECT *c; goto exit_loop; } } -#endif c->state=BIO_CONN_S_CONNECT; -#ifdef SO_KEEPALIVE +#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) i=1; i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); if (i < 0) @@ -315,7 +299,7 @@ BIO_CONNECT *c; ret=1; goto exit_loop; default: - abort(); + /* abort(); */ goto exit_loop; } @@ -326,21 +310,19 @@ BIO_CONNECT *c; } } - if (1) - { + /* Loop does not exit */ exit_loop: - if (cb != NULL) - ret=cb((BIO *)b,c->state,ret); - } + if (cb != NULL) + ret=cb((BIO *)b,c->state,ret); end: return(ret); } -BIO_CONNECT *BIO_CONNECT_new() +BIO_CONNECT *BIO_CONNECT_new(void) { BIO_CONNECT *ret; - if ((ret=(BIO_CONNECT *)Malloc(sizeof(BIO_CONNECT))) == NULL) + if ((ret=(BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL) return(NULL); ret->state=BIO_CONN_S_BEFORE; ret->param_hostname=NULL; @@ -353,27 +335,27 @@ BIO_CONNECT *BIO_CONNECT_new() ret->ip[3]=0; ret->port=0; memset((char *)&ret->them,0,sizeof(ret->them)); - ret->error=0; return(ret); } -void BIO_CONNECT_free(a) -BIO_CONNECT *a; +void BIO_CONNECT_free(BIO_CONNECT *a) { + if(a == NULL) + return; + if (a->param_hostname != NULL) - Free(a->param_hostname); + OPENSSL_free(a->param_hostname); if (a->param_port != NULL) - Free(a->param_port); - Free(a); + OPENSSL_free(a->param_port); + OPENSSL_free(a); } -BIO_METHOD *BIO_s_connect() +BIO_METHOD *BIO_s_connect(void) { return(&methods_connectp); } -static int conn_new(bi) -BIO *bi; +static int conn_new(BIO *bi) { bi->init=0; bi->num=INVALID_SOCKET; @@ -384,8 +366,7 @@ BIO *bi; return(1); } -static void conn_close_socket(bio) -BIO *bio; +static void conn_close_socket(BIO *bio) { BIO_CONNECT *c; @@ -395,17 +376,12 @@ BIO *bio; /* Only do a shutdown if things were established */ if (c->state == BIO_CONN_S_OK) shutdown(bio->num,2); -# ifdef WINDOWS closesocket(bio->num); -# else - close(bio->num); -# endif bio->num=INVALID_SOCKET; } } -static int conn_free(a) -BIO *a; +static int conn_free(BIO *a) { BIO_CONNECT *data; @@ -423,10 +399,7 @@ BIO *a; return(1); } -static int conn_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int conn_read(BIO *b, char *out, int outl) { int ret=0; BIO_CONNECT *data; @@ -442,11 +415,7 @@ int outl; if (out != NULL) { clear_socket_error(); -#if defined(WINDOWS) - ret=recv(b->num,out,outl,0); -#else - ret=read(b->num,out,outl); -#endif + ret=readsocket(b->num,out,outl); BIO_clear_retry_flags(b); if (ret <= 0) { @@ -457,10 +426,7 @@ int outl; return(ret); } -static int conn_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int conn_write(BIO *b, const char *in, int inl) { int ret; BIO_CONNECT *data; @@ -473,11 +439,7 @@ int inl; } clear_socket_error(); -#if defined(WINDOWS) - ret=send(b->num,in,inl,0); -#else - ret=write(b->num,in,inl); -#endif + ret=writesocket(b->num,in,inl); BIO_clear_retry_flags(b); if (ret <= 0) { @@ -487,15 +449,11 @@ int inl; return(ret); } -static long conn_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; int *ip; - char **pptr; + const char **pptr; long ret=1; BIO_CONNECT *data; @@ -519,7 +477,7 @@ char *ptr; case BIO_C_GET_CONNECT: if (ptr != NULL) { - pptr=(char **)ptr; + pptr=(const char **)ptr; if (num == 0) { *pptr=data->param_hostname; @@ -538,7 +496,7 @@ char *ptr; *((int *)ptr)=data->port; } if ((!b->init) || (ptr == NULL)) - *pptr="not initalised"; + *pptr="not initialized"; ret=1; } break; @@ -549,19 +507,37 @@ char *ptr; if (num == 0) { if (data->param_hostname != NULL) - Free(data->param_hostname); + OPENSSL_free(data->param_hostname); data->param_hostname=BUF_strdup(ptr); } else if (num == 1) { if (data->param_port != NULL) - Free(data->param_port); + OPENSSL_free(data->param_port); data->param_port=BUF_strdup(ptr); } else if (num == 2) - memcpy(data->ip,ptr,4); + { + char buf[16]; + char *p = ptr; + + sprintf(buf,"%d.%d.%d.%d", + p[0],p[1],p[2],p[3]); + if (data->param_hostname != NULL) + OPENSSL_free(data->param_hostname); + data->param_hostname=BUF_strdup(buf); + memcpy(&(data->ip[0]),ptr,4); + } else if (num == 3) + { + char buf[16]; + + sprintf(buf,"%d",*(int *)ptr); + if (data->param_port != NULL) + OPENSSL_free(data->param_port); + data->param_port=BUF_strdup(buf); data->port= *(int *)ptr; + } } break; case BIO_C_SET_NBIO: @@ -591,16 +567,26 @@ char *ptr; case BIO_CTRL_FLUSH: break; case BIO_CTRL_DUP: + { dbio=(BIO *)ptr; if (data->param_port) BIO_set_conn_port(dbio,data->param_port); if (data->param_hostname) BIO_set_conn_hostname(dbio,data->param_hostname); BIO_set_nbio(dbio,data->nbio); - BIO_set_info_callback(dbio,data->info_callback); + /* FIXME: the cast of the function seems unlikely to be a good idea */ + (void)BIO_set_info_callback(dbio,(bio_info_cb *)data->info_callback); + } break; case BIO_CTRL_SET_CALLBACK: - data->info_callback=(int (*)())ptr; + { +#if 0 /* FIXME: Should this be used? -- Richard Levitte */ + BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ret = -1; +#else + ret=0; +#endif + } break; case BIO_CTRL_GET_CALLBACK: { @@ -617,9 +603,28 @@ char *ptr; return(ret); } -static int conn_puts(bp,str) -BIO *bp; -char *str; +static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + BIO_CONNECT *data; + + data=(BIO_CONNECT *)b->ptr; + + switch (cmd) + { + case BIO_CTRL_SET_CALLBACK: + { + data->info_callback=(int (*)(const struct bio_st *, int, int))fp; + } + break; + default: + ret=0; + break; + } + return(ret); + } + +static int conn_puts(BIO *bp, const char *str) { int n,ret; @@ -628,8 +633,7 @@ char *str; return(ret); } -BIO *BIO_new_connect(str) -char *str; +BIO *BIO_new_connect(char *str) { BIO *ret; diff --git a/src/lib/libcrypto/bio/bss_fd.c b/src/lib/libcrypto/bio/bss_fd.c index 686c4909a2..5e3e187de6 100644 --- a/src/lib/libcrypto/bio/bss_fd.c +++ b/src/lib/libcrypto/bio/bss_fd.c @@ -56,7 +56,227 @@ * [including the GNU Public Licence.] */ -#define BIO_FD -#include "bss_sock.c" -#undef BIO_FD +#include +#include +#define USE_SOCKETS +#include "cryptlib.h" +#include +static int fd_write(BIO *h, const char *buf, int num); +static int fd_read(BIO *h, char *buf, int size); +static int fd_puts(BIO *h, const char *str); +static long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int fd_new(BIO *h); +static int fd_free(BIO *data); +int BIO_fd_should_retry(int s); + +static BIO_METHOD methods_fdp= + { + BIO_TYPE_FD,"file descriptor", + fd_write, + fd_read, + fd_puts, + NULL, /* fd_gets, */ + fd_ctrl, + fd_new, + fd_free, + NULL, + }; + +BIO_METHOD *BIO_s_fd(void) + { + return(&methods_fdp); + } + +BIO *BIO_new_fd(int fd,int close_flag) + { + BIO *ret; + ret=BIO_new(BIO_s_fd()); + if (ret == NULL) return(NULL); + BIO_set_fd(ret,fd,close_flag); + return(ret); + } + +static int fd_new(BIO *bi) + { + bi->init=0; + bi->num=0; + bi->ptr=NULL; + bi->flags=0; + return(1); + } + +static int fd_free(BIO *a) + { + if (a == NULL) return(0); + if (a->shutdown) + { + if (a->init) + { + close(a->num); + } + a->init=0; + a->flags=0; + } + return(1); + } + +static int fd_read(BIO *b, char *out,int outl) + { + int ret=0; + + if (out != NULL) + { + clear_sys_error(); + ret=read(b->num,out,outl); + BIO_clear_retry_flags(b); + if (ret <= 0) + { + if (BIO_fd_should_retry(ret)) + BIO_set_retry_read(b); + } + } + return(ret); + } + +static int fd_write(BIO *b, const char *in, int inl) + { + int ret; + clear_sys_error(); + ret=write(b->num,in,inl); + BIO_clear_retry_flags(b); + if (ret <= 0) + { + if (BIO_fd_should_retry(ret)) + BIO_set_retry_write(b); + } + return(ret); + } + +static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) + { + long ret=1; + int *ip; + + switch (cmd) + { + case BIO_CTRL_RESET: + num=0; + case BIO_C_FILE_SEEK: + ret=(long)lseek(b->num,num,0); + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret=(long)lseek(b->num,0,1); + break; + case BIO_C_SET_FD: + fd_free(b); + b->num= *((int *)ptr); + b->shutdown=(int)num; + b->init=1; + break; + case BIO_C_GET_FD: + if (b->init) + { + ip=(int *)ptr; + if (ip != NULL) *ip=b->num; + ret=b->num; + } + else + ret= -1; + break; + case BIO_CTRL_GET_CLOSE: + ret=b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown=(int)num; + break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: + ret=0; + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret=1; + break; + default: + ret=0; + break; + } + return(ret); + } + +static int fd_puts(BIO *bp, const char *str) + { + int n,ret; + + n=strlen(str); + ret=fd_write(bp,str,n); + return(ret); + } + +int BIO_fd_should_retry(int i) + { + int err; + + if ((i == 0) || (i == -1)) + { + err=get_last_sys_error(); + +#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ + if ((i == -1) && (err == 0)) + return(1); +#endif + + return(BIO_fd_non_fatal_error(err)); + } + return(0); + } + +int BIO_fd_non_fatal_error(int err) + { + switch (err) + { + +#ifdef EWOULDBLOCK +# ifdef WSAEWOULDBLOCK +# if WSAEWOULDBLOCK != EWOULDBLOCK + case EWOULDBLOCK: +# endif +# else + case EWOULDBLOCK: +# endif +#endif + +#if defined(ENOTCONN) + case ENOTCONN: +#endif + +#ifdef EINTR + case EINTR: +#endif + +#ifdef EAGAIN +#if EWOULDBLOCK != EAGAIN + case EAGAIN: +# endif +#endif + +#ifdef EPROTO + case EPROTO: +#endif + +#ifdef EINPROGRESS + case EINPROGRESS: +#endif + +#ifdef EALREADY + case EALREADY: +#endif + return(1); + /* break; */ + default: + break; + } + return(0); + } diff --git a/src/lib/libcrypto/bio/bss_file.c b/src/lib/libcrypto/bio/bss_file.c index 1484cf849e..8b3ff278d9 100644 --- a/src/lib/libcrypto/bio/bss_file.c +++ b/src/lib/libcrypto/bio/bss_file.c @@ -68,29 +68,18 @@ #include #include #include "cryptlib.h" -#include "bio.h" -#include "err.h" +#include +#include -#if !defined(NO_STDIO) +#if !defined(OPENSSL_NO_STDIO) -#ifndef NOPROTO -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_write(BIO *h, const char *buf, int num); +static int MS_CALLBACK file_read(BIO *h, char *buf, int size); +static int MS_CALLBACK file_puts(BIO *h, const 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, void *arg2); static int MS_CALLBACK file_new(BIO *h); static int MS_CALLBACK file_free(BIO *data); -#else -static int MS_CALLBACK file_write(); -static int MS_CALLBACK file_read(); -static int MS_CALLBACK file_puts(); -static int MS_CALLBACK file_gets(); -static long MS_CALLBACK file_ctrl(); -static int MS_CALLBACK file_new(); -static int MS_CALLBACK file_free(); -#endif - static BIO_METHOD methods_filep= { BIO_TYPE_FILE, @@ -102,11 +91,10 @@ static BIO_METHOD methods_filep= file_ctrl, file_new, file_free, + NULL, }; -BIO *BIO_new_file(filename,mode) -char *filename; -char *mode; +BIO *BIO_new_file(const char *filename, const char *mode) { BIO *ret; FILE *file; @@ -115,7 +103,10 @@ char *mode; { 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); + if (errno == ENOENT) + BIOerr(BIO_F_BIO_NEW_FILE,BIO_R_NO_SUCH_FILE); + else + BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB); return(NULL); } if ((ret=BIO_new(BIO_s_file_internal())) == NULL) @@ -125,9 +116,7 @@ char *mode; return(ret); } -BIO *BIO_new_fp(stream,close_flag) -FILE *stream; -int close_flag; +BIO *BIO_new_fp(FILE *stream, int close_flag) { BIO *ret; @@ -138,13 +127,12 @@ int close_flag; return(ret); } -BIO_METHOD *BIO_s_file() +BIO_METHOD *BIO_s_file(void) { return(&methods_filep); } -static int MS_CALLBACK file_new(bi) -BIO *bi; +static int MS_CALLBACK file_new(BIO *bi) { bi->init=0; bi->num=0; @@ -152,8 +140,7 @@ BIO *bi; return(1); } -static int MS_CALLBACK file_free(a) -BIO *a; +static int MS_CALLBACK file_free(BIO *a) { if (a == NULL) return(0); if (a->shutdown) @@ -168,10 +155,7 @@ BIO *a; return(1); } -static int MS_CALLBACK file_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int MS_CALLBACK file_read(BIO *b, char *out, int outl) { int ret=0; @@ -182,10 +166,7 @@ int outl; return(ret); } -static int MS_CALLBACK file_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int MS_CALLBACK file_write(BIO *b, const char *in, int inl) { int ret=0; @@ -194,18 +175,14 @@ int inl; if (fwrite(in,(int)inl,1,(FILE *)b->ptr)) ret=inl; /* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */ - /* acording to Tim Hudson , the commented + /* 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(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; FILE *fp=(FILE *)b->ptr; @@ -214,26 +191,33 @@ char *ptr; 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; + b->shutdown=(int)num&BIO_CLOSE; b->ptr=(char *)ptr; b->init=1; -#if defined(MSDOS) || defined(WINDOWS) +#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) /* Set correct text/binary mode */ if (num & BIO_FP_TEXT) _setmode(fileno((FILE *)ptr),_O_TEXT); else _setmode(fileno((FILE *)ptr),_O_BINARY); +#elif defined(OPENSSL_SYS_OS2) + 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: @@ -257,7 +241,7 @@ char *ptr; ret=0; break; } -#if defined(MSDOS) || defined(WINDOWS) +#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) if (!(num & BIO_FP_TEXT)) strcat(p,"b"); else @@ -307,10 +291,7 @@ char *ptr; return(ret); } -static int MS_CALLBACK file_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; +static int MS_CALLBACK file_gets(BIO *bp, char *buf, int size) { int ret=0; @@ -321,9 +302,7 @@ int size; return(ret); } -static int MS_CALLBACK file_puts(bp,str) -BIO *bp; -char *str; +static int MS_CALLBACK file_puts(BIO *bp, const char *str) { int n,ret; @@ -332,7 +311,7 @@ char *str; return(ret); } -#endif /* NO_STDIO */ +#endif /* OPENSSL_NO_STDIO */ #endif /* HEADER_BSS_FILE_C */ diff --git a/src/lib/libcrypto/bio/bss_log.c b/src/lib/libcrypto/bio/bss_log.c index db82e757e7..a39d95297c 100644 --- a/src/lib/libcrypto/bio/bss_log.c +++ b/src/lib/libcrypto/bio/bss_log.c @@ -57,8 +57,8 @@ Why BIO_s_log? BIO_s_log is useful for system daemons (or services under NT). - It is one-way BIO, it sends all stuff to syslogd (or event log - under NT). + It is one-way BIO, it sends all stuff to syslogd (on system that + commonly use that), or event log (on NT), or OPCOM (on OpenVMS). */ @@ -66,27 +66,71 @@ #include #include -#ifndef WIN32 -#ifdef __ultrix -#include -#else -#include -#endif +#include "cryptlib.h" + +#if defined(OPENSSL_SYS_WIN32) +# include +#elif defined(OPENSSL_SYS_VMS) +# include +# include +# include +# include +#elif defined(__ultrix) +# include +#elif !defined(MSDOS) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) /* Unix */ +# include #endif -#include "cryptlib.h" #include #include + #ifndef NO_SYSLOG +#if defined(OPENSSL_SYS_WIN32) +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 -static int MS_CALLBACK slg_write(BIO *h,char *buf,int num); -static int MS_CALLBACK slg_puts(BIO *h,char *str); -static long MS_CALLBACK slg_ctrl(BIO *h,int cmd,long arg1,char *arg2); +#define LOG_DAEMON (3<<3) +#elif defined(OPENSSL_SYS_VMS) +/* On VMS, we don't really care about these, but we need them to compile */ +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#define LOG_DAEMON OPC$M_NM_NTWORK +#endif + +static int MS_CALLBACK slg_write(BIO *h, const char *buf, int num); +static int MS_CALLBACK slg_puts(BIO *h, const char *str); +static long MS_CALLBACK slg_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int MS_CALLBACK slg_new(BIO *h); static int MS_CALLBACK slg_free(BIO *data); -static int xopenlog(BIO* bp, const char* name, int level); -static int xcloselog(BIO* bp); +static void xopenlog(BIO* bp, char* name, int level); +static void xsyslog(BIO* bp, int priority, const char* string); +static void xcloselog(BIO* bp); +#ifdef OPENSSL_SYS_WIN32 +LONG (WINAPI *go_for_advapi)() = RegOpenKeyEx; +HANDLE (WINAPI *register_event_source)() = NULL; +BOOL (WINAPI *deregister_event_source)() = NULL; +BOOL (WINAPI *report_event)() = NULL; +#define DL_PROC(m,f) (GetProcAddress( m, f )) +#ifdef UNICODE +#define DL_PROC_X(m,f) DL_PROC( m, f "W" ) +#else +#define DL_PROC_X(m,f) DL_PROC( m, f "A" ) +#endif +#endif static BIO_METHOD methods_slg= { @@ -98,6 +142,7 @@ static BIO_METHOD methods_slg= slg_ctrl, slg_new, slg_free, + NULL, }; BIO_METHOD *BIO_s_log(void) @@ -110,11 +155,7 @@ static int MS_CALLBACK slg_new(BIO *bi) bi->init=1; bi->num=0; bi->ptr=NULL; -#ifndef WIN32 xopenlog(bi, "application", LOG_DAEMON); -#else - xopenlog(bi, "application", 0); -#endif return(1); } @@ -125,64 +166,60 @@ static int MS_CALLBACK slg_free(BIO *a) return(1); } -static int MS_CALLBACK slg_write(BIO *b, char *in, int inl) +static int MS_CALLBACK slg_write(BIO *b, const char *in, int inl) { int ret= inl; - char* buf= in; + char* buf; char* pp; -#if defined(WIN32) - LPTSTR lpszStrings[1]; - WORD evtype= EVENTLOG_ERROR_TYPE; -#else - int priority; -#endif + int priority, i; + static struct + { + int strl; + char str[10]; + int log_level; + } + mapping[] = + { + { 6, "PANIC ", LOG_EMERG }, + { 6, "EMERG ", LOG_EMERG }, + { 4, "EMR ", LOG_EMERG }, + { 6, "ALERT ", LOG_ALERT }, + { 4, "ALR ", LOG_ALERT }, + { 5, "CRIT ", LOG_CRIT }, + { 4, "CRI ", LOG_CRIT }, + { 6, "ERROR ", LOG_ERR }, + { 4, "ERR ", LOG_ERR }, + { 8, "WARNING ", LOG_WARNING }, + { 5, "WARN ", LOG_WARNING }, + { 4, "WAR ", LOG_WARNING }, + { 7, "NOTICE ", LOG_NOTICE }, + { 5, "NOTE ", LOG_NOTICE }, + { 4, "NOT ", LOG_NOTICE }, + { 5, "INFO ", LOG_INFO }, + { 4, "INF ", LOG_INFO }, + { 6, "DEBUG ", LOG_DEBUG }, + { 4, "DBG ", LOG_DEBUG }, + { 0, "", LOG_ERR } /* The default */ + }; - if((buf= (char *)Malloc(inl+ 1)) == NULL){ + if((buf= (char *)OPENSSL_malloc(inl+ 1)) == NULL){ return(0); } strncpy(buf, in, inl); buf[inl]= '\0'; -#if defined(WIN32) - if(strncmp(buf, "ERR ", 4) == 0){ - evtype= EVENTLOG_ERROR_TYPE; - pp= buf+ 4; - }else if(strncmp(buf, "WAR ", 4) == 0){ - evtype= EVENTLOG_WARNING_TYPE; - pp= buf+ 4; - }else if(strncmp(buf, "INF ", 4) == 0){ - evtype= EVENTLOG_INFORMATION_TYPE; - pp= buf+ 4; - }else{ - evtype= EVENTLOG_ERROR_TYPE; - pp= buf; - } - lpszStrings[0]= pp; - if(b->ptr) - ReportEvent(b->ptr, evtype, 0, 1024, NULL, 1, 0, - lpszStrings, NULL); -#else - if(strncmp(buf, "ERR ", 4) == 0){ - priority= LOG_ERR; - pp= buf+ 4; - }else if(strncmp(buf, "WAR ", 4) == 0){ - priority= LOG_WARNING; - pp= buf+ 4; - }else if(strncmp(buf, "INF ", 4) == 0){ - priority= LOG_INFO; - pp= buf+ 4; - }else{ - priority= LOG_ERR; - pp= buf; - } + i = 0; + while(strncmp(buf, mapping[i].str, mapping[i].strl) != 0) i++; + priority = mapping[i].log_level; + pp = buf + mapping[i].strl; - syslog(priority, "%s", pp); -#endif - Free(buf); + xsyslog(b, priority, pp); + + OPENSSL_free(buf); return(ret); } -static long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, char *ptr) +static long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, void *ptr) { switch (cmd) { @@ -196,7 +233,7 @@ static long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, char *ptr) return(0); } -static int MS_CALLBACK slg_puts(BIO *bp, char *str) +static int MS_CALLBACK slg_puts(BIO *bp, const char *str) { int n,ret; @@ -205,28 +242,154 @@ static int MS_CALLBACK slg_puts(BIO *bp, char *str) return(ret); } -static int xopenlog(BIO* bp, const char* name, int level) +#if defined(OPENSSL_SYS_WIN32) + +static void xopenlog(BIO* bp, char* name, int level) { -#if defined(WIN32) - if((bp->ptr= (char *)RegisterEventSource(NULL, name)) == NULL){ - return(0); - } -#else - openlog(name, LOG_PID|LOG_CONS, level); -#endif - return(1); + if ( !register_event_source ) + { + HANDLE advapi; + if ( !(advapi = GetModuleHandle("advapi32")) ) + return; + register_event_source = (HANDLE (WINAPI *)())DL_PROC_X(advapi, + "RegisterEventSource" ); + deregister_event_source = (BOOL (WINAPI *)())DL_PROC(advapi, + "DeregisterEventSource"); + report_event = (BOOL (WINAPI *)())DL_PROC_X(advapi, + "ReportEvent" ); + if ( !(register_event_source && deregister_event_source && + report_event) ) + { + register_event_source = NULL; + deregister_event_source = NULL; + report_event = NULL; + return; + } + } + bp->ptr= (char *)register_event_source(NULL, name); } -static int xcloselog(BIO* bp) +static void xsyslog(BIO *bp, int priority, const char *string) +{ + LPCSTR lpszStrings[2]; + WORD evtype= EVENTLOG_ERROR_TYPE; + int pid = _getpid(); + char pidbuf[20]; + + switch (priority) + { + case LOG_EMERG: + case LOG_ALERT: + case LOG_CRIT: + case LOG_ERR: + evtype = EVENTLOG_ERROR_TYPE; + break; + case LOG_WARNING: + evtype = EVENTLOG_WARNING_TYPE; + break; + case LOG_NOTICE: + case LOG_INFO: + case LOG_DEBUG: + evtype = EVENTLOG_INFORMATION_TYPE; + break; + default: /* Should never happen, but set it + as error anyway. */ + evtype = EVENTLOG_ERROR_TYPE; + break; + } + + sprintf(pidbuf, "[%d] ", pid); + lpszStrings[0] = pidbuf; + lpszStrings[1] = string; + + if(report_event && bp->ptr) + report_event(bp->ptr, evtype, 0, 1024, NULL, 2, 0, + lpszStrings, NULL); +} + +static void xcloselog(BIO* bp) { -#if defined(WIN32) - if(bp->ptr) - DeregisterEventSource((HANDLE)(bp->ptr)); + if(deregister_event_source && bp->ptr) + deregister_event_source((HANDLE)(bp->ptr)); bp->ptr= NULL; -#else +} + +#elif defined(OPENSSL_SYS_VMS) + +static int VMS_OPC_target = LOG_DAEMON; + +static void xopenlog(BIO* bp, char* name, int level) +{ + VMS_OPC_target = level; +} + +static void xsyslog(BIO *bp, int priority, const char *string) +{ + struct dsc$descriptor_s opc_dsc; + struct opcdef *opcdef_p; + char buf[10240]; + unsigned int len; + struct dsc$descriptor_s buf_dsc; + $DESCRIPTOR(fao_cmd, "!AZ: !AZ"); + char *priority_tag; + + switch (priority) + { + case LOG_EMERG: priority_tag = "Emergency"; break; + case LOG_ALERT: priority_tag = "Alert"; break; + case LOG_CRIT: priority_tag = "Critical"; break; + case LOG_ERR: priority_tag = "Error"; break; + case LOG_WARNING: priority_tag = "Warning"; break; + case LOG_NOTICE: priority_tag = "Notice"; break; + case LOG_INFO: priority_tag = "Info"; break; + case LOG_DEBUG: priority_tag = "DEBUG"; break; + } + + buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + buf_dsc.dsc$b_class = DSC$K_CLASS_S; + buf_dsc.dsc$a_pointer = buf; + buf_dsc.dsc$w_length = sizeof(buf) - 1; + + lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string); + + /* we know there's an 8 byte header. That's documented */ + opcdef_p = (struct opcdef *) OPENSSL_malloc(8 + len); + opcdef_p->opc$b_ms_type = OPC$_RQ_RQST; + memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3); + opcdef_p->opc$l_ms_rqstid = 0; + memcpy(&opcdef_p->opc$l_ms_text, buf, len); + + opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + opc_dsc.dsc$b_class = DSC$K_CLASS_S; + opc_dsc.dsc$a_pointer = (char *)opcdef_p; + opc_dsc.dsc$w_length = len + 8; + + sys$sndopr(opc_dsc, 0); + + OPENSSL_free(opcdef_p); +} + +static void xcloselog(BIO* bp) +{ +} + +#else /* Unix */ + +static void xopenlog(BIO* bp, char* name, int level) +{ + openlog(name, LOG_PID|LOG_CONS, level); +} + +static void xsyslog(BIO *bp, int priority, const char *string) +{ + syslog(priority, "%s", string); +} + +static void xcloselog(BIO* bp) +{ closelog(); -#endif - return(1); } -#endif +#endif /* Unix */ + +#endif /* NO_SYSLOG */ diff --git a/src/lib/libcrypto/bio/bss_mem.c b/src/lib/libcrypto/bio/bss_mem.c index 40c4e39f02..28ff7582bf 100644 --- a/src/lib/libcrypto/bio/bss_mem.c +++ b/src/lib/libcrypto/bio/bss_mem.c @@ -59,26 +59,15 @@ #include #include #include "cryptlib.h" -#include "bio.h" +#include -#ifndef NOPROTO -static int mem_write(BIO *h,char *buf,int num); -static int mem_read(BIO *h,char *buf,int size); -static int mem_puts(BIO *h,char *str); -static int mem_gets(BIO *h,char *str,int size); -static long mem_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int mem_write(BIO *h, const char *buf, int num); +static int mem_read(BIO *h, char *buf, int size); +static int mem_puts(BIO *h, const char *str); +static int mem_gets(BIO *h, char *str, int size); +static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int mem_new(BIO *h); static int mem_free(BIO *data); -#else -static int mem_write(); -static int mem_read(); -static int mem_puts(); -static int mem_gets(); -static long mem_ctrl(); -static int mem_new(); -static int mem_free(); -#endif - static BIO_METHOD mem_method= { BIO_TYPE_MEM, @@ -90,15 +79,38 @@ static BIO_METHOD mem_method= mem_ctrl, mem_new, mem_free, + NULL, }; -BIO_METHOD *BIO_s_mem() +/* bio->num is used to hold the value to return on 'empty', if it is + * 0, should_retry is not set */ + +BIO_METHOD *BIO_s_mem(void) { return(&mem_method); } -static int mem_new(bi) -BIO *bi; +BIO *BIO_new_mem_buf(void *buf, int len) +{ + BIO *ret; + BUF_MEM *b; + if (!buf) { + BIOerr(BIO_F_BIO_NEW_MEM_BUF,BIO_R_NULL_PARAMETER); + return NULL; + } + if(len == -1) len = strlen(buf); + if(!(ret = BIO_new(BIO_s_mem())) ) return NULL; + b = (BUF_MEM *)ret->ptr; + b->data = buf; + b->length = len; + b->max = len; + ret->flags |= BIO_FLAGS_MEM_RDONLY; + /* Since this is static data retrying wont help */ + ret->num = 0; + return ret; +} + +static int mem_new(BIO *bi) { BUF_MEM *b; @@ -106,30 +118,29 @@ BIO *bi; return(0); bi->shutdown=1; bi->init=1; - bi->num=0; + bi->num= -1; bi->ptr=(char *)b; return(1); } -static int mem_free(a) -BIO *a; +static int mem_free(BIO *a) { if (a == NULL) return(0); if (a->shutdown) { if ((a->init) && (a->ptr != NULL)) { - BUF_MEM_free((BUF_MEM *)a->ptr); + BUF_MEM *b; + b = (BUF_MEM *)a->ptr; + if(a->flags & BIO_FLAGS_MEM_RDONLY) b->data = NULL; + BUF_MEM_free(b); a->ptr=NULL; } } return(1); } -static int mem_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int mem_read(BIO *b, char *out, int outl) { int ret= -1; BUF_MEM *bm; @@ -139,28 +150,27 @@ int outl; bm=(BUF_MEM *)b->ptr; BIO_clear_retry_flags(b); ret=(outl > bm->length)?bm->length:outl; - if ((out != NULL) && (ret > 0)) - { + if ((out != NULL) && (ret > 0)) { memcpy(out,bm->data,ret); bm->length-=ret; /* memmove(&(bm->data[0]),&(bm->data[ret]), bm->length); */ - from=(char *)&(bm->data[ret]); - to=(char *)&(bm->data[0]); - for (i=0; ilength; i++) - to[i]=from[i]; + if(b->flags & BIO_FLAGS_MEM_RDONLY) bm->data += ret; + else { + from=(char *)&(bm->data[ret]); + to=(char *)&(bm->data[0]); + for (i=0; ilength; i++) + to[i]=from[i]; } - else if (bm->length == 0) + } else if (bm->length == 0) { - BIO_set_retry_read(b); - ret= -1; + ret = b->num; + if (ret != 0) + BIO_set_retry_read(b); } return(ret); } -static int mem_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int mem_write(BIO *b, const char *in, int inl) { int ret= -1; int blen; @@ -173,6 +183,11 @@ int inl; goto end; } + if(b->flags & BIO_FLAGS_MEM_RDONLY) { + BIOerr(BIO_F_MEM_WRITE,BIO_R_WRITE_TO_READ_ONLY_BIO); + goto end; + } + BIO_clear_retry_flags(b); blen=bm->length; if (BUF_MEM_grow(bm,blen+inl) != (blen+inl)) @@ -183,11 +198,7 @@ end: return(ret); } -static long mem_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; char **pptr; @@ -198,12 +209,26 @@ char *ptr; { case BIO_CTRL_RESET: if (bm->data != NULL) - memset(bm->data,0,bm->max); - bm->length=0; + { + /* For read only case reset to the start again */ + if(b->flags & BIO_FLAGS_MEM_RDONLY) + { + bm->data -= bm->max - bm->length; + bm->length = bm->max; + } + else + { + memset(bm->data,0,bm->max); + bm->length=0; + } + } break; case BIO_CTRL_EOF: ret=(long)(bm->length == 0); break; + case BIO_C_SET_BUF_MEM_EOF_RETURN: + b->num=(int)num; + break; case BIO_CTRL_INFO: ret=(long)bm->length; if (ptr != NULL) @@ -250,10 +275,7 @@ char *ptr; return(ret); } -static int mem_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; +static int mem_gets(BIO *bp, char *buf, int size) { int i,j; int ret= -1; @@ -283,9 +305,7 @@ int size; return(ret); } -static int mem_puts(bp,str) -BIO *bp; -char *str; +static int mem_puts(BIO *bp, const char *str) { int n,ret; diff --git a/src/lib/libcrypto/bio/bss_null.c b/src/lib/libcrypto/bio/bss_null.c index 0791a2471a..46b73339df 100644 --- a/src/lib/libcrypto/bio/bss_null.c +++ b/src/lib/libcrypto/bio/bss_null.c @@ -59,26 +59,15 @@ #include #include #include "cryptlib.h" -#include "bio.h" +#include -#ifndef NOPROTO -static int null_write(BIO *h,char *buf,int num); -static int null_read(BIO *h,char *buf,int size); -static int null_puts(BIO *h,char *str); -static int null_gets(BIO *h,char *str,int size); -static long null_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int null_write(BIO *h, const char *buf, int num); +static int null_read(BIO *h, char *buf, int size); +static int null_puts(BIO *h, const char *str); +static int null_gets(BIO *h, char *str, int size); +static long null_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int null_new(BIO *h); static int null_free(BIO *data); -#else -static int null_write(); -static int null_read(); -static int null_puts(); -static int null_gets(); -static long null_ctrl(); -static int null_new(); -static int null_free(); -#endif - static BIO_METHOD null_method= { BIO_TYPE_NULL, @@ -90,15 +79,15 @@ static BIO_METHOD null_method= null_ctrl, null_new, null_free, + NULL, }; -BIO_METHOD *BIO_s_null() +BIO_METHOD *BIO_s_null(void) { return(&null_method); } -static int null_new(bi) -BIO *bi; +static int null_new(BIO *bi) { bi->init=1; bi->num=0; @@ -106,34 +95,23 @@ BIO *bi; return(1); } -static int null_free(a) -BIO *a; +static int null_free(BIO *a) { if (a == NULL) return(0); return(1); } -static int null_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int null_read(BIO *b, char *out, int outl) { return(0); } -static int null_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int null_write(BIO *b, const char *in, int inl) { return(inl); } -static long null_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long null_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; @@ -159,17 +137,12 @@ char *ptr; return(ret); } -static int null_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; +static int null_gets(BIO *bp, char *buf, int size) { return(0); } -static int null_puts(bp,str) -BIO *bp; -char *str; +static int null_puts(BIO *bp, const char *str) { if (str == NULL) return(0); return(strlen(str)); diff --git a/src/lib/libcrypto/bio/bss_sock.c b/src/lib/libcrypto/bio/bss_sock.c index d907a2867b..fdabd16d7e 100644 --- a/src/lib/libcrypto/bio/bss_sock.c +++ b/src/lib/libcrypto/bio/bss_sock.c @@ -56,55 +56,22 @@ * [including the GNU Public Licence.] */ -#if !defined(NO_SOCK) || defined(BIO_FD) +#ifndef OPENSSL_NO_SOCK #include #include #define USE_SOCKETS #include "cryptlib.h" -#include "bio.h" +#include -#ifndef BIO_FD -#ifndef NOPROTO -static int sock_write(BIO *h,char *buf,int num); -static int sock_read(BIO *h,char *buf,int size); -static int sock_puts(BIO *h,char *str); -static long sock_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int sock_write(BIO *h, const char *buf, int num); +static int sock_read(BIO *h, char *buf, int size); +static int sock_puts(BIO *h, const char *str); +static long sock_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int sock_new(BIO *h); static int sock_free(BIO *data); int BIO_sock_should_retry(int s); -#else -static int sock_write(); -static int sock_read(); -static int sock_puts(); -static long sock_ctrl(); -static int sock_new(); -static int sock_free(); -int BIO_sock_should_retry(); -#endif - -#else - -#ifndef NOPROTO -static int fd_write(BIO *h,char *buf,int num); -static int fd_read(BIO *h,char *buf,int size); -static int fd_puts(BIO *h,char *str); -static long fd_ctrl(BIO *h,int cmd,long arg1,char *arg2); -static int fd_new(BIO *h); -static int fd_free(BIO *data); -int BIO_fd_should_retry(int s); -#else -static int fd_write(); -static int fd_read(); -static int fd_puts(); -static long fd_ctrl(); -static int fd_new(); -static int fd_free(); -int BIO_fd_should_retry(); -#endif -#endif -#ifndef BIO_FD static BIO_METHOD methods_sockp= { BIO_TYPE_SOCKET, @@ -116,57 +83,25 @@ static BIO_METHOD methods_sockp= sock_ctrl, sock_new, sock_free, + NULL, }; -BIO_METHOD *BIO_s_socket() +BIO_METHOD *BIO_s_socket(void) { return(&methods_sockp); } -#else -static BIO_METHOD methods_fdp= - { - BIO_TYPE_FD,"file descriptor", - fd_write, - fd_read, - fd_puts, - NULL, /* fd_gets, */ - fd_ctrl, - fd_new, - fd_free, - }; -BIO_METHOD *BIO_s_fd() - { - return(&methods_fdp); - } -#endif - -#ifndef BIO_FD -BIO *BIO_new_socket(fd,close_flag) -#else -BIO *BIO_new_fd(fd,close_flag) -#endif -int fd; -int close_flag; +BIO *BIO_new_socket(int fd, int close_flag) { BIO *ret; -#ifndef BIO_FD ret=BIO_new(BIO_s_socket()); -#else - ret=BIO_new(BIO_s_fd()); -#endif if (ret == NULL) return(NULL); BIO_set_fd(ret,fd,close_flag); return(ret); } -#ifndef BIO_FD -static int sock_new(bi) -#else -static int fd_new(bi) -#endif -BIO *bi; +static int sock_new(BIO *bi) { bi->init=0; bi->num=0; @@ -175,29 +110,14 @@ BIO *bi; return(1); } -#ifndef BIO_FD -static int sock_free(a) -#else -static int fd_free(a) -#endif -BIO *a; +static int sock_free(BIO *a) { if (a == NULL) return(0); if (a->shutdown) { if (a->init) { -#ifndef BIO_FD - shutdown(a->num,2); -# ifdef WINDOWS - closesocket(a->num); -# else - close(a->num); -# endif -#else /* BIO_FD */ - close(a->num); -#endif - + SHUTDOWN2(a->num); } a->init=0; a->flags=0; @@ -205,80 +125,40 @@ BIO *a; return(1); } -#ifndef BIO_FD -static int sock_read(b,out,outl) -#else -static int fd_read(b,out,outl) -#endif -BIO *b; -char *out; -int outl; +static int sock_read(BIO *b, char *out, int outl) { int ret=0; if (out != NULL) { -#if defined(WINDOWS) && !defined(BIO_FD) clear_socket_error(); - ret=recv(b->num,out,outl,0); -#else - clear_sys_error(); - ret=read(b->num,out,outl); -#endif + ret=readsocket(b->num,out,outl); BIO_clear_retry_flags(b); if (ret <= 0) { -#ifndef BIO_FD if (BIO_sock_should_retry(ret)) -#else - if (BIO_fd_should_retry(ret)) -#endif BIO_set_retry_read(b); } } return(ret); } -#ifndef BIO_FD -static int sock_write(b,in,inl) -#else -static int fd_write(b,in,inl) -#endif -BIO *b; -char *in; -int inl; +static int sock_write(BIO *b, const char *in, int inl) { int ret; -#if defined(WINDOWS) && !defined(BIO_FD) clear_socket_error(); - ret=send(b->num,in,inl,0); -#else - clear_sys_error(); - ret=write(b->num,in,inl); -#endif + ret=writesocket(b->num,in,inl); BIO_clear_retry_flags(b); if (ret <= 0) { -#ifndef BIO_FD if (BIO_sock_should_retry(ret)) -#else - if (BIO_fd_should_retry(ret)) -#endif BIO_set_retry_write(b); } return(ret); } -#ifndef BIO_FD -static long sock_ctrl(b,cmd,num,ptr) -#else -static long fd_ctrl(b,cmd,num,ptr) -#endif -BIO *b; -int cmd; -long num; -char *ptr; +static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; int *ip; @@ -286,21 +166,16 @@ char *ptr; switch (cmd) { case BIO_CTRL_RESET: -#ifdef BIO_FD - ret=(long)lseek(b->num,0,0); -#else + num=0; + case BIO_C_FILE_SEEK: ret=0; -#endif break; + case BIO_C_FILE_TELL: case BIO_CTRL_INFO: ret=0; break; case BIO_C_SET_FD: -#ifndef BIO_FD sock_free(b); -#else - fd_free(b); -#endif b->num= *((int *)ptr); b->shutdown=(int)num; b->init=1; @@ -329,7 +204,6 @@ char *ptr; case BIO_CTRL_FLUSH: ret=1; break; - break; default: ret=0; break; @@ -337,82 +211,46 @@ char *ptr; return(ret); } -#ifdef undef -static int sock_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; - { - return(-1); - } -#endif - -#ifndef BIO_FD -static int sock_puts(bp,str) -#else -static int fd_puts(bp,str) -#endif -BIO *bp; -char *str; +static int sock_puts(BIO *bp, const char *str) { int n,ret; n=strlen(str); -#ifndef BIO_FD ret=sock_write(bp,str,n); -#else - ret=fd_write(bp,str,n); -#endif return(ret); } -#ifndef BIO_FD -int BIO_sock_should_retry(i) -#else -int BIO_fd_should_retry(i) -#endif -int i; +int BIO_sock_should_retry(int i) { int err; if ((i == 0) || (i == -1)) { -#if !defined(BIO_FD) && defined(WINDOWS) err=get_last_socket_error(); -#else - err=get_last_sys_error(); -#endif -#if defined(WINDOWS) /* more microsoft stupidity */ +#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ if ((i == -1) && (err == 0)) return(1); #endif -#ifndef BIO_FD return(BIO_sock_non_fatal_error(err)); -#else - return(BIO_fd_non_fatal_error(err)); -#endif } return(0); } -#ifndef BIO_FD -int BIO_sock_non_fatal_error(err) -#else -int BIO_fd_non_fatal_error(err) -#endif -int err; +int BIO_sock_non_fatal_error(int err) { switch (err) { -#if !defined(BIO_FD) && defined(WINDOWS) +#if defined(OPENSSL_SYS_WINDOWS) # if defined(WSAEWOULDBLOCK) case WSAEWOULDBLOCK: # endif -# if defined(WSAENOTCONN) +# if 0 /* This appears to always be an error */ +# if defined(WSAENOTCONN) case WSAENOTCONN: +# endif # endif #endif @@ -452,7 +290,7 @@ int err; case EALREADY: #endif return(1); - break; + /* break; */ default: break; } diff --git a/src/lib/libcrypto/bn/asm/bn-586.pl b/src/lib/libcrypto/bn/asm/bn-586.pl index 19d425ee96..33f6125920 100644 --- a/src/lib/libcrypto/bn/asm/bn-586.pl +++ b/src/lib/libcrypto/bn/asm/bn-586.pl @@ -1,18 +1,17 @@ -#!/usr/bin/perl -# - #!/usr/local/bin/perl push(@INC,"perlasm","../../perlasm"); require "x86asm.pl"; -&asm_init($ARGV[0],"bn-586.pl"); +&asm_init($ARGV[0],$0); &bn_mul_add_words("bn_mul_add_words"); &bn_mul_words("bn_mul_words"); &bn_sqr_words("bn_sqr_words"); -&bn_div64("bn_div64"); +&bn_div_words("bn_div_words"); &bn_add_words("bn_add_words"); +&bn_sub_words("bn_sub_words"); +&bn_sub_part_words("bn_sub_part_words"); &asm_finish(); @@ -228,7 +227,7 @@ sub bn_sqr_words &function_end($name); } -sub bn_div64 +sub bn_div_words { local($name)=@_; @@ -302,12 +301,292 @@ sub bn_add_words &add($tmp1,$tmp2); &adc($c,0); &dec($num) if ($i != 6); - &mov(&DWP($i*4,$r,"",0),$tmp1); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r &jz(&label("aw_end")) if ($i != 6); } &set_label("aw_end",0); - &mov("eax",$c); +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +sub bn_sub_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + +# &mov("eax",$c); # $c is "eax" + + &function_end($name); + } + +sub bn_sub_part_words + { + local($name)=@_; + + &function_begin($name,""); + + &comment(""); + $a="esi"; + $b="edi"; + $c="eax"; + $r="ebx"; + $tmp1="ecx"; + $tmp2="edx"; + $num="ebp"; + + &mov($r,&wparam(0)); # get r + &mov($a,&wparam(1)); # get a + &mov($b,&wparam(2)); # get b + &mov($num,&wparam(3)); # get num + &xor($c,$c); # clear carry + &and($num,0xfffffff8); # num / 8 + + &jz(&label("aw_finish")); + + &set_label("aw_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($a,32); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("aw_loop")); + + &set_label("aw_finish",0); + &mov($num,&wparam(3)); # get num + &and($num,7); + &jz(&label("aw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("Tail Round $i"); + &mov($tmp1,&DWP(0,$a,"",0)); # *a + &mov($tmp2,&DWP(0,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP(0,$r,"",0),$tmp1); # *r + &add($a, 4); + &add($b, 4); + &add($r, 4); + &dec($num) if ($i != 6); + &jz(&label("aw_end")) if ($i != 6); + } + &set_label("aw_end",0); + + &cmp(&wparam(4),0); + &je(&label("pw_end")); + + &mov($num,&wparam(4)); # get dl + &cmp($num,0); + &je(&label("pw_end")); + &jge(&label("pw_pos")); + + &comment("pw_neg"); + &mov($tmp2,0); + &sub($tmp2,$num); + &mov($num,$tmp2); + &and($num,0xfffffff8); # num / 8 + &jz(&label("pw_neg_finish")); + + &set_label("pw_neg_loop",0); + for ($i=0; $i<8; $i++) + { + &comment("dl<0 Round $i"); + + &mov($tmp1,0); + &mov($tmp2,&DWP($i*4,$b,"",0)); # *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + } + + &comment(""); + &add($b,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_neg_loop")); + + &set_label("pw_neg_finish",0); + &mov($tmp2,&wparam(4)); # get dl + &mov($num,0); + &sub($num,$tmp2); + &and($num,7); + &jz(&label("pw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("dl<0 Tail Round $i"); + &mov($tmp1,0); + &mov($tmp2,&DWP($i*4,$b,"",0));# *b + &sub($tmp1,$c); + &mov($c,0); + &adc($c,$c); + &sub($tmp1,$tmp2); + &adc($c,0); + &dec($num) if ($i != 6); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jz(&label("pw_end")) if ($i != 6); + } + + &jmp(&label("pw_end")); + + &set_label("pw_pos",0); + + &and($num,0xfffffff8); # num / 8 + &jz(&label("pw_pos_finish")); + + &set_label("pw_pos_loop",0); + + for ($i=0; $i<8; $i++) + { + &comment("dl>0 Round $i"); + + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &sub($tmp1,$c); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jnc(&label("pw_nc".$i)); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_pos_loop")); + + &set_label("pw_pos_finish",0); + &mov($num,&wparam(4)); # get dl + &and($num,7); + &jz(&label("pw_end")); + + for ($i=0; $i<7; $i++) + { + &comment("dl>0 Tail Round $i"); + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &sub($tmp1,$c); + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &jnc(&label("pw_tail_nc".$i)); + &dec($num) if ($i != 6); + &jz(&label("pw_end")) if ($i != 6); + } + &mov($c,1); + &jmp(&label("pw_end")); + + &set_label("pw_nc_loop",0); + for ($i=0; $i<8; $i++) + { + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &set_label("pw_nc".$i,0); + } + + &comment(""); + &add($a,32); + &add($r,32); + &sub($num,8); + &jnz(&label("pw_nc_loop")); + + &mov($num,&wparam(4)); # get dl + &and($num,7); + &jz(&label("pw_nc_end")); + + for ($i=0; $i<7; $i++) + { + &mov($tmp1,&DWP($i*4,$a,"",0)); # *a + &mov(&DWP($i*4,$r,"",0),$tmp1); # *r + &set_label("pw_tail_nc".$i,0); + &dec($num) if ($i != 6); + &jz(&label("pw_nc_end")) if ($i != 6); + } + + &set_label("pw_nc_end",0); + &mov($c,0); + + &set_label("pw_end",0); + +# &mov("eax",$c); # $c is "eax" &function_end($name); } diff --git a/src/lib/libcrypto/bn/asm/pa-risc2.s b/src/lib/libcrypto/bn/asm/pa-risc2.s index c2725996a4..af9730d062 100644 --- a/src/lib/libcrypto/bn/asm/pa-risc2.s +++ b/src/lib/libcrypto/bn/asm/pa-risc2.s @@ -1,416 +1,1618 @@ - .SPACE $PRIVATE$ - .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 - .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 - .SPACE $TEXT$ - .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 - .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY - .IMPORT $global$,DATA - .IMPORT $$dyncall,MILLICODE -; gcc_compiled.: - .SPACE $TEXT$ - .SUBSPA $CODE$ - - .align 4 - .EXPORT bn_mul_add_words,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR +; +; PA-RISC 2.0 implementation of bn_asm code, based on the +; 64-bit version of the code. This code is effectively the +; same as the 64-bit version except the register model is +; slightly different given all values must be 32-bit between +; function calls. Thus the 64-bit return values are returned +; in %ret0 and %ret1 vs just %ret0 as is done in 64-bit +; +; +; This code is approximately 2x faster than the C version +; for RSA/DSA. +; +; See http://devresource.hp.com/ for more details on the PA-RISC +; architecture. Also see the book "PA-RISC 2.0 Architecture" +; by Gerry Kane for information on the instruction set architecture. +; +; Code written by Chris Ruemmler (with some help from the HP C +; compiler). +; +; The code compiles with HP's assembler +; + + .level 2.0N + .space $TEXT$ + .subspa $CODE$,QUAD=0,ALIGN=8,ACCESS=0x2c,CODE_ONLY + +; +; Global Register definitions used for the routines. +; +; Some information about HP's runtime architecture for 32-bits. +; +; "Caller save" means the calling function must save the register +; if it wants the register to be preserved. +; "Callee save" means if a function uses the register, it must save +; the value before using it. +; +; For the floating point registers +; +; "caller save" registers: fr4-fr11, fr22-fr31 +; "callee save" registers: fr12-fr21 +; "special" registers: fr0-fr3 (status and exception registers) +; +; For the integer registers +; value zero : r0 +; "caller save" registers: r1,r19-r26 +; "callee save" registers: r3-r18 +; return register : r2 (rp) +; return values ; r28,r29 (ret0,ret1) +; Stack pointer ; r30 (sp) +; millicode return ptr ; r31 (also a caller save register) + + +; +; Arguments to the routines +; +r_ptr .reg %r26 +a_ptr .reg %r25 +b_ptr .reg %r24 +num .reg %r24 +n .reg %r23 + +; +; Note that the "w" argument for bn_mul_add_words and bn_mul_words +; is passed on the stack at a delta of -56 from the top of stack +; as the routine is entered. +; + +; +; Globals used in some routines +; + +top_overflow .reg %r23 +high_mask .reg %r22 ; value 0xffffffff80000000L + + +;------------------------------------------------------------------------------ +; +; bn_mul_add_words +; +;BN_ULONG bn_mul_add_words(BN_ULONG *r_ptr, BN_ULONG *a_ptr, +; int num, BN_ULONG w) +; +; arg0 = r_ptr +; arg1 = a_ptr +; arg3 = num +; -56(sp) = w +; +; Local register definitions +; + +fm1 .reg %fr22 +fm .reg %fr23 +ht_temp .reg %fr24 +ht_temp_1 .reg %fr25 +lt_temp .reg %fr26 +lt_temp_1 .reg %fr27 +fm1_1 .reg %fr28 +fm_1 .reg %fr29 + +fw_h .reg %fr7L +fw_l .reg %fr7R +fw .reg %fr7 + +fht_0 .reg %fr8L +flt_0 .reg %fr8R +t_float_0 .reg %fr8 + +fht_1 .reg %fr9L +flt_1 .reg %fr9R +t_float_1 .reg %fr9 + +tmp_0 .reg %r31 +tmp_1 .reg %r21 +m_0 .reg %r20 +m_1 .reg %r19 +ht_0 .reg %r1 +ht_1 .reg %r3 +lt_0 .reg %r4 +lt_1 .reg %r5 +m1_0 .reg %r6 +m1_1 .reg %r7 +rp_val .reg %r8 +rp_val_1 .reg %r9 + bn_mul_add_words - .PROC - .CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=4 - .ENTRY - stw %r2,-20(0,%r30) - stwm %r4,64(0,%r30) - copy %r24,%r31 - stw %r3,-60(0,%r30) - ldi 0,%r20 - ldo 12(%r26),%r2 - stw %r23,-16(0,%r30) - copy %r25,%r3 - ldo 12(%r3),%r1 - fldws -16(0,%r30),%fr8L -L$0010 - copy %r20,%r25 - ldi 0,%r24 - fldws 0(0,%r3),%fr9L - ldw 0(0,%r26),%r19 - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r19,%r23 - ldw -16(0,%r30),%r28 - ldw -12(0,%r30),%r29 - ldi 0,%r22 - add %r23,%r29,%r29 - addc %r22,%r28,%r28 - add %r25,%r29,%r29 - addc %r24,%r28,%r28 - copy %r28,%r21 - ldi 0,%r20 - copy %r21,%r20 - addib,= -1,%r31,L$0011 - stw %r29,0(0,%r26) - copy %r20,%r25 - ldi 0,%r24 - fldws -8(0,%r1),%fr9L - ldw -8(0,%r2),%r19 - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r19,%r23 - ldw -16(0,%r30),%r28 - ldw -12(0,%r30),%r29 - ldi 0,%r22 - add %r23,%r29,%r29 - addc %r22,%r28,%r28 - add %r25,%r29,%r29 - addc %r24,%r28,%r28 - copy %r28,%r21 - ldi 0,%r20 - copy %r21,%r20 - addib,= -1,%r31,L$0011 - stw %r29,-8(0,%r2) - copy %r20,%r25 - ldi 0,%r24 - fldws -4(0,%r1),%fr9L - ldw -4(0,%r2),%r19 - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r19,%r23 - ldw -16(0,%r30),%r28 - ldw -12(0,%r30),%r29 - ldi 0,%r22 - add %r23,%r29,%r29 - addc %r22,%r28,%r28 - add %r25,%r29,%r29 - addc %r24,%r28,%r28 - copy %r28,%r21 - ldi 0,%r20 - copy %r21,%r20 - addib,= -1,%r31,L$0011 - stw %r29,-4(0,%r2) - copy %r20,%r25 - ldi 0,%r24 - fldws 0(0,%r1),%fr9L - ldw 0(0,%r2),%r19 - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r19,%r23 - ldw -16(0,%r30),%r28 - ldw -12(0,%r30),%r29 - ldi 0,%r22 - add %r23,%r29,%r29 - addc %r22,%r28,%r28 - add %r25,%r29,%r29 - addc %r24,%r28,%r28 - copy %r28,%r21 - ldi 0,%r20 - copy %r21,%r20 - addib,= -1,%r31,L$0011 - stw %r29,0(0,%r2) - ldo 16(%r1),%r1 - ldo 16(%r3),%r3 - ldo 16(%r2),%r2 - bl L$0010,0 - ldo 16(%r26),%r26 -L$0011 - copy %r20,%r28 - ldw -84(0,%r30),%r2 - ldw -60(0,%r30),%r3 - bv 0(%r2) - ldwm -64(0,%r30),%r4 - .EXIT - .PROCEND - .align 4 - .EXPORT bn_mul_words,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR + .export bn_mul_add_words,entry,NO_RELOCATION,LONG_RETURN + .proc + .callinfo frame=128 + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + NOP ; Needed to make the loop 16-byte aligned + NOP ; needed to make the loop 16-byte aligned + + STD %r5,16(%sp) ; save r5 + NOP + STD %r6,24(%sp) ; save r6 + STD %r7,32(%sp) ; save r7 + + STD %r8,40(%sp) ; save r8 + STD %r9,48(%sp) ; save r9 + COPY %r0,%ret1 ; return 0 by default + DEPDI,Z 1,31,1,top_overflow ; top_overflow = 1 << 32 + + CMPIB,>= 0,num,bn_mul_add_words_exit ; if (num <= 0) then exit + LDO 128(%sp),%sp ; bump stack + + ; + ; The loop is unrolled twice, so if there is only 1 number + ; then go straight to the cleanup code. + ; + CMPIB,= 1,num,bn_mul_add_words_single_top + FLDD -184(%sp),fw ; (-56-128) load up w into fw (fw_h/fw_l) + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; + ; PA-RISC 2.0 chips have two fully pipelined multipliers, thus + ; two 32-bit mutiplies can be issued per cycle. + ; +bn_mul_add_words_unroll2 + + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + FLDD 8(a_ptr),t_float_1 ; load up 64-bit value (fr8L) ht(L)/lt(R) + LDD 0(r_ptr),rp_val ; rp[0] + LDD 8(r_ptr),rp_val_1 ; rp[1] + + XMPYU fht_0,fw_l,fm1 ; m1[0] = fht_0*fw_l + XMPYU fht_1,fw_l,fm1_1 ; m1[1] = fht_1*fw_l + FSTD fm1,-16(%sp) ; -16(sp) = m1[0] + FSTD fm1_1,-48(%sp) ; -48(sp) = m1[1] + + XMPYU flt_0,fw_h,fm ; m[0] = flt_0*fw_h + XMPYU flt_1,fw_h,fm_1 ; m[1] = flt_1*fw_h + FSTD fm,-8(%sp) ; -8(sp) = m[0] + FSTD fm_1,-40(%sp) ; -40(sp) = m[1] + + XMPYU fht_0,fw_h,ht_temp ; ht_temp = fht_0*fw_h + XMPYU fht_1,fw_h,ht_temp_1 ; ht_temp_1 = fht_1*fw_h + FSTD ht_temp,-24(%sp) ; -24(sp) = ht_temp + FSTD ht_temp_1,-56(%sp) ; -56(sp) = ht_temp_1 + + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + XMPYU flt_1,fw_l,lt_temp_1 ; lt_temp = lt*fw_l + FSTD lt_temp,-32(%sp) ; -32(sp) = lt_temp + FSTD lt_temp_1,-64(%sp) ; -64(sp) = lt_temp_1 + + LDD -8(%sp),m_0 ; m[0] + LDD -40(%sp),m_1 ; m[1] + LDD -16(%sp),m1_0 ; m1[0] + LDD -48(%sp),m1_1 ; m1[1] + + LDD -24(%sp),ht_0 ; ht[0] + LDD -56(%sp),ht_1 ; ht[1] + ADD,L m1_0,m_0,tmp_0 ; tmp_0 = m[0] + m1[0]; + ADD,L m1_1,m_1,tmp_1 ; tmp_1 = m[1] + m1[1]; + + LDD -32(%sp),lt_0 + LDD -64(%sp),lt_1 + CMPCLR,*>>= tmp_0,m1_0, %r0 ; if (m[0] < m1[0]) + ADD,L ht_0,top_overflow,ht_0 ; ht[0] += (1<<32) + + CMPCLR,*>>= tmp_1,m1_1,%r0 ; if (m[1] < m1[1]) + ADD,L ht_1,top_overflow,ht_1 ; ht[1] += (1<<32) + EXTRD,U tmp_0,31,32,m_0 ; m[0]>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1[0] = m[0]<<32 + + EXTRD,U tmp_1,31,32,m_1 ; m[1]>>32 + DEPD,Z tmp_1,31,32,m1_1 ; m1[1] = m[1]<<32 + ADD,L ht_0,m_0,ht_0 ; ht[0]+= (m[0]>>32) + ADD,L ht_1,m_1,ht_1 ; ht[1]+= (m[1]>>32) + + ADD lt_0,m1_0,lt_0 ; lt[0] = lt[0]+m1[0]; + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + ADD lt_1,m1_1,lt_1 ; lt[1] = lt[1]+m1[1]; + ADD,DC ht_1,%r0,ht_1 ; ht[1]++ + + ADD %ret1,lt_0,lt_0 ; lt[0] = lt[0] + c; + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + ADD lt_0,rp_val,lt_0 ; lt[0] = lt[0]+rp[0] + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + + LDO -2(num),num ; num = num - 2; + ADD ht_0,lt_1,lt_1 ; lt[1] = lt[1] + ht_0 (c); + ADD,DC ht_1,%r0,ht_1 ; ht[1]++ + STD lt_0,0(r_ptr) ; rp[0] = lt[0] + + ADD lt_1,rp_val_1,lt_1 ; lt[1] = lt[1]+rp[1] + ADD,DC ht_1,%r0,%ret1 ; ht[1]++ + LDO 16(a_ptr),a_ptr ; a_ptr += 2 + + STD lt_1,8(r_ptr) ; rp[1] = lt[1] + CMPIB,<= 2,num,bn_mul_add_words_unroll2 ; go again if more to do + LDO 16(r_ptr),r_ptr ; r_ptr += 2 + + CMPIB,=,N 0,num,bn_mul_add_words_exit ; are we done, or cleanup last one + + ; + ; Top of loop aligned on 64-byte boundary + ; +bn_mul_add_words_single_top + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + LDD 0(r_ptr),rp_val ; rp[0] + LDO 8(a_ptr),a_ptr ; a_ptr++ + XMPYU fht_0,fw_l,fm1 ; m1 = ht*fw_l + FSTD fm1,-16(%sp) ; -16(sp) = m1 + XMPYU flt_0,fw_h,fm ; m = lt*fw_h + FSTD fm,-8(%sp) ; -8(sp) = m + XMPYU fht_0,fw_h,ht_temp ; ht_temp = ht*fw_h + FSTD ht_temp,-24(%sp) ; -24(sp) = ht + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + FSTD lt_temp,-32(%sp) ; -32(sp) = lt + + LDD -8(%sp),m_0 + LDD -16(%sp),m1_0 ; m1 = temp1 + ADD,L m_0,m1_0,tmp_0 ; tmp_0 = m + m1; + LDD -24(%sp),ht_0 + LDD -32(%sp),lt_0 + + CMPCLR,*>>= tmp_0,m1_0,%r0 ; if (m < m1) + ADD,L ht_0,top_overflow,ht_0 ; ht += (1<<32) + + EXTRD,U tmp_0,31,32,m_0 ; m>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1 = m<<32 + + ADD,L ht_0,m_0,ht_0 ; ht+= (m>>32) + ADD lt_0,m1_0,tmp_0 ; tmp_0 = lt+m1; + ADD,DC ht_0,%r0,ht_0 ; ht++ + ADD %ret1,tmp_0,lt_0 ; lt = lt + c; + ADD,DC ht_0,%r0,ht_0 ; ht++ + ADD lt_0,rp_val,lt_0 ; lt = lt+rp[0] + ADD,DC ht_0,%r0,%ret1 ; ht++ + STD lt_0,0(r_ptr) ; rp[0] = lt + +bn_mul_add_words_exit + .EXIT + + EXTRD,U %ret1,31,32,%ret0 ; for 32-bit, return in ret0/ret1 + LDD -80(%sp),%r9 ; restore r9 + LDD -88(%sp),%r8 ; restore r8 + LDD -96(%sp),%r7 ; restore r7 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 ; restore r3 + .PROCEND ;in=23,24,25,26,29;out=28; + +;---------------------------------------------------------------------------- +; +;BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) +; +; arg0 = rp +; arg1 = ap +; arg3 = num +; w on stack at -56(sp) + bn_mul_words - .PROC - .CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=3 - .ENTRY - stw %r2,-20(0,%r30) - copy %r25,%r2 - stwm %r4,64(0,%r30) - copy %r24,%r19 - ldi 0,%r28 - stw %r23,-16(0,%r30) - ldo 12(%r26),%r31 - ldo 12(%r2),%r29 - fldws -16(0,%r30),%fr8L -L$0026 - fldws 0(0,%r2),%fr9L - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r28,%r21 - ldi 0,%r20 - ldw -16(0,%r30),%r24 - ldw -12(0,%r30),%r25 - add %r21,%r25,%r25 - addc %r20,%r24,%r24 - copy %r24,%r23 - ldi 0,%r22 - copy %r23,%r28 - addib,= -1,%r19,L$0027 - stw %r25,0(0,%r26) - fldws -8(0,%r29),%fr9L - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r28,%r21 - ldi 0,%r20 - ldw -16(0,%r30),%r24 - ldw -12(0,%r30),%r25 - add %r21,%r25,%r25 - addc %r20,%r24,%r24 - copy %r24,%r23 - ldi 0,%r22 - copy %r23,%r28 - addib,= -1,%r19,L$0027 - stw %r25,-8(0,%r31) - fldws -4(0,%r29),%fr9L - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r28,%r21 - ldi 0,%r20 - ldw -16(0,%r30),%r24 - ldw -12(0,%r30),%r25 - add %r21,%r25,%r25 - addc %r20,%r24,%r24 - copy %r24,%r23 - ldi 0,%r22 - copy %r23,%r28 - addib,= -1,%r19,L$0027 - stw %r25,-4(0,%r31) - fldws 0(0,%r29),%fr9L - xmpyu %fr8L,%fr9L,%fr9 - fstds %fr9,-16(0,%r30) - copy %r28,%r21 - ldi 0,%r20 - ldw -16(0,%r30),%r24 - ldw -12(0,%r30),%r25 - add %r21,%r25,%r25 - addc %r20,%r24,%r24 - copy %r24,%r23 - ldi 0,%r22 - copy %r23,%r28 - addib,= -1,%r19,L$0027 - stw %r25,0(0,%r31) - ldo 16(%r29),%r29 - ldo 16(%r2),%r2 - ldo 16(%r31),%r31 - bl L$0026,0 - ldo 16(%r26),%r26 -L$0027 - ldw -84(0,%r30),%r2 - bv 0(%r2) - ldwm -64(0,%r30),%r4 - .EXIT - .PROCEND - .align 4 - .EXPORT bn_sqr_words,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR + .proc + .callinfo frame=128 + .entry + .EXPORT bn_mul_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + NOP + STD %r5,16(%sp) ; save r5 + + STD %r6,24(%sp) ; save r6 + STD %r7,32(%sp) ; save r7 + COPY %r0,%ret1 ; return 0 by default + DEPDI,Z 1,31,1,top_overflow ; top_overflow = 1 << 32 + + CMPIB,>= 0,num,bn_mul_words_exit + LDO 128(%sp),%sp ; bump stack + + ; + ; See if only 1 word to do, thus just do cleanup + ; + CMPIB,= 1,num,bn_mul_words_single_top + FLDD -184(%sp),fw ; (-56-128) load up w into fw (fw_h/fw_l) + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; + ; PA-RISC 2.0 chips have two fully pipelined multipliers, thus + ; two 32-bit mutiplies can be issued per cycle. + ; +bn_mul_words_unroll2 + + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + FLDD 8(a_ptr),t_float_1 ; load up 64-bit value (fr8L) ht(L)/lt(R) + XMPYU fht_0,fw_l,fm1 ; m1[0] = fht_0*fw_l + XMPYU fht_1,fw_l,fm1_1 ; m1[1] = ht*fw_l + + FSTD fm1,-16(%sp) ; -16(sp) = m1 + FSTD fm1_1,-48(%sp) ; -48(sp) = m1 + XMPYU flt_0,fw_h,fm ; m = lt*fw_h + XMPYU flt_1,fw_h,fm_1 ; m = lt*fw_h + + FSTD fm,-8(%sp) ; -8(sp) = m + FSTD fm_1,-40(%sp) ; -40(sp) = m + XMPYU fht_0,fw_h,ht_temp ; ht_temp = fht_0*fw_h + XMPYU fht_1,fw_h,ht_temp_1 ; ht_temp = ht*fw_h + + FSTD ht_temp,-24(%sp) ; -24(sp) = ht + FSTD ht_temp_1,-56(%sp) ; -56(sp) = ht + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + XMPYU flt_1,fw_l,lt_temp_1 ; lt_temp = lt*fw_l + + FSTD lt_temp,-32(%sp) ; -32(sp) = lt + FSTD lt_temp_1,-64(%sp) ; -64(sp) = lt + LDD -8(%sp),m_0 + LDD -40(%sp),m_1 + + LDD -16(%sp),m1_0 + LDD -48(%sp),m1_1 + LDD -24(%sp),ht_0 + LDD -56(%sp),ht_1 + + ADD,L m1_0,m_0,tmp_0 ; tmp_0 = m + m1; + ADD,L m1_1,m_1,tmp_1 ; tmp_1 = m + m1; + LDD -32(%sp),lt_0 + LDD -64(%sp),lt_1 + + CMPCLR,*>>= tmp_0,m1_0, %r0 ; if (m < m1) + ADD,L ht_0,top_overflow,ht_0 ; ht += (1<<32) + CMPCLR,*>>= tmp_1,m1_1,%r0 ; if (m < m1) + ADD,L ht_1,top_overflow,ht_1 ; ht += (1<<32) + + EXTRD,U tmp_0,31,32,m_0 ; m>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1 = m<<32 + EXTRD,U tmp_1,31,32,m_1 ; m>>32 + DEPD,Z tmp_1,31,32,m1_1 ; m1 = m<<32 + + ADD,L ht_0,m_0,ht_0 ; ht+= (m>>32) + ADD,L ht_1,m_1,ht_1 ; ht+= (m>>32) + ADD lt_0,m1_0,lt_0 ; lt = lt+m1; + ADD,DC ht_0,%r0,ht_0 ; ht++ + + ADD lt_1,m1_1,lt_1 ; lt = lt+m1; + ADD,DC ht_1,%r0,ht_1 ; ht++ + ADD %ret1,lt_0,lt_0 ; lt = lt + c (ret1); + ADD,DC ht_0,%r0,ht_0 ; ht++ + + ADD ht_0,lt_1,lt_1 ; lt = lt + c (ht_0) + ADD,DC ht_1,%r0,ht_1 ; ht++ + STD lt_0,0(r_ptr) ; rp[0] = lt + STD lt_1,8(r_ptr) ; rp[1] = lt + + COPY ht_1,%ret1 ; carry = ht + LDO -2(num),num ; num = num - 2; + LDO 16(a_ptr),a_ptr ; ap += 2 + CMPIB,<= 2,num,bn_mul_words_unroll2 + LDO 16(r_ptr),r_ptr ; rp++ + + CMPIB,=,N 0,num,bn_mul_words_exit ; are we done? + + ; + ; Top of loop aligned on 64-byte boundary + ; +bn_mul_words_single_top + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + + XMPYU fht_0,fw_l,fm1 ; m1 = ht*fw_l + FSTD fm1,-16(%sp) ; -16(sp) = m1 + XMPYU flt_0,fw_h,fm ; m = lt*fw_h + FSTD fm,-8(%sp) ; -8(sp) = m + XMPYU fht_0,fw_h,ht_temp ; ht_temp = ht*fw_h + FSTD ht_temp,-24(%sp) ; -24(sp) = ht + XMPYU flt_0,fw_l,lt_temp ; lt_temp = lt*fw_l + FSTD lt_temp,-32(%sp) ; -32(sp) = lt + + LDD -8(%sp),m_0 + LDD -16(%sp),m1_0 + ADD,L m_0,m1_0,tmp_0 ; tmp_0 = m + m1; + LDD -24(%sp),ht_0 + LDD -32(%sp),lt_0 + + CMPCLR,*>>= tmp_0,m1_0,%r0 ; if (m < m1) + ADD,L ht_0,top_overflow,ht_0 ; ht += (1<<32) + + EXTRD,U tmp_0,31,32,m_0 ; m>>32 + DEPD,Z tmp_0,31,32,m1_0 ; m1 = m<<32 + + ADD,L ht_0,m_0,ht_0 ; ht+= (m>>32) + ADD lt_0,m1_0,lt_0 ; lt= lt+m1; + ADD,DC ht_0,%r0,ht_0 ; ht++ + + ADD %ret1,lt_0,lt_0 ; lt = lt + c; + ADD,DC ht_0,%r0,ht_0 ; ht++ + + COPY ht_0,%ret1 ; copy carry + STD lt_0,0(r_ptr) ; rp[0] = lt + +bn_mul_words_exit + .EXIT + EXTRD,U %ret1,31,32,%ret0 ; for 32-bit, return in ret0/ret1 + LDD -96(%sp),%r7 ; restore r7 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 ; restore r3 + .PROCEND + +;---------------------------------------------------------------------------- +; +;void bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num) +; +; arg0 = rp +; arg1 = ap +; arg2 = num +; + bn_sqr_words + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_sqr_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + NOP + STD %r5,16(%sp) ; save r5 + + CMPIB,>= 0,num,bn_sqr_words_exit + LDO 128(%sp),%sp ; bump stack + + ; + ; If only 1, the goto straight to cleanup + ; + CMPIB,= 1,num,bn_sqr_words_single_top + DEPDI,Z -1,32,33,high_mask ; Create Mask 0xffffffff80000000L + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; + +bn_sqr_words_unroll2 + FLDD 0(a_ptr),t_float_0 ; a[0] + FLDD 8(a_ptr),t_float_1 ; a[1] + XMPYU fht_0,flt_0,fm ; m[0] + XMPYU fht_1,flt_1,fm_1 ; m[1] + + FSTD fm,-24(%sp) ; store m[0] + FSTD fm_1,-56(%sp) ; store m[1] + XMPYU flt_0,flt_0,lt_temp ; lt[0] + XMPYU flt_1,flt_1,lt_temp_1 ; lt[1] + + FSTD lt_temp,-16(%sp) ; store lt[0] + FSTD lt_temp_1,-48(%sp) ; store lt[1] + XMPYU fht_0,fht_0,ht_temp ; ht[0] + XMPYU fht_1,fht_1,ht_temp_1 ; ht[1] + + FSTD ht_temp,-8(%sp) ; store ht[0] + FSTD ht_temp_1,-40(%sp) ; store ht[1] + LDD -24(%sp),m_0 + LDD -56(%sp),m_1 + + AND m_0,high_mask,tmp_0 ; m[0] & Mask + AND m_1,high_mask,tmp_1 ; m[1] & Mask + DEPD,Z m_0,30,31,m_0 ; m[0] << 32+1 + DEPD,Z m_1,30,31,m_1 ; m[1] << 32+1 + + LDD -16(%sp),lt_0 + LDD -48(%sp),lt_1 + EXTRD,U tmp_0,32,33,tmp_0 ; tmp_0 = m[0]&Mask >> 32-1 + EXTRD,U tmp_1,32,33,tmp_1 ; tmp_1 = m[1]&Mask >> 32-1 + + LDD -8(%sp),ht_0 + LDD -40(%sp),ht_1 + ADD,L ht_0,tmp_0,ht_0 ; ht[0] += tmp_0 + ADD,L ht_1,tmp_1,ht_1 ; ht[1] += tmp_1 + + ADD lt_0,m_0,lt_0 ; lt = lt+m + ADD,DC ht_0,%r0,ht_0 ; ht[0]++ + STD lt_0,0(r_ptr) ; rp[0] = lt[0] + STD ht_0,8(r_ptr) ; rp[1] = ht[1] + + ADD lt_1,m_1,lt_1 ; lt = lt+m + ADD,DC ht_1,%r0,ht_1 ; ht[1]++ + STD lt_1,16(r_ptr) ; rp[2] = lt[1] + STD ht_1,24(r_ptr) ; rp[3] = ht[1] + + LDO -2(num),num ; num = num - 2; + LDO 16(a_ptr),a_ptr ; ap += 2 + CMPIB,<= 2,num,bn_sqr_words_unroll2 + LDO 32(r_ptr),r_ptr ; rp += 4 + + CMPIB,=,N 0,num,bn_sqr_words_exit ; are we done? + + ; + ; Top of loop aligned on 64-byte boundary + ; +bn_sqr_words_single_top + FLDD 0(a_ptr),t_float_0 ; load up 64-bit value (fr8L) ht(L)/lt(R) + + XMPYU fht_0,flt_0,fm ; m + FSTD fm,-24(%sp) ; store m + + XMPYU flt_0,flt_0,lt_temp ; lt + FSTD lt_temp,-16(%sp) ; store lt + + XMPYU fht_0,fht_0,ht_temp ; ht + FSTD ht_temp,-8(%sp) ; store ht + + LDD -24(%sp),m_0 ; load m + AND m_0,high_mask,tmp_0 ; m & Mask + DEPD,Z m_0,30,31,m_0 ; m << 32+1 + LDD -16(%sp),lt_0 ; lt + + LDD -8(%sp),ht_0 ; ht + EXTRD,U tmp_0,32,33,tmp_0 ; tmp_0 = m&Mask >> 32-1 + ADD m_0,lt_0,lt_0 ; lt = lt+m + ADD,L ht_0,tmp_0,ht_0 ; ht += tmp_0 + ADD,DC ht_0,%r0,ht_0 ; ht++ + + STD lt_0,0(r_ptr) ; rp[0] = lt + STD ht_0,8(r_ptr) ; rp[1] = ht + +bn_sqr_words_exit + .EXIT + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + .PROCEND ;in=23,24,25,26,29;out=28; + + +;---------------------------------------------------------------------------- +; +;BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +; +; arg0 = rp +; arg1 = ap +; arg2 = bp +; arg3 = n + +t .reg %r22 +b .reg %r21 +l .reg %r20 + +bn_add_words + .proc + .entry + .callinfo + .EXPORT bn_add_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .align 64 + + CMPIB,>= 0,n,bn_add_words_exit + COPY %r0,%ret1 ; return 0 by default + + ; + ; If 2 or more numbers do the loop + ; + CMPIB,= 1,n,bn_add_words_single_top + NOP + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; +bn_add_words_unroll2 + LDD 0(a_ptr),t + LDD 0(b_ptr),b + ADD t,%ret1,t ; t = t+c; + ADD,DC %r0,%r0,%ret1 ; set c to carry + ADD t,b,l ; l = t + b[0] + ADD,DC %ret1,%r0,%ret1 ; c+= carry + STD l,0(r_ptr) + + LDD 8(a_ptr),t + LDD 8(b_ptr),b + ADD t,%ret1,t ; t = t+c; + ADD,DC %r0,%r0,%ret1 ; set c to carry + ADD t,b,l ; l = t + b[0] + ADD,DC %ret1,%r0,%ret1 ; c+= carry + STD l,8(r_ptr) + + LDO -2(n),n + LDO 16(a_ptr),a_ptr + LDO 16(b_ptr),b_ptr + + CMPIB,<= 2,n,bn_add_words_unroll2 + LDO 16(r_ptr),r_ptr + + CMPIB,=,N 0,n,bn_add_words_exit ; are we done? + +bn_add_words_single_top + LDD 0(a_ptr),t + LDD 0(b_ptr),b + + ADD t,%ret1,t ; t = t+c; + ADD,DC %r0,%r0,%ret1 ; set c to carry (could use CMPCLR??) + ADD t,b,l ; l = t + b[0] + ADD,DC %ret1,%r0,%ret1 ; c+= carry + STD l,0(r_ptr) + +bn_add_words_exit + .EXIT + BVE (%rp) + EXTRD,U %ret1,31,32,%ret0 ; for 32-bit, return in ret0/ret1 + .PROCEND ;in=23,24,25,26,29;out=28; + +;---------------------------------------------------------------------------- +; +;BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +; +; arg0 = rp +; arg1 = ap +; arg2 = bp +; arg3 = n + +t1 .reg %r22 +t2 .reg %r21 +sub_tmp1 .reg %r20 +sub_tmp2 .reg %r19 + + +bn_sub_words + .proc + .callinfo + .EXPORT bn_sub_words,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + CMPIB,>= 0,n,bn_sub_words_exit + COPY %r0,%ret1 ; return 0 by default + + ; + ; If 2 or more numbers do the loop + ; + CMPIB,= 1,n,bn_sub_words_single_top + NOP + + ; + ; This loop is unrolled 2 times (64-byte aligned as well) + ; +bn_sub_words_unroll2 + LDD 0(a_ptr),t1 + LDD 0(b_ptr),t2 + SUB t1,t2,sub_tmp1 ; t3 = t1-t2; + SUB sub_tmp1,%ret1,sub_tmp1 ; t3 = t3- c; + + CMPCLR,*>> t1,t2,sub_tmp2 ; clear if t1 > t2 + LDO 1(%r0),sub_tmp2 + + CMPCLR,*= t1,t2,%r0 + COPY sub_tmp2,%ret1 + STD sub_tmp1,0(r_ptr) + + LDD 8(a_ptr),t1 + LDD 8(b_ptr),t2 + SUB t1,t2,sub_tmp1 ; t3 = t1-t2; + SUB sub_tmp1,%ret1,sub_tmp1 ; t3 = t3- c; + CMPCLR,*>> t1,t2,sub_tmp2 ; clear if t1 > t2 + LDO 1(%r0),sub_tmp2 + + CMPCLR,*= t1,t2,%r0 + COPY sub_tmp2,%ret1 + STD sub_tmp1,8(r_ptr) + + LDO -2(n),n + LDO 16(a_ptr),a_ptr + LDO 16(b_ptr),b_ptr + + CMPIB,<= 2,n,bn_sub_words_unroll2 + LDO 16(r_ptr),r_ptr + + CMPIB,=,N 0,n,bn_sub_words_exit ; are we done? + +bn_sub_words_single_top + LDD 0(a_ptr),t1 + LDD 0(b_ptr),t2 + SUB t1,t2,sub_tmp1 ; t3 = t1-t2; + SUB sub_tmp1,%ret1,sub_tmp1 ; t3 = t3- c; + CMPCLR,*>> t1,t2,sub_tmp2 ; clear if t1 > t2 + LDO 1(%r0),sub_tmp2 + + CMPCLR,*= t1,t2,%r0 + COPY sub_tmp2,%ret1 + + STD sub_tmp1,0(r_ptr) + +bn_sub_words_exit + .EXIT + BVE (%rp) + EXTRD,U %ret1,31,32,%ret0 ; for 32-bit, return in ret0/ret1 + .PROCEND ;in=23,24,25,26,29;out=28; + +;------------------------------------------------------------------------------ +; +; unsigned long bn_div_words(unsigned long h, unsigned long l, unsigned long d) +; +; arg0 = h +; arg1 = l +; arg2 = d +; +; This is mainly just output from the HP C compiler. +; +;------------------------------------------------------------------------------ +bn_div_words .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - ldo 28(%r26),%r19 - ldo 12(%r25),%r28 -L$0042 - fldws 0(0,%r25),%fr8L - fldws 0(0,%r25),%fr8R - xmpyu %fr8L,%fr8R,%fr8 - fstds %fr8,-16(0,%r30) - ldw -16(0,%r30),%r22 - ldw -12(0,%r30),%r23 - stw %r23,0(0,%r26) - copy %r22,%r21 - ldi 0,%r20 - addib,= -1,%r24,L$0049 - stw %r21,-24(0,%r19) - fldws -8(0,%r28),%fr8L - fldws -8(0,%r28),%fr8R - xmpyu %fr8L,%fr8R,%fr8 - fstds %fr8,-16(0,%r30) - ldw -16(0,%r30),%r22 - ldw -12(0,%r30),%r23 - stw %r23,-20(0,%r19) - copy %r22,%r21 - ldi 0,%r20 - addib,= -1,%r24,L$0049 - stw %r21,-16(0,%r19) - fldws -4(0,%r28),%fr8L - fldws -4(0,%r28),%fr8R - xmpyu %fr8L,%fr8R,%fr8 - fstds %fr8,-16(0,%r30) - ldw -16(0,%r30),%r22 - ldw -12(0,%r30),%r23 - stw %r23,-12(0,%r19) - copy %r22,%r21 - ldi 0,%r20 - addib,= -1,%r24,L$0049 - stw %r21,-8(0,%r19) - fldws 0(0,%r28),%fr8L - fldws 0(0,%r28),%fr8R - xmpyu %fr8L,%fr8R,%fr8 - fstds %fr8,-16(0,%r30) - ldw -16(0,%r30),%r22 - ldw -12(0,%r30),%r23 - stw %r23,-4(0,%r19) - copy %r22,%r21 - ldi 0,%r20 - addib,= -1,%r24,L$0049 - stw %r21,0(0,%r19) - ldo 16(%r28),%r28 - ldo 16(%r25),%r25 - ldo 32(%r19),%r19 - bl L$0042,0 - ldo 32(%r26),%r26 -L$0049 - bv,n 0(%r2) - .EXIT - .PROCEND - .IMPORT BN_num_bits_word,CODE - .IMPORT fprintf,CODE - .IMPORT __iob,DATA - .SPACE $TEXT$ - .SUBSPA $LIT$ - - .align 4 -L$C0000 - .STRING "Division would overflow (%d)\x0a\x00" - .IMPORT abort,CODE - .SPACE $TEXT$ - .SUBSPA $CODE$ - - .align 4 - .EXPORT bn_div64,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR -bn_div64 + .EXPORT bn_div_words,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN + .IMPORT BN_num_bits_word,CODE + .IMPORT __iob,DATA + .IMPORT fprintf,CODE + .IMPORT abort,CODE + .IMPORT $$div2U,MILLICODE + .CALLINFO CALLER,FRAME=144,ENTRY_GR=%r9,SAVE_RP,ARGS_SAVED,ORDERING_AWARE + .ENTRY + STW %r2,-20(%r30) ;offset 0x8ec + STW,MA %r3,192(%r30) ;offset 0x8f0 + STW %r4,-188(%r30) ;offset 0x8f4 + DEPD %r5,31,32,%r6 ;offset 0x8f8 + STD %r6,-184(%r30) ;offset 0x8fc + DEPD %r7,31,32,%r8 ;offset 0x900 + STD %r8,-176(%r30) ;offset 0x904 + STW %r9,-168(%r30) ;offset 0x908 + LDD -248(%r30),%r3 ;offset 0x90c + COPY %r26,%r4 ;offset 0x910 + COPY %r24,%r5 ;offset 0x914 + DEPD %r25,31,32,%r4 ;offset 0x918 + CMPB,*<> %r3,%r0,$0006000C ;offset 0x91c + DEPD %r23,31,32,%r5 ;offset 0x920 + MOVIB,TR -1,%r29,$00060002 ;offset 0x924 + EXTRD,U %r29,31,32,%r28 ;offset 0x928 +$0006002A + LDO -1(%r29),%r29 ;offset 0x92c + SUB %r23,%r7,%r23 ;offset 0x930 +$00060024 + SUB %r4,%r31,%r25 ;offset 0x934 + AND %r25,%r19,%r26 ;offset 0x938 + CMPB,*<>,N %r0,%r26,$00060046 ;offset 0x93c + DEPD,Z %r25,31,32,%r20 ;offset 0x940 + OR %r20,%r24,%r21 ;offset 0x944 + CMPB,*<<,N %r21,%r23,$0006002A ;offset 0x948 + SUB %r31,%r2,%r31 ;offset 0x94c +$00060046 +$0006002E + DEPD,Z %r23,31,32,%r25 ;offset 0x950 + EXTRD,U %r23,31,32,%r26 ;offset 0x954 + AND %r25,%r19,%r24 ;offset 0x958 + ADD,L %r31,%r26,%r31 ;offset 0x95c + CMPCLR,*>>= %r5,%r24,%r0 ;offset 0x960 + LDO 1(%r31),%r31 ;offset 0x964 +$00060032 + CMPB,*<<=,N %r31,%r4,$00060036 ;offset 0x968 + LDO -1(%r29),%r29 ;offset 0x96c + ADD,L %r4,%r3,%r4 ;offset 0x970 +$00060036 + ADDIB,=,N -1,%r8,$D0 ;offset 0x974 + SUB %r5,%r24,%r28 ;offset 0x978 +$0006003A + SUB %r4,%r31,%r24 ;offset 0x97c + SHRPD %r24,%r28,32,%r4 ;offset 0x980 + DEPD,Z %r29,31,32,%r9 ;offset 0x984 + DEPD,Z %r28,31,32,%r5 ;offset 0x988 +$0006001C + EXTRD,U %r4,31,32,%r31 ;offset 0x98c + CMPB,*<>,N %r31,%r2,$00060020 ;offset 0x990 + MOVB,TR %r6,%r29,$D1 ;offset 0x994 + STD %r29,-152(%r30) ;offset 0x998 +$0006000C + EXTRD,U %r3,31,32,%r25 ;offset 0x99c + COPY %r3,%r26 ;offset 0x9a0 + EXTRD,U %r3,31,32,%r9 ;offset 0x9a4 + EXTRD,U %r4,31,32,%r8 ;offset 0x9a8 + .CALL ARGW0=GR,ARGW1=GR,RTNVAL=GR ;in=25,26;out=28; + B,L BN_num_bits_word,%r2 ;offset 0x9ac + EXTRD,U %r5,31,32,%r7 ;offset 0x9b0 + LDI 64,%r20 ;offset 0x9b4 + DEPD %r7,31,32,%r5 ;offset 0x9b8 + DEPD %r8,31,32,%r4 ;offset 0x9bc + DEPD %r9,31,32,%r3 ;offset 0x9c0 + CMPB,= %r28,%r20,$00060012 ;offset 0x9c4 + COPY %r28,%r24 ;offset 0x9c8 + MTSARCM %r24 ;offset 0x9cc + DEPDI,Z -1,%sar,1,%r19 ;offset 0x9d0 + CMPB,*>>,N %r4,%r19,$D2 ;offset 0x9d4 +$00060012 + SUBI 64,%r24,%r31 ;offset 0x9d8 + CMPCLR,*<< %r4,%r3,%r0 ;offset 0x9dc + SUB %r4,%r3,%r4 ;offset 0x9e0 +$00060016 + CMPB,= %r31,%r0,$0006001A ;offset 0x9e4 + COPY %r0,%r9 ;offset 0x9e8 + MTSARCM %r31 ;offset 0x9ec + DEPD,Z %r3,%sar,64,%r3 ;offset 0x9f0 + SUBI 64,%r31,%r26 ;offset 0x9f4 + MTSAR %r26 ;offset 0x9f8 + SHRPD %r4,%r5,%sar,%r4 ;offset 0x9fc + MTSARCM %r31 ;offset 0xa00 + DEPD,Z %r5,%sar,64,%r5 ;offset 0xa04 +$0006001A + DEPDI,Z -1,31,32,%r19 ;offset 0xa08 + AND %r3,%r19,%r29 ;offset 0xa0c + EXTRD,U %r29,31,32,%r2 ;offset 0xa10 + DEPDI,Z -1,63,32,%r6 ;offset 0xa14 + MOVIB,TR 2,%r8,$0006001C ;offset 0xa18 + EXTRD,U %r3,63,32,%r7 ;offset 0xa1c +$D2 + ADDIL LR'__iob-$global$,%r27,%r1 ;offset 0xa20 + LDIL LR'C$7,%r21 ;offset 0xa24 + LDO RR'__iob-$global$+32(%r1),%r26 ;offset 0xa28 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR ;in=24,25,26;out=28; + B,L fprintf,%r2 ;offset 0xa2c + LDO RR'C$7(%r21),%r25 ;offset 0xa30 + .CALL ; + B,L abort,%r2 ;offset 0xa34 + NOP ;offset 0xa38 + B $D3 ;offset 0xa3c + LDW -212(%r30),%r2 ;offset 0xa40 +$00060020 + COPY %r4,%r26 ;offset 0xa44 + EXTRD,U %r4,31,32,%r25 ;offset 0xa48 + COPY %r2,%r24 ;offset 0xa4c + .CALL ;in=23,24,25,26;out=20,21,22,28,29; (MILLICALL) + B,L $$div2U,%r31 ;offset 0xa50 + EXTRD,U %r2,31,32,%r23 ;offset 0xa54 + DEPD %r28,31,32,%r29 ;offset 0xa58 +$00060022 + STD %r29,-152(%r30) ;offset 0xa5c +$D1 + AND %r5,%r19,%r24 ;offset 0xa60 + EXTRD,U %r24,31,32,%r24 ;offset 0xa64 + STW %r2,-160(%r30) ;offset 0xa68 + STW %r7,-128(%r30) ;offset 0xa6c + FLDD -152(%r30),%fr4 ;offset 0xa70 + FLDD -152(%r30),%fr7 ;offset 0xa74 + FLDW -160(%r30),%fr8L ;offset 0xa78 + FLDW -128(%r30),%fr5L ;offset 0xa7c + XMPYU %fr8L,%fr7L,%fr10 ;offset 0xa80 + FSTD %fr10,-136(%r30) ;offset 0xa84 + XMPYU %fr8L,%fr7R,%fr22 ;offset 0xa88 + FSTD %fr22,-144(%r30) ;offset 0xa8c + XMPYU %fr5L,%fr4L,%fr11 ;offset 0xa90 + XMPYU %fr5L,%fr4R,%fr23 ;offset 0xa94 + FSTD %fr11,-112(%r30) ;offset 0xa98 + FSTD %fr23,-120(%r30) ;offset 0xa9c + LDD -136(%r30),%r28 ;offset 0xaa0 + DEPD,Z %r28,31,32,%r31 ;offset 0xaa4 + LDD -144(%r30),%r20 ;offset 0xaa8 + ADD,L %r20,%r31,%r31 ;offset 0xaac + LDD -112(%r30),%r22 ;offset 0xab0 + DEPD,Z %r22,31,32,%r22 ;offset 0xab4 + LDD -120(%r30),%r21 ;offset 0xab8 + B $00060024 ;offset 0xabc + ADD,L %r21,%r22,%r23 ;offset 0xac0 +$D0 + OR %r9,%r29,%r29 ;offset 0xac4 +$00060040 + EXTRD,U %r29,31,32,%r28 ;offset 0xac8 +$00060002 +$L2 + LDW -212(%r30),%r2 ;offset 0xacc +$D3 + LDW -168(%r30),%r9 ;offset 0xad0 + LDD -176(%r30),%r8 ;offset 0xad4 + EXTRD,U %r8,31,32,%r7 ;offset 0xad8 + LDD -184(%r30),%r6 ;offset 0xadc + EXTRD,U %r6,31,32,%r5 ;offset 0xae0 + LDW -188(%r30),%r4 ;offset 0xae4 + BVE (%r2) ;offset 0xae8 + .EXIT + LDW,MB -192(%r30),%r3 ;offset 0xaec + .PROCEND ;in=23,25;out=28,29;fpin=105,107; + + + + +;---------------------------------------------------------------------------- +; +; Registers to hold 64-bit values to manipulate. The "L" part +; of the register corresponds to the upper 32-bits, while the "R" +; part corresponds to the lower 32-bits +; +; Note, that when using b6 and b7, the code must save these before +; using them because they are callee save registers +; +; +; Floating point registers to use to save values that +; are manipulated. These don't collide with ftemp1-6 and +; are all caller save registers +; +a0 .reg %fr22 +a0L .reg %fr22L +a0R .reg %fr22R + +a1 .reg %fr23 +a1L .reg %fr23L +a1R .reg %fr23R + +a2 .reg %fr24 +a2L .reg %fr24L +a2R .reg %fr24R + +a3 .reg %fr25 +a3L .reg %fr25L +a3R .reg %fr25R + +a4 .reg %fr26 +a4L .reg %fr26L +a4R .reg %fr26R + +a5 .reg %fr27 +a5L .reg %fr27L +a5R .reg %fr27R + +a6 .reg %fr28 +a6L .reg %fr28L +a6R .reg %fr28R + +a7 .reg %fr29 +a7L .reg %fr29L +a7R .reg %fr29R + +b0 .reg %fr30 +b0L .reg %fr30L +b0R .reg %fr30R + +b1 .reg %fr31 +b1L .reg %fr31L +b1R .reg %fr31R + +; +; Temporary floating point variables, these are all caller save +; registers +; +ftemp1 .reg %fr4 +ftemp2 .reg %fr5 +ftemp3 .reg %fr6 +ftemp4 .reg %fr7 + +; +; The B set of registers when used. +; + +b2 .reg %fr8 +b2L .reg %fr8L +b2R .reg %fr8R + +b3 .reg %fr9 +b3L .reg %fr9L +b3R .reg %fr9R + +b4 .reg %fr10 +b4L .reg %fr10L +b4R .reg %fr10R + +b5 .reg %fr11 +b5L .reg %fr11L +b5R .reg %fr11R + +b6 .reg %fr12 +b6L .reg %fr12L +b6R .reg %fr12R + +b7 .reg %fr13 +b7L .reg %fr13L +b7R .reg %fr13R + +c1 .reg %r21 ; only reg +temp1 .reg %r20 ; only reg +temp2 .reg %r19 ; only reg +temp3 .reg %r31 ; only reg + +m1 .reg %r28 +c2 .reg %r23 +high_one .reg %r1 +ht .reg %r6 +lt .reg %r5 +m .reg %r4 +c3 .reg %r3 + +SQR_ADD_C .macro A0L,A0R,C1,C2,C3 + XMPYU A0L,A0R,ftemp1 ; m + FSTD ftemp1,-24(%sp) ; store m + + XMPYU A0R,A0R,ftemp2 ; lt + FSTD ftemp2,-16(%sp) ; store lt + + XMPYU A0L,A0L,ftemp3 ; ht + FSTD ftemp3,-8(%sp) ; store ht + + LDD -24(%sp),m ; load m + AND m,high_mask,temp2 ; m & Mask + DEPD,Z m,30,31,temp3 ; m << 32+1 + LDD -16(%sp),lt ; lt + + LDD -8(%sp),ht ; ht + EXTRD,U temp2,32,33,temp1 ; temp1 = m&Mask >> 32-1 + ADD temp3,lt,lt ; lt = lt+m + ADD,L ht,temp1,ht ; ht += temp1 + ADD,DC ht,%r0,ht ; ht++ + + ADD C1,lt,C1 ; c1=c1+lt + ADD,DC ht,%r0,ht ; ht++ + + ADD C2,ht,C2 ; c2=c2+ht + ADD,DC C3,%r0,C3 ; c3++ +.endm + +SQR_ADD_C2 .macro A0L,A0R,A1L,A1R,C1,C2,C3 + XMPYU A0L,A1R,ftemp1 ; m1 = bl*ht + FSTD ftemp1,-16(%sp) ; + XMPYU A0R,A1L,ftemp2 ; m = bh*lt + FSTD ftemp2,-8(%sp) ; + XMPYU A0R,A1R,ftemp3 ; lt = bl*lt + FSTD ftemp3,-32(%sp) + XMPYU A0L,A1L,ftemp4 ; ht = bh*ht + FSTD ftemp4,-24(%sp) ; + + LDD -8(%sp),m ; r21 = m + LDD -16(%sp),m1 ; r19 = m1 + ADD,L m,m1,m ; m+m1 + + DEPD,Z m,31,32,temp3 ; (m+m1<<32) + LDD -24(%sp),ht ; r24 = ht + + CMPCLR,*>>= m,m1,%r0 ; if (m < m1) + ADD,L ht,high_one,ht ; ht+=high_one + + EXTRD,U m,31,32,temp1 ; m >> 32 + LDD -32(%sp),lt ; lt + ADD,L ht,temp1,ht ; ht+= m>>32 + ADD lt,temp3,lt ; lt = lt+m1 + ADD,DC ht,%r0,ht ; ht++ + + ADD ht,ht,ht ; ht=ht+ht; + ADD,DC C3,%r0,C3 ; add in carry (c3++) + + ADD lt,lt,lt ; lt=lt+lt; + ADD,DC ht,%r0,ht ; add in carry (ht++) + + ADD C1,lt,C1 ; c1=c1+lt + ADD,DC,*NUV ht,%r0,ht ; add in carry (ht++) + LDO 1(C3),C3 ; bump c3 if overflow,nullify otherwise + + ADD C2,ht,C2 ; c2 = c2 + ht + ADD,DC C3,%r0,C3 ; add in carry (c3++) +.endm + +; +;void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a) +; arg0 = r_ptr +; arg1 = a_ptr +; + +bn_sqr_comba8 .PROC - .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=8 - .ENTRY - stw %r2,-20(0,%r30) - stwm %r8,128(0,%r30) - stw %r7,-124(0,%r30) - stw %r4,-112(0,%r30) - stw %r3,-108(0,%r30) - copy %r26,%r3 - copy %r25,%r4 - stw %r6,-120(0,%r30) - ldi 0,%r7 - stw %r5,-116(0,%r30) - movb,<> %r24,%r5,L$0051 - ldi 2,%r6 - bl L$0068,0 - ldi -1,%r28 -L$0051 - .CALL ARGW0=GR - bl BN_num_bits_word,%r2 - copy %r5,%r26 - copy %r28,%r24 - ldi 32,%r19 - comb,= %r19,%r24,L$0052 - subi 31,%r24,%r19 - mtsar %r19 - zvdepi 1,32,%r19 - comb,>>= %r19,%r3,L$0052 - addil LR'__iob-$global$+32,%r27 - ldo RR'__iob-$global$+32(%r1),%r26 - ldil LR'L$C0000,%r25 - .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR - bl fprintf,%r2 - ldo RR'L$C0000(%r25),%r25 - .CALL - bl abort,%r2 - nop -L$0052 - comb,>> %r5,%r3,L$0053 - subi 32,%r24,%r24 - sub %r3,%r5,%r3 -L$0053 - comib,= 0,%r24,L$0054 - subi 31,%r24,%r19 - mtsar %r19 - zvdep %r5,32,%r5 - zvdep %r3,32,%r21 - subi 32,%r24,%r20 - mtsar %r20 - vshd 0,%r4,%r20 - or %r21,%r20,%r3 - mtsar %r19 - zvdep %r4,32,%r4 -L$0054 - extru %r5,15,16,%r23 - extru %r5,31,16,%r28 -L$0055 - extru %r3,15,16,%r19 - comb,<> %r23,%r19,L$0058 - copy %r3,%r26 - bl L$0059,0 - zdepi -1,31,16,%r29 -L$0058 - .IMPORT $$divU,MILLICODE - bl $$divU,%r31 - copy %r23,%r25 -L$0059 - stw %r29,-16(0,%r30) - fldws -16(0,%r30),%fr10L - stw %r28,-16(0,%r30) - fldws -16(0,%r30),%fr10R - stw %r23,-16(0,%r30) - xmpyu %fr10L,%fr10R,%fr8 - fldws -16(0,%r30),%fr10R - fstws %fr8R,-16(0,%r30) - xmpyu %fr10L,%fr10R,%fr9 - ldw -16(0,%r30),%r8 - fstws %fr9R,-16(0,%r30) - copy %r8,%r22 - ldw -16(0,%r30),%r8 - extru %r4,15,16,%r24 - copy %r8,%r21 -L$0060 - sub %r3,%r21,%r20 - copy %r20,%r19 - depi 0,31,16,%r19 - comib,<> 0,%r19,L$0061 - zdep %r20,15,16,%r19 - addl %r19,%r24,%r19 - comb,>>= %r19,%r22,L$0061 - sub %r22,%r28,%r22 - sub %r21,%r23,%r21 - bl L$0060,0 - ldo -1(%r29),%r29 -L$0061 - stw %r29,-16(0,%r30) - fldws -16(0,%r30),%fr10L - stw %r28,-16(0,%r30) - fldws -16(0,%r30),%fr10R - xmpyu %fr10L,%fr10R,%fr8 - fstws %fr8R,-16(0,%r30) - ldw -16(0,%r30),%r8 - stw %r23,-16(0,%r30) - fldws -16(0,%r30),%fr10R - copy %r8,%r19 - xmpyu %fr10L,%fr10R,%fr8 - fstws %fr8R,-16(0,%r30) - extru %r19,15,16,%r20 - ldw -16(0,%r30),%r8 - zdep %r19,15,16,%r19 - addl %r8,%r20,%r20 - comclr,<<= %r19,%r4,0 - addi 1,%r20,%r20 - comb,<<= %r20,%r3,L$0066 - sub %r4,%r19,%r4 - addl %r3,%r5,%r3 - ldo -1(%r29),%r29 -L$0066 - addib,= -1,%r6,L$0056 - sub %r3,%r20,%r3 - zdep %r29,15,16,%r7 - shd %r3,%r4,16,%r3 - bl L$0055,0 - zdep %r4,15,16,%r4 -L$0056 - or %r7,%r29,%r28 -L$0068 - ldw -148(0,%r30),%r2 - ldw -124(0,%r30),%r7 - ldw -120(0,%r30),%r6 - ldw -116(0,%r30),%r5 - ldw -112(0,%r30),%r4 - ldw -108(0,%r30),%r3 - bv 0(%r2) - ldwm -128(0,%r30),%r8 - .EXIT - .PROCEND + .CALLINFO FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_sqr_comba8,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .ENTRY + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z -1,32,33,high_mask ; Create Mask 0xffffffff80000000L + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + FLDD 32(a_ptr),a4 + FLDD 40(a_ptr),a5 + FLDD 48(a_ptr),a6 + FLDD 56(a_ptr),a7 + + SQR_ADD_C a0L,a0R,c1,c2,c3 + STD c1,0(r_ptr) ; r[0] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a1L,a1R,a0L,a0R,c2,c3,c1 + STD c2,8(r_ptr) ; r[1] = c2; + COPY %r0,c2 + + SQR_ADD_C a1L,a1R,c3,c1,c2 + SQR_ADD_C2 a2L,a2R,a0L,a0R,c3,c1,c2 + STD c3,16(r_ptr) ; r[2] = c3; + COPY %r0,c3 + + SQR_ADD_C2 a3L,a3R,a0L,a0R,c1,c2,c3 + SQR_ADD_C2 a2L,a2R,a1L,a1R,c1,c2,c3 + STD c1,24(r_ptr) ; r[3] = c1; + COPY %r0,c1 + + SQR_ADD_C a2L,a2R,c2,c3,c1 + SQR_ADD_C2 a3L,a3R,a1L,a1R,c2,c3,c1 + SQR_ADD_C2 a4L,a4R,a0L,a0R,c2,c3,c1 + STD c2,32(r_ptr) ; r[4] = c2; + COPY %r0,c2 + + SQR_ADD_C2 a5L,a5R,a0L,a0R,c3,c1,c2 + SQR_ADD_C2 a4L,a4R,a1L,a1R,c3,c1,c2 + SQR_ADD_C2 a3L,a3R,a2L,a2R,c3,c1,c2 + STD c3,40(r_ptr) ; r[5] = c3; + COPY %r0,c3 + + SQR_ADD_C a3L,a3R,c1,c2,c3 + SQR_ADD_C2 a4L,a4R,a2L,a2R,c1,c2,c3 + SQR_ADD_C2 a5L,a5R,a1L,a1R,c1,c2,c3 + SQR_ADD_C2 a6L,a6R,a0L,a0R,c1,c2,c3 + STD c1,48(r_ptr) ; r[6] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a7L,a7R,a0L,a0R,c2,c3,c1 + SQR_ADD_C2 a6L,a6R,a1L,a1R,c2,c3,c1 + SQR_ADD_C2 a5L,a5R,a2L,a2R,c2,c3,c1 + SQR_ADD_C2 a4L,a4R,a3L,a3R,c2,c3,c1 + STD c2,56(r_ptr) ; r[7] = c2; + COPY %r0,c2 + + SQR_ADD_C a4L,a4R,c3,c1,c2 + SQR_ADD_C2 a5L,a5R,a3L,a3R,c3,c1,c2 + SQR_ADD_C2 a6L,a6R,a2L,a2R,c3,c1,c2 + SQR_ADD_C2 a7L,a7R,a1L,a1R,c3,c1,c2 + STD c3,64(r_ptr) ; r[8] = c3; + COPY %r0,c3 + + SQR_ADD_C2 a7L,a7R,a2L,a2R,c1,c2,c3 + SQR_ADD_C2 a6L,a6R,a3L,a3R,c1,c2,c3 + SQR_ADD_C2 a5L,a5R,a4L,a4R,c1,c2,c3 + STD c1,72(r_ptr) ; r[9] = c1; + COPY %r0,c1 + + SQR_ADD_C a5L,a5R,c2,c3,c1 + SQR_ADD_C2 a6L,a6R,a4L,a4R,c2,c3,c1 + SQR_ADD_C2 a7L,a7R,a3L,a3R,c2,c3,c1 + STD c2,80(r_ptr) ; r[10] = c2; + COPY %r0,c2 + + SQR_ADD_C2 a7L,a7R,a4L,a4R,c3,c1,c2 + SQR_ADD_C2 a6L,a6R,a5L,a5R,c3,c1,c2 + STD c3,88(r_ptr) ; r[11] = c3; + COPY %r0,c3 + + SQR_ADD_C a6L,a6R,c1,c2,c3 + SQR_ADD_C2 a7L,a7R,a5L,a5R,c1,c2,c3 + STD c1,96(r_ptr) ; r[12] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a7L,a7R,a6L,a6R,c2,c3,c1 + STD c2,104(r_ptr) ; r[13] = c2; + COPY %r0,c2 + + SQR_ADD_C a7L,a7R,c3,c1,c2 + STD c3, 112(r_ptr) ; r[14] = c3 + STD c1, 120(r_ptr) ; r[15] = c1 + + .EXIT + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + +;----------------------------------------------------------------------------- +; +;void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a) +; arg0 = r_ptr +; arg1 = a_ptr +; + +bn_sqr_comba4 + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_sqr_comba4,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z -1,32,33,high_mask ; Create Mask 0xffffffff80000000L + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + FLDD 32(a_ptr),a4 + FLDD 40(a_ptr),a5 + FLDD 48(a_ptr),a6 + FLDD 56(a_ptr),a7 + + SQR_ADD_C a0L,a0R,c1,c2,c3 + + STD c1,0(r_ptr) ; r[0] = c1; + COPY %r0,c1 + + SQR_ADD_C2 a1L,a1R,a0L,a0R,c2,c3,c1 + + STD c2,8(r_ptr) ; r[1] = c2; + COPY %r0,c2 + + SQR_ADD_C a1L,a1R,c3,c1,c2 + SQR_ADD_C2 a2L,a2R,a0L,a0R,c3,c1,c2 + + STD c3,16(r_ptr) ; r[2] = c3; + COPY %r0,c3 + + SQR_ADD_C2 a3L,a3R,a0L,a0R,c1,c2,c3 + SQR_ADD_C2 a2L,a2R,a1L,a1R,c1,c2,c3 + + STD c1,24(r_ptr) ; r[3] = c1; + COPY %r0,c1 + + SQR_ADD_C a2L,a2R,c2,c3,c1 + SQR_ADD_C2 a3L,a3R,a1L,a1R,c2,c3,c1 + + STD c2,32(r_ptr) ; r[4] = c2; + COPY %r0,c2 + + SQR_ADD_C2 a3L,a3R,a2L,a2R,c3,c1,c2 + STD c3,40(r_ptr) ; r[5] = c3; + COPY %r0,c3 + + SQR_ADD_C a3L,a3R,c1,c2,c3 + STD c1,48(r_ptr) ; r[6] = c1; + STD c2,56(r_ptr) ; r[7] = c2; + + .EXIT + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + + +;--------------------------------------------------------------------------- + +MUL_ADD_C .macro A0L,A0R,B0L,B0R,C1,C2,C3 + XMPYU A0L,B0R,ftemp1 ; m1 = bl*ht + FSTD ftemp1,-16(%sp) ; + XMPYU A0R,B0L,ftemp2 ; m = bh*lt + FSTD ftemp2,-8(%sp) ; + XMPYU A0R,B0R,ftemp3 ; lt = bl*lt + FSTD ftemp3,-32(%sp) + XMPYU A0L,B0L,ftemp4 ; ht = bh*ht + FSTD ftemp4,-24(%sp) ; + + LDD -8(%sp),m ; r21 = m + LDD -16(%sp),m1 ; r19 = m1 + ADD,L m,m1,m ; m+m1 + + DEPD,Z m,31,32,temp3 ; (m+m1<<32) + LDD -24(%sp),ht ; r24 = ht + + CMPCLR,*>>= m,m1,%r0 ; if (m < m1) + ADD,L ht,high_one,ht ; ht+=high_one + + EXTRD,U m,31,32,temp1 ; m >> 32 + LDD -32(%sp),lt ; lt + ADD,L ht,temp1,ht ; ht+= m>>32 + ADD lt,temp3,lt ; lt = lt+m1 + ADD,DC ht,%r0,ht ; ht++ + + ADD C1,lt,C1 ; c1=c1+lt + ADD,DC ht,%r0,ht ; bump c3 if overflow,nullify otherwise + + ADD C2,ht,C2 ; c2 = c2 + ht + ADD,DC C3,%r0,C3 ; add in carry (c3++) +.endm + + +; +;void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +; arg0 = r_ptr +; arg1 = a_ptr +; arg2 = b_ptr +; + +bn_mul_comba8 + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_mul_comba8,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + FSTD %fr12,32(%sp) ; save r6 + FSTD %fr13,40(%sp) ; save r7 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + FLDD 32(a_ptr),a4 + FLDD 40(a_ptr),a5 + FLDD 48(a_ptr),a6 + FLDD 56(a_ptr),a7 + + FLDD 0(b_ptr),b0 + FLDD 8(b_ptr),b1 + FLDD 16(b_ptr),b2 + FLDD 24(b_ptr),b3 + FLDD 32(b_ptr),b4 + FLDD 40(b_ptr),b5 + FLDD 48(b_ptr),b6 + FLDD 56(b_ptr),b7 + + MUL_ADD_C a0L,a0R,b0L,b0R,c1,c2,c3 + STD c1,0(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a0L,a0R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b0L,b0R,c2,c3,c1 + STD c2,8(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a2L,a2R,b0L,b0R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a0L,a0R,b2L,b2R,c3,c1,c2 + STD c3,16(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a0L,a0R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a1L,a1R,b2L,b2R,c1,c2,c3 + MUL_ADD_C a2L,a2R,b1L,b1R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b0L,b0R,c1,c2,c3 + STD c1,24(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a4L,a4R,b0L,b0R,c2,c3,c1 + MUL_ADD_C a3L,a3R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a2L,a2R,b2L,b2R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b3L,b3R,c2,c3,c1 + MUL_ADD_C a0L,a0R,b4L,b4R,c2,c3,c1 + STD c2,32(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a0L,a0R,b5L,b5R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b4L,b4R,c3,c1,c2 + MUL_ADD_C a2L,a2R,b3L,b3R,c3,c1,c2 + MUL_ADD_C a3L,a3R,b2L,b2R,c3,c1,c2 + MUL_ADD_C a4L,a4R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a5L,a5R,b0L,b0R,c3,c1,c2 + STD c3,40(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a6L,a6R,b0L,b0R,c1,c2,c3 + MUL_ADD_C a5L,a5R,b1L,b1R,c1,c2,c3 + MUL_ADD_C a4L,a4R,b2L,b2R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a2L,a2R,b4L,b4R,c1,c2,c3 + MUL_ADD_C a1L,a1R,b5L,b5R,c1,c2,c3 + MUL_ADD_C a0L,a0R,b6L,b6R,c1,c2,c3 + STD c1,48(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a0L,a0R,b7L,b7R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b6L,b6R,c2,c3,c1 + MUL_ADD_C a2L,a2R,b5L,b5R,c2,c3,c1 + MUL_ADD_C a3L,a3R,b4L,b4R,c2,c3,c1 + MUL_ADD_C a4L,a4R,b3L,b3R,c2,c3,c1 + MUL_ADD_C a5L,a5R,b2L,b2R,c2,c3,c1 + MUL_ADD_C a6L,a6R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a7L,a7R,b0L,b0R,c2,c3,c1 + STD c2,56(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a7L,a7R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a6L,a6R,b2L,b2R,c3,c1,c2 + MUL_ADD_C a5L,a5R,b3L,b3R,c3,c1,c2 + MUL_ADD_C a4L,a4R,b4L,b4R,c3,c1,c2 + MUL_ADD_C a3L,a3R,b5L,b5R,c3,c1,c2 + MUL_ADD_C a2L,a2R,b6L,b6R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b7L,b7R,c3,c1,c2 + STD c3,64(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a2L,a2R,b7L,b7R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b6L,b6R,c1,c2,c3 + MUL_ADD_C a4L,a4R,b5L,b5R,c1,c2,c3 + MUL_ADD_C a5L,a5R,b4L,b4R,c1,c2,c3 + MUL_ADD_C a6L,a6R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a7L,a7R,b2L,b2R,c1,c2,c3 + STD c1,72(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a7L,a7R,b3L,b3R,c2,c3,c1 + MUL_ADD_C a6L,a6R,b4L,b4R,c2,c3,c1 + MUL_ADD_C a5L,a5R,b5L,b5R,c2,c3,c1 + MUL_ADD_C a4L,a4R,b6L,b6R,c2,c3,c1 + MUL_ADD_C a3L,a3R,b7L,b7R,c2,c3,c1 + STD c2,80(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a4L,a4R,b7L,b7R,c3,c1,c2 + MUL_ADD_C a5L,a5R,b6L,b6R,c3,c1,c2 + MUL_ADD_C a6L,a6R,b5L,b5R,c3,c1,c2 + MUL_ADD_C a7L,a7R,b4L,b4R,c3,c1,c2 + STD c3,88(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a7L,a7R,b5L,b5R,c1,c2,c3 + MUL_ADD_C a6L,a6R,b6L,b6R,c1,c2,c3 + MUL_ADD_C a5L,a5R,b7L,b7R,c1,c2,c3 + STD c1,96(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a6L,a6R,b7L,b7R,c2,c3,c1 + MUL_ADD_C a7L,a7R,b6L,b6R,c2,c3,c1 + STD c2,104(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a7L,a7R,b7L,b7R,c3,c1,c2 + STD c3,112(r_ptr) + STD c1,120(r_ptr) + + .EXIT + FLDD -88(%sp),%fr13 + FLDD -96(%sp),%fr12 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + +;----------------------------------------------------------------------------- +; +;void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +; arg0 = r_ptr +; arg1 = a_ptr +; arg2 = b_ptr +; + +bn_mul_comba4 + .proc + .callinfo FRAME=128,ENTRY_GR=%r3,ARGS_SAVED,ORDERING_AWARE + .EXPORT bn_mul_comba4,ENTRY,PRIV_LEV=3,NO_RELOCATION,LONG_RETURN + .entry + .align 64 + + STD %r3,0(%sp) ; save r3 + STD %r4,8(%sp) ; save r4 + STD %r5,16(%sp) ; save r5 + STD %r6,24(%sp) ; save r6 + FSTD %fr12,32(%sp) ; save r6 + FSTD %fr13,40(%sp) ; save r7 + + ; + ; Zero out carries + ; + COPY %r0,c1 + COPY %r0,c2 + COPY %r0,c3 + + LDO 128(%sp),%sp ; bump stack + DEPDI,Z 1,31,1,high_one ; Create Value 1 << 32 + + ; + ; Load up all of the values we are going to use + ; + FLDD 0(a_ptr),a0 + FLDD 8(a_ptr),a1 + FLDD 16(a_ptr),a2 + FLDD 24(a_ptr),a3 + + FLDD 0(b_ptr),b0 + FLDD 8(b_ptr),b1 + FLDD 16(b_ptr),b2 + FLDD 24(b_ptr),b3 + + MUL_ADD_C a0L,a0R,b0L,b0R,c1,c2,c3 + STD c1,0(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a0L,a0R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b0L,b0R,c2,c3,c1 + STD c2,8(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a2L,a2R,b0L,b0R,c3,c1,c2 + MUL_ADD_C a1L,a1R,b1L,b1R,c3,c1,c2 + MUL_ADD_C a0L,a0R,b2L,b2R,c3,c1,c2 + STD c3,16(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a0L,a0R,b3L,b3R,c1,c2,c3 + MUL_ADD_C a1L,a1R,b2L,b2R,c1,c2,c3 + MUL_ADD_C a2L,a2R,b1L,b1R,c1,c2,c3 + MUL_ADD_C a3L,a3R,b0L,b0R,c1,c2,c3 + STD c1,24(r_ptr) + COPY %r0,c1 + + MUL_ADD_C a3L,a3R,b1L,b1R,c2,c3,c1 + MUL_ADD_C a2L,a2R,b2L,b2R,c2,c3,c1 + MUL_ADD_C a1L,a1R,b3L,b3R,c2,c3,c1 + STD c2,32(r_ptr) + COPY %r0,c2 + + MUL_ADD_C a2L,a2R,b3L,b3R,c3,c1,c2 + MUL_ADD_C a3L,a3R,b2L,b2R,c3,c1,c2 + STD c3,40(r_ptr) + COPY %r0,c3 + + MUL_ADD_C a3L,a3R,b3L,b3R,c1,c2,c3 + STD c1,48(r_ptr) + STD c2,56(r_ptr) + + .EXIT + FLDD -88(%sp),%fr13 + FLDD -96(%sp),%fr12 + LDD -104(%sp),%r6 ; restore r6 + LDD -112(%sp),%r5 ; restore r5 + LDD -120(%sp),%r4 ; restore r4 + BVE (%rp) + LDD,MB -128(%sp),%r3 + + .PROCEND + + + .SPACE $TEXT$ + .SUBSPA $CODE$ + .SPACE $PRIVATE$,SORT=16 + .IMPORT $global$,DATA + .SPACE $TEXT$ + .SUBSPA $CODE$ + .SUBSPA $LIT$,ACCESS=0x2c +C$7 + .ALIGN 8 + .STRINGZ "Division would overflow (%d)\n" + .END diff --git a/src/lib/libcrypto/bn/asm/pa-risc2W.s b/src/lib/libcrypto/bn/asm/pa-risc2W.s index 54b6606252..a99545754d 100644 --- a/src/lib/libcrypto/bn/asm/pa-risc2W.s +++ b/src/lib/libcrypto/bn/asm/pa-risc2W.s @@ -1598,7 +1598,7 @@ bn_mul_comba4 .IMPORT $global$,DATA .SPACE $TEXT$ .SUBSPA $CODE$ - .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=0x2c,SORT=16 + .SUBSPA $LIT$,ACCESS=0x2c C$4 .ALIGN 8 .STRINGZ "Division would overflow (%d)\n" diff --git a/src/lib/libcrypto/bn/bn.h b/src/lib/libcrypto/bn/bn.h index f935e1ca79..1eaf879553 100644 --- a/src/lib/libcrypto/bn/bn.h +++ b/src/lib/libcrypto/bn/bn.h @@ -59,38 +59,39 @@ #ifndef HEADER_BN_H #define HEADER_BN_H -#ifndef WIN16 +#include +#ifndef OPENSSL_NO_FP_API #include /* FILE */ #endif -#include #ifdef __cplusplus extern "C" { #endif -#ifdef VMS +#ifdef OPENSSL_SYS_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 nornal cc. This would - * be a common occurance because gcc normally produces code that is + * 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 assember code. */ -#if defined(MSDOS) || defined(WINDOWS) || defined(linux) -#define BN_DIV2W + * using "long long's", are 32bit, and are not using my assembler code. */ +#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \ + defined(OPENSSL_SYS_WIN32) || defined(linux) +# ifndef BN_DIV2W +# define BN_DIV2W +# endif #endif /* assuming long is 64bit - this is the DEC Alpha @@ -118,8 +119,8 @@ extern "C" { /* 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 relevent - * assember code :-). Do NOT define BN_LLONG. + * 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 @@ -135,14 +136,14 @@ extern "C" { #define BN_MASK2h (0xffffffff00000000LL) #define BN_MASK2h1 (0xffffffff80000000LL) #define BN_TBIT (0x8000000000000000LL) -#define BN_DEC_CONV (10000000000000000000LL) +#define BN_DEC_CONV (10000000000000000000ULL) #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__) +#if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) #define BN_ULLONG unsigned _int64 #else #define BN_ULLONG unsigned long long @@ -153,7 +154,7 @@ extern "C" { #define BN_BYTES 4 #define BN_BITS2 32 #define BN_BITS4 16 -#ifdef WIN32 +#ifdef OPENSSL_SYS_WIN32 /* VC++ doesn't like the LL suffix */ #define BN_MASK (0xffffffffffffffffL) #else @@ -233,19 +234,13 @@ 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 dmax; /* 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 -typedef struct bignum_ctx - { - int tos; - BIGNUM bn[BN_CTX_NUM+1]; - int flags; - } BN_CTX; +/* Used for temp variables (declaration hidden in bn_lcl.h) */ +typedef struct bignum_ctx BN_CTX; typedef struct bn_blinding_st { @@ -257,16 +252,15 @@ typedef struct bn_blinding_st /* Used for montgomery multiplication */ typedef struct bn_mont_ctx_st - { - int use_word; /* 0 for word form, 1 for long form */ - int ri; /* number of bits in R */ - BIGNUM RR; /* used to convert to montgomery form */ - BIGNUM N; /* The modulus */ - BIGNUM Ni; /* The inverse of N */ - BN_ULONG n0; /* word form of inverse, normally only one of - * Ni or n0 is defined */ + { + 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; + } BN_MONT_CTX; /* Used for reciprocal division/mod functions * It cannot be shared between threads @@ -280,97 +274,129 @@ typedef struct bn_recp_ctx_st 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 (5) +#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)) + +/* Note that BN_abs_is_word does not work reliably for w == 0 */ +#define BN_abs_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) +#define BN_is_zero(a) (((a)->top == 0) || BN_abs_is_word(a,0)) +#define BN_is_one(a) (BN_abs_is_word((a),1) && !(a)->neg) +#define BN_is_word(a,w) ((w) ? BN_abs_is_word((a),(w)) && !(a)->neg : \ + BN_is_zero((a))) +#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) */ -#define bn_expand(n,b) ((((((b+BN_BITS2-1))/BN_BITS2)) <= (n)->max)?\ - (n):bn_expand2((n),(b)/BN_BITS2+1)) -#define bn_wexpand(n,b) (((b) <= (n)->max)?(n):bn_expand2((n),(b))) - -#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; \ - } \ - } - -BIGNUM *BN_value_one(void); +const 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_pseudo_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); +void BN_swap(BIGNUM *a, 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); +BIGNUM *BN_mpi2bn(const 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, BIGNUM *a, BIGNUM *b); -int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, const BIGNUM *a,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(BIGNUM *a, BN_ULONG w); + BN_CTX *ctx); +#define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx)) +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m); +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m); +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m); + +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); +BN_ULONG BN_get_word(const 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_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_lshift1(BIGNUM *r, const BIGNUM *a); +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,BN_CTX *ctx); + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m,BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, const 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, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2,const BIGNUM *m, + BN_CTX *ctx,BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const 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 WIN16 -int BN_print_fp(FILE *fp, BIGNUM *a); +#ifndef OPENSSL_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(char *fp, const BIGNUM *a); +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); +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, const BIGNUM *a); void BN_clear(BIGNUM *a); -BIGNUM *bn_expand2(BIGNUM *b, int bits); BIGNUM *BN_dup(const BIGNUM *a); int BN_ucmp(const BIGNUM *a, const BIGNUM *b); int BN_set_bit(BIGNUM *a, int n); @@ -379,26 +405,30 @@ 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 strong,BIGNUM *add, - BIGNUM *rem,void (*callback)(int,int,void *),void *cb_arg); -int BN_is_prime(BIGNUM *p,int nchecks,void (*callback)(int,int,void *), - BN_CTX *ctx,void *cb_arg); -void ERR_load_BN_strings(void ); - -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); +int BN_gcd(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx); +int BN_kronecker(const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx); /* returns -2 for error */ +BIGNUM *BN_mod_inverse(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx); +BIGNUM *BN_mod_sqrt(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx); +BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe, + const BIGNUM *add, const 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); 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); +int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\ + (r),(a),&((mont)->RR),(mont),(ctx)) +int BN_from_montgomery(BIGNUM *r,const 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); @@ -416,18 +446,55 @@ 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_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const 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); + const BIGNUM *m, BN_CTX *ctx); +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); + +/* library internal functions */ + +#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\ + (a):bn_expand2((a),(bits)/BN_BITS2+1)) +#define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words))) +BIGNUM *bn_expand2(BIGNUM *a, int words); +BIGNUM *bn_dup_expand(const 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, const BN_ULONG *ap, int num, BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, const 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, const BN_ULONG *ap, const BN_ULONG *bp,int num); +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num); + +#ifdef BN_DEBUG +void bn_dump1(FILE *o, const char *a, const 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 + +int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom); /* 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. */ +void ERR_load_BN_strings(void); /* Error codes for the BN functions. */ @@ -438,30 +505,43 @@ int BN_div_recp(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, #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_EXPAND_INTERNAL 120 +#define BN_F_BN_MOD_EXP2_MONT 118 #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_LSHIFT_QUICK 119 #define BN_F_BN_MOD_MUL_RECIPROCAL 111 +#define BN_F_BN_MOD_SQRT 121 #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_BIGNUM_TOO_LONG 114 #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_INPUT_NOT_REDUCED 110 #define BN_R_INVALID_LENGTH 106 +#define BN_R_INVALID_RANGE 115 +#define BN_R_NOT_A_SQUARE 111 #define BN_R_NOT_INITIALIZED 107 #define BN_R_NO_INVERSE 108 +#define BN_R_P_IS_NOT_PRIME 112 +#define BN_R_TOO_MANY_ITERATIONS 113 +#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/bn/bn_add.c b/src/lib/libcrypto/bn/bn_add.c index efb2e312e8..6cba07e9f6 100644 --- a/src/lib/libcrypto/bn/bn_add.c +++ b/src/lib/libcrypto/bn/bn_add.c @@ -61,76 +61,70 @@ #include "bn_lcl.h" /* r can == a or b */ -int BN_add(r, a, b) -BIGNUM *r; -BIGNUM *a; -BIGNUM *b; +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) { - int i; - BIGNUM *tmp; + const BIGNUM *tmp; + int a_neg = a->neg; + + 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) + if (a_neg ^ b->neg) { /* only one is negative */ - if (a->neg) + if (a_neg) { tmp=a; a=b; b=tmp; } /* we are now a - b */ if (BN_ucmp(a,b) < 0) { - if (bn_wexpand(r,b->top) == NULL) return(0); - bn_qsub(r,b,a); + if (!BN_usub(r,b,a)) return(0); r->neg=1; } else { - if (bn_wexpand(r,a->top) == NULL) return(0); - bn_qsub(r,a,b); + if (!BN_usub(r,a,b)) return(0); r->neg=0; } return(1); } - if (a->neg) /* both are neg */ + if (!BN_uadd(r,a,b)) return(0); + if (a_neg) /* both are neg */ r->neg=1; else r->neg=0; - - i=(a->top > b->top); - - if (i) - { - if (bn_wexpand(r,a->top+1) == NULL) return(0); - bn_qadd(r,a,b); - } - else - { - if (bn_wexpand(r,b->top+1) == NULL) return(0); - bn_qadd(r,b,a); - } return(1); } /* unsigned add of b to a, r must be large enough */ -void bn_qadd(r,a,b) -BIGNUM *r; -BIGNUM *a; -BIGNUM *b; +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; @@ -160,8 +154,156 @@ BIGNUM *b; r->top++; } } - for (; ineg = 0; + return(1); + } + +/* unsigned subtraction of b from a, a must be larger than b. */ +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) + { + int max,min; + register BN_ULONG t1,t2,*ap,*bp,*rp; + int i,carry; +#if defined(IRIX_CC_BUG) && !defined(LINT) + int dummy; +#endif + + bn_check_top(a); + bn_check_top(b); + + if (a->top < 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; + r->neg=0; + 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/src/lib/libcrypto/bn/bn_asm.c b/src/lib/libcrypto/bn/bn_asm.c index 4d3da16a0c..be8aa3ffc5 100644 --- a/src/lib/libcrypto/bn/bn_asm.c +++ b/src/lib/libcrypto/bn/bn_asm.c @@ -56,97 +56,95 @@ * [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" -#ifdef BN_LLONG +#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 bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) { BN_ULONG c1=0; - bn_check_num(num); + assert(num >= 0); if (num <= 0) return(c1); - for (;;) + while (num&~3) { mul_add(rp[0],ap[0],w,c1); - if (--num == 0) break; mul_add(rp[1],ap[1],w,c1); - if (--num == 0) break; mul_add(rp[2],ap[2],w,c1); - if (--num == 0) break; mul_add(rp[3],ap[3],w,c1); - if (--num == 0) break; - ap+=4; - rp+=4; + 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 bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) { BN_ULONG c1=0; - bn_check_num(num); + assert(num >= 0); if (num <= 0) return(c1); - /* for (;;) */ - while (1) /* circumvent egcs-1.1.2 bug */ + while (num&~3) { mul(rp[0],ap[0],w,c1); - if (--num == 0) break; mul(rp[1],ap[1],w,c1); - if (--num == 0) break; mul(rp[2],ap[2],w,c1); - if (--num == 0) break; mul(rp[3],ap[3],w,c1); - if (--num == 0) break; - ap+=4; - rp+=4; + 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) +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) { - bn_check_num(n); + assert(n >= 0); if (n <= 0) return; - for (;;) + while (n&~3) { - BN_ULLONG t; - - t=(BN_ULLONG)(a[0])*(a[0]); - r[0]=Lw(t); r[1]=Hw(t); - if (--n == 0) break; - - t=(BN_ULLONG)(a[1])*(a[1]); - r[2]=Lw(t); r[3]=Hw(t); - if (--n == 0) break; - - t=(BN_ULLONG)(a[2])*(a[2]); - r[4]=Lw(t); r[5]=Hw(t); - if (--n == 0) break; - - t=(BN_ULLONG)(a[3])*(a[3]); - r[6]=Lw(t); r[7]=Hw(t); - if (--n == 0) break; - - a+=4; - r+=8; + 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 +#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 bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) { BN_ULONG c=0; BN_ULONG bl,bh; - bn_check_num(num); + assert(num >= 0); if (num <= 0) return((BN_ULONG)0); bl=LBITS(w); @@ -168,12 +166,12 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) return(c); } -BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) { BN_ULONG carry=0; BN_ULONG bl,bh; - bn_check_num(num); + assert(num >= 0); if (num <= 0) return((BN_ULONG)0); bl=LBITS(w); @@ -195,9 +193,9 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w) return(carry); } -void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) +void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) { - bn_check_num(n); + assert(n >= 0); if (n <= 0) return; for (;;) { @@ -218,7 +216,7 @@ void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n) } } -#endif +#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */ #if defined(BN_LLONG) && defined(BN_DIV2W) @@ -229,7 +227,7 @@ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) #else -/* Divide h-l by d and return the result. */ +/* Divide h,l by d and return the result. */ /* I need to test this some more :-( */ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) { @@ -239,13 +237,8 @@ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) if (d == 0) return(BN_MASK2); i=BN_num_bits_word(d); - if ((i != BN_BITS2) && (h > (BN_ULONG)1< (BN_ULONG)1<= d) h-=d; @@ -300,14 +293,14 @@ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) ret|=q; return(ret); } -#endif +#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */ #ifdef BN_LLONG -BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) { BN_ULLONG ll=0; - bn_check_num(n); + assert(n >= 0); if (n <= 0) return((BN_ULONG)0); for (;;) @@ -338,12 +331,12 @@ BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) } return((BN_ULONG)ll); } -#else -BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +#else /* !BN_LLONG */ +BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) { BN_ULONG c,l,t; - bn_check_num(n); + assert(n >= 0); if (n <= 0) return((BN_ULONG)0); c=0; @@ -387,14 +380,14 @@ BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) } return((BN_ULONG)c); } -#endif +#endif /* !BN_LLONG */ -BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) +BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) { BN_ULONG t1,t2; int c=0; - bn_check_num(n); + assert(n >= 0); if (n <= 0) return((BN_ULONG)0); for (;;) @@ -433,6 +426,11 @@ BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) #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; \ @@ -460,7 +458,39 @@ BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) #define sqr_add_c2(a,i,j,c0,c1,c2) \ mul_add_c2((a)[i],(a)[j],c0,c1,c2) -#else + +#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 += (c0A=BN_new()) == NULL) goto err; if ((ret->Ai=BN_new()) == NULL) goto err; @@ -78,26 +81,26 @@ BIGNUM *mod; return(ret); err: if (ret != NULL) BN_BLINDING_free(ret); - return(ret); + return(NULL); } -void BN_BLINDING_free(r) -BN_BLINDING *r; +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); + OPENSSL_free(r); } -int BN_BLINDING_update(b,ctx) -BN_BLINDING *b; -BN_CTX *ctx; +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_INITALISED); + BNerr(BN_F_BN_BLINDING_UPDATE,BN_R_NOT_INITIALIZED); goto err; } @@ -109,28 +112,26 @@ err: return(ret); } -int BN_BLINDING_convert(n,b,ctx) -BIGNUM *n; -BN_BLINDING *b; -BN_CTX *ctx; +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_INITALISED); + 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(n,b,ctx) -BIGNUM *n; -BN_BLINDING *b; -BN_CTX *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_INITALISED); + 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) diff --git a/src/lib/libcrypto/bn/bn_ctx.c b/src/lib/libcrypto/bn/bn_ctx.c index 46132fd180..7daf19eb84 100644 --- a/src/lib/libcrypto/bn/bn_ctx.c +++ b/src/lib/libcrypto/bn/bn_ctx.c @@ -61,15 +61,16 @@ #include #include + #include "cryptlib.h" -#include +#include "bn_lcl.h" BN_CTX *BN_CTX_new(void) { BN_CTX *ret; - ret=(BN_CTX *)Malloc(sizeof(BN_CTX)); + ret=(BN_CTX *)OPENSSL_malloc(sizeof(BN_CTX)); if (ret == NULL) { BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE); @@ -83,6 +84,7 @@ BN_CTX *BN_CTX_new(void) void BN_CTX_init(BN_CTX *ctx) { +#if 0 /* explicit version */ int i; ctx->tos = 0; ctx->flags = 0; @@ -90,6 +92,9 @@ void BN_CTX_init(BN_CTX *ctx) ctx->too_many = 0; for (i = 0; i < BN_CTX_NUM; i++) BN_init(&(ctx->bn[i])); +#else + memset(ctx, 0, sizeof *ctx); +#endif } void BN_CTX_free(BN_CTX *ctx) @@ -102,7 +107,7 @@ void BN_CTX_free(BN_CTX *ctx) for (i=0; i < BN_CTX_NUM; i++) BN_clear_free(&(ctx->bn[i])); if (ctx->flags & BN_FLG_MALLOCED) - Free(ctx); + OPENSSL_free(ctx); } void BN_CTX_start(BN_CTX *ctx) @@ -112,8 +117,14 @@ void BN_CTX_start(BN_CTX *ctx) ctx->depth++; } + BIGNUM *BN_CTX_get(BN_CTX *ctx) { + /* Note: If BN_CTX_get is ever changed to allocate BIGNUMs dynamically, + * make sure that if BN_CTX_get fails once it will return NULL again + * until BN_CTX_end is called. (This is so that callers have to check + * only the last return value.) + */ if (ctx->depth > BN_CTX_NUM_POS || ctx->tos >= BN_CTX_NUM) { if (!ctx->too_many) diff --git a/src/lib/libcrypto/bn/bn_div.c b/src/lib/libcrypto/bn/bn_div.c index 2263bdc7da..f9a095e3b3 100644 --- a/src/lib/libcrypto/bn/bn_div.c +++ b/src/lib/libcrypto/bn/bn_div.c @@ -57,21 +57,22 @@ */ #include +#include #include "cryptlib.h" #include "bn_lcl.h" + /* The old slow way */ #if 0 -int BN_div(dv, rem, m, d,ctx) -BIGNUM *dv; -BIGNUM *rem; -BIGNUM *m; -BIGNUM *d; -BN_CTX *ctx; +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); @@ -86,45 +87,83 @@ BN_CTX *ctx; return(1); } - D=ctx->bn[ctx->tos]; - if (dv == NULL) dv=ctx->bn[ctx->tos+1]; - if (rem == NULL) rem=ctx->bn[ctx->tos+2]; + 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) return(0); - if (BN_copy(rem,m) == NULL) return(0); + 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)) return(0); + if (!BN_lshift(D,D,nm-nd)) goto end; for (i=nm-nd; i>=0; i--) { - if (!BN_lshift1(dv,dv)) return(0); + if (!BN_lshift1(dv,dv)) goto end; if (BN_ucmp(rem,D) >= 0) { dv->d[0]|=1; - bn_qsub(rem,rem,D); + if (!BN_usub(rem,rem,D)) goto end; } /* CAN IMPROVE (and have now :=) */ - if (!BN_rshift1(D,D)) return(0); + if (!BN_rshift1(D,D)) goto end; } rem->neg=BN_is_zero(rem)?0:m->neg; dv->neg=m->neg^d->neg; - return(1); + ret = 1; + end: + BN_CTX_end(ctx); + return(ret); } #else -int BN_div(dv, rm, num, divisor,ctx) -BIGNUM *dv; -BIGNUM *rm; -BIGNUM *num; -BIGNUM *divisor; -BN_CTX *ctx; +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \ + && !defined(PEDANTIC) && !defined(BN_DIV3W) +# if defined(__GNUC__) && __GNUC__>=2 +# if defined(__i386) || 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 /* OPENSSL_NO_ASM */ + + +/* BN_div computes dv := num / divisor, rounding towards zero, and sets up + * rm such that dv*divisor + rm = num holds. + * Thus: + * dv->neg == num->neg ^ divisor->neg (unless the result is zero) + * rm->neg == num->neg (unless the remainder is zero) + * If 'dv' or 'rm' is NULL, the respective value is not returned. + */ +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; @@ -132,6 +171,9 @@ BN_CTX *ctx; 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); @@ -146,20 +188,22 @@ BN_CTX *ctx; return(1); } - tmp=ctx->bn[ctx->tos]; - tmp->neg=0; - snum=ctx->bn[ctx->tos+1]; - sdiv=ctx->bn[ctx->tos+2]; + BN_CTX_start(ctx); + tmp=BN_CTX_get(ctx); + snum=BN_CTX_get(ctx); + sdiv=BN_CTX_get(ctx); if (dv == NULL) - res=ctx->bn[ctx->tos+3]; + res=BN_CTX_get(ctx); else res=dv; + if (sdiv == NULL || res == NULL) goto err; + tmp->neg=0; /* First we normalise the numbers */ norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); - BN_lshift(sdiv,divisor,norm_shift); + if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err; sdiv->neg=0; norm_shift+=BN_BITS2; - BN_lshift(snum,num,norm_shift); + if (!(BN_lshift(snum,num,norm_shift))) goto err; snum->neg=0; div_n=sdiv->top; num_n=snum->top; @@ -168,10 +212,10 @@ BN_CTX *ctx; /* 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; /* a bit of a lie */ - wnum.neg= 0; + wnum.dmax= snum->dmax+1; /* a bit of a lie */ /* Get the top 2 words of sdiv */ /* i=sdiv->top; */ @@ -183,8 +227,8 @@ BN_CTX *ctx; /* Setup to 'res' */ res->neg= (num->neg^divisor->neg); - res->top=loop; if (!bn_wexpand(res,(loop+1))) goto err; + res->top=loop; resp= &(res->d[loop-1]); /* space for temp */ @@ -192,74 +236,98 @@ BN_CTX *ctx; if (BN_ucmp(&wnum,sdiv) >= 0) { - bn_qsub(&wnum,&wnum,sdiv); + if (!BN_usub(&wnum,&wnum,sdiv)) goto err; *resp=1; res->d[res->top-1]=1; } else res->top--; + if (res->top == 0) + res->neg = 0; resp--; for (i=0; i>BN_BITS2) || - (t2 <= ((BN_ULLONG)(rem< t1l) t3h++; - t3h=(t1h-t3h)&BN_MASK2; - - /*if ((t3>>BN_BITS2) || - (t2 <= ((t3<d,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); + if (!BN_sub(&wnum,&wnum,tmp)) goto err; snum->top=snum->top+wnum.top-j; @@ -267,7 +335,7 @@ BN_CTX *ctx; { q--; j=wnum.top; - BN_add(&wnum,&wnum,sdiv); + if (!BN_add(&wnum,&wnum,sdiv)) goto err; snum->top+=wnum.top-j; } *(resp--)=q; @@ -275,11 +343,18 @@ BN_CTX *ctx; } if (rm != NULL) { + /* Keep a copy of the neg flag in num because if rm==num + * BN_rshift() will overwrite it. + */ + int neg = num->neg; BN_rshift(rm,snum,norm_shift); - rm->neg=num->neg; + if (!BN_is_zero(rm)) + rm->neg = neg; } + BN_CTX_end(ctx); return(1); err: + BN_CTX_end(ctx); return(0); } diff --git a/src/lib/libcrypto/bn/bn_err.c b/src/lib/libcrypto/bn/bn_err.c index 029ae810d5..fb84ee96d8 100644 --- a/src/lib/libcrypto/bn/bn_err.c +++ b/src/lib/libcrypto/bn/bn_err.c @@ -1,66 +1,69 @@ -/* lib/bn/bn_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/bn/bn_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "bn.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA BN_str_functs[]= { {ERR_PACK(0,BN_F_BN_BLINDING_CONVERT,0), "BN_BLINDING_convert"}, @@ -69,40 +72,57 @@ static ERR_STRING_DATA BN_str_functs[]= {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_EXPAND_INTERNAL,0), "BN_EXPAND_INTERNAL"}, +{ERR_PACK(0,BN_F_BN_MOD_EXP2_MONT,0), "BN_mod_exp2_mont"}, {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_LSHIFT_QUICK,0), "BN_mod_lshift_quick"}, {ERR_PACK(0,BN_F_BN_MOD_MUL_RECIPROCAL,0), "BN_mod_mul_reciprocal"}, +{ERR_PACK(0,BN_F_BN_MOD_SQRT,0), "BN_mod_sqrt"}, {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"}, -{0,NULL}, +{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_BIGNUM_TOO_LONG ,"bignum too long"}, {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_INPUT_NOT_REDUCED ,"input not reduced"}, {BN_R_INVALID_LENGTH ,"invalid length"}, -{BN_R_NOT_INITALISED ,"not initalised"}, +{BN_R_INVALID_RANGE ,"invalid range"}, +{BN_R_NOT_A_SQUARE ,"not a square"}, +{BN_R_NOT_INITIALIZED ,"not initialized"}, {BN_R_NO_INVERSE ,"no inverse"}, -{0,NULL}, +{BN_R_P_IS_NOT_PRIME ,"p is not prime"}, +{BN_R_TOO_MANY_ITERATIONS ,"too many iterations"}, +{BN_R_TOO_MANY_TEMPORARY_VARIABLES ,"too many temporary variables"}, +{0,NULL} }; #endif -void ERR_load_BN_strings() +void ERR_load_BN_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_BN,BN_str_functs); ERR_load_strings(ERR_LIB_BN,BN_str_reasons); #endif diff --git a/src/lib/libcrypto/bn/bn_exp.c b/src/lib/libcrypto/bn/bn_exp.c index c056a5083f..afdfd580fb 100644 --- a/src/lib/libcrypto/bn/bn_exp.c +++ b/src/lib/libcrypto/bn/bn_exp.c @@ -55,112 +55,145 @@ * 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" -/* slow but works */ -int BN_mod_mul(ret, a, b, m, ctx) -BIGNUM *ret; -BIGNUM *a; -BIGNUM *b; -BIGNUM *m; -BN_CTX *ctx; - { - BIGNUM *t; - int r=0; - - t=ctx->bn[ctx->tos++]; - if (a == b) - { if (!BN_sqr(t,a,ctx)) goto err; } - else - { if (!BN_mul(t,a,b)) goto err; } - if (!BN_mod(ret,t,m,ctx)) goto err; - r=1; -err: - ctx->tos--; - return(r); - } +#define TABLE_SIZE 32 -#if 0 /* this one works - simple but works */ -int BN_mod_exp(r,a,p,m,ctx) -BIGNUM *r,*a,*p,*m; -BN_CTX *ctx; +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { int i,bits,ret=0; - BIGNUM *v,*tmp; + BIGNUM *v,*rr; - v=ctx->bn[ctx->tos++]; - tmp=ctx->bn[ctx->tos++]; + 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(r,a) == NULL) goto err; } - else { if (BN_one(r)) goto err; } + { if (BN_copy(rr,a) == NULL) goto err; } + else { if (!BN_one(rr)) goto err; } for (i=1; itos-=2; + if (r != rr) BN_copy(r,rr); + BN_CTX_end(ctx); return(ret); } -#endif - -/* this one works - simple but works */ -int BN_exp(r,a,p,ctx) -BIGNUM *r,*a,*p; -BN_CTX *ctx; - { - int i,bits,ret=0; - BIGNUM *v,*tmp; - - v=ctx->bn[ctx->tos++]; - tmp=ctx->bn[ctx->tos++]; - - if (BN_copy(v,a) == NULL) goto err; - bits=BN_num_bits(p); - - if (BN_is_odd(p)) - { if (BN_copy(r,a) == NULL) goto err; } - else { if (BN_one(r)) goto err; } - - for (i=1; itos-=2; - return(ret); - } -int BN_mod_exp(r,a,p,m,ctx) -BIGNUM *r; -BIGNUM *a; -BIGNUM *p; -BIGNUM *m; -BN_CTX *ctx; +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx) { int ret; + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + /* For even modulus m = 2^k*m_odd, it might make sense to compute + * a^p mod m_odd and a^p mod 2^k separately (with Montgomery + * exponentiation for the odd part), using appropriate exponent + * reductions, and combine the results using the CRT. + * + * For now, we use Montgomery only if the modulus is odd; otherwise, + * exponentiation using the reciprocal-based quick remaindering + * algorithm is used. + * + * (Timing obtained with expspeed.c [computations a^p mod m + * where a, p, m are of the same length: 256, 512, 1024, 2048, + * 4096, 8192 bits], compared to the running time of the + * standard algorithm: + * + * BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration] + * 55 .. 77 % [UltraSparc processor, but + * debug-solaris-sparcv8-gcc conf.] + * + * BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration] + * 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc] + * + * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont + * at 2048 and more bits, but at 512 and 1024 bits, it was + * slower even than the standard algorithm! + * + * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations] + * should be obtained when the new Montgomery reduction code + * has been integrated into OpenSSL.) + */ + +#define MONT_MUL_MOD +#define MONT_EXP_WORD +#define RECP_MUL_MOD + #ifdef MONT_MUL_MOD /* I have finally been able to take out this pre-condition of * the top bit being set. It was caused by an error in BN_div @@ -169,7 +202,17 @@ BN_CTX *ctx; /* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */ if (BN_is_odd(m)) - { ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); } + { +# ifdef MONT_EXP_WORD + if (a->top == 1 && !a->neg) + { + BN_ULONG A = a->d[0]; + ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL); + } + else +# endif + ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); + } else #endif #ifdef RECP_MUL_MOD @@ -181,55 +224,65 @@ BN_CTX *ctx; return(ret); } -/* #ifdef RECP_MUL_MOD */ -int BN_mod_exp_recp(r,a,p,m,ctx) -BIGNUM *r; -BIGNUM *a; -BIGNUM *p; -BIGNUM *m; -BN_CTX *ctx; + +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) { - int nb,i,j,bits,ret=0,wstart,wend,window,wvalue; - int start=1; - BIGNUM *d,*aa; - BIGNUM *val[16]; + 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; - d=ctx->bn[ctx->tos++]; - aa=ctx->bn[ctx->tos++]; bits=BN_num_bits(p); if (bits == 0) { - BN_one(r); - return(1); + ret = BN_one(r); + return ret; + } + + BN_CTX_start(ctx); + if ((aa = BN_CTX_get(ctx)) == NULL) goto err; + + BN_RECP_CTX_init(&recp); + if (m->neg) + { + /* ignore sign of 'm' */ + if (!BN_copy(aa, m)) goto err; + aa->neg = 0; + if (BN_RECP_CTX_set(&recp,aa,ctx) <= 0) goto err; } - nb=BN_reciprocal(d,m,ctx); - if (nb == -1) goto err; - - val[0]=BN_new(); - if (!BN_mod(val[0],a,m,ctx)) goto err; /* 1 */ - if (!BN_mod_mul_reciprocal(aa,val[0],val[0],m,d,nb,ctx)) - goto err; /* 2 */ - - if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */ - window=1; - else if (bits >= 256) - window=5; /* max size of window */ - else if (bits >= 128) - window=4; else - window=3; + { + if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err; + } + + BN_init(&(val[0])); + ts=1; - j=1<<(window-1); - for (i=1; i 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],m,d,nb,ctx)) + if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx)) goto err; /* move the 'window' down further */ @@ -290,84 +343,86 @@ BN_CTX *ctx; } ret=1; err: - ctx->tos-=2; - for (i=0; i<16; i++) - if (val[i] != NULL) BN_clear_free(val[i]); + 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); } - d=ctx->bn[ctx->tos++]; bits=BN_num_bits(p); if (bits == 0) { - BN_one(r); - return(1); + ret = BN_one(rr); + return ret; } + 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 1 if (in_mont != NULL) mont=in_mont; else -#endif { if ((mont=BN_MONT_CTX_new()) == NULL) goto err; if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; } - val[0]=BN_new(); - if (BN_ucmp(a,m) >= 0) + BN_init(&val[0]); + ts=1; + if (a->neg || BN_ucmp(a,m) >= 0) { - BN_mod(val[0],a,m,ctx); - aa=val[0]; + if (!BN_nnmod(&(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 */ - if (!BN_mod_mul_montgomery(d,val[0],val[0],mont,ctx)) goto err; /* 2 */ - - 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; + if (BN_is_zero(aa)) + { + ret = BN_zero(rr); + goto err; + } + if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */ - j=1<<(window-1); - for (i=1; i 1) { - val[i]=BN_new(); - if (!BN_mod_mul_montgomery(val[i],val[i-1],d,mont,ctx)) - goto err; + 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)) + if (!BN_mod_mul_montgomery(r,r,&(val[wvalue>>1]),mont,ctx)) goto err; /* move the 'window' down further */ @@ -428,62 +483,201 @@ BN_MONT_CTX *in_mont; start=0; if (wstart < 0) break; } - BN_from_montgomery(r,r,mont,ctx); + if (!BN_from_montgomery(rr,r,mont,ctx)) goto err; ret=1; err: if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); - ctx->tos--; - for (i=0; itop == 0 || !(m->d[0] & 1)) + { + BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS); + return(0); + } + if (m->top == 1) + a %= m->d[0]; /* make sure that 'a' is reduced */ + + bits = BN_num_bits(p); + if (bits == 0) + { + ret = BN_one(rr); + return ret; + } + if (a == 0) + { + ret = BN_zero(rr); + return ret; + } + + 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; + + 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(r,a,p,m,ctx) -BIGNUM *r; -BIGNUM *a; -BIGNUM *p; -BIGNUM *m; -BN_CTX *ctx; +int BN_mod_exp_simple(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 i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0; int start=1; BIGNUM *d; - BIGNUM *val[16]; + BIGNUM val[TABLE_SIZE]; - d=ctx->bn[ctx->tos++]; bits=BN_num_bits(p); if (bits == 0) { - BN_one(r); - return(1); + ret = BN_one(r); + return ret; } - val[0]=BN_new(); - if (!BN_mod(val[0],a,m,ctx)) goto err; /* 1 */ - if (!BN_mod_mul(d,val[0],val[0],m,ctx)) - goto err; /* 2 */ - - if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */ - window=1; - else if (bits >= 256) - window=5; /* max size of window */ - else if (bits >= 128) - window=4; - else - window=3; + BN_CTX_start(ctx); + if ((d = BN_CTX_get(ctx)) == NULL) goto err; - j=1<<(window-1); - for (i=1; i 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)) + if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx)) goto err; /* move the 'window' down further */ @@ -545,9 +739,9 @@ BN_CTX *ctx; } ret=1; err: - ctx->tos--; - for (i=0; i<16; i++) - if (val[i] != NULL) BN_clear_free(val[i]); + 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 improvment 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 */ +#define TABLE_SIZE 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 BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const 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]; + int i,j,bits,b,bits1,bits2,ret=0,wpos1,wpos2,window1,window2,wvalue1,wvalue2; + int r_is_one=1,ts1=0,ts2=0; + BIGNUM *d,*r; + const BIGNUM *a_mod_m; + BIGNUM val1[TABLE_SIZE], val2[TABLE_SIZE]; BN_MONT_CTX *mont=NULL; bn_check_top(a1); @@ -32,22 +134,23 @@ int BN_mod_exp2_mont(BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, BIGNUM *a2, if (!(m->d[0] & 1)) { - BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); + BNerr(BN_F_BN_MOD_EXP2_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); return(0); } - d= &(ctx->bn[ctx->tos++]); - r= &(ctx->bn[ctx->tos++]); bits1=BN_num_bits(p1); bits2=BN_num_bits(p2); if ((bits1 == 0) && (bits2 == 0)) { - BN_one(r); - return(1); + ret = BN_one(rr); + return ret; } + bits=(bits1 > bits2)?bits1:bits2; - /* If this is not done, things will break in the montgomery - * part */ + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + if (d == NULL || r == NULL) goto err; if (in_mont != NULL) mont=in_mont; @@ -57,139 +160,154 @@ int BN_mod_exp2_mont(BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, BIGNUM *a2, 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) + window1 = BN_window_bits_for_exponent_size(bits1); + window2 = BN_window_bits_for_exponent_size(bits2); + + /* + * Build table for a1: val1[i] := a1^(2*i + 1) mod m for i = 0 .. 2^(window1-1) + */ + BN_init(&val1[0]); + ts1=1; + if (a1->neg || BN_ucmp(a1,m) >= 0) { - BN_mod(&(val[1][0]),a1,m,ctx); - aa1= &(val[1][0]); + if (!BN_mod(&(val1[0]),a1,m,ctx)) + goto err; + a_mod_m = &(val1[0]); } else - aa1=a1; - if (BN_ucmp(a2,m) >= 0) + a_mod_m = a1; + if (BN_is_zero(a_mod_m)) { - 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)) + ret = BN_zero(rr); 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< 1) { - if (x >= 2) + if (!BN_mod_mul_montgomery(d,&(val1[0]),&(val1[0]),mont,ctx)) goto err; + + j=1<<(window1-1); + for (i=1; ineg || BN_ucmp(a2,m) >= 0) + { + if (!BN_mod(&(val2[0]),a2,m,ctx)) + goto err; + a_mod_m = &(val2[0]); + } + else + a_mod_m = a2; + if (BN_is_zero(a_mod_m)) + { + ret = BN_zero(rr); + goto err; + } + if (!BN_to_montgomery(&(val2[0]),a_mod_m,mont,ctx)) goto err; + if (window2 > 1) + { + if (!BN_mod_mul_montgomery(d,&(val2[0]),&(val2[0]),mont,ctx)) goto err; + + j=1<<(window2-1); + for (i=1; i 0, the bottom bit of the first window */ + wpos2=0; /* If wvalue2 > 0, the bottom bit of the second window */ + + if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err; + for (b=bits-1; b>=0; b--) { - xvalue=BN_is_bit_set(p1,wstart); - yvalue=BN_is_bit_set(p2,wstart); - if (!(xvalue || yvalue)) + if (!r_is_one) { - if (!start) + if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) + goto err; + } + + if (!wvalue1) + if (BN_is_bit_set(p1, b)) { - if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) - goto err; + /* consider bits b-window1+1 .. b for this window */ + i = b-window1+1; + while (!BN_is_bit_set(p1, i)) /* works for i<0 */ + i++; + wpos1 = i; + wvalue1 = 1; + for (i = b-1; i >= wpos1; i--) + { + wvalue1 <<= 1; + if (BN_is_bit_set(p1, i)) + wvalue1++; + } } - wstart--; - if (wstart < 0) break; - continue; - } - /* We now have wstart on a 'set' bit, we now need to work out - * how bit a window to do. To do this we need to scan - * forward until the last set bit before the end of the - * window */ - j=wstart; - /* xvalue=BN_is_bit_set(p1,wstart); already set */ - /* yvalue=BN_is_bit_set(p1,wstart); already set */ - wend=0; - for (i=1; i= wpos2; i--) + { + wvalue2 <<= 1; + if (BN_is_bit_set(p2, i)) + wvalue2++; + } } + + if (wvalue1 && b == wpos1) + { + /* wvalue1 is odd and < 2^window1 */ + if (!BN_mod_mul_montgomery(r,r,&(val1[wvalue1>>1]),mont,ctx)) + goto err; + wvalue1 = 0; + r_is_one = 0; + } - /* wvalue will be an odd number < 2^window */ - if (xvalue || yvalue) + if (wvalue2 && b == wpos2) { - if (!BN_mod_mul_montgomery(r,r,&(val[xvalue][yvalue]), - mont,ctx)) goto err; + /* wvalue2 is odd and < 2^window2 */ + if (!BN_mod_mul_montgomery(r,r,&(val2[wvalue2>>1]),mont,ctx)) + goto err; + wvalue2 = 0; + r_is_one = 0; } - - /* move the 'window' down further */ - wstart-=i; - start=0; - if (wstart < 0) break; } BN_from_montgomery(rr,r,mont,ctx); ret=1; err: if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); - ctx->tos-=2; - for (i=0; i #include "cryptlib.h" #include "bn_lcl.h" -#ifndef NOPROTO static BIGNUM *euclid(BIGNUM *a, BIGNUM *b); -#else -static BIGNUM *euclid(); -#endif -int BN_gcd(r,in_a,in_b,ctx) -BIGNUM *r,*in_a,*in_b; -BN_CTX *ctx; +int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) { BIGNUM *a,*b,*t; int ret=0; - a=ctx->bn[ctx->tos]; - b=ctx->bn[ctx->tos+1]; + 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; + a->neg = 0; + b->neg = 0; if (BN_cmp(a,b) < 0) { t=a; a=b; b=t; } t=euclid(a,b); @@ -86,19 +139,22 @@ BN_CTX *ctx; if (BN_copy(r,t) == NULL) goto err; ret=1; err: + BN_CTX_end(ctx); return(ret); } -static BIGNUM *euclid(a,b) -BIGNUM *a,*b; +static BIGNUM *euclid(BIGNUM *a, BIGNUM *b) { BIGNUM *t; int shifts=0; - for (;;) + bn_check_top(a); + bn_check_top(b); + + /* 0 <= b <= a */ + while (!BN_is_zero(b)) { - if (BN_is_zero(b)) - break; + /* 0 < b <= a */ if (BN_is_odd(a)) { @@ -131,7 +187,9 @@ BIGNUM *a,*b; shifts++; } } + /* 0 <= b <= a */ } + if (shifts) { if (!BN_lshift(a,a,shifts)) goto err; @@ -141,54 +199,284 @@ err: return(NULL); } + /* solves ax == 1 (mod n) */ -BIGNUM *BN_mod_inverse(a, n, ctx) -BIGNUM *a; -BIGNUM *n; -BN_CTX *ctx; +BIGNUM *BN_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { - BIGNUM *A,*B,*X,*Y,*M,*D,*R; - BIGNUM *ret=NULL,*T; + BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; + BIGNUM *ret=NULL; int sign; - A=ctx->bn[ctx->tos]; - B=ctx->bn[ctx->tos+1]; - X=ctx->bn[ctx->tos+2]; - D=ctx->bn[ctx->tos+3]; - M=ctx->bn[ctx->tos+4]; - Y=ctx->bn[ctx->tos+5]; - ctx->tos+=6; - R=BN_new(); + 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); + T = BN_CTX_get(ctx); + if (T == 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; + BN_one(X); + BN_zero(Y); + if (BN_copy(B,a) == NULL) goto err; + if (BN_copy(A,n) == NULL) goto err; + A->neg = 0; + if (B->neg || (BN_ucmp(B, A) >= 0)) + { + if (!BN_nnmod(B, B, A, ctx)) goto err; + } + sign = -1; + /* From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) + { + /* Binary inversion algorithm; requires odd modulus. + * This is faster than the general algorithm if the modulus + * is sufficiently small (about 400 .. 500 bits on 32-bit + * sytems, but much more on 64-bit systems) */ + int shift; + + while (!BN_is_zero(B)) + { + /* + * 0 < B < |n|, + * 0 < A <= |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|) + */ + + /* Now divide B by the maximum possible power of two in the integers, + * and divide X by the same value mod |n|. + * When we're done, (1) still holds. */ + shift = 0; + while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ + { + shift++; + + if (BN_is_odd(X)) + { + if (!BN_uadd(X, X, n)) goto err; + } + /* now X is even, so we can easily divide it by two */ + if (!BN_rshift1(X, X)) goto err; + } + if (shift > 0) + { + if (!BN_rshift(B, B, shift)) goto err; + } + - while (!BN_is_zero(B)) + /* Same for A and Y. Afterwards, (2) still holds. */ + shift = 0; + while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ + { + shift++; + + if (BN_is_odd(Y)) + { + if (!BN_uadd(Y, Y, n)) goto err; + } + /* now Y is even */ + if (!BN_rshift1(Y, Y)) goto err; + } + if (shift > 0) + { + if (!BN_rshift(A, A, shift)) goto err; + } + + + /* We still have (1) and (2). + * Both A and B are odd. + * The following computations ensure that + * + * 0 <= B < |n|, + * 0 < A < |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|), + * + * and that either A or B is even in the next iteration. + */ + if (BN_ucmp(B, A) >= 0) + { + /* -sign*(X + Y)*a == B - A (mod |n|) */ + if (!BN_uadd(X, X, Y)) goto err; + /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that + * actually makes the algorithm slower */ + if (!BN_usub(B, B, A)) goto err; + } + else + { + /* sign*(X + Y)*a == A - B (mod |n|) */ + if (!BN_uadd(Y, Y, X)) goto err; + /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ + if (!BN_usub(A, A, B)) goto err; + } + } + } + else { - 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)) goto err; - if (!BN_add(T,T,Y)) goto err; - M=Y; - Y=X; - X=T; - sign= -sign; + /* general inversion algorithm */ + + while (!BN_is_zero(B)) + { + BIGNUM *tmp; + + /* + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* (D, M) := (A/B, A%B) ... */ + if (BN_num_bits(A) == BN_num_bits(B)) + { + if (!BN_one(D)) goto err; + if (!BN_sub(M,A,B)) goto err; + } + else if (BN_num_bits(A) == BN_num_bits(B) + 1) + { + /* A/B is 1, 2, or 3 */ + if (!BN_lshift1(T,B)) goto err; + if (BN_ucmp(A,T) < 0) + { + /* A < 2*B, so D=1 */ + if (!BN_one(D)) goto err; + if (!BN_sub(M,A,B)) goto err; + } + else + { + /* A >= 2*B, so D=2 or D=3 */ + if (!BN_sub(M,A,T)) goto err; + if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */ + if (BN_ucmp(A,D) < 0) + { + /* A < 3*B, so D=2 */ + if (!BN_set_word(D,2)) goto err; + /* M (= A - 2*B) already has the correct value */ + } + else + { + /* only D=3 remains */ + if (!BN_set_word(D,3)) goto err; + /* currently M = A - 2*B, but we need M = A - 3*B */ + if (!BN_sub(M,M,B)) goto err; + } + } + } + else + { + if (!BN_div(D,M,A,B,ctx)) goto err; + } + + /* Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + + tmp=A; /* keep the BIGNUM object, the value does not matter */ + + /* (A, B) := (B, A mod B) ... */ + A=B; + B=M; + /* ... so we have 0 <= B < A again */ + + /* Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + /* most of the time D is very small, so we can optimize tmp := D*X+Y */ + if (BN_is_one(D)) + { + if (!BN_add(tmp,X,Y)) goto err; + } + else + { + if (BN_is_word(D,2)) + { + if (!BN_lshift1(tmp,X)) goto err; + } + else if (BN_is_word(D,4)) + { + if (!BN_lshift(tmp,X,2)) goto err; + } + else if (D->top == 1) + { + if (!BN_copy(tmp,X)) goto err; + if (!BN_mul_word(tmp,D->d[0])) goto err; + } + else + { + if (!BN_mul(tmp,D,X,ctx)) goto err; + } + if (!BN_add(tmp,tmp,Y)) goto err; + } + + M=Y; /* keep the BIGNUM object, the value does not matter */ + Y=X; + X=tmp; + sign = -sign; + } } + + /* + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } + /* Now Y*a == A (mod |n|). */ + if (BN_is_one(A)) - { if (!BN_mod(R,Y,n,ctx)) goto err; } + { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y,n) < 0) + { + if (!BN_copy(R,Y)) goto err; + } + else + { + if (!BN_nnmod(R,Y,n,ctx)) goto err; + } + } else { BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); @@ -196,8 +484,7 @@ BN_CTX *ctx; } ret=R; err: - if ((ret == NULL) && (R != NULL)) BN_free(R); - ctx->tos-=6; + if ((ret == NULL) && (in == NULL)) BN_free(R); + BN_CTX_end(ctx); return(ret); } - diff --git a/src/lib/libcrypto/bn/bn_lcl.h b/src/lib/libcrypto/bn/bn_lcl.h index edfd788338..8a4dba375a 100644 --- a/src/lib/libcrypto/bn/bn_lcl.h +++ b/src/lib/libcrypto/bn/bn_lcl.h @@ -55,30 +55,228 @@ * 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 "bn.h" +#include #ifdef __cplusplus extern "C" { #endif + +/* Used for temp variables */ +#define BN_CTX_NUM 32 +#define BN_CTX_NUM_POS 12 +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 */; + + +/* + * 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(OPENSSL_NO_ASM) && !defined(OPENSSL_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 /* OPENSSL_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) -#define bn_fix_top(a) \ - { \ - BN_ULONG *fix_top_l; \ - for (fix_top_l= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \ - if (*(fix_top_l--)) break; \ +/* 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_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?(n):bn_expand2((n),(b))) */ +#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) { \ @@ -95,6 +293,43 @@ extern "C" { (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 +#include #include #include "cryptlib.h" #include "bn_lcl.h" -char *BN_version="Big Number part of SSLeay 0.9.0b 29-Jun-1998"; +const char *BN_version="Big Number" OPENSSL_VERSION_PTEXT; -BIGNUM *BN_value_one() +/* 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); + return(bits[(int)(l>>56)]+56); } - else return(bits[l>>48]+48); + else return(bits[(int)(l>>48)]+48); } else { if (l & 0x0000ff0000000000L) { - return(bits[l>>40]+40); + return(bits[(int)(l>>40)]+40); } - else return(bits[l>>32]+32); + else return(bits[(int)(l>>32)]+32); } } else @@ -140,17 +205,17 @@ BN_ULONG l; { if (l & 0xff00000000000000LL) { - return(bits[l>>56]+56); + return(bits[(int)(l>>56)]+56); } - else return(bits[l>>48]+48); + else return(bits[(int)(l>>48)]+48); } else { if (l & 0x0000ff0000000000LL) { - return(bits[l>>40]+40); + return(bits[(int)(l>>40)]+40); } - else return(bits[l>>32]+32); + else return(bits[(int)(l>>32)]+32); } } else @@ -161,161 +226,256 @@ BN_ULONG l; if (l & 0xffff0000L) { if (l & 0xff000000L) - return(bits[l>>24L]+24); - else return(bits[l>>16L]+16); + 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[l>>8]+8); + return(bits[(int)(l>>8)]+8); else #endif - return(bits[l ] ); + return(bits[(int)(l )] ); } } } -int BN_num_bits(a) -BIGNUM *a; +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]; + assert(l != 0); 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(a) -BIGNUM *a; +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])); - Free(a->d); + memset(a->d,0,a->dmax*sizeof(a->d[0])); + if (!(BN_get_flags(a,BN_FLG_STATIC_DATA))) + OPENSSL_free(a->d); } + i=BN_get_flags(a,BN_FLG_MALLOCED); memset(a,0,sizeof(BIGNUM)); - Free(a); + if (i) + OPENSSL_free(a); } -void BN_free(a) -BIGNUM *a; +void BN_free(BIGNUM *a) { if (a == NULL) return; - if (a->d != NULL) Free(a->d); - Free(a); + if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA))) + OPENSSL_free(a->d); + a->flags|=BN_FLG_FREE; /* REMOVE? */ + if (a->flags & BN_FLG_MALLOCED) + OPENSSL_free(a); } -BIGNUM *BN_new() +void BN_init(BIGNUM *a) + { + memset(a,0,sizeof(BIGNUM)); + } + +BIGNUM *BN_new(void) { BIGNUM *ret; - BN_ULONG *p; - ret=(BIGNUM *)Malloc(sizeof(BIGNUM)); - if (ret == NULL) goto err; + if ((ret=(BIGNUM *)OPENSSL_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=(BN_DEFAULT_BITS/BN_BITS2); - p=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(ret->max+1)); - if (p == NULL) goto err; - ret->d=p; - - memset(p,0,(ret->max+1)*sizeof(p[0])); + ret->dmax=0; + ret->d=NULL; return(ret); -err: - BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE); - return(NULL); } -BN_CTX *BN_CTX_new() +/* This is used both by bn_expand2() and bn_dup_expand() */ +/* The caller MUST check that words > b->dmax before calling this */ +static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) { - BN_CTX *ret; - BIGNUM *n; - int i,j; + BN_ULONG *A,*a = NULL; + const BN_ULONG *B; + int i; - ret=(BN_CTX *)Malloc(sizeof(BN_CTX)); - if (ret == NULL) goto err2; + if (words > (INT_MAX/(4*BN_BITS2))) + { + BNerr(BN_F_BN_EXPAND_INTERNAL,BN_R_BIGNUM_TOO_LONG); + return NULL; + } - for (i=0; ibn[i]=n; + BNerr(BN_F_BN_EXPAND_INTERNAL,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return(NULL); + } + a=A=(BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG)*(words+1)); + if (A == NULL) + { + BNerr(BN_F_BN_EXPAND_INTERNAL,ERR_R_MALLOC_FAILURE); + return(NULL); + } +#if 1 + B=b->d; + /* Check if the previous number needs to be copied */ + if (B != NULL) + { + 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: /* workaround for ultrix cc: without 'case 0', the optimizer does + * the switch table by doing a=top&3; a--; goto jump_table[a]; + * which fails for top== 0 */ + ; + } } - /* There is actually an extra one, this is for debugging my - * stuff */ - ret->bn[BN_CTX_NUM]=NULL; + /* Now need to zero any data between b->top and b->max */ + /* XXX Why? */ - ret->tos=0; - return(ret); -err: - for (j=0; jbn[j]); - Free(ret); -err2: - BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE); - return(NULL); + A= &(a[b->top]); + for (i=(words - 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=(words - 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); +#endif + + return(a); } -void BN_CTX_free(c) -BN_CTX *c; +/* This is an internal function that can be used instead of bn_expand2() + * when there is a need to copy BIGNUMs instead of only expanding the + * data part, while still expanding them. + * Especially useful when needing to expand BIGNUMs that are declared + * 'const' and should therefore not be changed. + * The reason to use this instead of a BN_dup() followed by a bn_expand2() + * is memory allocation overhead. A BN_dup() followed by a bn_expand2() + * will allocate new memory for the BIGNUM data twice, and free it once, + * while bn_dup_expand() makes sure allocation is made only once. + */ + +BIGNUM *bn_dup_expand(const BIGNUM *b, int words) { - int i; + BIGNUM *r = NULL; + + if (words > b->dmax) + { + BN_ULONG *a = bn_expand_internal(b, words); - for (i=0; ibn[i]); - Free(c); + if (a) + { + r = BN_new(); + if (r) + { + r->top = b->top; + r->dmax = words; + r->neg = b->neg; + r->d = a; + } + else + { + /* r == NULL, BN_new failure */ + OPENSSL_free(a); + } + } + /* If a == NULL, there was an error in allocation in + bn_expand_internal(), and NULL should be returned */ + } + else + { + r = BN_dup(b); + } + + return r; } -BIGNUM *bn_expand2(b, words) -BIGNUM *b; -int words; - { - BN_ULONG *p; +/* 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. */ - if (words > b->max) +BIGNUM *bn_expand2(BIGNUM *b, int words) + { + if (words > b->dmax) { - p=(BN_ULONG *)Realloc(b->d,sizeof(BN_ULONG)*(words+1)); - if (p == NULL) + BN_ULONG *a = bn_expand_internal(b, words); + + if (a) { - BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); - return(NULL); + if (b->d) + OPENSSL_free(b->d); + b->d=a; + b->dmax=words; } - b->d=p; - memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); - b->max=words; + else + b = NULL; } - return(b); + return b; } -BIGNUM *BN_dup(a) -BIGNUM *a; +BIGNUM *BN_dup(const BIGNUM *a) { - BIGNUM *r; + BIGNUM *r, *t; - r=BN_new(); - if (r == NULL) return(NULL); - return((BIGNUM *)BN_copy(r,a)); + if (a == NULL) return NULL; + + bn_check_top(a); + + t = BN_new(); + if (t == NULL) return(NULL); + r = BN_copy(t, a); + /* now r == t || r == NULL */ + if (r == NULL) + BN_free(t); + return r; } -BIGNUM *BN_copy(a, b) -BIGNUM *a; -BIGNUM *b; +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) { int i; - BN_ULONG *A,*B; + BN_ULONG *A; + const BN_ULONG *B; + + bn_check_top(b); if (a == b) return(a); if (bn_wexpand(a,b->top) == NULL) return(NULL); @@ -323,35 +483,18 @@ BIGNUM *b; #if 1 A=a->d; B=b->d; - 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]; + 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_expand_internal */ } #else memcpy(a->d,b->d,sizeof(b->d[0])*b->top); @@ -359,52 +502,76 @@ BIGNUM *b; /* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/ a->top=b->top; - if (a->top == 0) + if ((a->top == 0) && (a->d != NULL)) a->d[0]=0; a->neg=b->neg; return(a); } -void BN_clear(a) -BIGNUM *a; +void BN_swap(BIGNUM *a, BIGNUM *b) + { + int flags_old_a, flags_old_b; + BN_ULONG *tmp_d; + int tmp_top, tmp_dmax, tmp_neg; + + flags_old_a = a->flags; + flags_old_b = b->flags; + + tmp_d = a->d; + tmp_top = a->top; + tmp_dmax = a->dmax; + tmp_neg = a->neg; + + a->d = b->d; + a->top = b->top; + a->dmax = b->dmax; + a->neg = b->neg; + + b->d = tmp_d; + b->top = tmp_top; + b->dmax = tmp_dmax; + b->neg = tmp_neg; + + a->flags = (flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA); + b->flags = (flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA); + } + + +void BN_clear(BIGNUM *a) { - memset(a->d,0,a->max*sizeof(a->d[0])); + if (a->d != NULL) + memset(a->d,0,a->dmax*sizeof(a->d[0])); a->top=0; a->neg=0; } -unsigned long BN_get_word(a) -BIGNUM *a; +BN_ULONG BN_get_word(const BIGNUM *a) { int i,n; - unsigned long ret=0; + BN_ULONG ret=0; n=BN_num_bytes(a); - if (n > sizeof(unsigned long)) -#ifdef SIXTY_FOUR_BIT_LONG + if (n > sizeof(BN_ULONG)) return(BN_MASK2); -#else - return(0xFFFFFFFFL); -#endif 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(a,w) -BIGNUM *a; -unsigned long w; +int BN_set_word(BIGNUM *a, BN_ULONG w) { int i,n; - if (bn_expand(a,sizeof(unsigned long)*8) == NULL) return(0); + if (bn_expand(a,sizeof(BN_ULONG)*8) == NULL) return(0); - n=sizeof(unsigned long)/BN_BYTES; + n=sizeof(BN_ULONG)/BN_BYTES; a->neg=0; a->top=0; a->d[0]=(BN_ULONG)w&BN_MASK2; @@ -417,6 +584,8 @@ unsigned long w; #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; @@ -424,11 +593,7 @@ unsigned long w; return(1); } -/* ignore negative */ -BIGNUM *BN_bin2bn(s, len, ret) -unsigned char *s; -int len; -BIGNUM *ret; +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) { unsigned int i,m; unsigned int n; @@ -448,6 +613,7 @@ BIGNUM *ret; i=((n-1)/BN_BYTES)+1; m=((n-1)%(BN_BYTES)); ret->top=i; + ret->neg=0; while (n-- > 0) { l=(l<<8L)| *(s++); @@ -465,9 +631,7 @@ BIGNUM *ret; } /* ignore negative */ -int BN_bn2bin(a, to) -BIGNUM *a; -unsigned char *to; +int BN_bn2bin(const BIGNUM *a, unsigned char *to) { int n,i; BN_ULONG l; @@ -481,13 +645,14 @@ unsigned char *to; return(n); } -int BN_ucmp(a, b) -BIGNUM *a; -BIGNUM *b; +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; @@ -502,9 +667,7 @@ BIGNUM *b; return(0); } -int BN_cmp(a, b) -BIGNUM *a; -BIGNUM *b; +int BN_cmp(const BIGNUM *a, const BIGNUM *b) { int i; int gt,lt; @@ -519,6 +682,10 @@ BIGNUM *b; else return(0); } + + bn_check_top(a); + bn_check_top(b); + if (a->neg != b->neg) { if (a->neg) @@ -541,27 +708,25 @@ BIGNUM *b; return(0); } -int BN_set_bit(a, n) -BIGNUM *a; -int n; +int BN_set_bit(BIGNUM *a, int n) { - int i,j; + int i,j,k; i=n/BN_BITS2; j=n%BN_BITS2; if (a->top <= i) { - if (bn_expand(a,n) == NULL) return(0); + if (bn_wexpand(a,i+1) == NULL) return(0); + for(k=a->top; kd[k]=0; a->top=i+1; } - a->d[i]|=(1L<d[i]|=(((BN_ULONG)1)<top <= i) return(0); - a->d[i]&=(~(1L<d[i]&=(~(((BN_ULONG)1)<d[i]&(((BN_ULONG)1)<top=w+1; a->d[w]&= ~(BN_MASK2<= 0) && (a->d[w] == 0)) + } + bn_fix_top(a); + return(1); + } + +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) + { + int i; + BN_ULONG aa,bb; + + aa=a[n-1]; + bb=b[n-1]; + if (aa != bb) return((aa > 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); + } + +/* Here follows a specialised variants of bn_cmp_words(). It has the + property of performing the operation on arrays of different sizes. + The sizes of those arrays is expressed through cl, which is the + common length ( basicall, min(len(a),len(b)) ), and dl, which is the + delta between the two lengths, calculated as len(a)-len(b). + All lengths are the number of BN_ULONGs... */ + +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl) + { + int n,i; + n = cl-1; + + if (dl < 0) + { + for (i=dl; i<0; i++) { - a->top--; - w--; + if (b[n-i] != 0) + return -1; /* a < b */ } } - return(1); + if (dl > 0) + { + for (i=dl; i>0; i--) + { + if (a[n+i] != 0) + return 1; /* a > b */ + } + } + return bn_cmp_words(a,b,cl); } diff --git a/src/lib/libcrypto/bn/bn_mod.c b/src/lib/libcrypto/bn/bn_mod.c index c351aac14f..5cf82480d7 100644 --- a/src/lib/libcrypto/bn/bn_mod.c +++ b/src/lib/libcrypto/bn/bn_mod.c @@ -1,4 +1,59 @@ /* crypto/bn/bn_mod.c */ +/* Includes code written by Lenka Fibikova + * 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). + * + */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,42 +111,186 @@ * [including the GNU Public Licence.] */ -#include #include "cryptlib.h" #include "bn_lcl.h" -/* rem != m */ -int BN_mod(rem, m, d,ctx) -BIGNUM *rem; -BIGNUM *m; -BIGNUM *d; -BN_CTX *ctx; + +#if 0 /* now just a #define */ +int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) + { + return(BN_div(NULL,rem,m,d,ctx)); + /* note that rem->neg == m->neg (unless the remainder is zero) */ + } +#endif + + +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) + { + /* like BN_mod, but returns non-negative remainder + * (i.e., 0 <= r < |d| always holds) */ + + if (!(BN_mod(r,m,d,ctx))) + return 0; + if (!r->neg) + return 1; + /* now -|d| < r < 0, so we have to set r := r + |d| */ + return (d->neg ? BN_sub : BN_add)(r, r, d); +} + + +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) + { + if (!BN_add(r, a, b)) return 0; + return BN_nnmod(r, r, m, ctx); + } + + +/* BN_mod_add variant that may be used if both a and b are non-negative + * and less than m */ +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m) + { + if (!BN_add(r, a, b)) return 0; + if (BN_ucmp(r, m) >= 0) + return BN_usub(r, r, m); + return 1; + } + + +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) + { + if (!BN_sub(r, a, b)) return 0; + return BN_nnmod(r, r, m, ctx); + } + + +/* BN_mod_sub variant that may be used if both a and b are non-negative + * and less than m */ +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m) + { + if (!BN_sub(r, a, b)) return 0; + if (r->neg) + return BN_add(r, r, m); + return 1; + } + + +/* slow but works */ +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) { -#if 0 /* The old slow way */ - int i,nm,nd; - BIGNUM *dv; + BIGNUM *t; + int ret=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_nnmod(r,t,m,ctx)) goto err; + ret=1; +err: + BN_CTX_end(ctx); + return(ret); + } - if (BN_ucmp(m,d) < 0) - return((BN_copy(rem,m) == NULL)?0:1); - dv=ctx->bn[ctx->tos]; +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) + { + if (!BN_sqr(r, a, ctx)) return 0; + /* r->neg == 0, thus we don't need BN_nnmod */ + return BN_mod(r, r, m, ctx); + } - if (!BN_copy(rem,m)) return(0); - nm=BN_num_bits(rem); - nd=BN_num_bits(d); - if (!BN_lshift(dv,d,nm-nd)) return(0); - for (i=nm-nd; i>=0; i--) +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) + { + if (!BN_lshift1(r, a)) return 0; + return BN_nnmod(r, r, m, ctx); + } + + +/* BN_mod_lshift1 variant that may be used if a is non-negative + * and less than m */ +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) + { + if (!BN_lshift1(r, a)) return 0; + if (BN_cmp(r, m) >= 0) + return BN_sub(r, r, m); + return 1; + } + + +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx) + { + BIGNUM *abs_m = NULL; + int ret; + + if (!BN_nnmod(r, a, m, ctx)) return 0; + + if (m->neg) { - if (BN_cmp(rem,dv) >= 0) + abs_m = BN_dup(m); + if (abs_m == NULL) return 0; + abs_m->neg = 0; + } + + ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m)); + + if (abs_m) + BN_free(abs_m); + return ret; + } + + +/* BN_mod_lshift variant that may be used if a is non-negative + * and less than m */ +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) + { + if (r != a) + { + if (BN_copy(r, a) == NULL) return 0; + } + + while (n > 0) + { + int max_shift; + + /* 0 < r < m */ + max_shift = BN_num_bits(m) - BN_num_bits(r); + /* max_shift >= 0 */ + + if (max_shift < 0) + { + BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED); + return 0; + } + + if (max_shift > n) + max_shift = n; + + if (max_shift) + { + if (!BN_lshift(r, r, max_shift)) return 0; + n -= max_shift; + } + else + { + if (!BN_lshift1(r, r)) return 0; + --n; + } + + /* BN_num_bits(r) <= BN_num_bits(m) */ + + if (BN_cmp(r, m) >= 0) { - if (!BN_sub(rem,rem,dv)) return(0); + if (!BN_sub(r, r, m)) return 0; } - if (!BN_rshift1(dv,dv)) return(0); } - return(1); -#else - return(BN_div(NULL,rem,m,d,ctx)); -#endif + + return 1; } - diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c index e435df61f8..c9ebdbaabe 100644 --- a/src/lib/libcrypto/bn/bn_mont.c +++ b/src/lib/libcrypto/bn/bn_mont.c @@ -56,59 +56,67 @@ * [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" -int BN_mod_mul_montgomery(r,a,b,mont,ctx) -BIGNUM *r,*a,*b; -BN_MONT_CTX *mont; -BN_CTX *ctx; +#define MONT_WORD /* use the faster word-based algorithm */ + +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; + int ret=0; - tmp=ctx->bn[ctx->tos++]; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) goto err; + bn_check_top(tmp); if (a == b) { if (!BN_sqr(tmp,a,ctx)) goto err; } else { - if (!BN_mul(tmp,a,b)) goto err; + if (!BN_mul(tmp,a,b,ctx)) goto err; } /* reduce from aRR to aR */ if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; - ctx->tos--; - return(1); + ret=1; err: - return(0); + BN_CTX_end(ctx); + return(ret); } -#define MONT_WORD +int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) + { + int retn=0; #ifdef MONT_WORD -int BN_from_montgomery(ret,a,mont,ctx) -BIGNUM *ret; -BIGNUM *a; -BN_MONT_CTX *mont; -BN_CTX *ctx; - { - BIGNUM *n,*t1,*r; - BN_ULONG *ap,*np,*rp,n0,v; + BIGNUM *n,*r; + BN_ULONG *ap,*np,*rp,n0,v,*nrp; int al,nl,max,i,x,ri; - int retn=0; - t1=ctx->bn[ctx->tos]; - r=ctx->bn[ctx->tos+1]; + BN_CTX_start(ctx); + if ((r = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_copy(r,a)) goto err; - n=mont->N; + n= &(mont->N); ap=a->d; - /* mont->ri is the size of mont->N in bits/words */ + /* 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); } @@ -119,6 +127,7 @@ BN_CTX *ctx; r->neg=a->neg^n->neg; np=n->d; rp=r->d; + nrp= &(r->d[nl]); /* clear the top words of T */ #if 1 @@ -131,176 +140,210 @@ BN_CTX *ctx; r->top=max; n0=mont->n0; +#ifdef BN_COUNT + fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl); +#endif for (i=0; i nl) - { - x2=nl; - x1=0; - } - else - { - x2=i+4; - x1=nl-x2; - } - v=bn_mul_add_words(&(rp[x1]),&(np[x1]),x2,(rp[x1]*n0)&BN_MASK2); +#ifdef __TANDEM + { + long long t1; + long long t2; + long long t3; + t1 = rp[0] * (n0 & 0177777); + t2 = 037777600000l; + t2 = n0 & t2; + t3 = rp[0] & 0177777; + t2 = (t3 * t2) & BN_MASK2; + t1 = t1 + t2; + v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1); + } #else v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); #endif - - if (((rp[nl]+=v)&BN_MASK2) < v) + nrp++; + rp++; + if (((nrp[-1]+=v)&BN_MASK2) >= v) + continue; + else { - for (x=(nl+1); (((++rp[x])&BN_MASK2) == 0); x++) - ; + if (((++nrp[0])&BN_MASK2) != 0) continue; + if (((++nrp[1])&BN_MASK2) != 0) continue; + for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; } - rp++; } - while (r->d[r->top-1] == 0) - r->top--; - + bn_fix_top(r); + /* mont->ri will be a multiple of the word size */ #if 0 BN_rshift(ret,r,mont->ri); #else - ap=r->d; - rp=ret->d; + ret->neg = r->neg; x=ri; - al=r->top-x; - for (i=0; id; + ap= &(r->d[x]); + if (r->top < x) + al=0; + else + al=r->top-x; ret->top=al; -#endif - - if (BN_ucmp(ret,mont->N) >= 0) + al-=4; + for (i=0; iN); /* XXX */ + BN_ULONG t1,t2,t3,t4; + + t1=ap[i+0]; + t2=ap[i+1]; + t3=ap[i+2]; + t4=ap[i+3]; + rp[i+0]=t1; + rp[i+1]=t2; + rp[i+2]=t3; + rp[i+3]=t4; } - retn=1; -err: - return(retn); - } -#else -int BN_from_montgomery(r,a,mont,ctx) -BIGNUM *r; -BIGNUM *a; -BN_MONT_CTX *mont; -BN_CTX *ctx; - { + al+=4; + for (; ibn[ctx->tos]; - t2=ctx->bn[ctx->tos+1]; - + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) goto err; + if (!BN_copy(t1,a)) goto err; - /* can cheat */ BN_mask_bits(t1,mont->ri); - if (!BN_mul(t2,t1,mont->Ni)) goto err; + if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err; BN_mask_bits(t2,mont->ri); - if (!BN_mul(t1,t2,mont->N)) goto err; + if (!BN_mul(t1,t2,&mont->N,ctx)) goto err; if (!BN_add(t2,a,t1)) goto err; - BN_rshift(r,t2,mont->ri); + if (!BN_rshift(ret,t2,mont->ri)) goto err; +#endif /* MONT_WORD */ - if (BN_ucmp(r,mont->N) >= 0) - bn_qsub(r,r,mont->N); - - return(1); -err: - return(0); + if (BN_ucmp(ret, &(mont->N)) >= 0) + { + if (!BN_usub(ret,ret,&(mont->N))) goto err; + } + retn=1; + err: + BN_CTX_end(ctx); + return(retn); } -#endif -BN_MONT_CTX *BN_MONT_CTX_new() +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); - ret->ri=0; - ret->RR=BN_new(); - ret->N=BN_new(); - ret->Ni=NULL; - if ((ret->RR == NULL) || (ret->N == NULL)) - { - BN_MONT_CTX_free(ret); + if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL) return(NULL); - } + + BN_MONT_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; return(ret); } -void BN_MONT_CTX_free(mont) -BN_MONT_CTX *mont; +void BN_MONT_CTX_init(BN_MONT_CTX *ctx) { - if (mont->RR != NULL) BN_free(mont->RR); - if (mont->N != NULL) BN_free(mont->N); - if (mont->Ni != NULL) BN_free(mont->Ni); - Free(mont); + ctx->ri=0; + BN_init(&(ctx->RR)); + BN_init(&(ctx->N)); + BN_init(&(ctx->Ni)); + ctx->flags=0; } -int BN_MONT_CTX_set(mont,mod,ctx) -BN_MONT_CTX *mont; -BIGNUM *mod; -BN_CTX *ctx; +void BN_MONT_CTX_free(BN_MONT_CTX *mont) { - BIGNUM *Ri=NULL,*R=NULL; + if(mont == NULL) + return; + + BN_free(&(mont->RR)); + BN_free(&(mont->N)); + BN_free(&(mont->Ni)); + if (mont->flags & BN_FLG_MALLOCED) + OPENSSL_free(mont); + } - if (mont->RR == NULL) mont->RR=BN_new(); - if (mont->N == NULL) mont->N=BN_new(); +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) + { + BIGNUM Ri,*R; - R=mont->RR; /* grab RR as a temp */ - BN_copy(mont->N,mod); /* Set N */ + BN_init(&Ri); + R= &(mont->RR); /* grab RR as a temp */ + BN_copy(&(mont->N),mod); /* Set N */ + mont->N.neg = 0; #ifdef MONT_WORD -{ - BIGNUM tmod; - BN_ULONG buf[2]; - /* int z; */ - - mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; - BN_lshift(R,BN_value_one(),BN_BITS2); /* R */ - /* I was bad, this modification of a passed variable was - * breaking the multithreaded stuff :-( - * z=mod->top; - * mod->top=1; */ - - buf[0]=mod->d[0]; - buf[1]=0; - tmod.d=buf; - tmod.top=1; - tmod.max=mod->max; - tmod.neg=mod->neg; - - if ((Ri=BN_mod_inverse(R,&tmod,ctx)) == NULL) goto err; /* Ri */ - BN_lshift(Ri,Ri,BN_BITS2); /* R*Ri */ - bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */ - BN_div(Ri,NULL,Ri,&tmod,ctx); - mont->n0=Ri->d[0]; - BN_free(Ri); - /* mod->top=z; */ -} -#else - mont->ri=BN_num_bits(mod); - BN_lshift(R,BN_value_one(),mont->ri); /* R */ - if ((Ri=BN_mod_inverse(R,mod,ctx)) == NULL) goto err; /* Ri */ - BN_lshift(Ri,Ri,mont->ri); /* R*Ri */ - bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */ - BN_div(Ri,NULL,Ri,mod,ctx); - if (mont->Ni != NULL) BN_free(mont->Ni); - mont->Ni=Ri; /* Ni=(R*Ri-1)/N */ + { + BIGNUM tmod; + BN_ULONG buf[2]; + + mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; + if (!(BN_zero(R))) goto err; + if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */ + + buf[0]=mod->d[0]; /* tmod = N mod word size */ + buf[1]=0; + tmod.d=buf; + tmod.top=1; + tmod.dmax=2; + tmod.neg=0; + /* Ri = R^-1 mod N*/ + if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) + goto err; + if (!BN_lshift(&Ri,&Ri,BN_BITS2)) goto err; /* R*Ri */ + if (!BN_is_zero(&Ri)) + { + if (!BN_sub_word(&Ri,1)) goto err; + } + else /* if N mod word size == 1 */ + { + if (!BN_set_word(&Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */ + } + if (!BN_div(&Ri,NULL,&Ri,&tmod,ctx)) goto err; + /* Ni = (R*Ri-1)/N, + * keep only least significant word: */ + mont->n0 = (Ri.top > 0) ? Ri.d[0] : 0; + BN_free(&Ri); + } +#else /* !MONT_WORD */ + { /* bignum version */ + mont->ri=BN_num_bits(&mont->N); + if (!BN_zero(R)) goto err; + if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */ + /* Ri = R^-1 mod N*/ + if ((BN_mod_inverse(&Ri,R,&mont->N,ctx)) == NULL) + goto err; + if (!BN_lshift(&Ri,&Ri,mont->ri)) goto err; /* R*Ri */ + if (!BN_sub_word(&Ri,1)) goto err; + /* Ni = (R*Ri-1) / N */ + if (!BN_div(&(mont->Ni),NULL,&Ri,&mont->N,ctx)) goto err; + BN_free(&Ri); + } #endif /* setup RR for conversions */ - BN_lshift(mont->RR,BN_value_one(),mont->ri*2); - BN_mod(mont->RR,mont->RR,mont->N,ctx); + if (!BN_zero(&(mont->RR))) goto err; + if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err; + if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err; 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); + + if (!BN_copy(&(to->RR),&(from->RR))) return NULL; + if (!BN_copy(&(to->N),&(from->N))) return NULL; + if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL; + to->ri=from->ri; + to->n0=from->n0; + return(to); + } + diff --git a/src/lib/libcrypto/bn/bn_mpi.c b/src/lib/libcrypto/bn/bn_mpi.c index 53945c1057..05fa9d1e9a 100644 --- a/src/lib/libcrypto/bn/bn_mpi.c +++ b/src/lib/libcrypto/bn/bn_mpi.c @@ -60,9 +60,7 @@ #include "cryptlib.h" #include "bn_lcl.h" -int BN_bn2mpi(a,d) -BIGNUM *a; -unsigned char *d; +int BN_bn2mpi(const BIGNUM *a, unsigned char *d) { int bits; int num=0; @@ -90,10 +88,7 @@ unsigned char *d; return(num+4+ext); } -BIGNUM *BN_mpi2bn(d,n,a) -unsigned char *d; -int n; -BIGNUM *a; +BIGNUM *BN_mpi2bn(const unsigned char *d, int n, BIGNUM *a) { long len; int neg=0; @@ -103,7 +98,7 @@ BIGNUM *a; BNerr(BN_F_BN_MPI2BN,BN_R_INVALID_LENGTH); return(NULL); } - len=(d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3]; + 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); diff --git a/src/lib/libcrypto/bn/bn_mul.c b/src/lib/libcrypto/bn/bn_mul.c index d0c04e1d4b..fd598b8b3d 100644 --- a/src/lib/libcrypto/bn/bn_mul.c +++ b/src/lib/libcrypto/bn/bn_mul.c @@ -56,154 +56,1108 @@ * [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" -/* r must be different to a and b */ -/* int BN_mmul(r, a, b) */ -int BN_mul(r, a, b) -BIGNUM *r; -BIGNUM *a; -BIGNUM *b; +#if defined(OPENSSL_NO_ASM) || !(defined(__i386) || defined(__i386__))/* Assembler implementation exists only for x86 */ +/* Here follows specialised variants of bn_add_words() and + bn_sub_words(). They have the property performing operations on + arrays of different sizes. The sizes of those arrays is expressed through + cl, which is the common length ( basicall, min(len(a),len(b)) ), and dl, + which is the delta between the two lengths, calculated as len(a)-len(b). + All lengths are the number of BN_ULONGs... For the operations that require + a result array as parameter, it must have the length cl+abs(dl). + These functions should probably end up in bn_asm.c as soon as there are + assembler counterparts for the systems that use assembler files. */ + +BN_ULONG bn_sub_part_words(BN_ULONG *r, + const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl) { - int i; - int max,al,bl; - BN_ULONG *ap,*bp,*rp; + BN_ULONG c, t; - al=a->top; - bl=b->top; - if ((al == 0) || (bl == 0)) + assert(cl >= 0); + c = bn_sub_words(r, a, b, cl); + + if (dl == 0) + return c; + + r += cl; + a += cl; + b += cl; + + if (dl < 0) { - r->top=0; - return(1); - } +#ifdef BN_COUNT + fprintf(stderr, " bn_sub_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c); +#endif + for (;;) + { + t = b[0]; + r[0] = (0-t-c)&BN_MASK2; + if (t != 0) c=1; + if (++dl >= 0) break; + + t = b[1]; + r[1] = (0-t-c)&BN_MASK2; + if (t != 0) c=1; + if (++dl >= 0) break; + + t = b[2]; + r[2] = (0-t-c)&BN_MASK2; + if (t != 0) c=1; + if (++dl >= 0) break; - max=(al+bl); - if (bn_wexpand(r,max) == NULL) return(0); - r->top=max; - r->neg=a->neg^b->neg; - ap=a->d; - bp=b->d; - rp=r->d; + t = b[3]; + r[3] = (0-t-c)&BN_MASK2; + if (t != 0) c=1; + if (++dl >= 0) break; - rp[al]=bn_mul_words(rp,ap,al,*(bp++)); - rp++; - for (i=1; i 0, c = %d)\n", cl, dl, c); +#endif + while(c) + { + t = a[0]; + r[0] = (t-c)&BN_MASK2; + if (t != 0) c=0; + if (--dl <= 0) break; + + t = a[1]; + r[1] = (t-c)&BN_MASK2; + if (t != 0) c=0; + if (--dl <= 0) break; + + t = a[2]; + r[2] = (t-c)&BN_MASK2; + if (t != 0) c=0; + if (--dl <= 0) break; + + t = a[3]; + r[3] = (t-c)&BN_MASK2; + if (t != 0) c=0; + if (--dl <= 0) break; + + save_dl = dl; + a += 4; + r += 4; + } + if (dl > 0) + { +#ifdef BN_COUNT + fprintf(stderr, " bn_sub_part_words %d + %d (dl > 0, c == 0)\n", cl, dl); +#endif + if (save_dl > dl) + { + switch (save_dl - dl) + { + case 1: + r[1] = a[1]; + if (--dl <= 0) break; + case 2: + r[2] = a[2]; + if (--dl <= 0) break; + case 3: + r[3] = a[3]; + if (--dl <= 0) break; + } + a += 4; + r += 4; + } + } + if (dl > 0) + { +#ifdef BN_COUNT + fprintf(stderr, " bn_sub_part_words %d + %d (dl > 0, copy)\n", cl, dl); +#endif + for(;;) + { + r[0] = a[0]; + if (--dl <= 0) break; + r[1] = a[1]; + if (--dl <= 0) break; + r[2] = a[2]; + if (--dl <= 0) break; + r[3] = a[3]; + if (--dl <= 0) break; + + a += 4; + r += 4; + } + } } - if (r->d[max-1] == 0) r->top--; - return(1); + return c; } +#endif -#if 0 -#include "stack.h" +BN_ULONG bn_add_part_words(BN_ULONG *r, + const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl) + { + BN_ULONG c, l, t; + + assert(cl >= 0); + c = bn_add_words(r, a, b, cl); + + if (dl == 0) + return c; + + r += cl; + a += cl; + b += cl; + + if (dl < 0) + { + int save_dl = dl; +#ifdef BN_COUNT + fprintf(stderr, " bn_add_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c); +#endif + while (c) + { + l=(c+b[0])&BN_MASK2; + c=(l < c); + r[0]=l; + if (++dl >= 0) break; + + l=(c+b[1])&BN_MASK2; + c=(l < c); + r[1]=l; + if (++dl >= 0) break; + + l=(c+b[2])&BN_MASK2; + c=(l < c); + r[2]=l; + if (++dl >= 0) break; -int limit=16; + l=(c+b[3])&BN_MASK2; + c=(l < c); + r[3]=l; + if (++dl >= 0) break; -typedef struct bn_pool_st + save_dl = dl; + b+=4; + r+=4; + } + if (dl < 0) + { +#ifdef BN_COUNT + fprintf(stderr, " bn_add_part_words %d + %d (dl < 0, c == 0)\n", cl, dl); +#endif + if (save_dl < dl) + { + switch (dl - save_dl) + { + case 1: + r[1] = b[1]; + if (++dl >= 0) break; + case 2: + r[2] = b[2]; + if (++dl >= 0) break; + case 3: + r[3] = b[3]; + if (++dl >= 0) break; + } + b += 4; + r += 4; + } + } + if (dl < 0) + { +#ifdef BN_COUNT + fprintf(stderr, " bn_add_part_words %d + %d (dl < 0, copy)\n", cl, dl); +#endif + for(;;) + { + r[0] = b[0]; + if (++dl >= 0) break; + r[1] = b[1]; + if (++dl >= 0) break; + r[2] = b[2]; + if (++dl >= 0) break; + r[3] = b[3]; + if (++dl >= 0) break; + + b += 4; + r += 4; + } + } + } + else + { + int save_dl = dl; +#ifdef BN_COUNT + fprintf(stderr, " bn_add_part_words %d + %d (dl > 0)\n", cl, dl); +#endif + while (c) + { + t=(a[0]+c)&BN_MASK2; + c=(t < c); + r[0]=t; + if (--dl <= 0) break; + + t=(a[1]+c)&BN_MASK2; + c=(t < c); + r[1]=t; + if (--dl <= 0) break; + + t=(a[2]+c)&BN_MASK2; + c=(t < c); + r[2]=t; + if (--dl <= 0) break; + + t=(a[3]+c)&BN_MASK2; + c=(t < c); + r[3]=t; + if (--dl <= 0) break; + + save_dl = dl; + a+=4; + r+=4; + } +#ifdef BN_COUNT + fprintf(stderr, " bn_add_part_words %d + %d (dl > 0, c == 0)\n", cl, dl); +#endif + if (dl > 0) + { + if (save_dl > dl) + { + switch (save_dl - dl) + { + case 1: + r[1] = a[1]; + if (--dl <= 0) break; + case 2: + r[2] = a[2]; + if (--dl <= 0) break; + case 3: + r[3] = a[3]; + if (--dl <= 0) break; + } + a += 4; + r += 4; + } + } + if (dl > 0) + { +#ifdef BN_COUNT + fprintf(stderr, " bn_add_part_words %d + %d (dl > 0, copy)\n", cl, dl); +#endif + for(;;) + { + r[0] = a[0]; + if (--dl <= 0) break; + r[1] = a[1]; + if (--dl <= 0) break; + r[2] = a[2]; + if (--dl <= 0) break; + r[3] = a[3]; + if (--dl <= 0) break; + + a += 4; + r += 4; + } + } + } + return c; + } + +#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, + int dna, int dnb, BN_ULONG *t) { - int used; - int tos; - STACK *sk; - } BN_POOL; + int n=n2/2,c1,c2; + int tna=n+dna, tnb=n+dnb; + unsigned int neg,zero; + BN_ULONG ln,lo,*p; + +# ifdef BN_COUNT + fprintf(stderr," 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 + /* Only call bn_mul_comba 8 if n2 == 8 and the + * two arrays are complete [steve] + */ + if (n2 == 8 && dna == 0 && dnb == 0) + { + bn_mul_comba8(r,a,b); + return; + } +# endif /* BN_MUL_COMBA */ + /* Else do normal multiply */ + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + bn_mul_normal(r,a,n2+dna,b,n2+dnb); + if ((dna + dnb) < 0) + memset(&r[2*n2 + dna + dnb], 0, + sizeof(BN_ULONG) * -(dna + dnb)); + return; + } + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna); + c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n); + zero=neg=0; + switch (c1*3+c2) + { + case -4: + bn_sub_part_words(t, &(a[n]),a, tna,tna-n); /* - */ + bn_sub_part_words(&(t[n]),b, &(b[n]),tnb,n-tnb); /* - */ + break; + case -3: + zero=1; + break; + case -2: + bn_sub_part_words(t, &(a[n]),a, tna,tna-n); /* - */ + bn_sub_part_words(&(t[n]),&(b[n]),b, tnb,tnb-n); /* + */ + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_part_words(t, a, &(a[n]),tna,n-tna); /* + */ + bn_sub_part_words(&(t[n]),b, &(b[n]),tnb,n-tnb); /* - */ + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_part_words(t, a, &(a[n]),tna,n-tna); + bn_sub_part_words(&(t[n]),&(b[n]),b, tnb,tnb-n); + break; + } + +# ifdef BN_MUL_COMBA + if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take + extra args to do this well */ + { + 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 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could + take extra args to do this + well */ + { + 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,0,0,p); + else + memset(&(t[n2]),0,n2*sizeof(BN_ULONG)); + bn_mul_recursive(r,a,b,n,0,0,p); + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,dna,dnb,p); + } -BIGNUM *BN_POOL_push(bp) -BN_POOL *bp; + /* 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 n, + int tna, int tnb, BN_ULONG *t) { - BIGNUM *ret; + int i,j,n2=n*2; + unsigned int c1,c2,neg,zero; + BN_ULONG ln,lo,*p; + +# ifdef BN_COUNT + fprintf(stderr," bn_mul_part_recursive (%d+%d) * (%d+%d)\n", + tna, n, tnb, n); +# endif + if (n < 8) + { + bn_mul_normal(r,a,n+tna,b,n+tnb); + return; + } - if (bp->used >= bp->tos) + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna); + c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n); + zero=neg=0; + switch (c1*3+c2) + { + case -4: + bn_sub_part_words(t, &(a[n]),a, tna,tna-n); /* - */ + bn_sub_part_words(&(t[n]),b, &(b[n]),tnb,n-tnb); /* - */ + break; + case -3: + zero=1; + /* break; */ + case -2: + bn_sub_part_words(t, &(a[n]),a, tna,tna-n); /* - */ + bn_sub_part_words(&(t[n]),&(b[n]),b, tnb,tnb-n); /* + */ + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + /* break; */ + case 2: + bn_sub_part_words(t, a, &(a[n]),tna,n-tna); /* + */ + bn_sub_part_words(&(t[n]),b, &(b[n]),tnb,n-tnb); /* - */ + neg=1; + break; + case 3: + zero=1; + /* break; */ + case 4: + bn_sub_part_words(t, a, &(a[n]),tna,n-tna); + bn_sub_part_words(&(t[n]),&(b[n]),b, tnb,tnb-n); + break; + } + /* The zero case isn't yet implemented here. The speedup + would probably be negligible. */ +# if 0 + if (n == 4) { - ret=BN_new(); - sk_push(bp->sk,(char *)ret); - bp->tos++; - bp->used++; + 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) { - ret=(BIGNUM *)sk_value(bp->sk,bp->used); - bp->used++; + bn_mul_comba8(&(t[n2]),t,&(t[n])); + bn_mul_comba8(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tna,&(b[n]),tnb); + memset(&(r[n2+tna+tnb]),0,sizeof(BN_ULONG)*(n2-tna-tnb)); + } + else + { + p= &(t[n2*2]); + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,0,0,p); + bn_mul_recursive(r,a,b,n,0,0,p); + i=n/2; + /* If there is only a bottom half to the number, + * just do it */ + if (tna > tnb) + j = tna - i; + else + j = tnb - i; + if (j == 0) + { + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]), + i,tna-i,tnb-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]), + i,tna-i,tnb-i,p); + memset(&(r[n2+tna+tnb]),0, + sizeof(BN_ULONG)*(n2-tna-tnb)); + } + else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + { + memset(&(r[n2]),0,sizeof(BN_ULONG)*n2); + if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL + && tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + bn_mul_normal(&(r[n2]),&(a[n]),tna,&(b[n]),tnb); + } + else + { + for (;;) + { + i/=2; + if (i < tna && i < tnb) + { + bn_mul_part_recursive(&(r[n2]), + &(a[n]),&(b[n]), + i,tna-i,tnb-i,p); + break; + } + else if (i <= tna && i <= tnb) + { + bn_mul_recursive(&(r[n2]), + &(a[n]),&(b[n]), + i,tna-i,tnb-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); + } } - return(ret); } -void BN_POOL_pop(bp,num) -BN_POOL *bp; -int num; +/* 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) { - bp->used-=num; + int n=n2/2; + +# ifdef BN_COUNT + fprintf(stderr," bn_mul_low_recursive %d * %d\n",n2,n2); +# endif + + bn_mul_recursive(r,a,b,n,0,0,&(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); + } } -int BN_mul(r,a,b) -BIGNUM *r,*a,*b; +/* 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) { - static BN_POOL bp; - static init=1; + int i,n; + int c1,c2; + int neg,oneg,zero; + BN_ULONG ll,lc,*lp,*mp; + +# ifdef BN_COUNT + fprintf(stderr," 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,0,0,&(t[n2])); + bn_mul_recursive(r,&(a[n]),&(b[n]),n,0,0,&(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); + } } - return(BN_mm(r,a,b,&bp)); } +#endif /* BN_RECURSION */ -/* r must be different to a and b */ -int BN_mm(m, A, B, bp) -BIGNUM *m,*A,*B; -BN_POOL *bp; +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { - int i,num; - int an,bn; - BIGNUM *a,*b,*c,*d,*ac,*bd; + int ret=0; + int top,al,bl; + BIGNUM *rr; +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + int i; +#endif +#ifdef BN_RECURSION + BIGNUM *t=NULL; + int j=0,k; +#endif + +#ifdef BN_COUNT + fprintf(stderr,"BN_mul %d * %d\n",a->top,b->top); +#endif - an=A->top; - bn=B->top; - if ((an <= limit) || (bn <= limit)) + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + + al=a->top; + bl=b->top; + + if ((al == 0) || (bl == 0)) { - return(BN_mmul(m,A,B)); + if (!BN_zero(r)) goto err; + return(1); } + top=al+bl; - a=BN_POOL_push(bp); - b=BN_POOL_push(bp); - c=BN_POOL_push(bp); - d=BN_POOL_push(bp); - ac=BN_POOL_push(bp); - bd=BN_POOL_push(bp); + BN_CTX_start(ctx); + if ((r == a) || (r == b)) + { + if ((rr = BN_CTX_get(ctx)) == NULL) goto err; + } + else + rr = r; + rr->neg=a->neg^b->neg; - num=(an <= bn)?an:bn; - num=1<<(BN_num_bits_word(num-1)-1); +#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 && i <= 1) + { + int sav_j =0; + /* Find out the power of two lower or equal + to the longest of the two numbers */ + if (i >= 0) + { + j = BN_num_bits_word((BN_ULONG)al); + } + if (i == -1) + { + j = BN_num_bits_word((BN_ULONG)bl); + } + sav_j = j; + j = 1<<(j-1); + assert(j <= al || j <= bl); + k = j+j; + t = BN_CTX_get(ctx); + if (al > j || bl > j) + { + bn_wexpand(t,k*4); + bn_wexpand(rr,k*4); + bn_mul_part_recursive(rr->d,a->d,b->d, + j,al-j,bl-j,t->d); + } + else /* al <= j || bl <= j */ + { + bn_wexpand(t,k*2); + bn_wexpand(rr,k*2); + bn_mul_recursive(rr->d,a->d,b->d, + j,al-j,bl-j,t->d); + } + rr->top=top; + goto end; + } +#if 0 + if (i == 1 && !BN_get_flags(b,BN_FLG_STATIC_DATA)) + { + BIGNUM *tmp_bn = (BIGNUM *)b; + if (bn_wexpand(tmp_bn,al) == NULL) goto err; + tmp_bn->d[bl]=0; + bl++; + i--; + } + else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA)) + { + BIGNUM *tmp_bn = (BIGNUM *)a; + if (bn_wexpand(tmp_bn,bl) == NULL) goto err; + tmp_bn->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 */ + { + if (bn_wexpand(t,k*2) == NULL) goto err; + if (bn_wexpand(rr,k*2) == NULL) goto err; + bn_mul_recursive(rr->d,a->d,b->d,al,t->d); + } + else + { + if (bn_wexpand(t,k*4) == NULL) goto err; + if (bn_wexpand(rr,k*4) == NULL) goto err; + bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d); + } + rr->top=top; + goto end; + } +#endif + } +#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); - /* Are going to now chop things into 'num' word chunks. */ - num*=BN_BITS2; +#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); + } - BN_copy(a,A); - BN_mask_bits(a,num); - BN_rshift(b,A,num); +void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) + { + BN_ULONG *rr; - BN_copy(c,B); - BN_mask_bits(c,num); - BN_rshift(d,B,num); +#ifdef BN_COUNT + fprintf(stderr," bn_mul_normal %d * %d\n",na,nb); +#endif - BN_sub(ac ,b,a); - BN_sub(bd,c,d); - BN_mm(m,ac,bd,bp); - BN_mm(ac,a,c,bp); - BN_mm(bd,b,d,bp); + if (na < nb) + { + int itmp; + BN_ULONG *ltmp; - BN_add(m,m,ac); - BN_add(m,m,bd); - BN_lshift(m,m,num); - BN_lshift(bd,bd,num*2); + itmp=na; na=nb; nb=itmp; + ltmp=a; a=b; b=ltmp; - BN_add(m,m,ac); - BN_add(m,m,bd); - BN_POOL_pop(bp,6); - return(1); + } + rr= &(r[na]); + if (nb <= 0) + { + (void)bn_mul_words(r,a,na,0); + return; + } + else + 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 + fprintf(stderr," 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/src/lib/libcrypto/bn/bn_prime.c b/src/lib/libcrypto/bn/bn_prime.c index 0c85f70b59..918b9237c6 100644 --- a/src/lib/libcrypto/bn/bn_prime.c +++ b/src/lib/libcrypto/bn/bn_prime.c @@ -55,53 +55,100 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "rand.h" +#include -/* The quick seive algorithm approach to weeding out primes is +/* 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" -#ifndef NOPROTO -static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx,BN_CTX *ctx2, - BN_MONT_CTX *mont); +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_strong(BIGNUM *rnd, int bits, - BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); -#else -static int witness(); -static int probable_prime(); -static int probable_prime_dh(); -static int probable_prime_dh_strong(); -#endif - -BIGNUM *BN_generate_prime(bits,strong,add,rem,callback,cb_arg) -int bits; -int strong; -BIGNUM *add; -BIGNUM *rem; -void (*callback)(P_I_I_P); -char *cb_arg; + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); +static int probable_prime_dh_safe(BIGNUM *rnd, int bits, + const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx); + +BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, + void (*callback)(int,int,void *), void *cb_arg) { BIGNUM *rnd=NULL; - BIGNUM *ret=NULL; - BIGNUM *t=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 ((rnd=BN_new()) == NULL) goto err; - if (strong) - if ((t=BN_new()) == 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) @@ -110,9 +157,9 @@ loop: } else { - if (strong) + if (safe) { - if (!probable_prime_dh_strong(rnd,bits,add,rem,ctx)) + if (!probable_prime_dh_safe(rnd,bits,add,rem,ctx)) goto err; } else @@ -124,171 +171,188 @@ loop: /* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */ if (callback != NULL) callback(0,c1++,cb_arg); - if (!strong) + if (!safe) { - i=BN_is_prime(rnd,BN_prime_checks,callback,ctx,cb_arg); + i=BN_is_prime_fasttest(rnd,checks,callback,ctx,cb_arg,0); if (i == -1) goto err; if (i == 0) goto loop; } else { - /* for a strong prime generation, + /* 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; + if (!BN_rshift1(&t,rnd)) goto err; - for (i=0; ibn[ctx->tos++]; + if ((ctx=BN_CTX_new()) == NULL) + goto err; + BN_CTX_start(ctx); - /* Setup the montgomery structure */ - if (!BN_MONT_CTX_set(mont,a,ctx2)) goto err; + /* A := abs(a) */ + if (a->neg) + { + 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; + } - for (i=0; itos--; - if ((ctx_passed == NULL) && (ctx != NULL)) - BN_CTX_free(ctx); - if (ctx2 != NULL) - BN_CTX_free(ctx2); - if (mont != NULL) BN_MONT_CTX_free(mont); - + 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); } -#define RECP_MUL_MOD - -static int witness(a,n,ctx,ctx2,mont) -BIGNUM *a; -BIGNUM *n; -BN_CTX *ctx,*ctx2; -BN_MONT_CTX *mont; +static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, + const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont) { - int k,i,ret= -1,good; - BIGNUM *d,*dd,*tmp,*d1,*d2,*n1; - BIGNUM *mont_one,*mont_n1,*mont_a; - - d1=ctx->bn[ctx->tos]; - d2=ctx->bn[ctx->tos+1]; - n1=ctx->bn[ctx->tos+2]; - ctx->tos+=3; - - mont_one=ctx2->bn[ctx2->tos]; - mont_n1=ctx2->bn[ctx2->tos+1]; - mont_a=ctx2->bn[ctx2->tos+2]; - ctx2->tos+=3; - - d=d1; - dd=d2; - if (!BN_one(d)) goto err; - if (!BN_sub(n1,n,d)) goto err; /* n1=n-1; */ - k=BN_num_bits(n1); - - if (!BN_to_montgomery(mont_one,BN_value_one(),mont,ctx2)) goto err; - if (!BN_to_montgomery(mont_n1,n1,mont,ctx2)) goto err; - if (!BN_to_montgomery(mont_a,a,mont,ctx2)) goto err; - - BN_copy(d,mont_one); - for (i=k-1; i>=0; i--) + 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_cmp(d,mont_one) != 0) && - (BN_cmp(d,mont_n1) != 0)) - good=1; - else - good=0; - - BN_mod_mul_montgomery(dd,d,d,mont,ctx2); - - if (good && (BN_cmp(dd,mont_one) == 0)) - { - ret=1; - goto err; - } - if (BN_is_bit_set(n1,i)) - { - BN_mod_mul_montgomery(d,dd,mont_a,mont,ctx2); - } - else - { - tmp=d; - d=dd; - dd=tmp; - } + 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 (BN_cmp(d,mont_one) == 0) - i=0; - else i=1; - ret=i; -err: - ctx->tos-=3; - ctx2->tos-=3; - return(ret); + /* 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(rnd, bits) -BIGNUM *rnd; -int bits; +static int probable_prime(BIGNUM *rnd, int bits) { int i; - MS_STATIC BN_ULONG mods[NUMPRIMES]; - BN_ULONG delta; + 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; ibn[ctx->tos++]; + BN_CTX_start(ctx); + if ((t1 = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_rand(rnd,bits,0,1)) goto err; @@ -338,7 +402,7 @@ BN_CTX *ctx; loop: for (i=1; itos--; + BN_CTX_end(ctx); return(ret); } -static int probable_prime_dh_strong(p, bits, padd, rem,ctx) -BIGNUM *p; -int bits; -BIGNUM *padd; -BIGNUM *rem; -BN_CTX *ctx; +static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd, + const BIGNUM *rem, BN_CTX *ctx) { int i,ret=0; - BIGNUM *t1,*qadd=NULL,*q=NULL; + BIGNUM *t1,*qadd,*q; bits--; - t1=ctx->bn[ctx->tos++]; - q=ctx->bn[ctx->tos++]; - qadd=ctx->bn[ctx->tos++]; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + qadd = BN_CTX_get(ctx); + if (qadd == NULL) goto err; if (!BN_rshift1(qadd,padd)) goto err; @@ -389,8 +451,8 @@ BN_CTX *ctx; /* check that p and q are prime */ /* check that for p and q * gcd(p-1,primes) == 1 (except for 2) */ - if ( (BN_mod_word(p,(BN_LONG)primes[i]) == 0) || - (BN_mod_word(q,(BN_LONG)primes[i]) == 0)) + if ( (BN_mod_word(p,(BN_ULONG)primes[i]) == 0) || + (BN_mod_word(q,(BN_ULONG)primes[i]) == 0)) { if (!BN_add(p,p,padd)) goto err; if (!BN_add(q,q,qadd)) goto err; @@ -399,75 +461,6 @@ BN_CTX *ctx; } ret=1; err: - ctx->tos-=3; - return(ret); - } - -#if 0 -static int witness(a, n,ctx) -BIGNUM *a; -BIGNUM *n; -BN_CTX *ctx; - { - int k,i,nb,ret= -1; - BIGNUM *d,*dd,*tmp; - BIGNUM *d1,*d2,*x,*n1,*inv; - - d1=ctx->bn[ctx->tos]; - d2=ctx->bn[ctx->tos+1]; - x=ctx->bn[ctx->tos+2]; - n1=ctx->bn[ctx->tos+3]; - inv=ctx->bn[ctx->tos+4]; - ctx->tos+=5; - - d=d1; - dd=d2; - if (!BN_one(d)) goto err; - if (!BN_sub(n1,n,d)) goto err; /* n1=n-1; */ - k=BN_num_bits(n1); - - /* i=BN_num_bits(n); */ -#ifdef RECP_MUL_MOD - nb=BN_reciprocal(inv,n,ctx); /**/ - if (nb == -1) goto err; -#endif - - for (i=k-1; i>=0; i--) - { - if (BN_copy(x,d) == NULL) goto err; -#ifndef RECP_MUL_MOD - if (!BN_mod_mul(dd,d,d,n,ctx)) goto err; -#else - if (!BN_mod_mul_reciprocal(dd,d,d,n,inv,nb,ctx)) goto err; -#endif - if ( BN_is_one(dd) && - !BN_is_one(x) && - (BN_cmp(x,n1) != 0)) - { - ret=1; - goto err; - } - if (BN_is_bit_set(n1,i)) - { -#ifndef RECP_MUL_MOD - if (!BN_mod_mul(d,dd,a,n,ctx)) goto err; -#else - if (!BN_mod_mul_reciprocal(d,dd,a,n,inv,nb,ctx)) goto err; -#endif - } - else - { - tmp=d; - d=dd; - dd=tmp; - } - } - if (BN_is_one(d)) - i=0; - else i=1; - ret=i; -err: - ctx->tos-=5; + BN_CTX_end(ctx); return(ret); } -#endif diff --git a/src/lib/libcrypto/bn/bn_prime.h b/src/lib/libcrypto/bn/bn_prime.h index 6fce0210cd..b7cf9a9bfe 100644 --- a/src/lib/libcrypto/bn/bn_prime.h +++ b/src/lib/libcrypto/bn/bn_prime.h @@ -1,4 +1,4 @@ -/* crypto/bn/bn_prime.h */ +/* Auto generated by bn_prime.pl */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -61,7 +61,7 @@ #else #define NUMPRIMES 54 #endif -static unsigned int primes[NUMPRIMES]= +static const unsigned int primes[NUMPRIMES]= { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, diff --git a/src/lib/libcrypto/bn/bn_prime.pl b/src/lib/libcrypto/bn/bn_prime.pl index 1b00c21a77..9fc3765486 100644 --- a/src/lib/libcrypto/bn/bn_prime.pl +++ b/src/lib/libcrypto/bn/bn_prime.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # bn_prime.pl $num=2048; @@ -18,13 +18,74 @@ loop: while ($#primes < $num-1) push(@primes,$p); } -print <<"EOF"; +# print <<"EOF"; +# /* Auto generated by bn_prime.pl */ +# /* Copyright (C) 1995-1997 Eric Young (eay\@mincom.oz.au). +# * All rights reserved. +# * Copyright remains Eric Young's, and as such any Copyright notices in +# * the code are not to be removed. +# * See the COPYRIGHT file in the SSLeay distribution for more details. +# */ +# +# EOF + +print <<\EOF; /* Auto generated by bn_prime.pl */ -/* Copyright (C) 1995-1997 Eric Young (eay\@mincom.oz.au). +/* 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. - * See the COPYRIGHT file in the SSLeay distribution for more details. + * 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.] */ EOF @@ -43,7 +104,7 @@ printf "#define NUMPRIMES %d\n",$num; printf "#else\n"; printf "#define NUMPRIMES %d\n",$eight; printf "#endif\n"; -print "static unsigned int primes[NUMPRIMES]=\n\t{\n\t"; +print "static const unsigned int primes[NUMPRIMES]=\n\t{\n\t"; $init=0; for ($i=0; $i <= $#primes; $i++) { diff --git a/src/lib/libcrypto/bn/bn_print.c b/src/lib/libcrypto/bn/bn_print.c index 2bcc11c852..5f46b1826c 100644 --- a/src/lib/libcrypto/bn/bn_print.c +++ b/src/lib/libcrypto/bn/bn_print.c @@ -59,20 +59,19 @@ #include #include #include "cryptlib.h" -#include "buffer.h" +#include #include "bn_lcl.h" -static char *Hex="0123456789ABCDEF"; +static const char *Hex="0123456789ABCDEF"; -/* Must 'Free' the returned data */ -char *BN_bn2hex(a) -BIGNUM *a; +/* Must 'OPENSSL_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); + buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2); if (buf == NULL) { BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE); @@ -100,9 +99,8 @@ err: return(buf); } -/* Must 'Free' the returned data */ -char *BN_bn2dec(a) -BIGNUM *a; +/* Must 'OPENSSL_free' the returned data */ +char *BN_bn2dec(const BIGNUM *a) { int i=0,num; char *buf=NULL; @@ -112,8 +110,8 @@ BIGNUM *a; 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); + bn_data=(BN_ULONG *)OPENSSL_malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG)); + buf=(char *)OPENSSL_malloc(num+3); if ((buf == NULL) || (bn_data == NULL)) { BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE); @@ -139,7 +137,7 @@ BIGNUM *a; } lp--; /* We now have a series of blocks, BN_DEC_NUM chars - * in length, where the last one needs trucation. + * 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++; @@ -151,14 +149,12 @@ BIGNUM *a; } } err: - if (bn_data != NULL) Free(bn_data); + if (bn_data != NULL) OPENSSL_free(bn_data); if (t != NULL) BN_free(t); return(buf); } -int BN_hex2bn(bn,a) -BIGNUM **bn; -char *a; +int BN_hex2bn(BIGNUM **bn, const char *a) { BIGNUM *ret=NULL; BN_ULONG l=0; @@ -169,13 +165,13 @@ char *a; if (*a == '-') { neg=1; a++; } - for (i=0; isxdigit(a[i]); i++) + for (i=0; isxdigit((unsigned char) a[i]); i++) ; num=i+neg; if (bn == NULL) return(num); - /* a is the start of the hex digets, and it is 'i' long */ + /* a is the start of the hex digits, and it is 'i' long */ if (*bn == NULL) { if ((ret=BN_new()) == NULL) return(0); @@ -189,7 +185,7 @@ char *a; /* i is the number of hex digests; */ if (bn_expand(ret,i*4) == NULL) goto err; - j=i; /* least significate 'hex' */ + j=i; /* least significant 'hex' */ m=0; h=0; while (j > 0) @@ -224,9 +220,7 @@ err: return(0); } -int BN_dec2bn(bn,a) -BIGNUM **bn; -char *a; +int BN_dec2bn(BIGNUM **bn, const char *a) { BIGNUM *ret=NULL; BN_ULONG l=0; @@ -236,14 +230,14 @@ char *a; if ((a == NULL) || (*a == '\0')) return(0); if (*a == '-') { neg=1; a++; } - for (i=0; isdigit(a[i]); i++) + for (i=0; isdigit((unsigned char) a[i]); i++) ; num=i+neg; if (bn == NULL) return(num); - /* a is the start of the digets, and it is 'i' long. - * We chop it into BN_DEC_NUM digets at a time */ + /* 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); @@ -283,12 +277,9 @@ err: return(0); } -#ifndef NO_BIO - -#ifndef NO_FP_API -int BN_print_fp(fp, a) -FILE *fp; -BIGNUM *a; +#ifndef OPENSSL_NO_BIO +#ifndef OPENSSL_NO_FP_API +int BN_print_fp(FILE *fp, const BIGNUM *a) { BIO *b; int ret; @@ -302,9 +293,7 @@ BIGNUM *a; } #endif -int BN_print(bp, a) -BIO *bp; -BIGNUM *a; +int BN_print(BIO *bp, const BIGNUM *a) { int i,j,v,z=0; int ret=0; @@ -329,5 +318,15 @@ BIGNUM *a; end: return(ret); } +#endif +#ifdef BN_DEBUG +void bn_dump1(FILE *o, const char *a, const 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/src/lib/libcrypto/bn/bn_rand.c b/src/lib/libcrypto/bn/bn_rand.c index 75b6b0493b..9e08ccd22e 100644 --- a/src/lib/libcrypto/bn/bn_rand.c +++ b/src/lib/libcrypto/bn/bn_rand.c @@ -55,28 +55,83 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "rand.h" +#include -int BN_rand(rnd, bits, top, bottom) -BIGNUM *rnd; -int bits; -int top; -int bottom; +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<= 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]|=(3<<(bit-1)); - buf[0]&= ~(mask<<1); + 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 */ + + /* BN_is_bit_set(range, n - 1) always holds */ + + if (n == 1) + { + if (!BN_zero(r)) return 0; + } + else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) + { + /* range = 100..._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); + } + else + { + do + { + /* range = 11..._2 or range = 101..._2 */ + if (!bn_rand(r, n, -1, 0)) return 0; + } + while (BN_cmp(r, range) >= 0); + } + + return 1; + } + + +int BN_rand_range(BIGNUM *r, BIGNUM *range) + { + return bn_rand_range(0, r, range); + } + +int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range) + { + return bn_rand_range(1, r, range); + } diff --git a/src/lib/libcrypto/bn/bn_recp.c b/src/lib/libcrypto/bn/bn_recp.c index 72cd69d3fc..ef5fdd4708 100644 --- a/src/lib/libcrypto/bn/bn_recp.c +++ b/src/lib/libcrypto/bn/bn_recp.c @@ -60,66 +60,171 @@ #include "cryptlib.h" #include "bn_lcl.h" -int BN_mod_mul_reciprocal(r, x, y, m, i, nb, ctx) -BIGNUM *r; -BIGNUM *x; -BIGNUM *y; -BIGNUM *m; -BIGNUM *i; -int nb; -BN_CTX *ctx; +void BN_RECP_CTX_init(BN_RECP_CTX *recp) { - int ret=0,j; - BIGNUM *a,*b,*c,*d; + 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 *)OPENSSL_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) + OPENSSL_free(recp); + } - a=ctx->bn[ctx->tos++]; - b=ctx->bn[ctx->tos++]; - c=ctx->bn[ctx->tos++]; - d=ctx->bn[ctx->tos++]; +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) + { + if (!BN_copy(&(recp->N),d)) return 0; + if (!BN_zero(&(recp->Nr))) return 0; + recp->num_bits=BN_num_bits(d); + recp->shift=0; + return(1); + } + +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx) + { + int ret=0; + BIGNUM *a; + const BIGNUM *ca; - if (x == y) - { if (!BN_sqr(a,x,ctx)) goto err; } + 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; } + ca = a; + } else - { if (!BN_mul(a,x,y)) goto err; } - if (!BN_rshift(d,a,nb)) goto err; - if (!BN_mul(b,d,i)) goto err; - if (!BN_rshift(c,b,nb)) goto err; - if (!BN_mul(b,m,c)) goto err; - if (!BN_sub(r,a,b)) goto err; + ca=x; /* Just do the mod */ + + ret = BN_div_recp(NULL,r,ca,recp,ctx); +err: + BN_CTX_end(ctx); + return(ret); + } + +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const 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) + { + if (!BN_zero(d)) return 0; + if (!BN_copy(r,m)) return 0; + 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 := max(BN_num_bits(m), 2*BN_num_bits(N)) */ + i=BN_num_bits(m); + j=recp->num_bits<<1; + if (j>i) i=j; + + /* Nr := round(2^i / N) */ + if (i != recp->shift) + recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N), + i,ctx); /* BN_reciprocal returns i, or -1 for an error */ + if (recp->shift == -1) goto err; + + /* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))| + * = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))| + * <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)| + * = |m/N| + */ + if (!BN_rshift(a,m,recp->num_bits)) goto err; + if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err; + if (!BN_rshift(d,b,i-recp->num_bits)) 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_cmp(r,m) >= 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_sub(r,r,m)) 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: - ctx->tos-=4; + BN_CTX_end(ctx); return(ret); - } + } -int BN_reciprocal(r, m,ctx) -BIGNUM *r; -BIGNUM *m; -BN_CTX *ctx; +/* 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. + */ +/* r := 2^len / m */ +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) { - int nm,ret= -1; - BIGNUM *t; + int ret= -1; + BIGNUM t; - t=ctx->bn[ctx->tos++]; + BN_init(&t); - nm=BN_num_bits(m); - if (!BN_lshift(t,BN_value_one(),nm*2)) goto err; + if (!BN_zero(&t)) goto err; + if (!BN_set_bit(&t,len)) goto err; - if (!BN_div(r,NULL,t,m,ctx)) goto err; - ret=nm; + if (!BN_div(r,NULL,&t,m,ctx)) goto err; + + ret=len; err: - ctx->tos--; + BN_free(&t); return(ret); } - diff --git a/src/lib/libcrypto/bn/bn_shift.c b/src/lib/libcrypto/bn/bn_shift.c index 944bf1794b..70f785ea18 100644 --- a/src/lib/libcrypto/bn/bn_shift.c +++ b/src/lib/libcrypto/bn/bn_shift.c @@ -60,9 +60,7 @@ #include "cryptlib.h" #include "bn_lcl.h" -int BN_lshift1(r, a) -BIGNUM *r; -BIGNUM *a; +int BN_lshift1(BIGNUM *r, const BIGNUM *a) { register BN_ULONG *ap,*rp,t,c; int i; @@ -94,9 +92,7 @@ BIGNUM *a; return(1); } -int BN_rshift1(r, a) -BIGNUM *r; -BIGNUM *a; +int BN_rshift1(BIGNUM *r, const BIGNUM *a) { BN_ULONG *ap,*rp,t,c; int i; @@ -125,18 +121,15 @@ BIGNUM *a; return(1); } -int BN_lshift(r, a, n) -BIGNUM *r; -BIGNUM *a; -int n; +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; + if (bn_wexpand(r,a->top+nw+1) == NULL) return(0); lb=n%BN_BITS2; rb=BN_BITS2-lb; f=a->d; @@ -160,10 +153,7 @@ int n; return(1); } -int BN_rshift(r, a, n) -BIGNUM *r; -BIGNUM *a; -int n; +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) { int i,j,nw,lb,rb; BN_ULONG *t,*f; @@ -172,7 +162,7 @@ int n; nw=n/BN_BITS2; rb=n%BN_BITS2; lb=BN_BITS2-rb; - if (nw > a->top) + if (nw > a->top || a->top == 0) { BN_zero(r); return(1); @@ -182,6 +172,11 @@ int n; r->neg=a->neg; if (bn_wexpand(r,a->top-nw+1) == NULL) return(0); } + else + { + if (n == 0) + return 1; /* or the copying loop will go berserk */ + } f= &(a->d[nw]); t=r->d; diff --git a/src/lib/libcrypto/bn/bn_sqr.c b/src/lib/libcrypto/bn/bn_sqr.c index a8464610e5..c1d0cca438 100644 --- a/src/lib/libcrypto/bn/bn_sqr.c +++ b/src/lib/libcrypto/bn/bn_sqr.c @@ -62,35 +62,105 @@ /* 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(r, a, ctx) -BIGNUM *r; -BIGNUM *a; -BN_CTX *ctx; +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { - int i,j,max,al; - BIGNUM *tmp; - BN_ULONG *ap,*rp; + int max,al; + int ret = 0; + BIGNUM *tmp,*rr; - tmp=ctx->bn[ctx->tos]; +#ifdef BN_COUNT + fprintf(stderr,"BN_sqr %d * %d\n",a->top,a->top); +#endif + bn_check_top(a); al=a->top; - if (al == 0) + if (al <= 0) { r->top=0; return(1); } - max=(al*2); - if (bn_wexpand(r,1+max) == NULL) return(0); - if (bn_wexpand(tmp,1+max) == NULL) return(0); + BN_CTX_start(ctx); + rr=(a != r) ? r : BN_CTX_get(ctx); + tmp=BN_CTX_get(ctx); + if (tmp == NULL) goto err; - r->neg=0; + max=(al+al); + if (bn_wexpand(rr,max+1) == NULL) goto err; - ap=a->d; - rp=r->d; + 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(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; + rr->neg=0; + 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, const BN_ULONG *a, int n, BN_ULONG *tmp) + { + int i,j,max; + const BN_ULONG *ap; + BN_ULONG *rp; + + max=n*2; + ap=a; + rp=r; rp[0]=rp[max-1]=0; rp++; - j=al; + j=n; if (--j > 0) { @@ -99,7 +169,7 @@ BN_CTX *ctx; rp+=2; } - for (i=2; i0; i--) { j--; ap++; @@ -107,16 +177,112 @@ BN_CTX *ctx; rp+=2; } - bn_add_words(r->d,r->d,r->d,max); + bn_add_words(r,r,r,max); /* There will not be a carry */ - bn_sqr_words(tmp->d,a->d,al); + bn_sqr_words(tmp,a,n); - bn_add_words(r->d,r->d,tmp->d,max); - - r->top=max; - if (r->d[max-1] == 0) r->top--; - return(1); + 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. (There's not actually a 'b' here ...) + * 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, const BN_ULONG *a, int n2, BN_ULONG *t) + { + int n=n2/2; + int zero,c1; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT + fprintf(stderr," 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,n2*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/src/lib/libcrypto/bn/bn_word.c b/src/lib/libcrypto/bn/bn_word.c index 4b3d0f011d..cd59baa2c4 100644 --- a/src/lib/libcrypto/bn/bn_word.c +++ b/src/lib/libcrypto/bn/bn_word.c @@ -60,9 +60,7 @@ #include "cryptlib.h" #include "bn_lcl.h" -BN_ULONG BN_mod_word(a, w) -BIGNUM *a; -unsigned long w; +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) { #ifndef BN_LLONG BN_ULONG ret=0; @@ -75,8 +73,8 @@ unsigned long w; for (i=a->top-1; i>=0; i--) { #ifndef BN_LLONG - ret=((ret<d[i]>>BN_BITS4)&BN_MASK2l))%(unsigned long)w; - ret=((ret<d[i]&BN_MASK2l))%(unsigned long)w; + 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); @@ -85,9 +83,7 @@ unsigned long w; return((BN_ULONG)ret); } -BN_ULONG BN_div_word(a, w) -BIGNUM *a; -unsigned long w; +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) { BN_ULONG ret; int i; @@ -100,18 +96,16 @@ unsigned long w; BN_ULONG l,d; l=a->d[i]; - d=bn_div64(ret,l,w); + d=bn_div_words(ret,l,w); ret=(l-((d*w)&BN_MASK2))&BN_MASK2; a->d[i]=d; } - if (a->d[a->top-1] == 0) + if ((a->top > 0) && (a->d[a->top-1] == 0)) a->top--; return(ret); } -int BN_add_word(a, w) -BIGNUM *a; -unsigned long w; +int BN_add_word(BIGNUM *a, BN_ULONG w) { BN_ULONG l; int i; @@ -121,7 +115,7 @@ unsigned long w; a->neg=0; i=BN_sub_word(a,w); if (!BN_is_zero(a)) - a->neg=1; + a->neg=!(a->neg); return(i); } w&=BN_MASK2; @@ -142,13 +136,11 @@ unsigned long w; return(1); } -int BN_sub_word(a, w) -BIGNUM *a; -unsigned long w; +int BN_sub_word(BIGNUM *a, BN_ULONG w) { int i; - if (a->neg) + if (BN_is_zero(a) || a->neg) { a->neg=0; i=BN_add_word(a,w); @@ -183,22 +175,25 @@ unsigned long w; return(1); } -int BN_mul_word(a,w) -BIGNUM *a; -unsigned long w; +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 (w == 0) + BN_zero(a); + else { - if (bn_wexpand(a,a->top+1) == NULL) return(0); - a->d[a->top++]=ll; + 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(0); + return(1); } diff --git a/src/lib/libcrypto/buffer/buf_err.c b/src/lib/libcrypto/buffer/buf_err.c index ff988852cc..5eee653e14 100644 --- a/src/lib/libcrypto/buffer/buf_err.c +++ b/src/lib/libcrypto/buffer/buf_err.c @@ -1,86 +1,94 @@ -/* lib/buf/buf_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/buffer/buf_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "buffer.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_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"}, -{ERR_PACK(0,BUF_F_PXYCLNT_READ,0), "PXYCLNT_READ"}, -{0,NULL}, +{0,NULL} + }; + +static ERR_STRING_DATA BUF_str_reasons[]= + { +{0,NULL} }; #endif -void ERR_load_BUF_strings() +void ERR_load_BUF_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_BUF,BUF_str_functs); + ERR_load_strings(ERR_LIB_BUF,BUF_str_reasons); #endif } diff --git a/src/lib/libcrypto/buffer/buffer.c b/src/lib/libcrypto/buffer/buffer.c index 7e8af9e2fa..9299baba9e 100644 --- a/src/lib/libcrypto/buffer/buffer.c +++ b/src/lib/libcrypto/buffer/buffer.c @@ -58,13 +58,13 @@ #include #include "cryptlib.h" -#include "buffer.h" +#include -BUF_MEM *BUF_MEM_new() +BUF_MEM *BUF_MEM_new(void) { BUF_MEM *ret; - ret=(BUF_MEM *)Malloc(sizeof(BUF_MEM)); + ret=OPENSSL_malloc(sizeof(BUF_MEM)); if (ret == NULL) { BUFerr(BUF_F_BUF_MEM_NEW,ERR_R_MALLOC_FAILURE); @@ -76,20 +76,20 @@ BUF_MEM *BUF_MEM_new() return(ret); } -void BUF_MEM_free(a) -BUF_MEM *a; +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); + OPENSSL_free(a->data); } - Free(a); + OPENSSL_free(a); } -int BUF_MEM_grow(str, len) -BUF_MEM *str; -int len; +int BUF_MEM_grow(BUF_MEM *str, int len) { char *ret; unsigned int n; @@ -101,15 +101,15 @@ int len; } if (str->max >= len) { - memset(&(str->data[str->length]),0,len-str->length); + memset(&str->data[str->length],0,len-str->length); str->length=len; return(len); } n=(len+3)/3*4; if (str->data == NULL) - ret=(char *)Malloc(n); + ret=OPENSSL_malloc(n); else - ret=(char *)Realloc(str->data,n); + ret=OPENSSL_realloc(str->data,n); if (ret == NULL) { BUFerr(BUF_F_BUF_MEM_GROW,ERR_R_MALLOC_FAILURE); @@ -118,14 +118,14 @@ int len; else { str->data=ret; - str->length=len; str->max=n; + memset(&str->data[str->length],0,len-str->length); + str->length=len; } return(len); } -char *BUF_strdup(str) -char *str; +char *BUF_strdup(const char *str) { char *ret; int n; @@ -133,7 +133,7 @@ char *str; if (str == NULL) return(NULL); n=strlen(str); - ret=Malloc(n+1); + ret=OPENSSL_malloc(n+1); if (ret == NULL) { BUFerr(BUF_F_BUF_STRDUP,ERR_R_MALLOC_FAILURE); diff --git a/src/lib/libcrypto/buffer/buffer.h b/src/lib/libcrypto/buffer/buffer.h index 417548c04a..11e2d0359a 100644 --- a/src/lib/libcrypto/buffer/buffer.h +++ b/src/lib/libcrypto/buffer/buffer.h @@ -70,38 +70,27 @@ typedef struct buf_mem_st int max; /* size of buffer */ } BUF_MEM; -#ifndef NOPROTO 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(char *str); - -void ERR_load_BUF_strings(void ); - -#else - -BUF_MEM *BUF_MEM_new(); -void BUF_MEM_free(); -int BUF_MEM_grow(); -char * BUF_strdup(); - -void ERR_load_BUF_strings(); - -#endif +char * BUF_strdup(const char *str); /* 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. + */ +void ERR_load_BUF_strings(void); + /* 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 -#define BUF_F_PXYCLNT_READ 103 /* Reason codes. */ - + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/cast/asm/cast-586.pl b/src/lib/libcrypto/cast/asm/cast-586.pl index d0be004c99..6be0bfe572 100644 --- a/src/lib/libcrypto/cast/asm/cast-586.pl +++ b/src/lib/libcrypto/cast/asm/cast-586.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # define for pentium pro friendly version $ppro=1; @@ -7,7 +7,7 @@ push(@INC,"perlasm","../../perlasm"); require "x86asm.pl"; require "cbc.pl"; -&asm_init($ARGV[0],"cast-586.pl"); +&asm_init($ARGV[0],"cast-586.pl",$ARGV[$#ARGV] eq "386"); $CAST_ROUNDS=16; $L="edi"; @@ -32,136 +32,145 @@ $S4="CAST_S_table3"; &asm_finish(); -sub CAST_encrypt - { - local($name,$enc)=@_; +sub CAST_encrypt { + local($name,$enc)=@_; - local($win_ex)=<<"EOF"; + local($win_ex)=<<"EOF"; EXTERN _CAST_S_table0:DWORD EXTERN _CAST_S_table1:DWORD EXTERN _CAST_S_table2:DWORD EXTERN _CAST_S_table3:DWORD EOF - &main'external_label( - "CAST_S_table0", - "CAST_S_table1", - "CAST_S_table2", - "CAST_S_table3", - ); - - &function_begin_B($name,$win_ex); - - &comment(""); - - &push("ebp"); - &push("ebx"); - &mov($tmp2,&wparam(0)); - &mov($K,&wparam(1)); - &push("esi"); - &push("edi"); - - &comment("Load the 2 words"); - &mov($L,&DWP(0,$tmp2,"",0)); - &mov($R,&DWP(4,$tmp2,"",0)); - - &xor( $tmp3, $tmp3); - - # encrypting part - - if ($enc) - { - &E_CAST( 0,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 1,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 2,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 3,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 4,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 5,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 6,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 7,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 8,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 9,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(10,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(11,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(12,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(13,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(14,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(15,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4,1); - } - else - { - &E_CAST(15,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(14,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(13,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(12,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(11,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST(10,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 9,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 8,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 7,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 6,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 5,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 4,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 3,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 2,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 1,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); - &E_CAST( 0,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4,1); - } - - &nop(); - &mov(&DWP(4,$tmp3,"",0),$L); - &mov(&DWP(0,$tmp3,"",0),$R); - &function_end($name); - } - -sub E_CAST - { - local($i,$S,$L,$R,$K,$OP1,$OP2,$OP3,$tmp1,$tmp2,$tmp3,$tmp4,$lst)=@_; - # Ri needs to have 16 pre added. - - &comment("round $i"); - &mov( $tmp4, &DWP($i*8,$K,"",1)); - - &mov( $tmp1, &DWP($i*8+4,$K,"",1));# must be word - &$OP1( $tmp4, $R); - - &rotl( $tmp4, &LB($tmp1)); - - if ($ppro) - { - &mov( $tmp2, $tmp4); # B - &xor( $tmp1, $tmp1); - - &movb( &LB($tmp1), &HB($tmp4)); # A - &and( $tmp2, 0xff); - - &shr( $tmp4, 16); # - &xor( $tmp3, $tmp3); - } - else - { - &mov( $tmp2, $tmp4); # B - &movb( &LB($tmp1), &HB($tmp4)); # A # BAD BAD BAD - - &shr( $tmp4, 16); # - &and( $tmp2, 0xff); - } - - &movb( &LB($tmp3), &HB($tmp4)); # C # BAD BAD BAD - &and( $tmp4, 0xff); # D - - &mov( $tmp1, &DWP($S1,"",$tmp1,4)); - &mov( $tmp2, &DWP($S2,"",$tmp2,4)); - - &$OP2( $tmp1, $tmp2); - &mov( $tmp2, &DWP($S3,"",$tmp3,4)); - - &$OP3( $tmp1, $tmp2); - &mov( $tmp2, &DWP($S4,"",$tmp4,4)); - - &$OP1( $tmp1, $tmp2); - &mov($tmp3,&wparam(0)) if $lst; - # XXX - - &xor( $L, $tmp1); - # XXX - } + &main::external_label( + "CAST_S_table0", + "CAST_S_table1", + "CAST_S_table2", + "CAST_S_table3", + ); + + &function_begin_B($name,$win_ex); + + &comment(""); + + &push("ebp"); + &push("ebx"); + &mov($tmp2,&wparam(0)); + &mov($K,&wparam(1)); + &push("esi"); + &push("edi"); + + &comment("Load the 2 words"); + &mov($L,&DWP(0,$tmp2,"",0)); + &mov($R,&DWP(4,$tmp2,"",0)); + + &comment('Get short key flag'); + &mov($tmp3,&DWP(128,$K,"",0)); + if($enc) { + &push($tmp3); + } else { + &or($tmp3,$tmp3); + &jnz(&label('cast_dec_skip')); + } + + &xor($tmp3, $tmp3); + + # encrypting part + + if ($enc) { + &E_CAST( 0,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 1,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 2,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 3,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 4,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 5,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 6,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 7,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 8,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 9,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(10,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(11,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &comment('test short key flag'); + &pop($tmp4); + &or($tmp4,$tmp4); + &jnz(&label('cast_enc_done')); + &E_CAST(12,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(13,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(14,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(15,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + } else { + &E_CAST(15,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(14,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(13,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(12,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &set_label('cast_dec_skip'); + &E_CAST(11,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST(10,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 9,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 8,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 7,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 6,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 5,$S,$L,$R,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 4,$S,$R,$L,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 3,$S,$L,$R,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 2,$S,$R,$L,$K,@F3,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 1,$S,$L,$R,$K,@F2,$tmp1,$tmp2,$tmp3,$tmp4); + &E_CAST( 0,$S,$R,$L,$K,@F1,$tmp1,$tmp2,$tmp3,$tmp4); + } + + &set_label('cast_enc_done') if $enc; +# Why the nop? - Ben 17/1/99 + &nop(); + &mov($tmp3,&wparam(0)); + &mov(&DWP(4,$tmp3,"",0),$L); + &mov(&DWP(0,$tmp3,"",0),$R); + &function_end($name); +} + +sub E_CAST { + local($i,$S,$L,$R,$K,$OP1,$OP2,$OP3,$tmp1,$tmp2,$tmp3,$tmp4)=@_; + # Ri needs to have 16 pre added. + + &comment("round $i"); + &mov( $tmp4, &DWP($i*8,$K,"",1)); + + &mov( $tmp1, &DWP($i*8+4,$K,"",1)); + &$OP1( $tmp4, $R); + + &rotl( $tmp4, &LB($tmp1)); + + if ($ppro) { + &mov( $tmp2, $tmp4); # B + &xor( $tmp1, $tmp1); + + &movb( &LB($tmp1), &HB($tmp4)); # A + &and( $tmp2, 0xff); + + &shr( $tmp4, 16); # + &xor( $tmp3, $tmp3); + } else { + &mov( $tmp2, $tmp4); # B + &movb( &LB($tmp1), &HB($tmp4)); # A # BAD BAD BAD + + &shr( $tmp4, 16); # + &and( $tmp2, 0xff); + } + + &movb( &LB($tmp3), &HB($tmp4)); # C # BAD BAD BAD + &and( $tmp4, 0xff); # D + + &mov( $tmp1, &DWP($S1,"",$tmp1,4)); + &mov( $tmp2, &DWP($S2,"",$tmp2,4)); + + &$OP2( $tmp1, $tmp2); + &mov( $tmp2, &DWP($S3,"",$tmp3,4)); + + &$OP3( $tmp1, $tmp2); + &mov( $tmp2, &DWP($S4,"",$tmp4,4)); + + &$OP1( $tmp1, $tmp2); + # XXX + + &xor( $L, $tmp1); + # XXX +} + diff --git a/src/lib/libcrypto/cast/c_cfb64.c b/src/lib/libcrypto/cast/c_cfb64.c index c46c375f75..514c005c32 100644 --- a/src/lib/libcrypto/cast/c_cfb64.c +++ b/src/lib/libcrypto/cast/c_cfb64.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -#include "cast.h" +#include #include "cast_lcl.h" /* The input and output encrypted as though 64bit cfb mode is being @@ -64,14 +64,9 @@ * 64bit block we have used is contained in *num; */ -void CAST_cfb64_encrypt(in, out, length, schedule, ivec, num, encrypt) -unsigned char *in; -unsigned char *out; -long length; -CAST_KEY *schedule; -unsigned char *ivec; -int *num; -int encrypt; +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, CAST_KEY *schedule, unsigned char *ivec, + int *num, int enc) { register CAST_LONG v0,v1,t; register int n= *num; @@ -79,8 +74,8 @@ int encrypt; CAST_LONG ti[2]; unsigned char *iv,c,cc; - iv=(unsigned char *)ivec; - if (encrypt) + iv=ivec; + if (enc) { while (l--) { @@ -89,10 +84,10 @@ int encrypt; n2l(iv,v0); ti[0]=v0; n2l(iv,v1); ti[1]=v1; CAST_encrypt((CAST_LONG *)ti,schedule); - iv=(unsigned char *)ivec; + iv=ivec; t=ti[0]; l2n(t,iv); t=ti[1]; l2n(t,iv); - iv=(unsigned char *)ivec; + iv=ivec; } c= *(in++)^iv[n]; *(out++)=c; @@ -109,10 +104,10 @@ int encrypt; n2l(iv,v0); ti[0]=v0; n2l(iv,v1); ti[1]=v1; CAST_encrypt((CAST_LONG *)ti,schedule); - iv=(unsigned char *)ivec; + iv=ivec; t=ti[0]; l2n(t,iv); t=ti[1]; l2n(t,iv); - iv=(unsigned char *)ivec; + iv=ivec; } cc= *(in++); c=iv[n]; diff --git a/src/lib/libcrypto/cast/c_ecb.c b/src/lib/libcrypto/cast/c_ecb.c index f0f2f4df0e..0b3da9ad87 100644 --- a/src/lib/libcrypto/cast/c_ecb.c +++ b/src/lib/libcrypto/cast/c_ecb.c @@ -56,22 +56,20 @@ * [including the GNU Public Licence.] */ -#include "cast.h" +#include #include "cast_lcl.h" +#include -char *CAST_version="CAST part of SSLeay 0.9.0b 29-Jun-1998"; +const char *CAST_version="CAST" OPENSSL_VERSION_PTEXT; -void CAST_ecb_encrypt(in, out, ks, encrypt) -unsigned char *in; -unsigned char *out; -CAST_KEY *ks; -int encrypt; +void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, + CAST_KEY *ks, int enc) { CAST_LONG l,d[2]; n2l(in,l); d[0]=l; n2l(in,l); d[1]=l; - if (encrypt) + if (enc) CAST_encrypt(d,ks); else CAST_decrypt(d,ks); diff --git a/src/lib/libcrypto/cast/c_enc.c b/src/lib/libcrypto/cast/c_enc.c index d998dd4953..0fe2cffecc 100644 --- a/src/lib/libcrypto/cast/c_enc.c +++ b/src/lib/libcrypto/cast/c_enc.c @@ -56,12 +56,10 @@ * [including the GNU Public Licence.] */ -#include "cast.h" +#include #include "cast_lcl.h" -void CAST_encrypt(data,key) -CAST_LONG *data; -CAST_KEY *key; +void CAST_encrypt(CAST_LONG *data, CAST_KEY *key) { register CAST_LONG l,r,*k,t; @@ -81,18 +79,19 @@ CAST_KEY *key; E_CAST( 9,k,r,l,+,^,-); E_CAST(10,k,l,r,^,-,+); E_CAST(11,k,r,l,-,+,^); - E_CAST(12,k,l,r,+,^,-); - E_CAST(13,k,r,l,^,-,+); - E_CAST(14,k,l,r,-,+,^); - E_CAST(15,k,r,l,+,^,-); + if(!key->short_key) + { + E_CAST(12,k,l,r,+,^,-); + E_CAST(13,k,r,l,^,-,+); + E_CAST(14,k,l,r,-,+,^); + E_CAST(15,k,r,l,+,^,-); + } data[1]=l&0xffffffffL; data[0]=r&0xffffffffL; } -void CAST_decrypt(data,key) -CAST_LONG *data; -CAST_KEY *key; +void CAST_decrypt(CAST_LONG *data, CAST_KEY *key) { register CAST_LONG l,r,*k,t; @@ -100,10 +99,13 @@ CAST_KEY *key; l=data[0]; r=data[1]; - E_CAST(15,k,l,r,+,^,-); - E_CAST(14,k,r,l,-,+,^); - E_CAST(13,k,l,r,^,-,+); - E_CAST(12,k,r,l,+,^,-); + if(!key->short_key) + { + E_CAST(15,k,l,r,+,^,-); + E_CAST(14,k,r,l,-,+,^); + E_CAST(13,k,l,r,^,-,+); + E_CAST(12,k,r,l,+,^,-); + } E_CAST(11,k,l,r,-,+,^); E_CAST(10,k,r,l,^,-,+); E_CAST( 9,k,l,r,+,^,-); @@ -121,20 +123,15 @@ CAST_KEY *key; data[0]=r&0xffffffffL; } -void CAST_cbc_encrypt(in, out, length, ks, iv, encrypt) -unsigned char *in; -unsigned char *out; -long length; -CAST_KEY *ks; -unsigned char *iv; -int encrypt; +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + CAST_KEY *ks, unsigned char *iv, int enc) { register CAST_LONG tin0,tin1; register CAST_LONG tout0,tout1,xor0,xor1; register long l=length; CAST_LONG tin[2]; - if (encrypt) + if (enc) { n2l(iv,tout0); n2l(iv,tout1); diff --git a/src/lib/libcrypto/cast/c_ofb64.c b/src/lib/libcrypto/cast/c_ofb64.c index 2aad2d6d96..fd0469a62f 100644 --- a/src/lib/libcrypto/cast/c_ofb64.c +++ b/src/lib/libcrypto/cast/c_ofb64.c @@ -56,20 +56,16 @@ * [including the GNU Public Licence.] */ -#include "cast.h" +#include #include "cast_lcl.h" /* The input and output encrypted as though 64bit ofb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ -void CAST_ofb64_encrypt(in, out, length, schedule, ivec, num) -unsigned char *in; -unsigned char *out; -long length; -CAST_KEY *schedule; -unsigned char *ivec; -int *num; +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, CAST_KEY *schedule, unsigned char *ivec, + int *num) { register CAST_LONG v0,v1,t; register int n= *num; @@ -80,7 +76,7 @@ int *num; unsigned char *iv; int save=0; - iv=(unsigned char *)ivec; + iv=ivec; n2l(iv,v0); n2l(iv,v1); ti[0]=v0; @@ -105,7 +101,7 @@ int *num; { v0=ti[0]; v1=ti[1]; - iv=(unsigned char *)ivec; + iv=ivec; l2n(v0,iv); l2n(v1,iv); } diff --git a/src/lib/libcrypto/cast/c_skey.c b/src/lib/libcrypto/cast/c_skey.c index 2fc3363dcd..76e40005c9 100644 --- a/src/lib/libcrypto/cast/c_skey.c +++ b/src/lib/libcrypto/cast/c_skey.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -#include "cast.h" +#include #include "cast_lcl.h" #include "cast_s.h" @@ -72,10 +72,7 @@ #define S6 CAST_S_table6 #define S7 CAST_S_table7 -void CAST_set_key(key,len,data) -CAST_KEY *key; -int len; -unsigned char *data; +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data) { CAST_LONG x[16]; CAST_LONG z[16]; @@ -88,6 +85,10 @@ unsigned char *data; if (len > 16) len=16; for (i=0; ishort_key=1; + else + key->short_key=0; K= &k[0]; X[0]=((x[ 0]<<24)|(x[ 1]<<16)|(x[ 2]<<8)|x[ 3])&0xffffffffL; diff --git a/src/lib/libcrypto/cast/cast.h b/src/lib/libcrypto/cast/cast.h index 528cb7c824..b28e4e4f3b 100644 --- a/src/lib/libcrypto/cast/cast.h +++ b/src/lib/libcrypto/cast/cast.h @@ -63,6 +63,10 @@ extern "C" { #endif +#ifdef OPENSSL_NO_CAST +#error CAST is disabled. +#endif + #define CAST_ENCRYPT 1 #define CAST_DECRYPT 0 @@ -74,33 +78,23 @@ extern "C" { typedef struct cast_key_st { CAST_LONG data[32]; + int short_key; /* Use reduced rounds for short key */ } CAST_KEY; -#ifndef NOPROTO -void CAST_set_key(CAST_KEY *key, int len, unsigned char *data); -void CAST_ecb_encrypt(unsigned char *in,unsigned char *out,CAST_KEY *key, - int enc); +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(unsigned char *in, unsigned char *out, long length, - CAST_KEY *ks, unsigned char *iv, int enc); -void CAST_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, - CAST_KEY *schedule, unsigned char *ivec, int *num, int enc); -void CAST_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, - CAST_KEY *schedule, unsigned char *ivec, int *num); - -#else - -void CAST_set_key(); -void CAST_ecb_encrypt(); -void CAST_encrypt(); -void CAST_decrypt(); -void CAST_cbc_encrypt(); -void CAST_cfb64_encrypt(); -void CAST_ofb64_encrypt(); - -#endif +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 } diff --git a/src/lib/libcrypto/cast/cast_lcl.h b/src/lib/libcrypto/cast/cast_lcl.h index 6587952a96..37f41cc6a4 100644 --- a/src/lib/libcrypto/cast/cast_lcl.h +++ b/src/lib/libcrypto/cast/cast_lcl.h @@ -56,10 +56,19 @@ * [including the GNU Public Licence.] */ -#ifdef WIN32 + +#include "e_os.h" + +#ifdef OPENSSL_SYS_WIN32 #include #endif + +#ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + #undef c2l #define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ l|=((unsigned long)(*((c)++)))<< 8L, \ @@ -148,7 +157,7 @@ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff)) -#if defined(WIN32) +#if defined(OPENSSL_SYS_WIN32) && defined(_MSC_VER) #define ROTL(a,n) (_lrotl(a,n)) #else #define ROTL(a,n) ((((a)<<(n))&0xffffffffL)|((a)>>(32-(n)))) @@ -213,12 +222,11 @@ } #endif -extern CAST_LONG CAST_S_table0[256]; -extern CAST_LONG CAST_S_table1[256]; -extern CAST_LONG CAST_S_table2[256]; -extern CAST_LONG CAST_S_table3[256]; -extern CAST_LONG CAST_S_table4[256]; -extern CAST_LONG CAST_S_table5[256]; -extern CAST_LONG CAST_S_table6[256]; -extern CAST_LONG CAST_S_table7[256]; - +OPENSSL_EXTERN const CAST_LONG CAST_S_table0[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table1[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table2[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table3[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table4[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table5[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table6[256]; +OPENSSL_EXTERN const CAST_LONG CAST_S_table7[256]; diff --git a/src/lib/libcrypto/cast/cast_s.h b/src/lib/libcrypto/cast/cast_s.h index 8fe0152149..c483fd5e43 100644 --- a/src/lib/libcrypto/cast/cast_s.h +++ b/src/lib/libcrypto/cast/cast_s.h @@ -55,7 +55,7 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ -CAST_LONG CAST_S_table0[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table0[256]={ 0x30fb40d4,0x9fa0ff0b,0x6beccd2f,0x3f258c7a, 0x1e213f2f,0x9c004dd3,0x6003e540,0xcf9fc949, 0xbfd4af27,0x88bbbdb5,0xe2034090,0x98d09675, @@ -121,7 +121,7 @@ CAST_LONG CAST_S_table0[256]={ 0x1a69e783,0x02cc4843,0xa2f7c579,0x429ef47d, 0x427b169c,0x5ac9f049,0xdd8f0f00,0x5c8165bf, }; -CAST_LONG CAST_S_table1[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table1[256]={ 0x1f201094,0xef0ba75b,0x69e3cf7e,0x393f4380, 0xfe61cf7a,0xeec5207a,0x55889c94,0x72fc0651, 0xada7ef79,0x4e1d7235,0xd55a63ce,0xde0436ba, @@ -187,7 +187,7 @@ CAST_LONG CAST_S_table1[256]={ 0x43d79572,0x7e6dd07c,0x06dfdf1e,0x6c6cc4ef, 0x7160a539,0x73bfbe70,0x83877605,0x4523ecf1, }; -CAST_LONG CAST_S_table2[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table2[256]={ 0x8defc240,0x25fa5d9f,0xeb903dbf,0xe810c907, 0x47607fff,0x369fe44b,0x8c1fc644,0xaececa90, 0xbeb1f9bf,0xeefbcaea,0xe8cf1950,0x51df07ae, @@ -253,7 +253,7 @@ CAST_LONG CAST_S_table2[256]={ 0xf7baefd5,0x4142ed9c,0xa4315c11,0x83323ec5, 0xdfef4636,0xa133c501,0xe9d3531c,0xee353783, }; -CAST_LONG CAST_S_table3[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table3[256]={ 0x9db30420,0x1fb6e9de,0xa7be7bef,0xd273a298, 0x4a4f7bdb,0x64ad8c57,0x85510443,0xfa020ed1, 0x7e287aff,0xe60fb663,0x095f35a1,0x79ebf120, @@ -319,7 +319,7 @@ CAST_LONG CAST_S_table3[256]={ 0x7ae5290c,0x3cb9536b,0x851e20fe,0x9833557e, 0x13ecf0b0,0xd3ffb372,0x3f85c5c1,0x0aef7ed2, }; -CAST_LONG CAST_S_table4[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table4[256]={ 0x7ec90c04,0x2c6e74b9,0x9b0e66df,0xa6337911, 0xb86a7fff,0x1dd358f5,0x44dd9d44,0x1731167f, 0x08fbf1fa,0xe7f511cc,0xd2051b00,0x735aba00, @@ -385,7 +385,7 @@ CAST_LONG CAST_S_table4[256]={ 0xe822fe15,0x88570983,0x750e6249,0xda627e55, 0x5e76ffa8,0xb1534546,0x6d47de08,0xefe9e7d4, }; -CAST_LONG CAST_S_table5[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table5[256]={ 0xf6fa8f9d,0x2cac6ce1,0x4ca34867,0xe2337f7c, 0x95db08e7,0x016843b4,0xeced5cbc,0x325553ac, 0xbf9f0960,0xdfa1e2ed,0x83f0579d,0x63ed86b9, @@ -451,7 +451,7 @@ CAST_LONG CAST_S_table5[256]={ 0xa2d762cf,0x49c92f54,0x38b5f331,0x7128a454, 0x48392905,0xa65b1db8,0x851c97bd,0xd675cf2f, }; -CAST_LONG CAST_S_table6[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table6[256]={ 0x85e04019,0x332bf567,0x662dbfff,0xcfc65693, 0x2a8d7f6f,0xab9bc912,0xde6008a1,0x2028da1f, 0x0227bce7,0x4d642916,0x18fac300,0x50f18b82, @@ -517,7 +517,7 @@ CAST_LONG CAST_S_table6[256]={ 0x518f36b2,0x84b1d370,0x0fedce83,0x878ddada, 0xf2a279c7,0x94e01be8,0x90716f4b,0x954b8aa3, }; -CAST_LONG CAST_S_table7[256]={ +OPENSSL_GLOBAL const CAST_LONG CAST_S_table7[256]={ 0xe216300d,0xbbddfffc,0xa7ebdabd,0x35648095, 0x7789f8b7,0xe6c1121b,0x0e241600,0x052ce8b5, 0x11a9cfb0,0xe5952f11,0xece7990a,0x9386d174, diff --git a/src/lib/libcrypto/comp/c_rle.c b/src/lib/libcrypto/comp/c_rle.c index 1a819e3737..efd366fa22 100644 --- a/src/lib/libcrypto/comp/c_rle.c +++ b/src/lib/libcrypto/comp/c_rle.c @@ -17,6 +17,7 @@ static COMP_METHOD rle_method={ rle_compress_block, rle_expand_block, NULL, + NULL, }; COMP_METHOD *COMP_rle(void) diff --git a/src/lib/libcrypto/comp/c_zlib.c b/src/lib/libcrypto/comp/c_zlib.c index 6684ab4841..cd2f8a491b 100644 --- a/src/lib/libcrypto/comp/c_zlib.c +++ b/src/lib/libcrypto/comp/c_zlib.c @@ -6,11 +6,10 @@ COMP_METHOD *COMP_zlib(void ); -#ifndef ZLIB - -static COMP_METHOD zlib_method={ +static COMP_METHOD zlib_method_nozlib={ NID_undef, - "(null)", + "(undef)", + NULL, NULL, NULL, NULL, @@ -18,6 +17,8 @@ static COMP_METHOD zlib_method={ NULL, }; +#ifndef ZLIB +#undef ZLIB_SHARED #else #include @@ -38,8 +39,56 @@ static COMP_METHOD zlib_method={ zlib_compress_block, zlib_expand_block, NULL, + NULL, }; +/* + * When OpenSSL is built on Windows, we do not want to require that + * the ZLIB.DLL be available in order for the OpenSSL DLLs to + * work. Therefore, all ZLIB routines are loaded at run time + * and we do not link to a .LIB file. + */ +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +# include + +# define Z_CALLCONV _stdcall +# define ZLIB_SHARED +#else +# define Z_CALLCONV +#endif /* !(OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32) */ + +#ifdef ZLIB_SHARED +#include + +/* Prototypes for built in stubs */ +static int stub_compress(Bytef *dest,uLongf *destLen, + const Bytef *source, uLong sourceLen); +static int stub_inflateEnd(z_streamp strm); +static int stub_inflate(z_streamp strm, int flush); +static int stub_inflateInit_(z_streamp strm, const char * version, + int stream_size); + +/* Function pointers */ +typedef int (Z_CALLCONV *compress_ft)(Bytef *dest,uLongf *destLen, + const Bytef *source, uLong sourceLen); +typedef int (Z_CALLCONV *inflateEnd_ft)(z_streamp strm); +typedef int (Z_CALLCONV *inflate_ft)(z_streamp strm, int flush); +typedef int (Z_CALLCONV *inflateInit__ft)(z_streamp strm, + const char * version, int stream_size); +static compress_ft p_compress=NULL; +static inflateEnd_ft p_inflateEnd=NULL; +static inflate_ft p_inflate=NULL; +static inflateInit__ft p_inflateInit_=NULL; + +static int zlib_loaded = 0; /* only attempt to init func pts once */ +static DSO *zlib_dso = NULL; + +#define compress stub_compress +#define inflateEnd stub_inflateEnd +#define inflate stub_inflate +#define inflateInit_ stub_inflateInit_ +#endif /* ZLIB_SHARED */ + static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, unsigned int olen, unsigned char *in, unsigned int ilen) { @@ -66,7 +115,10 @@ static int zlib_compress_block(COMP_CTX *ctx, unsigned char *out, memcpy(&(out[1]),in,ilen); l=ilen+1; } -fprintf(stderr,"compress(%4d)->%4d %s\n",ilen,(int)l,(clear)?"clear":"zlib"); +#ifdef DEBUG_ZLIB + fprintf(stderr,"compress(%4d)->%4d %s\n", + ilen,(int)l,(clear)?"clear":"zlib"); +#endif return((int)l); } @@ -88,7 +140,10 @@ static int zlib_expand_block(COMP_CTX *ctx, unsigned char *out, memcpy(out,&(in[1]),ilen-1); l=ilen-1; } - fprintf(stderr,"expand (%4d)->%4d %s\n",ilen,(int)l,in[0]?"zlib":"clear"); +#ifdef DEBUG_ZLIB + fprintf(stderr,"expand (%4d)->%4d %s\n", + ilen,(int)l,in[0]?"zlib":"clear"); +#endif return((int)l); } @@ -128,6 +183,78 @@ static int zz_uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, COMP_METHOD *COMP_zlib(void) { - return(&zlib_method); + COMP_METHOD *meth = &zlib_method_nozlib; + +#ifdef ZLIB_SHARED + if (!zlib_loaded) + { +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) + zlib_dso = DSO_load(NULL, "ZLIB", NULL, 0); +#else + zlib_dso = DSO_load(NULL, "z", NULL, 0); +#endif + if (zlib_dso != NULL) + { + p_compress + = (compress_ft) DSO_bind_func(zlib_dso, + "compress"); + p_inflateEnd + = (inflateEnd_ft) DSO_bind_func(zlib_dso, + "inflateEnd"); + p_inflate + = (inflate_ft) DSO_bind_func(zlib_dso, + "inflate"); + p_inflateInit_ + = (inflateInit__ft) DSO_bind_func(zlib_dso, + "inflateInit_"); + zlib_loaded++; + meth = &zlib_method; + } + } + +#elif defined(ZLIB) + meth = &zlib_method; +#endif + + return(meth); + } + +#ifdef ZLIB_SHARED +/* Stubs for each function to be dynamicly loaded */ +static int +stub_compress(Bytef *dest,uLongf *destLen,const Bytef *source, uLong sourceLen) + { + if (p_compress) + return(p_compress(dest,destLen,source,sourceLen)); + else + return(Z_MEM_ERROR); + } + +static int +stub_inflateEnd(z_streamp strm) + { + if ( p_inflateEnd ) + return(p_inflateEnd(strm)); + else + return(Z_MEM_ERROR); + } + +static int +stub_inflate(z_streamp strm, int flush) + { + if ( p_inflate ) + return(p_inflate(strm,flush)); + else + return(Z_MEM_ERROR); + } + +static int +stub_inflateInit_(z_streamp strm, const char * version, int stream_size) + { + if ( p_inflateInit_ ) + return(p_inflateInit_(strm,version,stream_size)); + else + return(Z_MEM_ERROR); } +#endif /* ZLIB_SHARED */ diff --git a/src/lib/libcrypto/comp/comp.h b/src/lib/libcrypto/comp/comp.h index 93bd9c34c8..ab48b78ae9 100644 --- a/src/lib/libcrypto/comp/comp.h +++ b/src/lib/libcrypto/comp/comp.h @@ -2,12 +2,12 @@ #ifndef HEADER_COMP_H #define HEADER_COMP_H +#include + #ifdef __cplusplus extern "C" { #endif -#include - typedef struct comp_method_st { int type; /* NID for compression library */ @@ -17,6 +17,7 @@ typedef struct comp_method_st int (*compress)(); int (*expand)(); long (*ctrl)(); + long (*callback_ctrl)(); } COMP_METHOD; typedef struct comp_ctx_st @@ -38,14 +39,13 @@ int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, unsigned char *in, int ilen); COMP_METHOD *COMP_rle(void ); -#ifdef ZLIB COMP_METHOD *COMP_zlib(void ); -#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. */ +void ERR_load_COMP_strings(void); /* Error codes for the COMP functions. */ @@ -57,4 +57,3 @@ COMP_METHOD *COMP_zlib(void ); } #endif #endif - diff --git a/src/lib/libcrypto/comp/comp_err.c b/src/lib/libcrypto/comp/comp_err.c index 77a3f7070c..1652b8c2c4 100644 --- a/src/lib/libcrypto/comp/comp_err.c +++ b/src/lib/libcrypto/comp/comp_err.c @@ -54,7 +54,8 @@ */ /* 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. + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. */ #include @@ -62,7 +63,7 @@ #include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA COMP_str_functs[]= { {0,NULL} @@ -82,7 +83,7 @@ void ERR_load_COMP_strings(void) if (init) { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_COMP,COMP_str_functs); ERR_load_strings(ERR_LIB_COMP,COMP_str_reasons); #endif diff --git a/src/lib/libcrypto/comp/comp_lib.c b/src/lib/libcrypto/comp/comp_lib.c index a67ef23bc0..beb98ce8cc 100644 --- a/src/lib/libcrypto/comp/comp_lib.c +++ b/src/lib/libcrypto/comp/comp_lib.c @@ -8,7 +8,7 @@ COMP_CTX *COMP_CTX_new(COMP_METHOD *meth) { COMP_CTX *ret; - if ((ret=(COMP_CTX *)Malloc(sizeof(COMP_CTX))) == NULL) + if ((ret=(COMP_CTX *)OPENSSL_malloc(sizeof(COMP_CTX))) == NULL) { /* ZZZZZZZZZZZZZZZZ */ return(NULL); @@ -17,7 +17,7 @@ COMP_CTX *COMP_CTX_new(COMP_METHOD *meth) ret->meth=meth; if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { - Free(ret); + OPENSSL_free(ret); ret=NULL; } #if 0 @@ -37,7 +37,7 @@ void COMP_CTX_free(COMP_CTX *ctx) if (ctx->meth->finish != NULL) ctx->meth->finish(ctx); - Free(ctx); + OPENSSL_free(ctx); } int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, diff --git a/src/lib/libcrypto/conf/conf.h b/src/lib/libcrypto/conf/conf.h index 1446226a16..3c03fb19c0 100644 --- a/src/lib/libcrypto/conf/conf.h +++ b/src/lib/libcrypto/conf/conf.h @@ -59,13 +59,16 @@ #ifndef HEADER_CONF_H #define HEADER_CONF_H +#include +#include +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include "stack.h" -#include "lhash.h" - typedef struct { char *section; @@ -73,42 +76,173 @@ typedef struct char *value; } CONF_VALUE; -#ifndef NOPROTO +DECLARE_STACK_OF(CONF_VALUE) +DECLARE_STACK_OF(CONF_MODULE) +DECLARE_STACK_OF(CONF_IMODULE) + +struct conf_st; +typedef struct conf_st CONF; +struct conf_method_st; +typedef struct conf_method_st CONF_METHOD; + +struct conf_method_st + { + const char *name; + CONF *(*create)(CONF_METHOD *meth); + int (*init)(CONF *conf); + int (*destroy)(CONF *conf); + int (*destroy_data)(CONF *conf); + int (*load_bio)(CONF *conf, BIO *bp, long *eline); + int (*dump)(const CONF *conf, BIO *bp); + int (*is_number)(const CONF *conf, char c); + int (*to_int)(const CONF *conf, char c); + int (*load)(CONF *conf, const char *name, long *eline); + }; + +/* Module definitions */ + +typedef struct conf_imodule_st CONF_IMODULE; +typedef struct conf_module_st CONF_MODULE; -LHASH *CONF_load(LHASH *conf,char *file,long *eline); -STACK *CONF_get_section(LHASH *conf,char *section); -char *CONF_get_string(LHASH *conf,char *group,char *name); -long CONF_get_number(LHASH *conf,char *group,char *name); +/* DSO module function typedefs */ +typedef int conf_init_func(CONF_IMODULE *md, const CONF *cnf); +typedef void conf_finish_func(CONF_IMODULE *md); + +#define CONF_MFLAGS_IGNORE_ERRORS 0x1 +#define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2 +#define CONF_MFLAGS_SILENT 0x4 +#define CONF_MFLAGS_NO_DSO 0x8 +#define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 + +int CONF_set_default_method(CONF_METHOD *meth); +void CONF_set_nconf(CONF *conf,LHASH *hash); +LHASH *CONF_load(LHASH *conf,const char *file,long *eline); +#ifndef OPENSSL_NO_FP_API +LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline); +#endif +LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline); +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section); +char *CONF_get_string(LHASH *conf,const char *group,const char *name); +long CONF_get_number(LHASH *conf,const char *group,const char *name); void CONF_free(LHASH *conf); -void ERR_load_CONF_strings(void ); +int CONF_dump_fp(LHASH *conf, FILE *out); +int CONF_dump_bio(LHASH *conf, BIO *out); -#else +void OPENSSL_config(const char *config_name); -LHASH *CONF_load(); -STACK *CONF_get_section(); -char *CONF_get_string(); -long CONF_get_number(); -void CONF_free(); -void ERR_load_CONF_strings(); +/* New conf code. The semantics are different from the functions above. + If that wasn't the case, the above functions would have been replaced */ +struct conf_st + { + CONF_METHOD *meth; + void *meth_data; + LHASH *data; + }; + +CONF *NCONF_new(CONF_METHOD *meth); +CONF_METHOD *NCONF_default(); +CONF_METHOD *NCONF_WIN32(); +#if 0 /* Just to give you an idea of what I have in mind */ +CONF_METHOD *NCONF_XML(); #endif +void NCONF_free(CONF *conf); +void NCONF_free_data(CONF *conf); + +int NCONF_load(CONF *conf,const char *file,long *eline); +#ifndef OPENSSL_NO_FP_API +int NCONF_load_fp(CONF *conf, FILE *fp,long *eline); +#endif +int NCONF_load_bio(CONF *conf, BIO *bp,long *eline); +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section); +char *NCONF_get_string(const CONF *conf,const char *group,const char *name); +int NCONF_get_number_e(const CONF *conf,const char *group,const char *name, + long *result); +int NCONF_dump_fp(const CONF *conf, FILE *out); +int NCONF_dump_bio(const CONF *conf, BIO *out); + +#if 0 /* The following function has no error checking, + and should therefore be avoided */ +long NCONF_get_number(CONF *conf,char *group,char *name); +#else +#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r) +#endif + +/* Module functions */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags); +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags); +void CONF_modules_unload(int all); +void CONF_modules_finish(void); +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc); + +const char *CONF_imodule_get_name(const CONF_IMODULE *md); +const char *CONF_imodule_get_value(const CONF_IMODULE *md); +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md); +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data); +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md); +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md); +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags); +void *CONF_module_get_usr_data(CONF_MODULE *pmod); +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data); + +char *CONF_get1_default_config_file(void); + +int CONF_parse_list(const char *list, int sep, int nospc, + int (*list_cb)(const char *elem, int len, void *usr), void *arg); + +void OPENSSL_load_builtin_modules(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. + */ +void ERR_load_CONF_strings(void); + /* Error codes for the CONF functions. */ /* Function codes. */ +#define CONF_F_CONF_DUMP_FP 104 #define CONF_F_CONF_LOAD 100 +#define CONF_F_CONF_LOAD_BIO 102 +#define CONF_F_CONF_LOAD_FP 103 +#define CONF_F_CONF_MODULES_LOAD 116 +#define CONF_F_MODULE_INIT 115 +#define CONF_F_MODULE_LOAD_DSO 117 +#define CONF_F_MODULE_RUN 118 +#define CONF_F_NCONF_DUMP_BIO 105 +#define CONF_F_NCONF_DUMP_FP 106 +#define CONF_F_NCONF_GET_NUMBER 107 +#define CONF_F_NCONF_GET_NUMBER_E 112 +#define CONF_F_NCONF_GET_SECTION 108 +#define CONF_F_NCONF_GET_STRING 109 +#define CONF_F_NCONF_LOAD 113 +#define CONF_F_NCONF_LOAD_BIO 110 +#define CONF_F_NCONF_LOAD_FP 114 +#define CONF_F_NCONF_NEW 111 #define CONF_F_STR_COPY 101 /* Reason codes. */ +#define CONF_R_ERROR_LOADING_DSO 110 #define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100 #define CONF_R_MISSING_EQUAL_SIGN 101 +#define CONF_R_MISSING_FINISH_FUNCTION 111 +#define CONF_R_MISSING_INIT_FUNCTION 112 +#define CONF_R_MODULE_INITIALIZATION_ERROR 109 #define CONF_R_NO_CLOSE_BRACE 102 +#define CONF_R_NO_CONF 105 +#define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106 +#define CONF_R_NO_SECTION 107 +#define CONF_R_NO_SUCH_FILE 114 +#define CONF_R_NO_VALUE 108 #define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103 +#define CONF_R_UNKNOWN_MODULE_NAME 113 #define CONF_R_VARIABLE_HAS_NO_VALUE 104 - + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/conf/conf_api.c b/src/lib/libcrypto/conf/conf_api.c index d05a778ff6..0032baa711 100644 --- a/src/lib/libcrypto/conf/conf_api.c +++ b/src/lib/libcrypto/conf/conf_api.c @@ -67,26 +67,34 @@ #include #include #include +#include "e_os.h" static void value_free_hash(CONF_VALUE *a, LHASH *conf); static void value_free_stack(CONF_VALUE *a,LHASH *conf); -static unsigned long hash(CONF_VALUE *v); -static int cmp_conf(CONF_VALUE *a,CONF_VALUE *b); +static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_hash, CONF_VALUE *, LHASH *) +static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_stack, CONF_VALUE *, LHASH *) +/* We don't use function pointer casting or wrapper functions - but cast each + * callback parameter inside the callback functions. */ +/* static unsigned long hash(CONF_VALUE *v); */ +static unsigned long hash(const void *v_void); +/* static int cmp_conf(CONF_VALUE *a,CONF_VALUE *b); */ +static int cmp_conf(const void *a_void,const void *b_void); /* Up until OpenSSL 0.9.5a, this was get_section */ -CONF_VALUE *_CONF_get_section(CONF *conf, char *section) +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section) { CONF_VALUE *v,vv; if ((conf == NULL) || (section == NULL)) return(NULL); vv.name=NULL; - vv.section=section; + vv.section=(char *)section; v=(CONF_VALUE *)lh_retrieve(conf->data,&vv); return(v); } /* Up until OpenSSL 0.9.5a, this was CONF_get_section */ -STACK_OF(CONF_VALUE) *_CONF_get_section_values(CONF *conf, char *section) +STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, + const char *section) { CONF_VALUE *v; @@ -121,7 +129,7 @@ int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value) return 1; } -char *_CONF_get_string(CONF *conf, char *section, char *name) +char *_CONF_get_string(const CONF *conf, const char *section, const char *name) { CONF_VALUE *v,vv; char *p; @@ -131,8 +139,8 @@ char *_CONF_get_string(CONF *conf, char *section, char *name) { if (section != NULL) { - vv.name=name; - vv.section=section; + vv.name=(char *)name; + vv.section=(char *)section; v=(CONF_VALUE *)lh_retrieve(conf->data,&vv); if (v != NULL) return(v->value); if (strcmp(section,"ENV") == 0) @@ -142,7 +150,7 @@ char *_CONF_get_string(CONF *conf, char *section, char *name) } } vv.section="default"; - vv.name=name; + vv.name=(char *)name; v=(CONF_VALUE *)lh_retrieve(conf->data,&vv); if (v != NULL) return(v->value); @@ -153,6 +161,9 @@ char *_CONF_get_string(CONF *conf, char *section, char *name) return(Getenv(name)); } +#if 0 /* There's no way to provide error checking with this function, so + force implementors of the higher levels to get a string and read + the number themselves. */ long _CONF_get_number(CONF *conf, char *section, char *name) { char *str; @@ -169,6 +180,7 @@ long _CONF_get_number(CONF *conf, char *section, char *name) str++; } } +#endif int _CONF_new_data(CONF *conf) { @@ -177,7 +189,7 @@ int _CONF_new_data(CONF *conf) return 0; } if (conf->data == NULL) - if ((conf->data = lh_new(hash,cmp_conf)) == NULL) + if ((conf->data = lh_new(hash, cmp_conf)) == NULL) { return 0; } @@ -190,12 +202,14 @@ void _CONF_free_data(CONF *conf) conf->data->down_load=0; /* evil thing to make sure the 'OPENSSL_free()' * works as expected */ - lh_doall_arg(conf->data,(void (*)())value_free_hash,conf->data); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_hash), + conf->data); /* We now have only 'section' entries in the hash table. * Due to problems with */ - lh_doall_arg(conf->data,(void (*)())value_free_stack,conf->data); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_stack), + conf->data); lh_free(conf->data); } @@ -228,14 +242,19 @@ static void value_free_stack(CONF_VALUE *a, LHASH *conf) OPENSSL_free(a); } -static unsigned long hash(CONF_VALUE *v) +/* static unsigned long hash(CONF_VALUE *v) */ +static unsigned long hash(const void *v_void) { + CONF_VALUE *v = (CONF_VALUE *)v_void; return((lh_strhash(v->section)<<2)^lh_strhash(v->name)); } -static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) +/* static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) */ +static int cmp_conf(const void *a_void,const void *b_void) { int i; + CONF_VALUE *a = (CONF_VALUE *)a_void; + CONF_VALUE *b = (CONF_VALUE *)b_void; if (a->section != b->section) { @@ -255,7 +274,7 @@ static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) } /* Up until OpenSSL 0.9.5a, this was new_section */ -CONF_VALUE *_CONF_new_section(CONF *conf, char *section) +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section) { STACK *sk=NULL; int ok=0,i; diff --git a/src/lib/libcrypto/conf/conf_api.h b/src/lib/libcrypto/conf/conf_api.h index a5cc17b233..87a954aff6 100644 --- a/src/lib/libcrypto/conf/conf_api.h +++ b/src/lib/libcrypto/conf/conf_api.h @@ -67,15 +67,17 @@ extern "C" { #endif /* Up until OpenSSL 0.9.5a, this was new_section */ -CONF_VALUE *_CONF_new_section(CONF *conf, char *section); +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section); /* Up until OpenSSL 0.9.5a, this was get_section */ -CONF_VALUE *_CONF_get_section(CONF *conf, char *section); +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section); /* Up until OpenSSL 0.9.5a, this was CONF_get_section */ -STACK_OF(CONF_VALUE) *_CONF_get_section_values(CONF *conf, char *section); +STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, + const char *section); int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value); -char *_CONF_get_string(CONF *conf, char *section, char *name); -long _CONF_get_number(CONF *conf, char *section, char *name); +char *_CONF_get_string(const CONF *conf, const char *section, + const char *name); +long _CONF_get_number(const CONF *conf, const char *section, const char *name); int _CONF_new_data(CONF *conf); void _CONF_free_data(CONF *conf); diff --git a/src/lib/libcrypto/conf/conf_def.c b/src/lib/libcrypto/conf/conf_def.c index 773df32c68..31f2766246 100644 --- a/src/lib/libcrypto/conf/conf_def.c +++ b/src/lib/libcrypto/conf/conf_def.c @@ -81,10 +81,11 @@ static int def_init_default(CONF *conf); static int def_init_WIN32(CONF *conf); static int def_destroy(CONF *conf); static int def_destroy_data(CONF *conf); -static int def_load(CONF *conf, BIO *bp, long *eline); -static int def_dump(CONF *conf, BIO *bp); -static int def_is_number(CONF *conf, char c); -static int def_to_int(CONF *conf, char c); +static int def_load(CONF *conf, const char *name, long *eline); +static int def_load_bio(CONF *conf, BIO *bp, long *eline); +static int def_dump(const CONF *conf, BIO *bp); +static int def_is_number(const CONF *conf, char c); +static int def_to_int(const CONF *conf, char c); const char *CONF_def_version="CONF_def" OPENSSL_VERSION_PTEXT; @@ -94,10 +95,11 @@ static CONF_METHOD default_method = { def_init_default, def_destroy, def_destroy_data, - def_load, + def_load_bio, def_dump, def_is_number, - def_to_int + def_to_int, + def_load }; static CONF_METHOD WIN32_method = { @@ -106,10 +108,11 @@ static CONF_METHOD WIN32_method = { def_init_WIN32, def_destroy, def_destroy_data, - def_load, + def_load_bio, def_dump, def_is_number, - def_to_int + def_to_int, + def_load }; CONF_METHOD *NCONF_default() @@ -177,7 +180,32 @@ static int def_destroy_data(CONF *conf) return 1; } -static int def_load(CONF *conf, BIO *in, long *line) +static int def_load(CONF *conf, const char *name, long *line) + { + int ret; + BIO *in=NULL; + +#ifdef OPENSSL_SYS_VMS + in=BIO_new_file(name, "r"); +#else + in=BIO_new_file(name, "rb"); +#endif + if (in == NULL) + { + if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE) + CONFerr(CONF_F_CONF_LOAD,CONF_R_NO_SUCH_FILE); + else + CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB); + return 0; + } + + ret = def_load_bio(conf, in, line); + BIO_free(in); + + return ret; + } + +static int def_load_bio(CONF *conf, BIO *in, long *line) { #define BUFSIZE 512 char btmp[16]; @@ -418,7 +446,11 @@ err: if (line != NULL) *line=eline; sprintf(btmp,"%ld",eline); ERR_add_error_data(2,"line ",btmp); - if ((h != conf->data) && (conf->data != NULL)) CONF_free(conf->data); + if ((h != conf->data) && (conf->data != NULL)) + { + CONF_free(conf->data); + conf->data=NULL; + } if (v != NULL) { if (v->name != NULL) OPENSSL_free(v->name); @@ -685,18 +717,20 @@ static void dump_value(CONF_VALUE *a, BIO *out) BIO_printf(out, "[[%s]]\n", a->section); } -static int def_dump(CONF *conf, BIO *out) +static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE *, BIO *) + +static int def_dump(const CONF *conf, BIO *out) { - lh_doall_arg(conf->data, (void (*)())dump_value, out); + lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value), out); return 1; } -static int def_is_number(CONF *conf, char c) +static int def_is_number(const CONF *conf, char c) { return IS_NUMBER(conf,c); } -static int def_to_int(CONF *conf, char c) +static int def_to_int(const CONF *conf, char c) { return c - '0'; } diff --git a/src/lib/libcrypto/conf/conf_def.h b/src/lib/libcrypto/conf/conf_def.h index 3244d9a331..92a7d8ad77 100644 --- a/src/lib/libcrypto/conf/conf_def.h +++ b/src/lib/libcrypto/conf/conf_def.h @@ -71,6 +71,7 @@ #define CONF_COMMENT 128 #define CONF_FCOMMENT 2048 #define CONF_EOF 8 +#define CONF_HIGHBIT 4096 #define CONF_ALPHA (CONF_UPPER|CONF_LOWER) #define CONF_ALPHA_NUMERIC (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) #define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \ @@ -78,68 +79,102 @@ #define KEYTYPES(c) ((unsigned short *)((c)->meth_data)) #ifndef CHARSET_EBCDIC -#define IS_COMMENT(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_COMMENT) -#define IS_FCOMMENT(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_FCOMMENT) -#define IS_EOF(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_EOF) -#define IS_ESC(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_ESC) -#define IS_NUMBER(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_NUMBER) -#define IS_WS(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_WS) -#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_ALPHA_NUMERIC) +#define IS_COMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC) #define IS_ALPHA_NUMERIC_PUNCT(c,a) \ - (KEYTYPES(c)[(a)&0x7f]&CONF_ALPHA_NUMERIC_PUNCT) -#define IS_QUOTE(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_QUOTE) -#define IS_DQUOTE(c,a) (KEYTYPES(c)[(a)&0x7f]&CONF_DQUOTE) + (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_DQUOTE) +#define IS_HIGHBIT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_HIGHBIT) #else /*CHARSET_EBCDIC*/ -#define IS_COMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_COMMENT) -#define IS_FCOMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_FCOMMENT) -#define IS_EOF(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_EOF) -#define IS_ESC(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_ESC) -#define IS_NUMBER(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_NUMBER) -#define IS_WS(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_WS) -#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_ALPHA_NUMERIC) +#define IS_COMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_ALPHA_NUMERIC) #define IS_ALPHA_NUMERIC_PUNCT(c,a) \ - (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_ALPHA_NUMERIC_PUNCT) -#define IS_QUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_QUOTE) -#define IS_DQUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0x7f]&CONF_DQUOTE) + (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_DQUOTE) +#define IS_HIGHBIT(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_HIGHBIT) #endif /*CHARSET_EBCDIC*/ -static unsigned short CONF_type_default[128]={ - 0x008,0x000,0x000,0x000,0x000,0x000,0x000,0x000, - 0x000,0x010,0x010,0x000,0x000,0x010,0x000,0x000, - 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, - 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, - 0x010,0x200,0x040,0x080,0x000,0x200,0x200,0x040, - 0x000,0x000,0x200,0x200,0x200,0x200,0x200,0x200, - 0x001,0x001,0x001,0x001,0x001,0x001,0x001,0x001, - 0x001,0x001,0x000,0x200,0x000,0x000,0x000,0x200, - 0x200,0x002,0x002,0x002,0x002,0x002,0x002,0x002, - 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, - 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, - 0x002,0x002,0x002,0x000,0x020,0x000,0x200,0x100, - 0x040,0x004,0x004,0x004,0x004,0x004,0x004,0x004, - 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, - 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, - 0x004,0x004,0x004,0x000,0x200,0x000,0x200,0x000, +static unsigned short CONF_type_default[256]={ + 0x0008,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0010,0x0010,0x0000,0x0000,0x0010,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0010,0x0200,0x0040,0x0080,0x0000,0x0200,0x0200,0x0040, + 0x0000,0x0000,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200, + 0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001, + 0x0001,0x0001,0x0000,0x0200,0x0000,0x0000,0x0000,0x0200, + 0x0200,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0000,0x0020,0x0000,0x0200,0x0100, + 0x0040,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0000,0x0200,0x0000,0x0200,0x0000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, }; -static unsigned short CONF_type_win32[128]={ - 0x008,0x000,0x000,0x000,0x000,0x000,0x000,0x000, - 0x000,0x010,0x010,0x000,0x000,0x010,0x000,0x000, - 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, - 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, - 0x010,0x200,0x400,0x000,0x000,0x200,0x200,0x000, - 0x000,0x000,0x200,0x200,0x200,0x200,0x200,0x200, - 0x001,0x001,0x001,0x001,0x001,0x001,0x001,0x001, - 0x001,0x001,0x000,0xA00,0x000,0x000,0x000,0x200, - 0x200,0x002,0x002,0x002,0x002,0x002,0x002,0x002, - 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, - 0x002,0x002,0x002,0x002,0x002,0x002,0x002,0x002, - 0x002,0x002,0x002,0x000,0x000,0x000,0x200,0x100, - 0x000,0x004,0x004,0x004,0x004,0x004,0x004,0x004, - 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, - 0x004,0x004,0x004,0x004,0x004,0x004,0x004,0x004, - 0x004,0x004,0x004,0x000,0x200,0x000,0x200,0x000, +static unsigned short CONF_type_win32[256]={ + 0x0008,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0010,0x0010,0x0000,0x0000,0x0010,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0010,0x0200,0x0400,0x0000,0x0000,0x0200,0x0200,0x0000, + 0x0000,0x0000,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200, + 0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001, + 0x0001,0x0001,0x0000,0x0A00,0x0000,0x0000,0x0000,0x0200, + 0x0200,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0002,0x0002,0x0000,0x0000,0x0000,0x0200,0x0100, + 0x0000,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, + 0x0004,0x0004,0x0004,0x0000,0x0200,0x0000,0x0200,0x0000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, }; diff --git a/src/lib/libcrypto/conf/conf_err.c b/src/lib/libcrypto/conf/conf_err.c index a8db8f266f..ee07bfe9d9 100644 --- a/src/lib/libcrypto/conf/conf_err.c +++ b/src/lib/libcrypto/conf/conf_err.c @@ -1,93 +1,123 @@ -/* lib/conf/conf_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/conf/conf_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "conf.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA CONF_str_functs[]= { +{ERR_PACK(0,CONF_F_CONF_DUMP_FP,0), "CONF_dump_fp"}, {ERR_PACK(0,CONF_F_CONF_LOAD,0), "CONF_load"}, +{ERR_PACK(0,CONF_F_CONF_LOAD_BIO,0), "CONF_load_bio"}, +{ERR_PACK(0,CONF_F_CONF_LOAD_FP,0), "CONF_load_fp"}, +{ERR_PACK(0,CONF_F_CONF_MODULES_LOAD,0), "CONF_modules_load"}, +{ERR_PACK(0,CONF_F_MODULE_INIT,0), "MODULE_INIT"}, +{ERR_PACK(0,CONF_F_MODULE_LOAD_DSO,0), "MODULE_LOAD_DSO"}, +{ERR_PACK(0,CONF_F_MODULE_RUN,0), "MODULE_RUN"}, +{ERR_PACK(0,CONF_F_NCONF_DUMP_BIO,0), "NCONF_dump_bio"}, +{ERR_PACK(0,CONF_F_NCONF_DUMP_FP,0), "NCONF_dump_fp"}, +{ERR_PACK(0,CONF_F_NCONF_GET_NUMBER,0), "NCONF_get_number"}, +{ERR_PACK(0,CONF_F_NCONF_GET_NUMBER_E,0), "NCONF_get_number_e"}, +{ERR_PACK(0,CONF_F_NCONF_GET_SECTION,0), "NCONF_get_section"}, +{ERR_PACK(0,CONF_F_NCONF_GET_STRING,0), "NCONF_get_string"}, +{ERR_PACK(0,CONF_F_NCONF_LOAD,0), "NCONF_load"}, +{ERR_PACK(0,CONF_F_NCONF_LOAD_BIO,0), "NCONF_load_bio"}, +{ERR_PACK(0,CONF_F_NCONF_LOAD_FP,0), "NCONF_load_fp"}, +{ERR_PACK(0,CONF_F_NCONF_NEW,0), "NCONF_new"}, {ERR_PACK(0,CONF_F_STR_COPY,0), "STR_COPY"}, -{0,NULL}, +{0,NULL} }; static ERR_STRING_DATA CONF_str_reasons[]= { +{CONF_R_ERROR_LOADING_DSO ,"error loading dso"}, {CONF_R_MISSING_CLOSE_SQUARE_BRACKET ,"missing close square bracket"}, {CONF_R_MISSING_EQUAL_SIGN ,"missing equal sign"}, +{CONF_R_MISSING_FINISH_FUNCTION ,"missing finish function"}, +{CONF_R_MISSING_INIT_FUNCTION ,"missing init function"}, +{CONF_R_MODULE_INITIALIZATION_ERROR ,"module initialization error"}, {CONF_R_NO_CLOSE_BRACE ,"no close brace"}, +{CONF_R_NO_CONF ,"no conf"}, +{CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE ,"no conf or environment variable"}, +{CONF_R_NO_SECTION ,"no section"}, +{CONF_R_NO_SUCH_FILE ,"no such file"}, +{CONF_R_NO_VALUE ,"no value"}, {CONF_R_UNABLE_TO_CREATE_NEW_SECTION ,"unable to create new section"}, +{CONF_R_UNKNOWN_MODULE_NAME ,"unknown module name"}, {CONF_R_VARIABLE_HAS_NO_VALUE ,"variable has no value"}, -{0,NULL}, +{0,NULL} }; #endif -void ERR_load_CONF_strings() +void ERR_load_CONF_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_CONF,CONF_str_functs); ERR_load_strings(ERR_LIB_CONF,CONF_str_reasons); #endif diff --git a/src/lib/libcrypto/conf/conf_lib.c b/src/lib/libcrypto/conf/conf_lib.c index 4c8ca9e9ae..7998f34c7b 100644 --- a/src/lib/libcrypto/conf/conf_lib.c +++ b/src/lib/libcrypto/conf/conf_lib.c @@ -67,6 +67,17 @@ const char *CONF_version="CONF" OPENSSL_VERSION_PTEXT; static CONF_METHOD *default_CONF_method=NULL; +/* Init a 'CONF' structure from an old LHASH */ + +void CONF_set_nconf(CONF *conf, LHASH *hash) + { + if (default_CONF_method == NULL) + default_CONF_method = NCONF_default(); + + default_CONF_method->init(conf); + conf->data = hash; + } + /* The following section contains the "CONF classic" functions, rewritten in terms of the new CONF interface. */ @@ -81,7 +92,7 @@ LHASH *CONF_load(LHASH *conf, const char *file, long *eline) LHASH *ltmp; BIO *in=NULL; -#ifdef VMS +#ifdef OPENSSL_SYS_VMS in=BIO_new_file(file, "r"); #else in=BIO_new_file(file, "rb"); @@ -98,7 +109,7 @@ LHASH *CONF_load(LHASH *conf, const char *file, long *eline) return ltmp; } -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline) { BIO *btmp; @@ -118,66 +129,74 @@ LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline) CONF ctmp; int ret; - if (default_CONF_method == NULL) - default_CONF_method = NCONF_default(); + CONF_set_nconf(&ctmp, conf); - default_CONF_method->init(&ctmp); - ctmp.data = conf; ret = NCONF_load_bio(&ctmp, bp, eline); if (ret) return ctmp.data; return NULL; } -STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,char *section) +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section) { - CONF ctmp; - - if (default_CONF_method == NULL) - default_CONF_method = NCONF_default(); - - default_CONF_method->init(&ctmp); - ctmp.data = conf; - return NCONF_get_section(&ctmp, section); + if (conf == NULL) + { + return NULL; + } + else + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return NCONF_get_section(&ctmp, section); + } } -char *CONF_get_string(LHASH *conf,char *group,char *name) +char *CONF_get_string(LHASH *conf,const char *group,const char *name) { - CONF ctmp; - - if (default_CONF_method == NULL) - default_CONF_method = NCONF_default(); - - default_CONF_method->init(&ctmp); - ctmp.data = conf; - return NCONF_get_string(&ctmp, group, name); + if (conf == NULL) + { + return NCONF_get_string(NULL, group, name); + } + else + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return NCONF_get_string(&ctmp, group, name); + } } -long CONF_get_number(LHASH *conf,char *group,char *name) +long CONF_get_number(LHASH *conf,const char *group,const char *name) { - CONF ctmp; + int status; + long result = 0; - if (default_CONF_method == NULL) - default_CONF_method = NCONF_default(); + if (conf == NULL) + { + status = NCONF_get_number_e(NULL, group, name, &result); + } + else + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + status = NCONF_get_number_e(&ctmp, group, name, &result); + } - default_CONF_method->init(&ctmp); - ctmp.data = conf; - return NCONF_get_number(&ctmp, group, name); + if (status == 0) + { + /* This function does not believe in errors... */ + ERR_get_error(); + } + return result; } void CONF_free(LHASH *conf) { CONF ctmp; - - if (default_CONF_method == NULL) - default_CONF_method = NCONF_default(); - - default_CONF_method->init(&ctmp); - ctmp.data = conf; + CONF_set_nconf(&ctmp, conf); NCONF_free_data(&ctmp); } -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API int CONF_dump_fp(LHASH *conf, FILE *out) { BIO *btmp; @@ -196,12 +215,7 @@ int CONF_dump_fp(LHASH *conf, FILE *out) int CONF_dump_bio(LHASH *conf, BIO *out) { CONF ctmp; - - if (default_CONF_method == NULL) - default_CONF_method = NCONF_default(); - - default_CONF_method->init(&ctmp); - ctmp.data = conf; + CONF_set_nconf(&ctmp, conf); return NCONF_dump_bio(&ctmp, out); } @@ -244,34 +258,23 @@ void NCONF_free_data(CONF *conf) int NCONF_load(CONF *conf, const char *file, long *eline) { - int ret; - BIO *in=NULL; - -#ifdef VMS - in=BIO_new_file(file, "r"); -#else - in=BIO_new_file(file, "rb"); -#endif - if (in == NULL) + if (conf == NULL) { - CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB); + CONFerr(CONF_F_NCONF_LOAD,CONF_R_NO_CONF); return 0; } - ret = NCONF_load_bio(conf, in, eline); - BIO_free(in); - - return ret; + return conf->meth->load(conf, file, eline); } -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API int NCONF_load_fp(CONF *conf, FILE *fp,long *eline) { BIO *btmp; int ret; if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) { - CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB); + CONFerr(CONF_F_NCONF_LOAD_FP,ERR_R_BUF_LIB); return 0; } ret = NCONF_load_bio(conf, btmp, eline); @@ -288,10 +291,10 @@ int NCONF_load_bio(CONF *conf, BIO *bp,long *eline) return 0; } - return conf->meth->load(conf, bp, eline); + return conf->meth->load_bio(conf, bp, eline); } -STACK_OF(CONF_VALUE) *NCONF_get_section(CONF *conf,char *section) +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section) { if (conf == NULL) { @@ -299,33 +302,62 @@ STACK_OF(CONF_VALUE) *NCONF_get_section(CONF *conf,char *section) return NULL; } + if (section == NULL) + { + CONFerr(CONF_F_NCONF_GET_SECTION,CONF_R_NO_SECTION); + return NULL; + } + return _CONF_get_section_values(conf, section); } -char *NCONF_get_string(CONF *conf,char *group,char *name) +char *NCONF_get_string(const CONF *conf,const char *group,const char *name) { + char *s = _CONF_get_string(conf, group, name); + + /* Since we may get a value from an environment variable even + if conf is NULL, let's check the value first */ + if (s) return s; + if (conf == NULL) { - CONFerr(CONF_F_NCONF_GET_STRING,CONF_R_NO_CONF); + CONFerr(CONF_F_NCONF_GET_STRING, + CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE); return NULL; } - - return _CONF_get_string(conf, group, name); + CONFerr(CONF_F_NCONF_GET_STRING, + CONF_R_NO_VALUE); + ERR_add_error_data(4,"group=",group," name=",name); + return NULL; } -long NCONF_get_number(CONF *conf,char *group,char *name) +int NCONF_get_number_e(const CONF *conf,const char *group,const char *name, + long *result) { - if (conf == NULL) + char *str; + + if (result == NULL) { - CONFerr(CONF_F_NCONF_GET_NUMBER,CONF_R_NO_CONF); + CONFerr(CONF_F_NCONF_GET_NUMBER_E,ERR_R_PASSED_NULL_PARAMETER); return 0; } - - return _CONF_get_number(conf, group, name); + + str = NCONF_get_string(conf,group,name); + + if (str == NULL) + return 0; + + for (*result = 0;conf->meth->is_number(conf, *str);) + { + *result = (*result)*10 + conf->meth->to_int(conf, *str); + str++; + } + + return 1; } -#ifndef NO_FP_API -int NCONF_dump_fp(CONF *conf, FILE *out) +#ifndef OPENSSL_NO_FP_API +int NCONF_dump_fp(const CONF *conf, FILE *out) { BIO *btmp; int ret; @@ -339,7 +371,7 @@ int NCONF_dump_fp(CONF *conf, FILE *out) } #endif -int NCONF_dump_bio(CONF *conf, BIO *out) +int NCONF_dump_bio(const CONF *conf, BIO *out) { if (conf == NULL) { @@ -350,3 +382,19 @@ int NCONF_dump_bio(CONF *conf, BIO *out) return conf->meth->dump(conf, out); } +/* This function should be avoided */ +#undef NCONF_get_number +long NCONF_get_number(CONF *conf,char *group,char *name) + { + int status; + long ret=0; + + status = NCONF_get_number_e(conf, group, name, &ret); + if (status == 0) + { + /* This function does not believe in errors... */ + ERR_get_error(); + } + return ret; + } + diff --git a/src/lib/libcrypto/conf/keysets.pl b/src/lib/libcrypto/conf/keysets.pl index e40fed0ca1..50ed67fa52 100644 --- a/src/lib/libcrypto/conf/keysets.pl +++ b/src/lib/libcrypto/conf/keysets.pl @@ -1,16 +1,20 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl $NUMBER=0x01; $UPPER=0x02; $LOWER=0x04; -$EOF=0x08; +$UNDER=0x100; +$PUNCTUATION=0x200; $WS=0x10; $ESC=0x20; $QUOTE=0x40; +$DQUOTE=0x400; $COMMENT=0x80; -$UNDER=0x100; +$FCOMMENT=0x800; +$EOF=0x08; +$HIGHBIT=0x1000; -foreach (0 .. 127) +foreach (0 .. 255) { $v=0; $c=sprintf("%c",$_); @@ -18,44 +22,164 @@ foreach (0 .. 127) $v|=$UPPER if ($c =~ /[A-Z]/); $v|=$LOWER if ($c =~ /[a-z]/); $v|=$UNDER if ($c =~ /_/); - $v|=$WS if ($c =~ / \t\r\n/); + $v|=$PUNCTUATION if ($c =~ /[!\.%&\*\+,\/;\?\@\^\~\|-]/); + $v|=$WS if ($c =~ /[ \t\r\n]/); $v|=$ESC if ($c =~ /\\/); - $v|=$QUOTE if ($c =~ /['`"]/); + $v|=$QUOTE if ($c =~ /['`"]/); # for emacs: "`'}/) $v|=$COMMENT if ($c =~ /\#/); $v|=$EOF if ($c =~ /\0/); + $v|=$HIGHBIT if ($c =~/[\x80-\xff]/); + + push(@V_def,$v); + } + +foreach (0 .. 255) + { + $v=0; + $c=sprintf("%c",$_); + $v|=$NUMBER if ($c =~ /[0-9]/); + $v|=$UPPER if ($c =~ /[A-Z]/); + $v|=$LOWER if ($c =~ /[a-z]/); + $v|=$UNDER if ($c =~ /_/); + $v|=$PUNCTUATION if ($c =~ /[!\.%&\*\+,\/;\?\@\^\~\|-]/); + $v|=$WS if ($c =~ /[ \t\r\n]/); + $v|=$DQUOTE if ($c =~ /["]/); # for emacs: "}/) + $v|=$FCOMMENT if ($c =~ /;/); + $v|=$EOF if ($c =~ /\0/); + $v|=$HIGHBIT if ($c =~/[\x80-\xff]/); - push(@V,$v); + push(@V_w32,$v); } print <<"EOF"; +/* crypto/conf/conf_def.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.] + */ + +/* THIS FILE WAS AUTOMAGICALLY GENERATED! + Please modify and use keysets.pl to regenerate it. */ + #define CONF_NUMBER $NUMBER #define CONF_UPPER $UPPER #define CONF_LOWER $LOWER -#define CONF_EOF $EOF +#define CONF_UNDER $UNDER +#define CONF_PUNCTUATION $PUNCTUATION #define CONF_WS $WS #define CONF_ESC $ESC #define CONF_QUOTE $QUOTE +#define CONF_DQUOTE $DQUOTE #define CONF_COMMENT $COMMENT +#define CONF_FCOMMENT $FCOMMENT +#define CONF_EOF $EOF +#define CONF_HIGHBIT $HIGHBIT #define CONF_ALPHA (CONF_UPPER|CONF_LOWER) #define CONF_ALPHA_NUMERIC (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) -#define CONF_UNDER $UNDER +#define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \\ + CONF_PUNCTUATION) + +#define KEYTYPES(c) ((unsigned short *)((c)->meth_data)) +#ifndef CHARSET_EBCDIC +#define IS_COMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC) +#define IS_ALPHA_NUMERIC_PUNCT(c,a) \\ + (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_DQUOTE) +#define IS_HIGHBIT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_HIGHBIT) -#define IS_COMMENT(a) (CONF_COMMENT&(CONF_type[(a)&0x7f])) -#define IS_EOF(a) ((a) == '\\0') -#define IS_ESC(a) ((a) == '\\\\') -#define IS_NUMER(a) (CONF_type[(a)&0x7f]&CONF_NUMBER) -#define IS_WS(a) (CONF_type[(a)&0x7f]&CONF_WS) -#define IS_ALPHA_NUMERIC(a) (CONF_type[(a)&0x7f]&CONF_ALPHA_NUMERIC) -#define IS_QUOTE(a) (CONF_type[(a)&0x7f]&CONF_QUOTE) +#else /*CHARSET_EBCDIC*/ + +#define IS_COMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_COMMENT) +#define IS_FCOMMENT(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_FCOMMENT) +#define IS_EOF(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_EOF) +#define IS_ESC(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_ESC) +#define IS_NUMBER(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_NUMBER) +#define IS_WS(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_WS) +#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_ALPHA_NUMERIC) +#define IS_ALPHA_NUMERIC_PUNCT(c,a) \\ + (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_ALPHA_NUMERIC_PUNCT) +#define IS_QUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_QUOTE) +#define IS_DQUOTE(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_DQUOTE) +#define IS_HIGHBIT(c,a) (KEYTYPES(c)[os_toascii[a]&0xff]&CONF_HIGHBIT) +#endif /*CHARSET_EBCDIC*/ EOF -print "static unsigned short CONF_type[128]={"; +print "static unsigned short CONF_type_default[256]={"; + +for ($i=0; $i<256; $i++) + { + print "\n\t" if ($i % 8) == 0; + printf "0x%04X,",$V_def[$i]; + } + +print "\n\t};\n\n"; + +print "static unsigned short CONF_type_win32[256]={"; -for ($i=0; $i<128; $i++) +for ($i=0; $i<256; $i++) { print "\n\t" if ($i % 8) == 0; - printf "0x%03X,",$V[$i]; + printf "0x%04X,",$V_w32[$i]; } -print "\n\t};\n"; +print "\n\t};\n\n"; diff --git a/src/lib/libcrypto/cpt_err.c b/src/lib/libcrypto/cpt_err.c index ea3c135d39..1b4a1cb4d4 100644 --- a/src/lib/libcrypto/cpt_err.c +++ b/src/lib/libcrypto/cpt_err.c @@ -1,85 +1,101 @@ -/* lib/crypto/crypto_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/cpt_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "crypto.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA CRYPTO_str_functs[]= { {ERR_PACK(0,CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,0), "CRYPTO_get_ex_new_index"}, +{ERR_PACK(0,CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,0), "CRYPTO_get_new_dynlockid"}, {ERR_PACK(0,CRYPTO_F_CRYPTO_GET_NEW_LOCKID,0), "CRYPTO_get_new_lockid"}, {ERR_PACK(0,CRYPTO_F_CRYPTO_SET_EX_DATA,0), "CRYPTO_set_ex_data"}, -{0,NULL}, +{ERR_PACK(0,CRYPTO_F_DEF_ADD_INDEX,0), "DEF_ADD_INDEX"}, +{ERR_PACK(0,CRYPTO_F_DEF_GET_CLASS,0), "DEF_GET_CLASS"}, +{ERR_PACK(0,CRYPTO_F_INT_DUP_EX_DATA,0), "INT_DUP_EX_DATA"}, +{ERR_PACK(0,CRYPTO_F_INT_FREE_EX_DATA,0), "INT_FREE_EX_DATA"}, +{ERR_PACK(0,CRYPTO_F_INT_NEW_EX_DATA,0), "INT_NEW_EX_DATA"}, +{0,NULL} + }; + +static ERR_STRING_DATA CRYPTO_str_reasons[]= + { +{CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK ,"no dynlock create callback"}, +{0,NULL} }; #endif -void ERR_load_CRYPTO_strings() +void ERR_load_CRYPTO_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_CRYPTO,CRYPTO_str_functs); + ERR_load_strings(ERR_LIB_CRYPTO,CRYPTO_str_reasons); #endif } diff --git a/src/lib/libcrypto/cryptlib.c b/src/lib/libcrypto/cryptlib.c index 9a7e80b7f8..612b3b93b4 100644 --- a/src/lib/libcrypto/cryptlib.c +++ b/src/lib/libcrypto/cryptlib.c @@ -59,19 +59,22 @@ #include #include #include "cryptlib.h" -#include "crypto.h" -#include "date.h" +#include +#include -#if defined(WIN32) || defined(WIN16) +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ #endif +DECLARE_STACK_OF(CRYPTO_dynlock) +IMPLEMENT_STACK_OF(CRYPTO_dynlock) + /* real #defines in crypto.h, keep these upto date */ -static char* lock_names[CRYPTO_NUM_LOCKS] = +static const char* lock_names[CRYPTO_NUM_LOCKS] = { "<>", "err", - "err_hash", + "ex_data", "x509", "x509_info", "x509_pkey", @@ -84,100 +87,283 @@ static char* lock_names[CRYPTO_NUM_LOCKS] = "ssl_ctx", "ssl_cert", "ssl_session", + "ssl_sess_cert", "ssl", "rand", + "rand2", "debug_malloc", "BIO", - "bio_gethostbyname", + "gethostbyname", + "getservbyname", + "readdir", "RSA_blinding", + "dh", + "debug_malloc2", + "dso", + "dynlock", + "engine", + "ui", +#if CRYPTO_NUM_LOCKS != 31 +# error "Inconsistency between crypto.h and cryptlib.c" +#endif }; +/* This is for applications to allocate new type names in the non-dynamic + array of lock names. These are numbered with positive numbers. */ static STACK *app_locks=NULL; -#ifndef NOPROTO +/* For applications that want a more dynamic way of handling threads, the + following stack is used. These are externally numbered with negative + numbers. */ +static STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL; + + static void (MS_FAR *locking_callback)(int mode,int type, - char *file,int line)=NULL; + const char *file,int line)=NULL; static int (MS_FAR *add_lock_callback)(int *pointer,int amount, - int type,char *file,int line)=NULL; + int type,const char *file,int line)=NULL; static unsigned long (MS_FAR *id_callback)(void)=NULL; -#else -static void (MS_FAR *locking_callback)()=NULL; -static int (MS_FAR *add_lock_callback)()=NULL; -static unsigned long (MS_FAR *id_callback)()=NULL; -#endif +static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback) + (const char *file,int line)=NULL; +static void (MS_FAR *dynlock_lock_callback)(int mode, + struct CRYPTO_dynlock_value *l, const char *file,int line)=NULL; +static void (MS_FAR *dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l, + const char *file,int line)=NULL; -int CRYPTO_get_new_lockid(name) -char *name; +int CRYPTO_get_new_lockid(char *name) { char *str; int i; +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) /* 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) - if ((app_locks=sk_new_null()) == NULL) - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); - return(0); + 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) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); return(0); + } i=sk_push(app_locks,str); if (!i) - Free(str); + OPENSSL_free(str); else i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ return(i); } -void (*CRYPTO_get_locking_callback(P_V))(P_I_I_P_I) +int CRYPTO_num_locks(void) + { + return CRYPTO_NUM_LOCKS; + } + +int CRYPTO_get_new_dynlockid(void) + { + int i = 0; + CRYPTO_dynlock *pointer = NULL; + + if (dynlock_create_callback == NULL) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK); + return(0); + } + CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); + if ((dyn_locks == NULL) + && ((dyn_locks=sk_CRYPTO_dynlock_new_null()) == NULL)) + { + CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); + CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); + return(0); + } + CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); + + pointer = (CRYPTO_dynlock *)OPENSSL_malloc(sizeof(CRYPTO_dynlock)); + if (pointer == NULL) + { + CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); + return(0); + } + pointer->references = 1; + pointer->data = dynlock_create_callback(__FILE__,__LINE__); + if (pointer->data == NULL) + { + OPENSSL_free(pointer); + CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); + return(0); + } + + CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); + /* First, try to find an existing empty slot */ + i=sk_CRYPTO_dynlock_find(dyn_locks,NULL); + /* If there was none, push, thereby creating a new one */ + if (i == -1) + i=sk_CRYPTO_dynlock_push(dyn_locks,pointer); + CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); + + if (!i) + { + dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); + OPENSSL_free(pointer); + } + else + i += 1; /* to avoid 0 */ + return -i; + } + +void CRYPTO_destroy_dynlockid(int i) + { + CRYPTO_dynlock *pointer = NULL; + if (i) + i = -i-1; + if (dynlock_destroy_callback == NULL) + return; + + CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); + + if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) + { + CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); + return; + } + pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); + if (pointer != NULL) + { + --pointer->references; +#ifdef REF_CHECK + if (pointer->references < 0) + { + fprintf(stderr,"CRYPTO_destroy_dynlockid, bad reference count\n"); + abort(); + } + else +#endif + if (pointer->references <= 0) + { + sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); + } + else + pointer = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); + + if (pointer) + { + dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); + OPENSSL_free(pointer); + } + } + +struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i) + { + CRYPTO_dynlock *pointer = NULL; + if (i) + i = -i-1; + + CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); + + if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks)) + pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); + if (pointer) + pointer->references++; + + CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); + + if (pointer) + return pointer->data; + return NULL; + } + +struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void)) + (const char *file,int line) + { + return(dynlock_create_callback); + } + +void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, + struct CRYPTO_dynlock_value *l, const char *file,int line) + { + return(dynlock_lock_callback); + } + +void (*CRYPTO_get_dynlock_destroy_callback(void)) + (struct CRYPTO_dynlock_value *l, const char *file,int line) + { + return(dynlock_destroy_callback); + } + +void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func) + (const char *file, int line)) + { + dynlock_create_callback=func; + } + +void CRYPTO_set_dynlock_lock_callback(void (*func)(int mode, + struct CRYPTO_dynlock_value *l, const char *file, int line)) + { + dynlock_lock_callback=func; + } + +void CRYPTO_set_dynlock_destroy_callback(void (*func) + (struct CRYPTO_dynlock_value *l, const char *file, int line)) + { + dynlock_destroy_callback=func; + } + + +void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, + int line) { return(locking_callback); } -int (*CRYPTO_get_add_lock_callback(P_V))(P_IP_I_I_P_I) +int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, + const char *file,int line) { return(add_lock_callback); } -void CRYPTO_set_locking_callback(func) -void (*func)(P_I_I_P_I); +void CRYPTO_set_locking_callback(void (*func)(int mode,int type, + const char *file,int line)) { locking_callback=func; } -void CRYPTO_set_add_lock_callback(func) -int (*func)(P_IP_I_I_P_I); +void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, + const char *file,int line)) { add_lock_callback=func; } -unsigned long (*CRYPTO_get_id_callback(P_V))(P_V) +unsigned long (*CRYPTO_get_id_callback(void))(void) { return(id_callback); } -void CRYPTO_set_id_callback(func) -unsigned long (*func)(P_V); +void CRYPTO_set_id_callback(unsigned long (*func)(void)) { id_callback=func; } -unsigned long CRYPTO_thread_id() +unsigned long CRYPTO_thread_id(void) { unsigned long ret=0; if (id_callback == NULL) { -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 ret=(unsigned long)GetCurrentTask(); -#elif defined(WIN32) +#elif defined(OPENSSL_SYS_WIN32) ret=(unsigned long)GetCurrentThreadId(); -#elif defined(MSDOS) +#elif defined(GETPID_IS_MEANINGLESS) ret=1L; #else ret=(unsigned long)getpid(); @@ -188,11 +374,7 @@ unsigned long CRYPTO_thread_id() return(ret); } -void CRYPTO_lock(mode,type,file,line) -int mode; -int type; -char *file; -int line; +void CRYPTO_lock(int mode, int type, const char *file, int line) { #ifdef LOCK_DEBUG { @@ -217,18 +399,27 @@ int line; CRYPTO_get_lock_name(type), file, line); } #endif - if (locking_callback != NULL) - locking_callback(mode,type,file,line); + if (type < 0) + { + struct CRYPTO_dynlock_value *pointer + = CRYPTO_get_dynlock_value(type); + + if (pointer && dynlock_lock_callback) + { + dynlock_lock_callback(mode, pointer, file, line); + } + + CRYPTO_destroy_dynlockid(type); + } + else + if (locking_callback != NULL) + locking_callback(mode,type,file,line); } -int CRYPTO_add_lock(pointer,amount,type,file,line) -int *pointer; -int amount; -int type; -char *file; -int line; +int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, + int line) { - int ret; + int ret = 0; if (add_lock_callback != NULL) { @@ -244,7 +435,6 @@ int line; CRYPTO_get_lock_name(type), file,line); #endif - *pointer=ret; } else { @@ -264,11 +454,10 @@ int line; return(ret); } -char *CRYPTO_get_lock_name(type) -int type; +const char *CRYPTO_get_lock_name(int type) { if (type < 0) - return("ERROR"); + return("dynamic"); else if (type < CRYPTO_NUM_LOCKS) return(lock_names[type]); else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks)) @@ -278,15 +467,13 @@ int type; } #ifdef _DLL -#ifdef WIN32 +#ifdef OPENSSL_SYS_WIN32 /* All we really need to do is remove the 'error' state when a thread * detaches */ -BOOL WINAPI DLLEntryPoint(hinstDLL,fdwReason,lpvReserved) -HINSTANCE hinstDLL; -DWORD fdwReason; -LPVOID lpvReserved; +BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, + LPVOID lpvReserved) { switch(fdwReason) { diff --git a/src/lib/libcrypto/cryptlib.h b/src/lib/libcrypto/cryptlib.h index 32757c9efb..a0489e57fc 100644 --- a/src/lib/libcrypto/cryptlib.h +++ b/src/lib/libcrypto/cryptlib.h @@ -62,33 +62,29 @@ #include #include +#include "e_os.h" + +#include +#include +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -/* #ifdef FLAT_INC */ - -#include "e_os.h" -#include "crypto.h" -#include "buffer.h" -#include "bio.h" -#include "err.h" - -/* +#ifndef OPENSSL_SYS_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 - -#include "../e_os.h" -#include "crypto.h" -#include "buffer/buffer.h" -#include "bio/bio.h" -#include "err/err.h" +#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_AREA "/etc/ssl" -#define X509_CERT_DIR "/etc/ssl/certs" -#define X509_CERT_FILE "/etc/ssl/cert.pem" -#define X509_PRIVATE_DIR "/etc/ssl/private" #define X509_CERT_DIR_EVP "SSL_CERT_DIR" #define X509_CERT_FILE_EVP "SSL_CERT_FILE" diff --git a/src/lib/libcrypto/crypto.h b/src/lib/libcrypto/crypto.h index 0a38b5b87c..fc6ff860af 100644 --- a/src/lib/libcrypto/crypto.h +++ b/src/lib/libcrypto/crypto.h @@ -59,27 +59,45 @@ #ifndef HEADER_CRYPTO_H #define HEADER_CRYPTO_H +#include + +#ifndef OPENSSL_NO_FP_API +#include +#endif + +#include +#include +#include + +#ifdef CHARSET_EBCDIC +#include +#endif + +/* Resolve problems on some operating systems with symbol names that clash + one way or another */ +#include + #ifdef __cplusplus extern "C" { #endif -#include "stack.h" - +/* 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 0x0902 /* Version 0.5.1c would be 0513 */ - +#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 +#define SSLEAY_DIR 5 /* 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_EX_DATA 2 #define CRYPTO_LOCK_X509 3 #define CRYPTO_LOCK_X509_INFO 4 #define CRYPTO_LOCK_X509_PKEY 5 @@ -92,19 +110,30 @@ extern "C" { #define CRYPTO_LOCK_SSL_CTX 12 #define CRYPTO_LOCK_SSL_CERT 13 #define CRYPTO_LOCK_SSL_SESSION 14 -#define CRYPTO_LOCK_SSL 15 -#define CRYPTO_LOCK_RAND 16 -#define CRYPTO_LOCK_MALLOC 17 -#define CRYPTO_LOCK_BIO 18 -#define CRYPTO_LOCK_BIO_GETHOSTBYNAME 19 -#define CRYPTO_LOCK_RSA_BLINDING 20 -#define CRYPTO_NUM_LOCKS 21 +#define CRYPTO_LOCK_SSL_SESS_CERT 15 +#define CRYPTO_LOCK_SSL 16 +#define CRYPTO_LOCK_RAND 17 +#define CRYPTO_LOCK_RAND2 18 +#define CRYPTO_LOCK_MALLOC 19 +#define CRYPTO_LOCK_BIO 20 +#define CRYPTO_LOCK_GETHOSTBYNAME 21 +#define CRYPTO_LOCK_GETSERVBYNAME 22 +#define CRYPTO_LOCK_READDIR 23 +#define CRYPTO_LOCK_RSA_BLINDING 24 +#define CRYPTO_LOCK_DH 25 +#define CRYPTO_LOCK_MALLOC2 26 +#define CRYPTO_LOCK_DSO 27 +#define CRYPTO_LOCK_DYNLOCK 28 +#define CRYPTO_LOCK_ENGINE 29 +#define CRYPTO_LOCK_UI 30 +#define CRYPTO_NUM_LOCKS 31 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 #define CRYPTO_READ 4 #define CRYPTO_WRITE 8 +#ifndef OPENSSL_NO_LOCKING #ifndef CRYPTO_w_lock #define CRYPTO_w_lock(type) \ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) @@ -116,23 +145,44 @@ extern "C" { 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 +/* Some applications as well as some parts of OpenSSL need to allocate + and deallocate locks in a dynamic fashion. The following typedef + makes this possible in a type-safe manner. */ +/* struct CRYPTO_dynlock_value has to be defined by the application. */ +typedef struct + { + int references; + struct CRYPTO_dynlock_value *data; + } CRYPTO_dynlock; + + /* 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 -#define CRYPTO_MEM_CHECK_ON 0x1 +#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) -/* -typedef struct crypto_mem_st - { - char *(*malloc_func)(); - char *(*realloc_func)(); - void (*free_func)(); - } CRYPTO_MEM_FUNC; -*/ /* predec of the BIO type */ typedef struct bio_st BIO_dummy; @@ -143,24 +193,30 @@ typedef struct crypto_ex_data_st 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_SESION, and a few more */ + * The current classes are SSL_CTX, SSL, SSL_SESSION, and a few more */ + typedef struct crypto_ex_data_func_st { long argl; /* Arbitary long */ - char *argp; /* Arbitary char * */ - /* Called when a new object is created */ - int (*new_func)(/*char *obj, - char *item,int index,long argl,char *argp*/); - /* Called when this object is free()ed */ - void (*free_func)(/*char *obj, - char *item,int index,long argl,char *argp*/); - - /* Called when we need to dup this one */ - int (*dup_func)(/*char *obj_to,char *obj_from, - char **new,int index,long argl,char *argp*/); + 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. */ @@ -171,149 +227,225 @@ typedef struct crypto_ex_data_func_st #define CRYPTO_EX_INDEX_SSL_SESSION 3 #define CRYPTO_EX_INDEX_X509_STORE 4 #define CRYPTO_EX_INDEX_X509_STORE_CTX 5 +#define CRYPTO_EX_INDEX_RSA 6 +#define CRYPTO_EX_INDEX_DSA 7 +#define CRYPTO_EX_INDEX_DH 8 +#define CRYPTO_EX_INDEX_ENGINE 9 +#define CRYPTO_EX_INDEX_X509 10 +#define CRYPTO_EX_INDEX_UI 11 -/* Use this for win32 DLL's */ +/* Dynamically assigned indexes start from this value (don't use directly, use + * via CRYPTO_ex_data_new_class). */ +#define CRYPTO_EX_INDEX_USER 100 + + +/* 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(\ - (char *(*)())malloc,\ - (char *(*)())realloc,\ - (void (*)())free) - -#ifdef CRYPTO_MDEBUG -#define Malloc(num) CRYPTO_dbg_malloc((int)num,__FILE__,__LINE__) -#define Realloc(addr,num) \ - CRYPTO_dbg_realloc((char *)addr,(int)num,__FILE__,__LINE__) -#define Remalloc(addr,num) \ - CRYPTO_dbg_remalloc((char **)addr,(int)num,__FILE__,__LINE__) -#define FreeFunc CRYPTO_dbg_free -#define Free(addr) CRYPTO_dbg_free((char *)(addr)) -#else -#define Remalloc CRYPTO_remalloc -#if defined(WIN32) || defined(MFUNC) -#define Malloc CRYPTO_malloc -#define Realloc(a,n) CRYPTO_realloc((char *)(a),(n)) -#define FreeFunc CRYPTO_free -#define Free(addr) CRYPTO_free((char *)(addr)) -#else -#define Malloc malloc -#define Realloc realloc -#define FreeFunc free -#define Free(addr) free((char *)(addr)) -#endif /* WIN32 || MFUNC */ -#endif /* MDEBUG */ - -/* Case insensiteve linking causes problems.... */ -#ifdef WIN16 -#define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings + 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 -#ifndef NOPROTO +/* Set standard debugging functions (not done by default + * unless CRYPTO_MDEBUG is defined) */ +#define CRYPTO_malloc_debug_init() do {\ + CRYPTO_set_mem_debug_functions(\ + CRYPTO_dbg_malloc,\ + CRYPTO_dbg_realloc,\ + CRYPTO_dbg_free,\ + CRYPTO_dbg_set_options,\ + 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() -char *SSLeay_version(int type); +#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__) +#define OPENSSL_realloc(addr,num) \ + CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__) +#define OPENSSL_remalloc(addr,num) \ + CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__) +#define OPENSSL_freeFunc CRYPTO_free +#define OPENSSL_free(addr) CRYPTO_free(addr) + +#define OPENSSL_malloc_locked(num) \ + CRYPTO_malloc_locked((int)num,__FILE__,__LINE__) +#define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr) + + +const char *SSLeay_version(int type); unsigned long SSLeay(void); -int CRYPTO_get_ex_new_index(int idx,STACK **sk,long argl,char *argp, - int (*new_func)(),int (*dup_func)(),void (*free_func)()); -int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad,int idx,char *val); -char *CRYPTO_get_ex_data(CRYPTO_EX_DATA *ad,int idx); -int CRYPTO_dup_ex_data(STACK *meth,CRYPTO_EX_DATA *from,CRYPTO_EX_DATA *to); -void CRYPTO_free_ex_data(STACK *meth,char *obj,CRYPTO_EX_DATA *ad); -void CRYPTO_new_ex_data(STACK *meth, char *obj, CRYPTO_EX_DATA *ad); +int OPENSSL_issetugid(void); + +/* An opaque type representing an implementation of "ex_data" support */ +typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL; +/* Return an opaque pointer to the current "ex_data" implementation */ +const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void); +/* Sets the "ex_data" implementation to be used (if it's not too late) */ +int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i); +/* Get a new "ex_data" class, and return the corresponding "class_index" */ +int CRYPTO_ex_data_new_class(void); +/* Within a given class, get/register a new index */ +int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +/* Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a given + * class (invokes whatever per-class callbacks are applicable) */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from); +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +/* Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular index + * (relative to the class type involved) */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad,int idx); +/* This function cleans up all "ex_data" state. It mustn't be called under + * potential race-conditions. */ +void CRYPTO_cleanup_all_ex_data(void); -int CRYPTO_mem_ctrl(int mode); int CRYPTO_get_new_lockid(char *name); -void CRYPTO_lock(int mode, int type,char *file,int line); -void CRYPTO_set_locking_callback(void (*func)(int mode,int type,char *file, - int line)); -void (*CRYPTO_get_locking_callback(void))(int mode,int type,char *file, + +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,char *file, int line)); -int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount, - int type,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); -char *CRYPTO_get_lock_name(int type); -int CRYPTO_add_lock(int *pointer,int amount,int type, char *file,int line); - -void CRYPTO_set_mem_functions(char *(*m)(),char *(*r)(), void (*free_func)()); -void CRYPTO_get_mem_functions(char *(**m)(),char *(**r)(), void (**f)()); - -char *CRYPTO_malloc(int num); -char *CRYPTO_realloc(char *addr,int num); -void CRYPTO_free(char *); -char *CRYPTO_remalloc(char *addr,int num); - -char *CRYPTO_dbg_malloc(int num,char *file,int line); -char *CRYPTO_dbg_realloc(char *addr,int num,char *file,int line); -void CRYPTO_dbg_free(char *); -char *CRYPTO_dbg_remalloc(char *addr,int num,char *file,int line); -#ifndef NO_FP_API +const char *CRYPTO_get_lock_name(int type); +int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file, + int line); + +int CRYPTO_get_new_dynlockid(void); +void CRYPTO_destroy_dynlockid(int i); +struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i); +void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, int line)); +void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)); +void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, const char *file, int line)); +struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(const char *file,int line); +void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, struct CRYPTO_dynlock_value *l, const char *file,int line); +void (*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l, 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_ex_functions(void *(*m)(size_t,const char *,int), + void *(*r)(void *,size_t,const char *,int), + void (*f)(void *)); +int CRYPTO_set_locked_mem_ex_functions(void *(*m)(size_t,const char *,int), + void (*free_func)(void *)); +int CRYPTO_set_mem_debug_functions(void (*m)(void *,int,const char *,int,int), + void (*r)(void *,void *,int,const char *,int,int), + void (*f)(void *,int), + void (*so)(long), + long (*go)(void)); +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_ex_functions(void *(**m)(size_t,const char *,int), + void *(**r)(void *, size_t,const char *,int), + void (**f)(void *)); +void CRYPTO_get_locked_mem_ex_functions(void *(**m)(size_t,const char *,int), + void (**f)(void *)); +void CRYPTO_get_mem_debug_functions(void (**m)(void *,int,const char *,int,int), + void (**r)(void *,void *,int,const char *,int,int), + void (**f)(void *,int), + void (**so)(long), + long (**go)(void)); + +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); + + +/* Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro; + * used as default in CRYPTO_MDEBUG compilations): */ +/* 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. + * V_CRYPTO_MDEBUG_TIME (1): Set the "Show Time" option. + * V_CRYPTO_MDEBUG_THREAD (2): Set the "Show Thread Number" option. + * V_CRYPTO_MDEBUG_ALL (3): 1 + 2 + */ +void CRYPTO_dbg_set_options(long bits); +long CRYPTO_dbg_get_options(void); + + +#ifndef OPENSSL_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 ); - -#else - -int CRYPTO_get_ex_new_index(); -int CRYPTO_set_ex_data(); -char *CRYPTO_get_ex_data(); -int CRYPTO_dup_ex_data(); -void CRYPTO_free_ex_data(); -void CRYPTO_new_ex_data(); - -int CRYPTO_mem_ctrl(); -char *SSLeay_version(); -unsigned long SSLeay(); - -int CRYPTO_get_new_lockid(); -void CRYPTO_lock(); -void CRYPTO_set_locking_callback(); -void (*CRYPTO_get_locking_callback())(); -void CRYPTO_set_add_lock_callback(); -int (*CRYPTO_get_add_lock_callback())(); -void CRYPTO_set_id_callback(); -unsigned long (*CRYPTO_get_id_callback())(); -unsigned long CRYPTO_thread_id(); -char *CRYPTO_get_lock_name(); -int CRYPTO_add_lock(); - -void CRYPTO_set_mem_functions(); -void CRYPTO_get_mem_functions(); -char *CRYPTO_malloc(); -char *CRYPTO_realloc(); -void CRYPTO_free(); -char *CRYPTO_remalloc(); -char *CRYPTO_dbg_remalloc(); -char *CRYPTO_dbg_malloc(); -char *CRYPTO_dbg_realloc(); -void CRYPTO_dbg_free(); -#ifndef NO_FP_API -void CRYPTO_mem_leaks_fp(); -#endif -void CRYPTO_mem_leaks(); -void CRYPTO_mem_leaks_cb(); +typedef void *CRYPTO_MEM_LEAK_CB(unsigned long, const char *, int, int, void *); +void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb); -void ERR_load_CRYPTO_strings(); - -#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. + */ +void ERR_load_CRYPTO_strings(void); + /* Error codes for the CRYPTO functions. */ /* Function codes. */ #define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100 +#define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID 103 #define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101 #define CRYPTO_F_CRYPTO_SET_EX_DATA 102 +#define CRYPTO_F_DEF_ADD_INDEX 104 +#define CRYPTO_F_DEF_GET_CLASS 105 +#define CRYPTO_F_INT_DUP_EX_DATA 106 +#define CRYPTO_F_INT_FREE_EX_DATA 107 +#define CRYPTO_F_INT_NEW_EX_DATA 108 /* Reason codes. */ - +#define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100 + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/cversion.c b/src/lib/libcrypto/cversion.c index 4e823be52f..8ecfba7b16 100644 --- a/src/lib/libcrypto/cversion.c +++ b/src/lib/libcrypto/cversion.c @@ -59,40 +59,59 @@ #include #include #include "cryptlib.h" -#include "crypto.h" -#include "date.h" +#include -char *SSLeay_version(t) -int t; +#include "buildinf.h" + +const char *SSLeay_version(int t) { if (t == SSLEAY_VERSION) - return("SSLeay 0.9.0b 29-Jun-1998"); + return OPENSSL_VERSION_TEXT; if (t == SSLEAY_BUILT_ON) { #ifdef DATE - static char buf[sizeof(DATE)+10]; + static char buf[sizeof(DATE)+11]; - sprintf(buf,"built on %s",DATE); - return(buf); + sprintf(buf,"built on: %s",DATE); + return(buf); #else - return("build date not available"); + return("built on: date not available"); #endif } if (t == SSLEAY_CFLAGS) { #ifdef CFLAGS - static char buf[sizeof(CFLAGS)+10]; + static char buf[sizeof(CFLAGS)+11]; + + sprintf(buf,"compiler: %s",CFLAGS); + return(buf); +#else + return("compiler: information not available"); +#endif + } + if (t == SSLEAY_PLATFORM) + { +#ifdef PLATFORM + static char buf[sizeof(PLATFORM)+11]; - sprintf(buf,"C flags:%s",CFLAGS); + sprintf(buf,"platform: %s", PLATFORM); return(buf); #else - return("C flags not available"); + return("platform: information not available"); +#endif + } + if (t == SSLEAY_DIR) + { +#ifdef OPENSSLDIR + return "OPENSSLDIR: \"" OPENSSLDIR "\""; +#else + return "OPENSSLDIR: N/A"; #endif } return("not available"); } -unsigned long SSLeay() +unsigned long SSLeay(void) { return(SSLEAY_VERSION_NUMBER); } diff --git a/src/lib/libcrypto/des/asm/crypt586.pl b/src/lib/libcrypto/des/asm/crypt586.pl index 297e38dec8..3d41d82f69 100644 --- a/src/lib/libcrypto/des/asm/crypt586.pl +++ b/src/lib/libcrypto/des/asm/crypt586.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # # The inner loop instruction sequence and the IP/FP modifications are from # Svend Olaf Mikkelsen @@ -14,7 +14,7 @@ require "x86asm.pl"; $L="edi"; $R="esi"; -&external_label("des_SPtrans"); +&external_label("DES_SPtrans"); &fcrypt_body("fcrypt_body"); &asm_finish(); @@ -22,7 +22,7 @@ sub fcrypt_body { local($name,$do_ip)=@_; - &function_begin($name,"EXTRN _des_SPtrans:DWORD"); + &function_begin($name,"EXTRN _DES_SPtrans:DWORD"); &comment(""); &comment("Load the 2 words"); @@ -32,18 +32,18 @@ sub fcrypt_body &xor( $R, $R); &mov($ks,&wparam(1)); - &push(25); # add a variable + &push(&DWC(25)); # add a variable &set_label("start"); for ($i=0; $i<16; $i+=2) { &comment(""); &comment("Round $i"); - &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); + &D_ENCRYPT($i,$L,$R,$i*2,$ks,"DES_SPtrans","eax","ebx","ecx","edx"); &comment(""); &comment("Round ".sprintf("%d",$i+1)); - &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); + &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"DES_SPtrans","eax","ebx","ecx","edx"); } &mov("ebx", &swtmp(0)); &mov("eax", $L); diff --git a/src/lib/libcrypto/des/asm/des-586.pl b/src/lib/libcrypto/des/asm/des-586.pl index 7f2e09fa7a..0d08e8a3a9 100644 --- a/src/lib/libcrypto/des/asm/des-586.pl +++ b/src/lib/libcrypto/des/asm/des-586.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # # The inner loop instruction sequence and the IP/FP modifications are from # Svend Olaf Mikkelsen @@ -19,21 +19,21 @@ require "desboth.pl"; $L="edi"; $R="esi"; -&external_label("des_SPtrans"); -&des_encrypt("des_encrypt",1); -&des_encrypt("des_encrypt2",0); -&des_encrypt3("des_encrypt3",1); -&des_encrypt3("des_decrypt3",0); -&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); -&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); +&external_label("DES_SPtrans"); +&DES_encrypt("DES_encrypt1",1); +&DES_encrypt("DES_encrypt2",0); +&DES_encrypt3("DES_encrypt3",1); +&DES_encrypt3("DES_decrypt3",0); +&cbc("DES_ncbc_encrypt","DES_encrypt1","DES_encrypt1",0,4,5,3,5,-1); +&cbc("DES_ede3_cbc_encrypt","DES_encrypt3","DES_decrypt3",0,6,7,3,4,5); &asm_finish(); -sub des_encrypt +sub DES_encrypt { local($name,$do_ip)=@_; - &function_begin_B($name,"EXTRN _des_SPtrans:DWORD"); + &function_begin_B($name,"EXTRN _DES_SPtrans:DWORD"); &push("esi"); &push("edi"); @@ -80,11 +80,11 @@ sub des_encrypt { &comment(""); &comment("Round $i"); - &D_ENCRYPT($i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); + &D_ENCRYPT($i,$L,$R,$i*2,$ks,"DES_SPtrans","eax","ebx","ecx","edx"); &comment(""); &comment("Round ".sprintf("%d",$i+1)); - &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); + &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$ks,"DES_SPtrans","eax","ebx","ecx","edx"); } &jmp(&label("end")); @@ -94,10 +94,10 @@ sub des_encrypt { &comment(""); &comment("Round $i"); - &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); + &D_ENCRYPT(15-$i,$L,$R,$i*2,$ks,"DES_SPtrans","eax","ebx","ecx","edx"); &comment(""); &comment("Round ".sprintf("%d",$i-1)); - &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"des_SPtrans","eax","ebx","ecx","edx"); + &D_ENCRYPT(15-$i+1,$R,$L,($i-1)*2,$ks,"DES_SPtrans","eax","ebx","ecx","edx"); } &set_label("end"); @@ -187,6 +187,8 @@ sub R_PERM_OP &mov( $tt, $a ); &xor( $a, $b ); &and( $a, $mask ); + # This can never succeed, and besides it is difficult to see what the + # idea was - Ben 13 Feb 99 if (!$last eq $b) { &xor( $b, $a ); diff --git a/src/lib/libcrypto/des/asm/desboth.pl b/src/lib/libcrypto/des/asm/desboth.pl index 8f939953a6..eec00886e4 100644 --- a/src/lib/libcrypto/des/asm/desboth.pl +++ b/src/lib/libcrypto/des/asm/desboth.pl @@ -1,9 +1,9 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl $L="edi"; $R="esi"; -sub des_encrypt3 +sub DES_encrypt3 { local($name,$enc)=@_; @@ -44,18 +44,18 @@ sub des_encrypt3 &mov("edi",&wparam(2)); &mov("eax",&wparam(3)); } - &mov(&swtmp(2), (($enc)?"1":"0")); + &mov(&swtmp(2), (DWC(($enc)?"1":"0"))); &mov(&swtmp(1), "eax"); &mov(&swtmp(0), "ebx"); - &call("des_encrypt2"); - &mov(&swtmp(2), (($enc)?"0":"1")); + &call("DES_encrypt2"); + &mov(&swtmp(2), (DWC(($enc)?"0":"1"))); &mov(&swtmp(1), "edi"); &mov(&swtmp(0), "ebx"); - &call("des_encrypt2"); - &mov(&swtmp(2), (($enc)?"1":"0")); + &call("DES_encrypt2"); + &mov(&swtmp(2), (DWC(($enc)?"1":"0"))); &mov(&swtmp(1), "esi"); &mov(&swtmp(0), "ebx"); - &call("des_encrypt2"); + &call("DES_encrypt2"); &stack_pop(3); &mov($L,&DWP(0,"ebx","",0)); diff --git a/src/lib/libcrypto/des/cbc_cksm.c b/src/lib/libcrypto/des/cbc_cksm.c index edfdec8a0f..6c5305b99d 100644 --- a/src/lib/libcrypto/des/cbc_cksm.c +++ b/src/lib/libcrypto/des/cbc_cksm.c @@ -58,21 +58,15 @@ #include "des_locl.h" -DES_LONG des_cbc_cksum(input, output, length, schedule, ivec) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule schedule; -des_cblock (*ivec); +DES_LONG DES_cbc_cksum(const unsigned char *in, DES_cblock *output, + long length, DES_key_schedule *schedule, + const_DES_cblock *ivec) { register DES_LONG tout0,tout1,tin0,tin1; register long l=length; DES_LONG tin[2]; - unsigned char *in,*out,*iv; - - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; + unsigned char *out = &(*output)[0]; + const unsigned char *iv = &(*ivec)[0]; c2l(iv,tout0); c2l(iv,tout1); @@ -88,7 +82,7 @@ des_cblock (*ivec); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT); /* fix 15/10/91 eay - thanks to keithr@sco.COM */ tout0=tin[0]; tout1=tin[1]; diff --git a/src/lib/libcrypto/des/cbc_enc.c b/src/lib/libcrypto/des/cbc_enc.c index a84a53633c..677903ae4e 100644 --- a/src/lib/libcrypto/des/cbc_enc.c +++ b/src/lib/libcrypto/des/cbc_enc.c @@ -56,80 +56,6 @@ * [including the GNU Public Licence.] */ -#include "des_locl.h" - -void des_cbc_encrypt(input, output, length, schedule, ivec, enc) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int enc; - { - register DES_LONG tin0,tin1; - register DES_LONG tout0,tout1,xor0,xor1; - register unsigned char *in,*out; - register long l=length; - DES_LONG tin[2]; - unsigned char *iv; - - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; - - if (enc) - { - c2l(iv,tout0); - c2l(iv,tout1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); - c2l(in,tin1); - tin0^=tout0; tin[0]=tin0; - tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); - tout0=tin[0]; l2c(tout0,out); - tout1=tin[1]; l2c(tout1,out); - } - if (l != -8) - { - c2ln(in,tin0,tin1,l+8); - tin0^=tout0; tin[0]=tin0; - tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); - tout0=tin[0]; l2c(tout0,out); - tout1=tin[1]; l2c(tout1,out); - } - } - else - { - c2l(iv,xor0); - c2l(iv,xor1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); tin[0]=tin0; - c2l(in,tin1); tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); - 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; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); - tout0=tin[0]^xor0; - tout1=tin[1]^xor1; - l2cn(tout0,tout1,out,l+8); - /* xor0=tin0; - xor1=tin1; */ - } - } - tin0=tin1=tout0=tout1=xor0=xor1=0; - tin[0]=tin[1]=0; - } +#define CBC_ENC_C__DONT_UPDATE_IV +#include "ncbc_enc.c" /* des_cbc_encrypt */ diff --git a/src/lib/libcrypto/des/cfb64ede.c b/src/lib/libcrypto/des/cfb64ede.c index 80b8a9eaaa..60c1aa08db 100644 --- a/src/lib/libcrypto/des/cfb64ede.c +++ b/src/lib/libcrypto/des/cfb64ede.c @@ -63,14 +63,10 @@ * 64bit block we have used is contained in *num; */ -void des_ede3_cfb64_encrypt(in, out, length, ks1,ks2,ks3, ivec, num, enc) -unsigned char *in; -unsigned char *out; -long length; -des_key_schedule ks1,ks2,ks3; -des_cblock (*ivec); -int *num; -int enc; +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc) { register DES_LONG v0,v1; register long l=length; @@ -78,7 +74,7 @@ int enc; DES_LONG ti[2]; unsigned char *iv,c,cc; - iv=(unsigned char *)ivec; + iv=&(*ivec)[0]; if (enc) { while (l--) @@ -90,14 +86,14 @@ int enc; ti[0]=v0; ti[1]=v1; - des_encrypt3((DES_LONG *)ti,ks1,ks2,ks3); + DES_encrypt3(ti,ks1,ks2,ks3); v0=ti[0]; v1=ti[1]; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(v0,iv); l2c(v1,iv); - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; } c= *(in++)^iv[n]; *(out++)=c; @@ -116,14 +112,14 @@ int enc; ti[0]=v0; ti[1]=v1; - des_encrypt3((DES_LONG *)ti,ks1,ks2,ks3); + DES_encrypt3(ti,ks1,ks2,ks3); v0=ti[0]; v1=ti[1]; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(v0,iv); l2c(v1,iv); - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; } cc= *(in++); c=iv[n]; @@ -137,15 +133,10 @@ int enc; } #ifdef undef /* MACRO */ -void des_ede2_cfb64_encrypt(in, out, length, ks1,ks2, ivec, num, enc) -unsigned char *in; -unsigned char *out; -long length; -des_key_schedule ks1,ks2; -des_cblock (*ivec); -int *num; -int enc; +void DES_ede2_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + DES_key_schedule ks1, DES_key_schedule ks2, DES_cblock (*ivec), + int *num, int enc) { - des_ede3_cfb64_encrypt(in,out,length,ks1,ks2,ks1,ivec,num,enc); + DES_ede3_cfb64_encrypt(in,out,length,ks1,ks2,ks1,ivec,num,enc); } #endif diff --git a/src/lib/libcrypto/des/cfb64enc.c b/src/lib/libcrypto/des/cfb64enc.c index 403da479df..5ec8683e40 100644 --- a/src/lib/libcrypto/des/cfb64enc.c +++ b/src/lib/libcrypto/des/cfb64enc.c @@ -63,14 +63,9 @@ * 64bit block we have used is contained in *num; */ -void des_cfb64_encrypt(in, out, length, schedule, ivec, num, enc) -unsigned char *in; -unsigned char *out; -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int *num; -int enc; +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num, int enc) { register DES_LONG v0,v1; register long l=length; @@ -78,7 +73,7 @@ int enc; DES_LONG ti[2]; unsigned char *iv,c,cc; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; if (enc) { while (l--) @@ -87,12 +82,11 @@ int enc; { c2l(iv,v0); ti[0]=v0; c2l(iv,v1); ti[1]=v1; - des_encrypt((DES_LONG *)ti, - schedule,DES_ENCRYPT); - iv=(unsigned char *)ivec; + DES_encrypt1(ti,schedule,DES_ENCRYPT); + iv = &(*ivec)[0]; v0=ti[0]; l2c(v0,iv); v0=ti[1]; l2c(v0,iv); - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; } c= *(in++)^iv[n]; *(out++)=c; @@ -108,12 +102,11 @@ int enc; { c2l(iv,v0); ti[0]=v0; c2l(iv,v1); ti[1]=v1; - des_encrypt((DES_LONG *)ti, - schedule,DES_ENCRYPT); - iv=(unsigned char *)ivec; + DES_encrypt1(ti,schedule,DES_ENCRYPT); + iv = &(*ivec)[0]; v0=ti[0]; l2c(v0,iv); v0=ti[1]; l2c(v0,iv); - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; } cc= *(in++); c=iv[n]; diff --git a/src/lib/libcrypto/des/cfb_enc.c b/src/lib/libcrypto/des/cfb_enc.c index 342e785691..17bf77ca9e 100644 --- a/src/lib/libcrypto/des/cfb_enc.c +++ b/src/lib/libcrypto/des/cfb_enc.c @@ -64,14 +64,8 @@ * the second. The second 12 bits will come from the 3rd and half the 4th * byte. */ -void des_cfb_encrypt(in, out, numbits, length, schedule, ivec, enc) -unsigned char *in; -unsigned char *out; -int numbits; -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int enc; +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, DES_cblock *ivec, int enc) { register DES_LONG d0,d1,v0,v1,n=(numbits+7)/8; register DES_LONG mask0,mask1; @@ -96,7 +90,7 @@ int enc; mask1=0x00000000L; } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; c2l(iv,v0); c2l(iv,v1); if (enc) @@ -106,7 +100,7 @@ int enc; l-=n; ti[0]=v0; ti[1]=v1; - des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)ti,schedule,DES_ENCRYPT); c2ln(in,d0,d1,n); in+=n; d0=(d0^ti[0])&mask0; @@ -138,7 +132,7 @@ int enc; l-=n; ti[0]=v0; ti[1]=v1; - des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)ti,schedule,DES_ENCRYPT); c2ln(in,d0,d1,n); in+=n; /* 30-08-94 - eay - changed because l>>32 and @@ -163,7 +157,7 @@ int enc; out+=n; } } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(v0,iv); l2c(v1,iv); v0=v1=d0=d1=ti[0]=ti[1]=0; diff --git a/src/lib/libcrypto/des/des.h b/src/lib/libcrypto/des/des.h index 67f90aaf17..4cb9d84fdf 100644 --- a/src/lib/libcrypto/des/des.h +++ b/src/lib/libcrypto/des/des.h @@ -59,43 +59,50 @@ #ifndef HEADER_DES_H #define HEADER_DES_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef NO_DES +#ifdef OPENSSL_NO_DES #error DES is disabled. #endif -#ifdef _KERBEROS_DES_H -#error replaces . -#endif - -#include #include /* DES_LONG */ #include /* OPENSSL_EXTERN */ -typedef unsigned char des_cblock[8]; -typedef /* const */ unsigned char const_des_cblock[8]; -/* With "const", gcc 2.8.1 on Solaris thinks that des_cblock * - * and const_des_cblock * are incompatible pointer types. - * I haven't seen that warning on other systems ... I'll look - * what the standard says. */ +#ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif +typedef unsigned char DES_cblock[8]; +typedef /* const */ unsigned char const_DES_cblock[8]; +/* With "const", gcc 2.8.1 on Solaris thinks that DES_cblock * + * and const_DES_cblock * are incompatible pointer types. */ -typedef struct des_ks_struct +typedef struct DES_ks + { + union { - union { - des_cblock cblock; - /* make sure things are correct size on machines with - * 8 byte longs */ - DES_LONG deslong[2]; - } ks; - int weak_key; - } des_key_schedule[16]; - -#define DES_KEY_SZ (sizeof(des_cblock)) -#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) + DES_cblock cblock; + /* make sure things are correct size on machines with + * 8 byte longs */ + DES_LONG deslong[2]; + } ks[16]; + } DES_key_schedule; + +#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT +# ifndef OPENSSL_ENABLE_OLD_DES_SUPPORT +# define OPENSSL_ENABLE_OLD_DES_SUPPORT +# endif +#endif + +#ifdef OPENSSL_ENABLE_OLD_DES_SUPPORT +# include +#endif + +#define DES_KEY_SZ (sizeof(DES_cblock)) +#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) #define DES_ENCRYPT 1 #define DES_DECRYPT 0 @@ -103,144 +110,128 @@ typedef struct des_ks_struct #define DES_CBC_MODE 0 #define DES_PCBC_MODE 1 -#define des_ecb2_encrypt(i,o,k1,k2,e) \ - des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) - -#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ - des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) - -#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ - des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) - -#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ - des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) - -OPENSSL_EXTERN int des_check_key; /* defaults to false */ -OPENSSL_EXTERN int des_rw_mode; /* defaults to DES_PCBC_MODE */ -OPENSSL_EXTERN int des_set_weak_key_flag; /* set the weak key flag */ - -const char *des_options(void); -void des_ecb3_encrypt(const_des_cblock *input, des_cblock *output, - des_key_schedule ks1,des_key_schedule ks2, - des_key_schedule ks3, int enc); -DES_LONG des_cbc_cksum(const unsigned char *input,des_cblock *output, - long length,des_key_schedule schedule, - const_des_cblock *ivec); -/* des_cbc_encrypt does not update the IV! Use des_ncbc_encrypt instead. */ -void des_cbc_encrypt(const unsigned char *input,unsigned char *output, - long length,des_key_schedule schedule,des_cblock *ivec, +#define DES_ecb2_encrypt(i,o,k1,k2,e) \ + DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +#define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +#define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +#define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +OPENSSL_DECLARE_GLOBAL(int,DES_check_key); /* defaults to false */ +#define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key) +OPENSSL_DECLARE_GLOBAL(int,DES_rw_mode); /* defaults to DES_PCBC_MODE */ +#define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode) + +const char *DES_options(void); +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1,DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc); +DES_LONG DES_cbc_cksum(const unsigned char *input,DES_cblock *output, + long length,DES_key_schedule *schedule, + const_DES_cblock *ivec); +/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */ +void DES_cbc_encrypt(const unsigned char *input,unsigned char *output, + long length,DES_key_schedule *schedule,DES_cblock *ivec, int enc); -void des_ncbc_encrypt(const unsigned char *input,unsigned char *output, - long length,des_key_schedule schedule,des_cblock *ivec, +void DES_ncbc_encrypt(const unsigned char *input,unsigned char *output, + long length,DES_key_schedule *schedule,DES_cblock *ivec, int enc); -void des_xcbc_encrypt(const unsigned char *input,unsigned char *output, - long length,des_key_schedule schedule,des_cblock *ivec, - const_des_cblock *inw,const_des_cblock *outw,int enc); -void des_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits, - long length,des_key_schedule schedule,des_cblock *ivec, +void DES_xcbc_encrypt(const unsigned char *input,unsigned char *output, + long length,DES_key_schedule *schedule,DES_cblock *ivec, + const_DES_cblock *inw,const_DES_cblock *outw,int enc); +void DES_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits, + long length,DES_key_schedule *schedule,DES_cblock *ivec, int enc); -void des_ecb_encrypt(const_des_cblock *input,des_cblock *output, - des_key_schedule ks,int enc); -void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); -void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); -void des_encrypt3(DES_LONG *data, des_key_schedule ks1, - des_key_schedule ks2, des_key_schedule ks3); -void des_decrypt3(DES_LONG *data, des_key_schedule ks1, - des_key_schedule ks2, des_key_schedule ks3); -void des_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output, +void DES_ecb_encrypt(const_DES_cblock *input,DES_cblock *output, + DES_key_schedule *ks,int enc); + +/* This is the DES encryption function that gets called by just about + every other DES routine in the library. You should not use this + function except to implement 'modes' of DES. I say this because the + functions that call this routine do the conversion from 'char *' to + long, and this needs to be done to make sure 'non-aligned' memory + access do not occur. The characters are loaded 'little endian'. + Data is a pointer to 2 unsigned long's and ks is the + DES_key_schedule to use. enc, is non zero specifies encryption, + zero if decryption. */ +void DES_encrypt1(DES_LONG *data,DES_key_schedule *ks, int enc); + +/* This functions is the same as DES_encrypt1() except that the DES + initial permutation (IP) and final permutation (FP) have been left + out. As for DES_encrypt1(), you should not use this function. + It is used by the routines in the library that implement triple DES. + IP() DES_encrypt2() DES_encrypt2() DES_encrypt2() FP() is the same + as DES_encrypt1() DES_encrypt1() DES_encrypt1() except faster :-). */ +void DES_encrypt2(DES_LONG *data,DES_key_schedule *ks, int enc); + +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output, long length, - des_key_schedule ks1,des_key_schedule ks2, - des_key_schedule ks3,des_cblock *ivec,int enc); -void des_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out, + DES_key_schedule *ks1,DES_key_schedule *ks2, + DES_key_schedule *ks3,DES_cblock *ivec,int enc); +void DES_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out, long length, - des_key_schedule ks1,des_key_schedule ks2, - des_key_schedule ks3, - des_cblock *ivec1,des_cblock *ivec2, + DES_key_schedule *ks1,DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec1,DES_cblock *ivec2, int enc); -void des_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out, - long length,des_key_schedule ks1, - des_key_schedule ks2,des_key_schedule ks3, - des_cblock *ivec,int *num,int enc); -void des_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out, - long length,des_key_schedule ks1, - des_key_schedule ks2,des_key_schedule ks3, - des_cblock *ivec,int *num); - -void des_xwhite_in2out(const_des_cblock *des_key,const_des_cblock *in_white, - des_cblock *out_white); - -int des_enc_read(int fd,void *buf,int len,des_key_schedule sched, - des_cblock *iv); -int des_enc_write(int fd,const void *buf,int len,des_key_schedule sched, - des_cblock *iv); -char *des_fcrypt(const char *buf,const char *salt, char *ret); -char *des_crypt(const char *buf,const char *salt); -#if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) -char *crypt(const char *buf,const char *salt); -#endif -void des_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits, - long length,des_key_schedule schedule,des_cblock *ivec); -void des_pcbc_encrypt(const unsigned char *input,unsigned char *output, - long length,des_key_schedule schedule,des_cblock *ivec, +void DES_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out, + long length,DES_key_schedule *ks1, + DES_key_schedule *ks2,DES_key_schedule *ks3, + DES_cblock *ivec,int *num,int enc); +void DES_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out, + long length,DES_key_schedule *ks1, + DES_key_schedule *ks2,DES_key_schedule *ks3, + DES_cblock *ivec,int *num); + +void DES_xwhite_in2out(const_DES_cblock *DES_key,const_DES_cblock *in_white, + DES_cblock *out_white); + +int DES_enc_read(int fd,void *buf,int len,DES_key_schedule *sched, + DES_cblock *iv); +int DES_enc_write(int fd,const void *buf,int len,DES_key_schedule *sched, + DES_cblock *iv); +char *DES_fcrypt(const char *buf,const char *salt, char *ret); +char *DES_crypt(const char *buf,const char *salt); +void DES_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits, + long length,DES_key_schedule *schedule,DES_cblock *ivec); +void DES_pcbc_encrypt(const unsigned char *input,unsigned char *output, + long length,DES_key_schedule *schedule,DES_cblock *ivec, int enc); -DES_LONG des_quad_cksum(const unsigned char *input,des_cblock output[], - long length,int out_count,des_cblock *seed); -void des_random_seed(des_cblock *key); -void des_random_key(des_cblock *ret); -int des_read_password(des_cblock *key,const char *prompt,int verify); -int des_read_2passwords(des_cblock *key1,des_cblock *key2, - const char *prompt,int verify); -int des_read_pw_string(char *buf,int length,const char *prompt,int verify); -void des_set_odd_parity(des_cblock *key); -int des_is_weak_key(const_des_cblock *key); -int des_set_key(const_des_cblock *key,des_key_schedule schedule); -int des_key_sched(const_des_cblock *key,des_key_schedule schedule); -void des_string_to_key(const char *str,des_cblock *key); -void des_string_to_2keys(const char *str,des_cblock *key1,des_cblock *key2); -void des_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length, - des_key_schedule schedule,des_cblock *ivec,int *num, +DES_LONG DES_quad_cksum(const unsigned char *input,DES_cblock output[], + long length,int out_count,DES_cblock *seed); +int DES_random_key(DES_cblock *ret); +void DES_set_odd_parity(DES_cblock *key); +int DES_check_key_parity(const_DES_cblock *key); +int DES_is_weak_key(const_DES_cblock *key); +/* DES_set_key (= set_key = DES_key_sched = key_sched) calls + * DES_set_key_checked if global variable DES_check_key is set, + * DES_set_key_unchecked otherwise. */ +int DES_set_key(const_DES_cblock *key,DES_key_schedule *schedule); +int DES_key_sched(const_DES_cblock *key,DES_key_schedule *schedule); +int DES_set_key_checked(const_DES_cblock *key,DES_key_schedule *schedule); +void DES_set_key_unchecked(const_DES_cblock *key,DES_key_schedule *schedule); +void DES_string_to_key(const char *str,DES_cblock *key); +void DES_string_to_2keys(const char *str,DES_cblock *key1,DES_cblock *key2); +void DES_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length, + DES_key_schedule *schedule,DES_cblock *ivec,int *num, int enc); -void des_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length, - des_key_schedule schedule,des_cblock *ivec,int *num); -int des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify); +void DES_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length, + DES_key_schedule *schedule,DES_cblock *ivec,int *num); -/* Extra functions from Mark Murray */ -void des_cblock_print_file(const_des_cblock *cb, FILE *fp); - -/* The following definitions provide compatibility with the MIT Kerberos - * library. The des_key_schedule structure is not binary compatible. */ - -#define _KERBEROS_DES_H - -#define KRBDES_ENCRYPT DES_ENCRYPT -#define KRBDES_DECRYPT DES_DECRYPT - -#ifdef KERBEROS -# define ENCRYPT DES_ENCRYPT -# define DECRYPT DES_DECRYPT -#endif - -#ifndef NCOMPAT -# define C_Block des_cblock -# define Key_schedule des_key_schedule -# define KEY_SZ DES_KEY_SZ -# define string_to_key des_string_to_key -# define read_pw_string des_read_pw_string -# define random_key des_random_key -# define pcbc_encrypt des_pcbc_encrypt -# define set_key des_set_key -# define key_sched des_key_sched -# define ecb_encrypt des_ecb_encrypt -# define cbc_encrypt des_cbc_encrypt -# define ncbc_encrypt des_ncbc_encrypt -# define xcbc_encrypt des_xcbc_encrypt -# define cbc_cksum des_cbc_cksum -# define quad_cksum des_quad_cksum -#endif +int DES_read_password(DES_cblock *key, const char *prompt, int verify); +int DES_read_2passwords(DES_cblock *key1, DES_cblock *key2, const char *prompt, + int verify); -typedef des_key_schedule bit_64; -#define des_fixup_key_parity des_set_odd_parity -#define des_check_key_parity check_parity +#define DES_fixup_key_parity DES_set_odd_parity #ifdef __cplusplus } diff --git a/src/lib/libcrypto/des/des_enc.c b/src/lib/libcrypto/des/des_enc.c index e4db09299e..1c37ab96d3 100644 --- a/src/lib/libcrypto/des/des_enc.c +++ b/src/lib/libcrypto/des/des_enc.c @@ -58,14 +58,11 @@ #include "des_locl.h" -void des_encrypt(data, ks, enc) -DES_LONG *data; -des_key_schedule ks; -int enc; +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc) { register DES_LONG l,r,t,u; #ifdef DES_PTR - register unsigned char *des_SP=(unsigned char *)des_SPtrans; + register const unsigned char *des_SP=(const unsigned char *)DES_SPtrans; #endif #ifndef DES_UNROLL register int i; @@ -78,7 +75,7 @@ int enc; IP(r,l); /* Things have been modified so that the initial rotate is * done outside the loop. This required the - * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * DES_SPtrans values in sp.h to be rotated 1 bit to the right. * One perl script later and things have a 5% speed up on a sparc2. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> * for pointing this out. */ @@ -87,7 +84,7 @@ int enc; r=ROTATE(r,29)&0xffffffffL; l=ROTATE(l,29)&0xffffffffL; - s=(DES_LONG *)ks; + s=ks->ks->deslong; /* I don't know if it is worth the effort of loop unrolling the * inner loop */ if (enc) @@ -159,14 +156,11 @@ int enc; l=r=t=u=0; } -void des_encrypt2(data, ks, enc) -DES_LONG *data; -des_key_schedule ks; -int enc; +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc) { register DES_LONG l,r,t,u; #ifdef DES_PTR - register unsigned char *des_SP=(unsigned char *)des_SPtrans; + register const unsigned char *des_SP=(const unsigned char *)DES_SPtrans; #endif #ifndef DES_UNROLL register int i; @@ -178,7 +172,7 @@ int enc; /* Things have been modified so that the initial rotate is * done outside the loop. This required the - * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * DES_SPtrans values in sp.h to be rotated 1 bit to the right. * One perl script later and things have a 5% speed up on a sparc2. * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> * for pointing this out. */ @@ -186,7 +180,7 @@ int enc; r=ROTATE(r,29)&0xffffffffL; l=ROTATE(l,29)&0xffffffffL; - s=(DES_LONG *)ks; + s=ks->ks->deslong; /* I don't know if it is worth the effort of loop unrolling the * inner loop */ if (enc) @@ -253,11 +247,8 @@ int enc; l=r=t=u=0; } -void des_encrypt3(data,ks1,ks2,ks3) -DES_LONG *data; -des_key_schedule ks1; -des_key_schedule ks2; -des_key_schedule ks3; +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3) { register DES_LONG l,r; @@ -266,9 +257,9 @@ des_key_schedule ks3; IP(l,r); data[0]=l; data[1]=r; - des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); - des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); - des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); + DES_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); + DES_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); + DES_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); l=data[0]; r=data[1]; FP(r,l); @@ -276,11 +267,8 @@ des_key_schedule ks3; data[1]=r; } -void des_decrypt3(data,ks1,ks2,ks3) -DES_LONG *data; -des_key_schedule ks1; -des_key_schedule ks2; -des_key_schedule ks3; +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3) { register DES_LONG l,r; @@ -289,9 +277,9 @@ des_key_schedule ks3; IP(l,r); data[0]=l; data[1]=r; - des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); - des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); - des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); + DES_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); + DES_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); + DES_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); l=data[0]; r=data[1]; FP(r,l); @@ -301,108 +289,25 @@ des_key_schedule ks3; #ifndef DES_DEFAULT_OPTIONS -void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int enc; - { - register DES_LONG tin0,tin1; - register DES_LONG tout0,tout1,xor0,xor1; - register unsigned char *in,*out; - register long l=length; - DES_LONG tin[2]; - unsigned char *iv; - - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; - - if (enc) - { - c2l(iv,tout0); - c2l(iv,tout1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); - c2l(in,tin1); - tin0^=tout0; tin[0]=tin0; - tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); - tout0=tin[0]; l2c(tout0,out); - tout1=tin[1]; l2c(tout1,out); - } - if (l != -8) - { - c2ln(in,tin0,tin1,l+8); - tin0^=tout0; tin[0]=tin0; - tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); - tout0=tin[0]; l2c(tout0,out); - tout1=tin[1]; l2c(tout1,out); - } - iv=(unsigned char *)ivec; - l2c(tout0,iv); - l2c(tout1,iv); - } - else - { - c2l(iv,xor0); - c2l(iv,xor1); - for (l-=8; l>=0; l-=8) - { - c2l(in,tin0); tin[0]=tin0; - c2l(in,tin1); tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); - 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; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); - tout0=tin[0]^xor0; - tout1=tin[1]^xor1; - l2cn(tout0,tout1,out,l+8); - xor0=tin0; - xor1=tin1; - } - - iv=(unsigned char *)ivec; - l2c(xor0,iv); - l2c(xor1,iv); - } - tin0=tin1=tout0=tout1=xor0=xor1=0; - tin[0]=tin[1]=0; - } +#undef CBC_ENC_C__DONT_UPDATE_IV +#include "ncbc_enc.c" /* DES_ncbc_encrypt */ -void des_ede3_cbc_encrypt(input, output, length, ks1, ks2, ks3, ivec, enc) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule ks1; -des_key_schedule ks2; -des_key_schedule ks3; -des_cblock (*ivec); -int enc; +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc) { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; - register unsigned char *in,*out; + register const unsigned char *in; + unsigned char *out; register long l=length; DES_LONG tin[2]; unsigned char *iv; - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; + in=input; + out=output; + iv = &(*ivec)[0]; if (enc) { @@ -417,7 +322,7 @@ int enc; tin[0]=tin0; tin[1]=tin1; - des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); + DES_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; @@ -432,14 +337,14 @@ int enc; tin[0]=tin0; tin[1]=tin1; - des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); + DES_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; l2c(tout0,out); l2c(tout1,out); } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(tout0,iv); l2c(tout1,iv); } @@ -459,7 +364,7 @@ int enc; tin[0]=tin0; tin[1]=tin1; - des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); + DES_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; @@ -480,7 +385,7 @@ int enc; tin[0]=tin0; tin[1]=tin1; - des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); + DES_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); tout0=tin[0]; tout1=tin[1]; @@ -491,7 +396,7 @@ int enc; xor1=t1; } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(xor0,iv); l2c(xor1,iv); } diff --git a/src/lib/libcrypto/des/des_locl.h b/src/lib/libcrypto/des/des_locl.h index d6ea17cb68..70e833be3f 100644 --- a/src/lib/libcrypto/des/des_locl.h +++ b/src/lib/libcrypto/des/des_locl.h @@ -59,36 +59,45 @@ #ifndef HEADER_DES_LOCL_H #define HEADER_DES_LOCL_H -#if defined(WIN32) || defined(WIN16) -#ifndef MSDOS -#define MSDOS +#include + +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) +#ifndef OPENSSL_SYS_MSDOS +#define OPENSSL_SYS_MSDOS #endif #endif #include #include -#include - -#ifndef MSDOS -#if !defined(VMS) || defined(__DECC) -#include OPENSSL_UNISTD +#ifndef OPENSSL_SYS_MSDOS +#if !defined(OPENSSL_SYS_VMS) || defined(__DECC) +#ifdef OPENSSL_UNISTD +# include OPENSSL_UNISTD +#else +# include +#endif #include #endif #endif #include -#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ +#ifdef OPENSSL_SYS_MSDOS /* Visual C++ 2.1 (Windows NT/95) */ #include #include #include #include #endif -#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) +#if defined(__STDC__) || defined(OPENSSL_SYS_VMS) || defined(M_XENIX) || defined(OPENSSL_SYS_MSDOS) #include #endif +#ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif + #define ITERATIONS 16 #define HALF_ITERATIONS 8 @@ -151,7 +160,7 @@ } \ } -#if defined(WIN32) +#if defined(OPENSSL_SYS_WIN32) && defined(_MSC_VER) #define ROTATE(a,n) (_lrotr(a,n)) #else #define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) @@ -178,14 +187,14 @@ #endif /* The changes to this macro may help or hinder, depending on the - * compiler and the achitecture. gcc2 always seems to do well :-). + * compiler and the architecture. gcc2 always seems to do well :-). * Inspired by Dana How * DO NOT use the alternative version on machines with 8 byte longs. * It does not seem to work on the Alpha, even when DES_LONG is 4 * bytes, probably an issue of accessing non-word aligned objects :-( */ #ifdef DES_PTR -/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there +/* It recently occurred to me that 0^0^0^0^0^0^0 == 0, so there * is no reason to not xor all the sub items together. This potentially * saves a register since things can be xored directly into L */ @@ -274,24 +283,24 @@ u1=(int)u&0x3f; \ u2&=0x3f; \ u>>=16L; \ - LL^=des_SPtrans[0][u1]; \ - LL^=des_SPtrans[2][u2]; \ + LL^=DES_SPtrans[0][u1]; \ + LL^=DES_SPtrans[2][u2]; \ u3=(int)u>>8L; \ u1=(int)u&0x3f; \ u3&=0x3f; \ - LL^=des_SPtrans[4][u1]; \ - LL^=des_SPtrans[6][u3]; \ + LL^=DES_SPtrans[4][u1]; \ + LL^=DES_SPtrans[6][u3]; \ u2=(int)t>>8L; \ u1=(int)t&0x3f; \ u2&=0x3f; \ t>>=16L; \ - LL^=des_SPtrans[1][u1]; \ - LL^=des_SPtrans[3][u2]; \ + LL^=DES_SPtrans[1][u1]; \ + LL^=DES_SPtrans[3][u2]; \ u3=(int)t>>8L; \ u1=(int)t&0x3f; \ u3&=0x3f; \ - LL^=des_SPtrans[5][u1]; \ - LL^=des_SPtrans[7][u3]; } + LL^=DES_SPtrans[5][u1]; \ + LL^=DES_SPtrans[7][u3]; } #endif #ifdef DES_RISC2 #define D_ENCRYPT(LL,R,S) {\ @@ -302,25 +311,25 @@ u2=(int)u>>8L; \ u1=(int)u&0x3f; \ u2&=0x3f; \ - LL^=des_SPtrans[0][u1]; \ - LL^=des_SPtrans[2][u2]; \ + LL^=DES_SPtrans[0][u1]; \ + LL^=DES_SPtrans[2][u2]; \ s1=(int)u>>16L; \ s2=(int)u>>24L; \ s1&=0x3f; \ s2&=0x3f; \ - LL^=des_SPtrans[4][s1]; \ - LL^=des_SPtrans[6][s2]; \ + LL^=DES_SPtrans[4][s1]; \ + LL^=DES_SPtrans[6][s2]; \ u2=(int)t>>8L; \ u1=(int)t&0x3f; \ u2&=0x3f; \ - LL^=des_SPtrans[1][u1]; \ - LL^=des_SPtrans[3][u2]; \ + LL^=DES_SPtrans[1][u1]; \ + LL^=DES_SPtrans[3][u2]; \ s1=(int)t>>16; \ s2=(int)t>>24L; \ s1&=0x3f; \ s2&=0x3f; \ - LL^=des_SPtrans[5][s1]; \ - LL^=des_SPtrans[7][s2]; } + LL^=DES_SPtrans[5][s1]; \ + LL^=DES_SPtrans[7][s2]; } #endif #else @@ -329,14 +338,14 @@ LOAD_DATA_tmp(R,S,u,t,E0,E1); \ t=ROTATE(t,4); \ LL^=\ - des_SPtrans[0][(u>> 2L)&0x3f]^ \ - des_SPtrans[2][(u>>10L)&0x3f]^ \ - des_SPtrans[4][(u>>18L)&0x3f]^ \ - des_SPtrans[6][(u>>26L)&0x3f]^ \ - des_SPtrans[1][(t>> 2L)&0x3f]^ \ - des_SPtrans[3][(t>>10L)&0x3f]^ \ - des_SPtrans[5][(t>>18L)&0x3f]^ \ - des_SPtrans[7][(t>>26L)&0x3f]; } + DES_SPtrans[0][(u>> 2L)&0x3f]^ \ + DES_SPtrans[2][(u>>10L)&0x3f]^ \ + DES_SPtrans[4][(u>>18L)&0x3f]^ \ + DES_SPtrans[6][(u>>26L)&0x3f]^ \ + DES_SPtrans[1][(t>> 2L)&0x3f]^ \ + DES_SPtrans[3][(t>>10L)&0x3f]^ \ + DES_SPtrans[5][(t>>18L)&0x3f]^ \ + DES_SPtrans[7][(t>>26L)&0x3f]; } #endif #endif @@ -401,8 +410,8 @@ PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ } -OPENSSL_EXTERN const DES_LONG des_SPtrans[8][64]; +OPENSSL_EXTERN const DES_LONG DES_SPtrans[8][64]; -void fcrypt_body(DES_LONG *out,des_key_schedule ks, - DES_LONG Eswap0, DES_LONG Eswap1); +void fcrypt_body(DES_LONG *out,DES_key_schedule *ks, + DES_LONG Eswap0, DES_LONG Eswap1); #endif diff --git a/src/lib/libcrypto/des/ecb3_enc.c b/src/lib/libcrypto/des/ecb3_enc.c index 140f6b5285..c3437bc606 100644 --- a/src/lib/libcrypto/des/ecb3_enc.c +++ b/src/lib/libcrypto/des/ecb3_enc.c @@ -58,28 +58,24 @@ #include "des_locl.h" -void des_ecb3_encrypt(input, output, ks1, ks2, ks3, enc) -des_cblock (*input); -des_cblock (*output); -des_key_schedule ks1; -des_key_schedule ks2; -des_key_schedule ks3; -int enc; +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, + int enc) { register DES_LONG l0,l1; - register unsigned char *in,*out; DES_LONG ll[2]; + const unsigned char *in = &(*input)[0]; + unsigned char *out = &(*output)[0]; - in=(unsigned char *)input; - out=(unsigned char *)output; c2l(in,l0); c2l(in,l1); ll[0]=l0; ll[1]=l1; if (enc) - des_encrypt3(ll,ks1,ks2,ks3); + DES_encrypt3(ll,ks1,ks2,ks3); else - des_decrypt3(ll,ks1,ks2,ks3); + DES_decrypt3(ll,ks1,ks2,ks3); l0=ll[0]; l1=ll[1]; l2c(l0,out); diff --git a/src/lib/libcrypto/des/ecb_enc.c b/src/lib/libcrypto/des/ecb_enc.c index acf23fdd00..4650f2fa0f 100644 --- a/src/lib/libcrypto/des/ecb_enc.c +++ b/src/lib/libcrypto/des/ecb_enc.c @@ -58,20 +58,20 @@ #include "des_locl.h" #include "spr.h" +#include -char *libdes_version="libdes v 3.24 - 20-Apr-1996 - eay"; -char *DES_version="DES part of SSLeay 0.9.0b 29-Jun-1998"; +OPENSSL_GLOBAL const char *libdes_version="libdes" OPENSSL_VERSION_PTEXT; +OPENSSL_GLOBAL const char *DES_version="DES" OPENSSL_VERSION_PTEXT; -char *des_options() +const char *DES_options(void) { static int init=1; static char buf[32]; if (init) { - char *ptr,*unroll,*risc,*size; + const char *ptr,*unroll,*risc,*size; - init=0; #ifdef DES_PTR ptr="ptr"; #else @@ -97,28 +97,24 @@ char *des_options() else size="long"; sprintf(buf,"des(%s,%s,%s,%s)",ptr,risc,unroll,size); + init=0; } return(buf); } -void des_ecb_encrypt(input, output, ks, enc) -des_cblock (*input); -des_cblock (*output); -des_key_schedule ks; -int enc; +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc) { register DES_LONG l; - register unsigned char *in,*out; DES_LONG ll[2]; + const unsigned char *in = &(*input)[0]; + unsigned char *out = &(*output)[0]; - in=(unsigned char *)input; - out=(unsigned char *)output; c2l(in,l); ll[0]=l; c2l(in,l); ll[1]=l; - des_encrypt(ll,ks,enc); + DES_encrypt1(ll,ks,enc); l=ll[0]; l2c(l,out); l=ll[1]; l2c(l,out); l=ll[0]=ll[1]=0; } - diff --git a/src/lib/libcrypto/des/ede_cbcm_enc.c b/src/lib/libcrypto/des/ede_cbcm_enc.c index c53062481d..fa45aa272b 100644 --- a/src/lib/libcrypto/des/ede_cbcm_enc.c +++ b/src/lib/libcrypto/des/ede_cbcm_enc.c @@ -68,12 +68,12 @@ http://www.cs.technion.ac.il/users/wwwb/cgi-bin/tr-get.cgi/1998/CS/CS0928.ps.gz */ -#ifndef NO_DESCBCM +#ifndef OPENSSL_NO_DESCBCM #include "des_locl.h" -void des_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, - long length, des_key_schedule ks1, des_key_schedule ks2, - des_key_schedule ks3, des_cblock *ivec1, des_cblock *ivec2, +void DES_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, DES_cblock *ivec1, DES_cblock *ivec2, int enc) { register DES_LONG tin0,tin1; @@ -95,7 +95,7 @@ void des_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, { tin[0]=m0; tin[1]=m1; - des_encrypt(tin,ks3,1); + DES_encrypt1(tin,ks3,1); m0=tin[0]; m1=tin[1]; @@ -113,13 +113,13 @@ void des_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, tin[0]=tin0; tin[1]=tin1; - des_encrypt(tin,ks1,1); + DES_encrypt1(tin,ks1,1); tin[0]^=m0; tin[1]^=m1; - des_encrypt(tin,ks2,0); + DES_encrypt1(tin,ks2,0); tin[0]^=m0; tin[1]^=m1; - des_encrypt(tin,ks1,1); + DES_encrypt1(tin,ks1,1); tout0=tin[0]; tout1=tin[1]; @@ -146,7 +146,7 @@ void des_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, { tin[0]=m0; tin[1]=m1; - des_encrypt(tin,ks3,1); + DES_encrypt1(tin,ks3,1); m0=tin[0]; m1=tin[1]; @@ -158,13 +158,13 @@ void des_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, tin[0]=tin0; tin[1]=tin1; - des_encrypt(tin,ks1,0); + DES_encrypt1(tin,ks1,0); tin[0]^=m0; tin[1]^=m1; - des_encrypt(tin,ks2,1); + DES_encrypt1(tin,ks2,1); tin[0]^=m0; tin[1]^=m1; - des_encrypt(tin,ks1,0); + DES_encrypt1(tin,ks1,0); tout0=tin[0]; tout1=tin[1]; diff --git a/src/lib/libcrypto/des/enc_read.c b/src/lib/libcrypto/des/enc_read.c index e08a904d75..c70fb686b8 100644 --- a/src/lib/libcrypto/des/enc_read.c +++ b/src/lib/libcrypto/des/enc_read.c @@ -58,18 +58,34 @@ #include #include +#include "cryptlib.h" #include "des_locl.h" /* This has some uglies in it but it works - even over sockets. */ /*extern int errno;*/ -int des_rw_mode=DES_PCBC_MODE; - -int des_enc_read(fd, buf, len, sched, iv) -int fd; -char *buf; -int len; -des_key_schedule sched; -des_cblock (*iv); +OPENSSL_IMPLEMENT_GLOBAL(int,DES_rw_mode)=DES_PCBC_MODE; + + +/* + * WARNINGS: + * + * - The data format used by DES_enc_write() and DES_enc_read() + * has a cryptographic weakness: When asked to write more + * than MAXWRITE bytes, DES_enc_write will split the data + * into several chunks that are all encrypted + * using the same IV. So don't use these functions unless you + * are sure you know what you do (in which case you might + * not want to use them anyway). + * + * - This code cannot handle non-blocking sockets. + * + * - This function uses an internal state and thus cannot be + * used on multiple files. + */ + + +int DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched, + DES_cblock *iv) { /* data to be unencrypted */ int net_num=0; @@ -77,27 +93,27 @@ des_cblock (*iv); /* extra unencrypted data * for when a block of 100 comes in but is des_read one byte at * a time. */ - static char *unnet=NULL; + static unsigned char *unnet=NULL; static int unnet_start=0; static int unnet_left=0; - static char *tmpbuf=NULL; + static unsigned char *tmpbuf=NULL; int i; long num=0,rnum; unsigned char *p; if (tmpbuf == NULL) { - tmpbuf=(char *)malloc(BSIZE); + tmpbuf=OPENSSL_malloc(BSIZE); if (tmpbuf == NULL) return(-1); } if (net == NULL) { - net=(unsigned char *)malloc(BSIZE); + net=OPENSSL_malloc(BSIZE); if (net == NULL) return(-1); } if (unnet == NULL) { - unnet=(char *)malloc(BSIZE); + unnet=OPENSSL_malloc(BSIZE); if (unnet == NULL) return(-1); } /* left over data from last decrypt */ @@ -109,7 +125,7 @@ des_cblock (*iv); * with the number of bytes we have - should always * check the return value */ memcpy(buf,&(unnet[unnet_start]), - (unsigned int)unnet_left); + unnet_left); /* eay 26/08/92 I had the next 2 lines * reversed :-( */ i=unnet_left; @@ -117,7 +133,7 @@ des_cblock (*iv); } else { - memcpy(buf,&(unnet[unnet_start]),(unsigned int)len); + memcpy(buf,&(unnet[unnet_start]),len); unnet_start+=len; unnet_left-=len; i=len; @@ -131,7 +147,7 @@ des_cblock (*iv); /* first - get the length */ while (net_num < HDRSIZE) { - i=read(fd,&(net[net_num]),(unsigned int)HDRSIZE-net_num); + i=read(fd,(void *)&(net[net_num]),HDRSIZE-net_num); #ifdef EINTR if ((i == -1) && (errno == EINTR)) continue; #endif @@ -153,7 +169,7 @@ des_cblock (*iv); net_num=0; while (net_num < rnum) { - i=read(fd,&(net[net_num]),(unsigned int)rnum-net_num); + i=read(fd,(void *)&(net[net_num]),rnum-net_num); #ifdef EINTR if ((i == -1) && (errno == EINTR)) continue; #endif @@ -164,15 +180,13 @@ des_cblock (*iv); /* Check if there will be data left over. */ if (len < num) { - if (des_rw_mode & DES_PCBC_MODE) - des_pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet, - num,sched,iv,DES_DECRYPT); + if (DES_rw_mode & DES_PCBC_MODE) + DES_pcbc_encrypt(net,unnet,num,sched,iv,DES_DECRYPT); else - des_cbc_encrypt((des_cblock *)net,(des_cblock *)unnet, - num,sched,iv,DES_DECRYPT); - memcpy(buf,unnet,(unsigned int)len); + DES_cbc_encrypt(net,unnet,num,sched,iv,DES_DECRYPT); + memcpy(buf,unnet,len); unnet_start=len; - unnet_left=(int)num-len; + unnet_left=num-len; /* The following line is done because we return num * as the number of bytes read. */ @@ -188,31 +202,27 @@ des_cblock (*iv); if (len < rnum) { - if (des_rw_mode & DES_PCBC_MODE) - des_pcbc_encrypt((des_cblock *)net, - (des_cblock *)tmpbuf, - num,sched,iv,DES_DECRYPT); + if (DES_rw_mode & DES_PCBC_MODE) + DES_pcbc_encrypt(net,tmpbuf,num,sched,iv, + DES_DECRYPT); else - des_cbc_encrypt((des_cblock *)net, - (des_cblock *)tmpbuf, - num,sched,iv,DES_DECRYPT); + DES_cbc_encrypt(net,tmpbuf,num,sched,iv, + DES_DECRYPT); /* eay 26/08/92 fix a bug that returned more * bytes than you asked for (returned len bytes :-( */ - memcpy(buf,tmpbuf,(unsigned int)num); + memcpy(buf,tmpbuf,num); } else { - if (des_rw_mode & DES_PCBC_MODE) - des_pcbc_encrypt((des_cblock *)net, - (des_cblock *)buf,num,sched,iv, - DES_DECRYPT); + if (DES_rw_mode & DES_PCBC_MODE) + DES_pcbc_encrypt(net,buf,num,sched,iv, + DES_DECRYPT); else - des_cbc_encrypt((des_cblock *)net, - (des_cblock *)buf,num,sched,iv, - DES_DECRYPT); + DES_cbc_encrypt(net,buf,num,sched,iv, + DES_DECRYPT); } } - return((int)num); + return num; } diff --git a/src/lib/libcrypto/des/enc_writ.c b/src/lib/libcrypto/des/enc_writ.c index 29a7330fb0..af5b8c2349 100644 --- a/src/lib/libcrypto/des/enc_writ.c +++ b/src/lib/libcrypto/des/enc_writ.c @@ -58,32 +58,44 @@ #include #include +#include +#include "cryptlib.h" #include "des_locl.h" +#include -int des_enc_write(fd, buf, len, sched, iv) -int fd; -char *buf; -int len; -des_key_schedule sched; -des_cblock (*iv); +/* + * WARNINGS: + * + * - The data format used by DES_enc_write() and DES_enc_read() + * has a cryptographic weakness: When asked to write more + * than MAXWRITE bytes, DES_enc_write will split the data + * into several chunks that are all encrypted + * using the same IV. So don't use these functions unless you + * are sure you know what you do (in which case you might + * not want to use them anyway). + * + * - This code cannot handle non-blocking sockets. + */ + +int DES_enc_write(int fd, const void *_buf, int len, + DES_key_schedule *sched, DES_cblock *iv) { #ifdef _LIBC - extern int srandom(); extern unsigned long time(); - extern int random(); extern int write(); #endif - + const unsigned char *buf=_buf; long rnum; int i,j,k,outnum; - static char *outbuf=NULL; - char shortbuf[8]; - char *p; + static unsigned char *outbuf=NULL; + unsigned char shortbuf[8]; + unsigned char *p; + const unsigned char *cp; static int start=1; if (outbuf == NULL) { - outbuf=(char *)malloc(BSIZE+HDRSIZE); + outbuf=OPENSSL_malloc(BSIZE+HDRSIZE); if (outbuf == NULL) return(-1); } /* If we are sending less than 8 bytes, the same char will look @@ -91,7 +103,6 @@ des_cblock (*iv); if (start) { start=0; - srandom((unsigned int)time(NULL)); } /* lets recurse if we want to send the data in small chunks */ @@ -100,7 +111,7 @@ des_cblock (*iv); j=0; for (i=0; i MAXWRITE)?MAXWRITE:(len-i),sched,iv); if (k < 0) return(k); @@ -117,40 +128,40 @@ des_cblock (*iv); /* pad short strings */ if (len < 8) { - p=shortbuf; - memcpy(shortbuf,buf,(unsigned int)len); - for (i=len; i<8; i++) - shortbuf[i]=random(); + cp=shortbuf; + memcpy(shortbuf,buf,len); + RAND_pseudo_bytes(shortbuf+len, 8-len); rnum=8; } else { - p=buf; + cp=buf; rnum=((len+7)/8*8); /* round up to nearest eight */ } - if (des_rw_mode & DES_PCBC_MODE) - des_pcbc_encrypt((des_cblock *)p, - (des_cblock *)&(outbuf[HDRSIZE]), - (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); + if (DES_rw_mode & DES_PCBC_MODE) + DES_pcbc_encrypt(cp,&(outbuf[HDRSIZE]),(len<8)?8:len,sched,iv, + DES_ENCRYPT); else - des_cbc_encrypt((des_cblock *)p, - (des_cblock *)&(outbuf[HDRSIZE]), - (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); + DES_cbc_encrypt(cp,&(outbuf[HDRSIZE]),(len<8)?8:len,sched,iv, + DES_ENCRYPT); /* output */ - outnum=(int)rnum+HDRSIZE; + outnum=rnum+HDRSIZE; for (j=0; j +#ifdef _OSD_POSIX +#ifndef CHARSET_EBCDIC +#define CHARSET_EBCDIC 1 +#endif +#endif +#ifdef CHARSET_EBCDIC +#include +#endif -/* This version of crypt has been developed from my MIT compatable +/* This version of crypt has been developed from my MIT compatible * DES library. - * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au * Eric Young (eay@cryptsoft.com) */ @@ -11,7 +18,7 @@ * I have included directive PARA for shared memory computers. * I have included a directive LONGCRYPT to using this routine to cipher * passwords with more then 8 bytes like HP-UX 10.x it used. The MAXPLEN - * definition is the maximum of lenght of password and can changed. I have + * definition is the maximum of length of password and can changed. I have * defined 24. */ @@ -51,48 +58,54 @@ static unsigned const char cov_2char[64]={ 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A }; -#ifndef NOPROTO -void fcrypt_body(DES_LONG *out,des_key_schedule ks, - DES_LONG Eswap0, DES_LONG Eswap1); +void fcrypt_body(DES_LONG *out,DES_key_schedule *ks, + DES_LONG Eswap0, DES_LONG Eswap1); -#if defined(PERL5) || defined(FreeBSD) -char *des_crypt(const char *buf,const char *salt); -#else -char *crypt(const char *buf,const char *salt); -#endif -#else -void fcrypt_body(); -#ifdef PERL5 -char *des_crypt(); -#else -char *crypt(); -#endif -#endif - -#if defined(PERL5) || defined(FreeBSD) -char *des_crypt(buf,salt) -#else -char *crypt(buf,salt) -#endif -const char *buf; -const char *salt; +char *DES_crypt(const char *buf, const char *salt) { static char buff[14]; - return(des_fcrypt(buf,salt,buff)); +#ifndef CHARSET_EBCDIC + return(DES_fcrypt(buf,salt,buff)); +#else + char e_salt[2+1]; + char e_buf[32+1]; /* replace 32 by 8 ? */ + char *ret; + + /* Copy at most 2 chars of salt */ + if ((e_salt[0] = salt[0]) != '\0') + e_salt[1] = salt[1]; + + /* Copy at most 32 chars of password */ + strncpy (e_buf, buf, sizeof(e_buf)); + + /* Make sure we have a delimiter */ + e_salt[sizeof(e_salt)-1] = e_buf[sizeof(e_buf)-1] = '\0'; + + /* Convert the e_salt to ASCII, as that's what DES_fcrypt works on */ + ebcdic2ascii(e_salt, e_salt, sizeof e_salt); + + /* Convert the cleartext password to ASCII */ + ebcdic2ascii(e_buf, e_buf, sizeof e_buf); + + /* Encrypt it (from/to ASCII) */ + ret = DES_fcrypt(e_buf,e_salt,buff); + + /* Convert the result back to EBCDIC */ + ascii2ebcdic(ret, ret, strlen(ret)); + + return ret; +#endif } -char *des_fcrypt(buf,salt,ret) -const char *buf; -const char *salt; -char *ret; +char *DES_fcrypt(const char *buf, const char *salt, char *ret) { unsigned int i,j,x,y; DES_LONG Eswap0,Eswap1; DES_LONG out[2],ll; - des_cblock key; - des_key_schedule ks; + DES_cblock key; + DES_key_schedule ks; unsigned char bb[9]; unsigned char *b=bb; unsigned char c,u; @@ -103,12 +116,19 @@ char *ret; * returns *\0XXXXXXXXX * The \0 makes the string look like * so the pwd "*" would * crypt to "*". This was found when replacing the crypt in - * our shared libraries. People found that the disbled - * accounts effectivly had no passwd :-(. */ + * our shared libraries. People found that the disabled + * accounts effectively had no passwd :-(. */ +#ifndef CHARSET_EBCDIC x=ret[0]=((salt[0] == '\0')?'A':salt[0]); Eswap0=con_salt[x]<<2; x=ret[1]=((salt[1] == '\0')?'A':salt[1]); Eswap1=con_salt[x]<<6; +#else + x=ret[0]=((salt[0] == '\0')?os_toascii['A']:salt[0]); + Eswap0=con_salt[x]<<2; + x=ret[1]=((salt[1] == '\0')?os_toascii['A']:salt[1]); + Eswap1=con_salt[x]<<6; +#endif /* EAY r=strlen(buf); @@ -123,8 +143,8 @@ r=(r+7)/8; for (; i<8; i++) key[i]=0; - des_set_key((des_cblock *)(key),ks); - fcrypt_body(&(out[0]),ks,Eswap0,Eswap1); + DES_set_key_unchecked(&key,&ks); + fcrypt_body(&(out[0]),&ks,Eswap0,Eswap1); ll=out[0]; l2c(ll,b); ll=out[1]; l2c(ll,b); diff --git a/src/lib/libcrypto/des/fcrypt_b.c b/src/lib/libcrypto/des/fcrypt_b.c index 1544634bc1..1390138787 100644 --- a/src/lib/libcrypto/des/fcrypt_b.c +++ b/src/lib/libcrypto/des/fcrypt_b.c @@ -58,7 +58,7 @@ #include -/* This version of crypt has been developed from my MIT compatable +/* This version of crypt has been developed from my MIT compatible * DES library. * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au * Eric Young (eay@cryptsoft.com) @@ -77,15 +77,12 @@ #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ (a)=(a)^(t)^(t>>(16-(n))))\ -void fcrypt_body(out, ks, Eswap0, Eswap1) -DES_LONG *out; -des_key_schedule ks; -DES_LONG Eswap0; -DES_LONG Eswap1; +void fcrypt_body(DES_LONG *out, DES_key_schedule *ks, DES_LONG Eswap0, + DES_LONG Eswap1) { register DES_LONG l,r,t,u; #ifdef DES_PTR - register unsigned char *des_SP=(unsigned char *)des_SPtrans; + register const unsigned char *des_SP=(const unsigned char *)DES_SPtrans; #endif register DES_LONG *s; register int j; @@ -100,7 +97,7 @@ DES_LONG Eswap1; for (j=0; j<25; j++) { -#ifdef DES_UNROLL +#ifndef DES_UNROLL register int i; for (i=0; i<32; i+=8) diff --git a/src/lib/libcrypto/des/ncbc_enc.c b/src/lib/libcrypto/des/ncbc_enc.c index 1d1a368c22..fda23d522f 100644 --- a/src/lib/libcrypto/des/ncbc_enc.c +++ b/src/lib/libcrypto/des/ncbc_enc.c @@ -1,4 +1,9 @@ /* crypto/des/ncbc_enc.c */ +/* + * #included by: + * cbc_enc.c (DES_cbc_encrypt) + * des_enc.c (DES_ncbc_encrypt) + */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -58,24 +63,21 @@ #include "des_locl.h" -void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int enc; +#ifdef CBC_ENC_C__DONT_UPDATE_IV +void DES_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + DES_key_schedule *_schedule, DES_cblock *ivec, int enc) +#else +void DES_ncbc_encrypt(const unsigned char *in, unsigned char *out, long length, + DES_key_schedule *_schedule, DES_cblock *ivec, int enc) +#endif { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; - register unsigned char *in,*out; register long l=length; DES_LONG tin[2]; unsigned char *iv; - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; if (enc) { @@ -87,7 +89,7 @@ int enc; c2l(in,tin1); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)tin,_schedule,DES_ENCRYPT); tout0=tin[0]; l2c(tout0,out); tout1=tin[1]; l2c(tout1,out); } @@ -96,13 +98,15 @@ int enc; c2ln(in,tin0,tin1,l+8); tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)tin,_schedule,DES_ENCRYPT); tout0=tin[0]; l2c(tout0,out); tout1=tin[1]; l2c(tout1,out); } - iv=(unsigned char *)ivec; +#ifndef CBC_ENC_C__DONT_UPDATE_IV + iv = &(*ivec)[0]; l2c(tout0,iv); l2c(tout1,iv); +#endif } else { @@ -112,7 +116,7 @@ int enc; { c2l(in,tin0); tin[0]=tin0; c2l(in,tin1); tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); + DES_encrypt1((DES_LONG *)tin,_schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; l2c(tout0,out); @@ -120,11 +124,25 @@ int enc; xor0=tin0; xor1=tin1; } - iv=(unsigned char *)ivec; + if (l != -8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + DES_encrypt1((DES_LONG *)tin,_schedule,DES_DECRYPT); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2cn(tout0,tout1,out,l+8); +#ifndef CBC_ENC_C__DONT_UPDATE_IV + xor0=tin0; + xor1=tin1; +#endif + } +#ifndef CBC_ENC_C__DONT_UPDATE_IV + iv = &(*ivec)[0]; l2c(xor0,iv); l2c(xor1,iv); +#endif } tin0=tin1=tout0=tout1=xor0=xor1=0; tin[0]=tin[1]=0; } - diff --git a/src/lib/libcrypto/des/ofb64ede.c b/src/lib/libcrypto/des/ofb64ede.c index 4b1b0199f1..26bbf9a6a7 100644 --- a/src/lib/libcrypto/des/ofb64ede.c +++ b/src/lib/libcrypto/des/ofb64ede.c @@ -62,24 +62,22 @@ * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ -void des_ede3_ofb64_encrypt(in, out, length, k1,k2,k3, ivec, num) -register unsigned char *in; -register unsigned char *out; -long length; -des_key_schedule k1,k2,k3; -des_cblock (*ivec); -int *num; +void DES_ede3_ofb64_encrypt(register const unsigned char *in, + register unsigned char *out, long length, + DES_key_schedule *k1, DES_key_schedule *k2, + DES_key_schedule *k3, DES_cblock *ivec, + int *num) { register DES_LONG v0,v1; register int n= *num; register long l=length; - des_cblock d; + DES_cblock d; register char *dp; DES_LONG ti[2]; unsigned char *iv; int save=0; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; c2l(iv,v0); c2l(iv,v1); ti[0]=v0; @@ -93,7 +91,7 @@ int *num; { /* ti[0]=v0; */ /* ti[1]=v1; */ - des_encrypt3((DES_LONG *)ti,k1,k2,k3); + DES_encrypt3(ti,k1,k2,k3); v0=ti[0]; v1=ti[1]; @@ -109,7 +107,7 @@ int *num; { /* v0=ti[0]; v1=ti[1];*/ - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(v0,iv); l2c(v1,iv); } @@ -118,14 +116,10 @@ int *num; } #ifdef undef /* MACRO */ -void des_ede2_ofb64_encrypt(in, out, length, k1,k2, ivec, num) -register unsigned char *in; -register unsigned char *out; -long length; -des_key_schedule k1,k2; -des_cblock (*ivec); -int *num; +void DES_ede2_ofb64_encrypt(register unsigned char *in, + register unsigned char *out, long length, DES_key_schedule k1, + DES_key_schedule k2, DES_cblock (*ivec), int *num) { - des_ede3_ofb64_encrypt(in, out, length, k1,k2,k1, ivec, num); + DES_ede3_ofb64_encrypt(in, out, length, k1,k2,k1, ivec, num); } #endif diff --git a/src/lib/libcrypto/des/ofb64enc.c b/src/lib/libcrypto/des/ofb64enc.c index ea7e612697..8ca3d49dea 100644 --- a/src/lib/libcrypto/des/ofb64enc.c +++ b/src/lib/libcrypto/des/ofb64enc.c @@ -62,37 +62,33 @@ * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ -void des_ofb64_encrypt(in, out, length, schedule, ivec, num) -register unsigned char *in; -register unsigned char *out; -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int *num; +void DES_ofb64_encrypt(register const unsigned char *in, + register unsigned char *out, long length, + DES_key_schedule *schedule, DES_cblock *ivec, int *num) { register DES_LONG v0,v1,t; register int n= *num; register long l=length; - des_cblock d; - register char *dp; + DES_cblock d; + register unsigned char *dp; DES_LONG ti[2]; unsigned char *iv; int save=0; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; c2l(iv,v0); c2l(iv,v1); ti[0]=v0; ti[1]=v1; - dp=(char *)d; + dp=d; l2c(v0,dp); l2c(v1,dp); while (l--) { if (n == 0) { - des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); - dp=(char *)d; + DES_encrypt1(ti,schedule,DES_ENCRYPT); + dp=d; t=ti[0]; l2c(t,dp); t=ti[1]; l2c(t,dp); save++; @@ -104,7 +100,7 @@ int *num; { v0=ti[0]; v1=ti[1]; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(v0,iv); l2c(v1,iv); } diff --git a/src/lib/libcrypto/des/ofb_enc.c b/src/lib/libcrypto/des/ofb_enc.c index 4db0cdbd60..e887a3c6f4 100644 --- a/src/lib/libcrypto/des/ofb_enc.c +++ b/src/lib/libcrypto/des/ofb_enc.c @@ -64,13 +64,9 @@ * the second. The second 12 bits will come from the 3rd and half the 4th * byte. */ -void des_ofb_encrypt(in, out, numbits, length, schedule, ivec) -unsigned char *in; -unsigned char *out; -int numbits; -long length; -des_key_schedule schedule; -des_cblock (*ivec); +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec) { register DES_LONG d0,d1,vv0,vv1,v0,v1,n=(numbits+7)/8; register DES_LONG mask0,mask1; @@ -97,7 +93,7 @@ des_cblock (*ivec); mask1=0x00000000L; } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; c2l(iv,v0); c2l(iv,v1); ti[0]=v0; @@ -106,7 +102,7 @@ des_cblock (*ivec); { ti[0]=v0; ti[1]=v1; - des_encrypt((DES_LONG *)ti,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)ti,schedule,DES_ENCRYPT); vv0=ti[0]; vv1=ti[1]; c2ln(in,d0,d1,n); @@ -131,7 +127,7 @@ des_cblock (*ivec); v1=((v1>>num)|(vv0<<(32-num)))&0xffffffffL; } } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(v0,iv); l2c(v1,iv); v0=v1=d0=d1=ti[0]=ti[1]=vv0=vv1=0; diff --git a/src/lib/libcrypto/des/pcbc_enc.c b/src/lib/libcrypto/des/pcbc_enc.c index 4513207d90..17a40f9520 100644 --- a/src/lib/libcrypto/des/pcbc_enc.c +++ b/src/lib/libcrypto/des/pcbc_enc.c @@ -58,21 +58,18 @@ #include "des_locl.h" -void des_pcbc_encrypt(input, output, length, schedule, ivec, enc) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule schedule; -des_cblock (*ivec); -int enc; +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc) { register DES_LONG sin0,sin1,xor0,xor1,tout0,tout1; DES_LONG tin[2]; - unsigned char *in,*out,*iv; + const unsigned char *in; + unsigned char *out,*iv; - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; + in=input; + out=output; + iv = &(*ivec)[0]; if (enc) { @@ -89,7 +86,7 @@ int enc; c2ln(in,sin0,sin1,length); tin[0]=sin0^xor0; tin[1]=sin1^xor1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + DES_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT); tout0=tin[0]; tout1=tin[1]; xor0=sin0^tout0; @@ -107,7 +104,7 @@ int enc; c2l(in,sin1); tin[0]=sin0; tin[1]=sin1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); + DES_encrypt1((DES_LONG *)tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0; tout1=tin[1]^xor1; if (length >= 8) diff --git a/src/lib/libcrypto/des/qud_cksm.c b/src/lib/libcrypto/des/qud_cksm.c index 8526abf334..dac201227e 100644 --- a/src/lib/libcrypto/des/qud_cksm.c +++ b/src/lib/libcrypto/des/qud_cksm.c @@ -73,28 +73,32 @@ /* Got the value MIT uses via brute force :-) 2/10/90 eay */ #define NOISE ((DES_LONG)83653421L) -DES_LONG des_quad_cksum(input, output, length, out_count, seed) -des_cblock (*input); -des_cblock (*output); -long length; -int out_count; -des_cblock (*seed); +DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[], + long length, int out_count, DES_cblock *seed) { DES_LONG z0,z1,t0,t1; int i; long l; - unsigned char *cp; - unsigned char *lp; + const unsigned char *cp; +#ifdef _CRAY + struct lp_st { int a:32; int b:32; } *lp; +#else + DES_LONG *lp; +#endif if (out_count < 1) out_count=1; - lp=(unsigned char *)output; +#ifdef _CRAY + lp = (struct lp_st *) &(output[0])[0]; +#else + lp = (DES_LONG *) &(output[0])[0]; +#endif z0=Q_B0((*seed)[0])|Q_B1((*seed)[1])|Q_B2((*seed)[2])|Q_B3((*seed)[3]); z1=Q_B0((*seed)[4])|Q_B1((*seed)[5])|Q_B2((*seed)[6])|Q_B3((*seed)[7]); for (i=0; ((i<4)&&(i 0) { @@ -118,25 +122,16 @@ des_cblock (*seed); } if (lp != NULL) { - /* I believe I finally have things worked out. - * The MIT library assumes that the checksum - * is one huge number and it is returned in a - * host dependant byte order. - */ - static DES_LONG ltmp=1; - static unsigned char *c=(unsigned char *)<mp; - - if (c[0]) - { - l2c(z0,lp); - l2c(z1,lp); - } - else - { - lp=output[out_count-i-1]; - l2n(z1,lp); - l2n(z0,lp); - } + /* The MIT library assumes that the checksum is + * composed of 2*out_count 32 bit ints */ +#ifdef _CRAY + (*lp).a = z0; + (*lp).b = z1; + lp++; +#else + *lp++ = z0; + *lp++ = z1; +#endif } } return(z0); diff --git a/src/lib/libcrypto/des/rand_key.c b/src/lib/libcrypto/des/rand_key.c index 8c30bd029a..2398165568 100644 --- a/src/lib/libcrypto/des/rand_key.c +++ b/src/lib/libcrypto/des/rand_key.c @@ -1,118 +1,68 @@ /* crypto/des/rand_key.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "des_locl.h" -#include +#include +#include -static int seed=0; -static des_cblock init; - -void des_random_seed(key) -des_cblock key; - { - memcpy(init,key,sizeof(des_cblock)); - seed=1; - } - -void des_random_key(ret) -unsigned char *ret; +int DES_random_key(DES_cblock *ret) { - des_key_schedule ks; - static DES_LONG c=0; - static unsigned short pid=0; - static des_cblock data={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; - des_cblock key; - unsigned char *p; - DES_LONG t; - int i; - -#ifdef MSDOS - pid=1; -#else - if (!pid) pid=getpid(); -#endif - p=key; - if (seed) + do { - for (i=0; i<8; i++) - { - data[i] ^= init[i]; - init[i]=0; - } - seed=0; - } - t=(DES_LONG)time(NULL); - l2c(t,p); - t=(DES_LONG)((pid)|((c++)<<16)); - l2c(t,p); - - des_set_odd_parity((des_cblock *)data); - des_set_key((des_cblock *)data,ks); - des_cbc_cksum((des_cblock *)key,(des_cblock *)key, - (long)sizeof(key),ks,(des_cblock *)data); - - des_set_odd_parity((des_cblock *)key); - des_set_key((des_cblock *)key,ks); - des_cbc_cksum((des_cblock *)key,(des_cblock *)data, - (long)sizeof(key),ks,(des_cblock *)key); - - memcpy(ret,data,sizeof(key)); - memset(key,0,sizeof(key)); - memset(ks,0,sizeof(ks)); - t=0; + if (RAND_bytes((unsigned char *)ret, sizeof(DES_cblock)) != 1) + return (0); + } while (DES_is_weak_key(ret)); + DES_set_odd_parity(ret); + return (1); } diff --git a/src/lib/libcrypto/des/set_key.c b/src/lib/libcrypto/des/set_key.c index c3bcd7ee2b..683916e71b 100644 --- a/src/lib/libcrypto/des/set_key.c +++ b/src/lib/libcrypto/des/set_key.c @@ -64,19 +64,28 @@ * 1.0 First working version */ #include "des_locl.h" -#include "podd.h" -#include "sk.h" -#ifndef NOPROTO -static int check_parity(des_cblock (*key)); -#else -static int check_parity(); -#endif +OPENSSL_IMPLEMENT_GLOBAL(int,DES_check_key); /* defaults to false */ -int des_check_key=0; +static const unsigned char odd_parity[256]={ + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, +112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, +128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, +145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, +161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, +176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, +193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, +208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, +224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, +241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; -void des_set_odd_parity(key) -des_cblock (*key); +void DES_set_odd_parity(DES_cblock *key) { int i; @@ -84,8 +93,7 @@ des_cblock (*key); (*key)[i]=odd_parity[(*key)[i]]; } -static int check_parity(key) -des_cblock (*key); +int DES_check_key_parity(const_DES_cblock *key) { int i; @@ -107,12 +115,12 @@ des_cblock (*key); * (and actual cblock values). */ #define NUM_WEAK_KEY 16 -static des_cblock weak_keys[NUM_WEAK_KEY]={ +static DES_cblock weak_keys[NUM_WEAK_KEY]={ /* weak keys */ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE}, - {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, - {0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0}, + {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, + {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1}, /* semi-weak keys */ {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01}, @@ -127,19 +135,18 @@ static des_cblock weak_keys[NUM_WEAK_KEY]={ {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}}; -int des_is_weak_key(key) -des_cblock (*key); +int DES_is_weak_key(const_DES_cblock *key) { int i; for (i=0; i>(16-(n)))) +static const DES_LONG des_skb[8][64]={ + { + /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L,0x00000010L,0x20000000L,0x20000010L, + 0x00010000L,0x00010010L,0x20010000L,0x20010010L, + 0x00000800L,0x00000810L,0x20000800L,0x20000810L, + 0x00010800L,0x00010810L,0x20010800L,0x20010810L, + 0x00000020L,0x00000030L,0x20000020L,0x20000030L, + 0x00010020L,0x00010030L,0x20010020L,0x20010030L, + 0x00000820L,0x00000830L,0x20000820L,0x20000830L, + 0x00010820L,0x00010830L,0x20010820L,0x20010830L, + 0x00080000L,0x00080010L,0x20080000L,0x20080010L, + 0x00090000L,0x00090010L,0x20090000L,0x20090010L, + 0x00080800L,0x00080810L,0x20080800L,0x20080810L, + 0x00090800L,0x00090810L,0x20090800L,0x20090810L, + 0x00080020L,0x00080030L,0x20080020L,0x20080030L, + 0x00090020L,0x00090030L,0x20090020L,0x20090030L, + 0x00080820L,0x00080830L,0x20080820L,0x20080830L, + 0x00090820L,0x00090830L,0x20090820L,0x20090830L, + },{ + /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000L,0x02000000L,0x00002000L,0x02002000L, + 0x00200000L,0x02200000L,0x00202000L,0x02202000L, + 0x00000004L,0x02000004L,0x00002004L,0x02002004L, + 0x00200004L,0x02200004L,0x00202004L,0x02202004L, + 0x00000400L,0x02000400L,0x00002400L,0x02002400L, + 0x00200400L,0x02200400L,0x00202400L,0x02202400L, + 0x00000404L,0x02000404L,0x00002404L,0x02002404L, + 0x00200404L,0x02200404L,0x00202404L,0x02202404L, + 0x10000000L,0x12000000L,0x10002000L,0x12002000L, + 0x10200000L,0x12200000L,0x10202000L,0x12202000L, + 0x10000004L,0x12000004L,0x10002004L,0x12002004L, + 0x10200004L,0x12200004L,0x10202004L,0x12202004L, + 0x10000400L,0x12000400L,0x10002400L,0x12002400L, + 0x10200400L,0x12200400L,0x10202400L,0x12202400L, + 0x10000404L,0x12000404L,0x10002404L,0x12002404L, + 0x10200404L,0x12200404L,0x10202404L,0x12202404L, + },{ + /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000L,0x00000001L,0x00040000L,0x00040001L, + 0x01000000L,0x01000001L,0x01040000L,0x01040001L, + 0x00000002L,0x00000003L,0x00040002L,0x00040003L, + 0x01000002L,0x01000003L,0x01040002L,0x01040003L, + 0x00000200L,0x00000201L,0x00040200L,0x00040201L, + 0x01000200L,0x01000201L,0x01040200L,0x01040201L, + 0x00000202L,0x00000203L,0x00040202L,0x00040203L, + 0x01000202L,0x01000203L,0x01040202L,0x01040203L, + 0x08000000L,0x08000001L,0x08040000L,0x08040001L, + 0x09000000L,0x09000001L,0x09040000L,0x09040001L, + 0x08000002L,0x08000003L,0x08040002L,0x08040003L, + 0x09000002L,0x09000003L,0x09040002L,0x09040003L, + 0x08000200L,0x08000201L,0x08040200L,0x08040201L, + 0x09000200L,0x09000201L,0x09040200L,0x09040201L, + 0x08000202L,0x08000203L,0x08040202L,0x08040203L, + 0x09000202L,0x09000203L,0x09040202L,0x09040203L, + },{ + /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000L,0x00100000L,0x00000100L,0x00100100L, + 0x00000008L,0x00100008L,0x00000108L,0x00100108L, + 0x00001000L,0x00101000L,0x00001100L,0x00101100L, + 0x00001008L,0x00101008L,0x00001108L,0x00101108L, + 0x04000000L,0x04100000L,0x04000100L,0x04100100L, + 0x04000008L,0x04100008L,0x04000108L,0x04100108L, + 0x04001000L,0x04101000L,0x04001100L,0x04101100L, + 0x04001008L,0x04101008L,0x04001108L,0x04101108L, + 0x00020000L,0x00120000L,0x00020100L,0x00120100L, + 0x00020008L,0x00120008L,0x00020108L,0x00120108L, + 0x00021000L,0x00121000L,0x00021100L,0x00121100L, + 0x00021008L,0x00121008L,0x00021108L,0x00121108L, + 0x04020000L,0x04120000L,0x04020100L,0x04120100L, + 0x04020008L,0x04120008L,0x04020108L,0x04120108L, + 0x04021000L,0x04121000L,0x04021100L,0x04121100L, + 0x04021008L,0x04121008L,0x04021108L,0x04121108L, + },{ + /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L,0x10000000L,0x00010000L,0x10010000L, + 0x00000004L,0x10000004L,0x00010004L,0x10010004L, + 0x20000000L,0x30000000L,0x20010000L,0x30010000L, + 0x20000004L,0x30000004L,0x20010004L,0x30010004L, + 0x00100000L,0x10100000L,0x00110000L,0x10110000L, + 0x00100004L,0x10100004L,0x00110004L,0x10110004L, + 0x20100000L,0x30100000L,0x20110000L,0x30110000L, + 0x20100004L,0x30100004L,0x20110004L,0x30110004L, + 0x00001000L,0x10001000L,0x00011000L,0x10011000L, + 0x00001004L,0x10001004L,0x00011004L,0x10011004L, + 0x20001000L,0x30001000L,0x20011000L,0x30011000L, + 0x20001004L,0x30001004L,0x20011004L,0x30011004L, + 0x00101000L,0x10101000L,0x00111000L,0x10111000L, + 0x00101004L,0x10101004L,0x00111004L,0x10111004L, + 0x20101000L,0x30101000L,0x20111000L,0x30111000L, + 0x20101004L,0x30101004L,0x20111004L,0x30111004L, + },{ + /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000L,0x08000000L,0x00000008L,0x08000008L, + 0x00000400L,0x08000400L,0x00000408L,0x08000408L, + 0x00020000L,0x08020000L,0x00020008L,0x08020008L, + 0x00020400L,0x08020400L,0x00020408L,0x08020408L, + 0x00000001L,0x08000001L,0x00000009L,0x08000009L, + 0x00000401L,0x08000401L,0x00000409L,0x08000409L, + 0x00020001L,0x08020001L,0x00020009L,0x08020009L, + 0x00020401L,0x08020401L,0x00020409L,0x08020409L, + 0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, + 0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, + 0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, + 0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, + 0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, + 0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, + 0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, + 0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, + },{ + /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000L,0x00000100L,0x00080000L,0x00080100L, + 0x01000000L,0x01000100L,0x01080000L,0x01080100L, + 0x00000010L,0x00000110L,0x00080010L,0x00080110L, + 0x01000010L,0x01000110L,0x01080010L,0x01080110L, + 0x00200000L,0x00200100L,0x00280000L,0x00280100L, + 0x01200000L,0x01200100L,0x01280000L,0x01280100L, + 0x00200010L,0x00200110L,0x00280010L,0x00280110L, + 0x01200010L,0x01200110L,0x01280010L,0x01280110L, + 0x00000200L,0x00000300L,0x00080200L,0x00080300L, + 0x01000200L,0x01000300L,0x01080200L,0x01080300L, + 0x00000210L,0x00000310L,0x00080210L,0x00080310L, + 0x01000210L,0x01000310L,0x01080210L,0x01080310L, + 0x00200200L,0x00200300L,0x00280200L,0x00280300L, + 0x01200200L,0x01200300L,0x01280200L,0x01280300L, + 0x00200210L,0x00200310L,0x00280210L,0x00280310L, + 0x01200210L,0x01200310L,0x01280210L,0x01280310L, + },{ + /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000L,0x04000000L,0x00040000L,0x04040000L, + 0x00000002L,0x04000002L,0x00040002L,0x04040002L, + 0x00002000L,0x04002000L,0x00042000L,0x04042000L, + 0x00002002L,0x04002002L,0x00042002L,0x04042002L, + 0x00000020L,0x04000020L,0x00040020L,0x04040020L, + 0x00000022L,0x04000022L,0x00040022L,0x04040022L, + 0x00002020L,0x04002020L,0x00042020L,0x04042020L, + 0x00002022L,0x04002022L,0x00042022L,0x04042022L, + 0x00000800L,0x04000800L,0x00040800L,0x04040800L, + 0x00000802L,0x04000802L,0x00040802L,0x04040802L, + 0x00002800L,0x04002800L,0x00042800L,0x04042800L, + 0x00002802L,0x04002802L,0x00042802L,0x04042802L, + 0x00000820L,0x04000820L,0x00040820L,0x04040820L, + 0x00000822L,0x04000822L,0x00040822L,0x04040822L, + 0x00002820L,0x04002820L,0x00042820L,0x04042820L, + 0x00002822L,0x04002822L,0x00042822L,0x04042822L, + }}; + +int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule) + { + if (DES_check_key) + { + return DES_set_key_checked(key, schedule); + } + else + { + DES_set_key_unchecked(key, schedule); + return 0; + } + } + /* return 0 if key parity is odd (correct), * return -1 if key parity error, * return -2 if illegal weak key. */ -int des_set_key(key, schedule) -des_cblock (*key); -des_key_schedule schedule; +int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule) + { + if (!DES_check_key_parity(key)) + return(-1); + if (DES_is_weak_key(key)) + return(-2); + DES_set_key_unchecked(key, schedule); + return 0; + } + +void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule) { static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; register DES_LONG c,d,t,s,t2; - register unsigned char *in; + register const unsigned char *in; register DES_LONG *k; register int i; - if (des_check_key) - { - if (!check_parity(key)) - return(-1); - - if (des_is_weak_key(key)) - return(-2); - } - - k=(DES_LONG *)schedule; - in=(unsigned char *)key; +#if OPENBSD_DEV_CRYPTO + memcpy(schedule->key,key,sizeof schedule->key); + schedule->session=NULL; +#endif + k = &schedule->ks->deslong[0]; + in = &(*key)[0]; c2l(in,c); c2l(in,d); - /* do PC1 in 60 simple operations */ -/* PERM_OP(d,c,t,4,0x0f0f0f0fL); - HPERM_OP(c,t,-2, 0xcccc0000L); - HPERM_OP(c,t,-1, 0xaaaa0000L); - HPERM_OP(c,t, 8, 0x00ff0000L); - HPERM_OP(c,t,-1, 0xaaaa0000L); - HPERM_OP(d,t,-8, 0xff000000L); - HPERM_OP(d,t, 8, 0x00ff0000L); - HPERM_OP(d,t, 2, 0x33330000L); - d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); - d=(d>>8)|((c&0xf0000000L)>>4); - c&=0x0fffffffL; */ - - /* I now do it in 47 simple operations :-) + /* do PC1 in 47 simple operations :-) * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) * for the inspiration. :-) */ PERM_OP (d,c,t,4,0x0f0f0f0fL); @@ -219,9 +376,9 @@ des_key_schedule schedule; /* could be a few less shifts but I am to lazy at this * point in time to investigate */ s= des_skb[0][ (c )&0x3f ]| - des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| - des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| - des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | + des_skb[1][((c>> 6L)&0x03)|((c>> 7L)&0x3c)]| + des_skb[2][((c>>13L)&0x0f)|((c>>14L)&0x30)]| + des_skb[3][((c>>20L)&0x01)|((c>>21L)&0x06) | ((c>>22L)&0x38)]; t= des_skb[4][ (d )&0x3f ]| des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| @@ -235,12 +392,16 @@ des_key_schedule schedule; t2=((s>>16L)|(t&0xffff0000L)); *(k++)=ROTATE(t2,26)&0xffffffffL; } - return(0); } -int des_key_sched(key, schedule) -des_cblock (*key); -des_key_schedule schedule; +int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule) + { + return(DES_set_key(key,schedule)); + } +/* +#undef des_fixup_key_parity +void des_fixup_key_parity(des_cblock *key) { - return(des_set_key(key,schedule)); + des_set_odd_parity(key); } +*/ diff --git a/src/lib/libcrypto/des/spr.h b/src/lib/libcrypto/des/spr.h index 81813f9f7a..b91936a5a5 100644 --- a/src/lib/libcrypto/des/spr.h +++ b/src/lib/libcrypto/des/spr.h @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -const DES_LONG des_SPtrans[8][64]={ +OPENSSL_GLOBAL const DES_LONG DES_SPtrans[8][64]={ { /* nibble 0 */ 0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, diff --git a/src/lib/libcrypto/des/str2key.c b/src/lib/libcrypto/des/str2key.c index 3365c1bcf3..36c3f81d99 100644 --- a/src/lib/libcrypto/des/str2key.c +++ b/src/lib/libcrypto/des/str2key.c @@ -58,13 +58,9 @@ #include "des_locl.h" -extern int des_check_key; - -void des_string_to_key(str, key) -char *str; -des_cblock (*key); +void DES_string_to_key(const char *str, DES_cblock *key) { - des_key_schedule ks; + DES_key_schedule ks; int i,length; register unsigned char j; @@ -89,23 +85,22 @@ des_cblock (*key); } } #endif - des_set_odd_parity((des_cblock *)key); - i=des_check_key; - des_check_key=0; - des_set_key((des_cblock *)key,ks); - des_check_key=i; - des_cbc_cksum((des_cblock *)str,(des_cblock *)key,(long)length,ks, - (des_cblock *)key); - memset(ks,0,sizeof(ks)); - des_set_odd_parity((des_cblock *)key); + DES_set_odd_parity(key); +#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; + DES_set_key(key,&ks); +#else + DES_set_key_unchecked(key,&ks); +#endif + DES_cbc_cksum((const unsigned char*)str,key,length,&ks,key); + memset(&ks,0,sizeof(ks)); + DES_set_odd_parity(key); } -void des_string_to_2keys(str, key1, key2) -char *str; -des_cblock (*key1); -des_cblock (*key2); +void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2) { - des_key_schedule ks; + DES_key_schedule ks; int i,length; register unsigned char j; @@ -154,18 +149,25 @@ des_cblock (*key2); } if (length <= 8) memcpy(key2,key1,8); #endif - des_set_odd_parity((des_cblock *)key1); - des_set_odd_parity((des_cblock *)key2); - i=des_check_key; - des_check_key=0; - des_set_key((des_cblock *)key1,ks); - des_cbc_cksum((des_cblock *)str,(des_cblock *)key1,(long)length,ks, - (des_cblock *)key1); - des_set_key((des_cblock *)key2,ks); - des_cbc_cksum((des_cblock *)str,(des_cblock *)key2,(long)length,ks, - (des_cblock *)key2); - des_check_key=i; - memset(ks,0,sizeof(ks)); - des_set_odd_parity(key1); - des_set_odd_parity(key2); + DES_set_odd_parity(key1); + DES_set_odd_parity(key2); +#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY + if(DES_is_weak_key(key1)) + (*key1)[7] ^= 0xF0; + DES_set_key(key1,&ks); +#else + DES_set_key_unchecked(key1,&ks); +#endif + DES_cbc_cksum((const unsigned char*)str,key1,length,&ks,key1); +#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY + if(DES_is_weak_key(key2)) + (*key2)[7] ^= 0xF0; + DES_set_key(key2,&ks); +#else + DES_set_key_unchecked(key2,&ks); +#endif + DES_cbc_cksum((const unsigned char*)str,key2,length,&ks,key2); + memset(&ks,0,sizeof(ks)); + DES_set_odd_parity(key1); + DES_set_odd_parity(key2); } diff --git a/src/lib/libcrypto/des/xcbc_enc.c b/src/lib/libcrypto/des/xcbc_enc.c index 031589bf50..47246eb466 100644 --- a/src/lib/libcrypto/des/xcbc_enc.c +++ b/src/lib/libcrypto/des/xcbc_enc.c @@ -79,18 +79,14 @@ static unsigned char desx_white_in2out[256]={ 0xA7,0x1C,0xC9,0x09,0x69,0x9A,0x83,0xCF,0x29,0x39,0xB9,0xE9,0x4C,0xFF,0x43,0xAB, }; -void des_xwhite_in2out(des_key,in_white,out_white) -des_cblock (*des_key); -des_cblock (*in_white); -des_cblock (*out_white); +void DES_xwhite_in2out(const_DES_cblock *des_key, const_DES_cblock *in_white, + DES_cblock *out_white) { - unsigned char *key,*in,*out; int out0,out1; int i; - - key=(unsigned char *)des_key; - in=(unsigned char *)in_white; - out=(unsigned char *)out_white; + const unsigned char *key = &(*des_key)[0]; + const unsigned char *in = &(*in_white)[0]; + unsigned char *out = &(*out_white)[0]; out[0]=out[1]=out[2]=out[3]=out[4]=out[5]=out[6]=out[7]=0; out0=out1=0; @@ -111,34 +107,27 @@ des_cblock (*out_white); } } -void des_xcbc_encrypt(input, output, length, schedule, ivec, inw,outw,enc) -des_cblock (*input); -des_cblock (*output); -long length; -des_key_schedule schedule; -des_cblock (*ivec); -des_cblock (*inw); -des_cblock (*outw); -int enc; +void DES_xcbc_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, const_DES_cblock *inw, + const_DES_cblock *outw, int enc) { register DES_LONG tin0,tin1; register DES_LONG tout0,tout1,xor0,xor1; register DES_LONG inW0,inW1,outW0,outW1; - register unsigned char *in,*out; + register const unsigned char *in2; register long l=length; DES_LONG tin[2]; unsigned char *iv; - in=(unsigned char *)inw; - c2l(in,inW0); - c2l(in,inW1); - in=(unsigned char *)outw; - c2l(in,outW0); - c2l(in,outW1); + in2 = &(*inw)[0]; + c2l(in2,inW0); + c2l(in2,inW1); + in2 = &(*outw)[0]; + c2l(in2,outW0); + c2l(in2,outW1); - in=(unsigned char *)input; - out=(unsigned char *)output; - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; if (enc) { @@ -150,7 +139,7 @@ int enc; c2l(in,tin1); tin0^=tout0^inW0; tin[0]=tin0; tin1^=tout1^inW1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + DES_encrypt1(tin,schedule,DES_ENCRYPT); tout0=tin[0]^outW0; l2c(tout0,out); tout1=tin[1]^outW1; l2c(tout1,out); } @@ -159,11 +148,11 @@ int enc; c2ln(in,tin0,tin1,l+8); tin0^=tout0^inW0; tin[0]=tin0; tin1^=tout1^inW1; tin[1]=tin1; - des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + DES_encrypt1(tin,schedule,DES_ENCRYPT); tout0=tin[0]^outW0; l2c(tout0,out); tout1=tin[1]^outW1; l2c(tout1,out); } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(tout0,iv); l2c(tout1,iv); } @@ -175,7 +164,7 @@ int enc; { c2l(in,tin0); tin[0]=tin0^outW0; c2l(in,tin1); tin[1]=tin1^outW1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); + DES_encrypt1(tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0^inW0; tout1=tin[1]^xor1^inW1; l2c(tout0,out); @@ -187,7 +176,7 @@ int enc; { c2l(in,tin0); tin[0]=tin0^outW0; c2l(in,tin1); tin[1]=tin1^outW1; - des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); + DES_encrypt1(tin,schedule,DES_DECRYPT); tout0=tin[0]^xor0^inW0; tout1=tin[1]^xor1^inW1; l2cn(tout0,tout1,out,l+8); @@ -195,7 +184,7 @@ int enc; xor1=tin1; } - iv=(unsigned char *)ivec; + iv = &(*ivec)[0]; l2c(xor0,iv); l2c(xor1,iv); } diff --git a/src/lib/libcrypto/dh/dh.h b/src/lib/libcrypto/dh/dh.h index 4cc1df2650..05851f8429 100644 --- a/src/lib/libcrypto/dh/dh.h +++ b/src/lib/libcrypto/dh/dh.h @@ -59,15 +59,41 @@ #ifndef HEADER_DH_H #define HEADER_DH_H +#ifdef OPENSSL_NO_DH +#error DH is disabled. +#endif + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include + +#define DH_FLAG_CACHE_MONT_P 0x01 + #ifdef __cplusplus extern "C" { #endif -#ifndef HEADER_BN_H -#define BIGNUM char -#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,const BIGNUM *pub_key,DH *dh); + int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const 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; -typedef struct dh_st +struct dh_st { /* This first argument is used to pick up errors when * a DH is passed instead of a EVP_PKEY */ @@ -75,10 +101,24 @@ typedef struct dh_st int version; BIGNUM *p; BIGNUM *g; - int length; /* optional */ - BIGNUM *pub_key; /* y */ + long length; /* optional */ + BIGNUM *pub_key; /* g^x */ BIGNUM *priv_key; /* x */ - } DH; + + 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; + const DH_METHOD *meth; + ENGINE *engine; + }; #define DH_GENERATOR_2 2 /* #define DH_GENERATOR_3 3 */ @@ -86,10 +126,14 @@ typedef struct dh_st /* DH_check error codes */ #define DH_CHECK_P_NOT_PRIME 0x01 -#define DH_CHECK_P_NOT_STRONG_PRIME 0x02 +#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, \ @@ -98,50 +142,51 @@ typedef struct dh_st (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 + +const DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(const DH_METHOD *meth); +const DH_METHOD *DH_get_default_method(void); +int DH_set_method(DH *dh, const DH_METHOD *meth); +DH *DH_new_method(ENGINE *engine); -#ifndef NOPROTO DH * DH_new(void); void DH_free(DH *dh); -int DH_size(DH *dh); +int DH_up_ref(DH *dh); +int DH_size(const 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,char *),char *cb_arg); -int DH_check(DH *dh,int *codes); + void (*callback)(int,int,void *),void *cb_arg); +int DH_check(const 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); +int DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh); +DH * d2i_DHparams(DH **a,const unsigned char **pp, long length); +int i2d_DHparams(const DH *a,unsigned char **pp); +#ifndef OPENSSL_NO_FP_API +int DHparams_print_fp(FILE *fp, const DH *x); #endif -#ifdef HEADER_BIO_H -int DHparams_print(BIO *bp, DH *x); +#ifndef OPENSSL_NO_BIO +int DHparams_print(BIO *bp, const DH *x); #else -int DHparams_print(char *bp, DH *x); -#endif -void ERR_load_DH_strings(void ); - -#else - -DH * DH_new(); -void DH_free(); -int DH_size(); -DH * DH_generate_parameters(); -int DH_check(); -int DH_generate_key(); -int DH_compute_key(); -DH * d2i_DHparams(); -int i2d_DHparams(); -#ifndef NO_FP_API -int DHparams_print_fp(); -#endif -int DHparams_print(); -void ERR_load_DH_strings(); - +int DHparams_print(char *bp, const DH *x); #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. + */ +void ERR_load_DH_strings(void); + /* Error codes for the DH functions. */ /* Function codes. */ @@ -150,13 +195,13 @@ void ERR_load_DH_strings(); #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 +#define DH_F_DH_NEW_METHOD 105 /* Reason codes. */ +#define DH_R_BAD_GENERATOR 101 #define DH_R_NO_PRIVATE_VALUE 100 - + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/dh/dh_check.c b/src/lib/libcrypto/dh/dh_check.c index 65602e494f..f0373f7d68 100644 --- a/src/lib/libcrypto/dh/dh_check.c +++ b/src/lib/libcrypto/dh/dh_check.c @@ -58,10 +58,10 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "dh.h" +#include +#include -/* Check that p is a strong prime and +/* 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 @@ -70,9 +70,7 @@ * should hold. */ -int DH_check(dh,ret) -DH *dh; -int *ret; +int DH_check(const DH *dh, int *ret) { int ok=0; BN_CTX *ctx=NULL; @@ -90,11 +88,13 @@ int *ret; l=BN_mod_word(dh->p,24); if (l != 11) *ret|=DH_NOT_SUITABLE_GENERATOR; } -/* else if (BN_is_word(dh->g,DH_GENERATOR_3)) +#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); @@ -110,7 +110,7 @@ int *ret; { if (!BN_rshift1(q,dh->p)) goto err; if (!BN_is_prime(q,BN_prime_checks,NULL,ctx,NULL)) - *ret|=DH_CHECK_P_NOT_STRONG_PRIME; + *ret|=DH_CHECK_P_NOT_SAFE_PRIME; } ok=1; err: diff --git a/src/lib/libcrypto/dh/dh_err.c b/src/lib/libcrypto/dh/dh_err.c index 9d5c06ac24..d837950aec 100644 --- a/src/lib/libcrypto/dh/dh_err.c +++ b/src/lib/libcrypto/dh/dh_err.c @@ -1,66 +1,69 @@ -/* lib/dh/dh_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/dh/dh_err.c */ +/* ==================================================================== + * Copyright (c) 1999-2002 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "dh.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA DH_str_functs[]= { {ERR_PACK(0,DH_F_DHPARAMS_PRINT,0), "DHparams_print"}, @@ -68,26 +71,27 @@ static ERR_STRING_DATA DH_str_functs[]= {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}, +{ERR_PACK(0,DH_F_DH_NEW_METHOD,0), "DH_new_method"}, +{0,NULL} }; static ERR_STRING_DATA DH_str_reasons[]= { +{DH_R_BAD_GENERATOR ,"bad generator"}, {DH_R_NO_PRIVATE_VALUE ,"no private value"}, -{0,NULL}, +{0,NULL} }; #endif -void ERR_load_DH_strings() +void ERR_load_DH_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_DH,DH_str_functs); ERR_load_strings(ERR_LIB_DH,DH_str_reasons); #endif diff --git a/src/lib/libcrypto/dh/dh_gen.c b/src/lib/libcrypto/dh/dh_gen.c index 04c7046a7b..06f78b35ab 100644 --- a/src/lib/libcrypto/dh/dh_gen.c +++ b/src/lib/libcrypto/dh/dh_gen.c @@ -58,8 +58,8 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "dh.h" +#include +#include /* We generate DH parameters as follows * find a prime q which is prime_len/2 bits long. @@ -72,22 +72,22 @@ * 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 strong primes. + * 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 strong prime (both p and q are prime), + * 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(prime_len,generator,callback,cb_arg) -int prime_len; -int generator; -void (*callback)(P_I_I_P); -char *cb_arg; +/* Actually there is no reason to insist that 'generator' be a generator. + * It's just as OK (and in some sense better) to use a generator of the + * order-q subgroup. + */ +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; @@ -95,38 +95,53 @@ char *cb_arg; BN_CTX *ctx=NULL; ret=DH_new(); + if (ret == NULL) goto err; ctx=BN_CTX_new(); if (ctx == NULL) goto err; - t1=ctx->bn[0]; - t2=ctx->bn[1]; - ctx->tos=2; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t1 == NULL || t2 == NULL) goto err; + if (generator <= 1) + { + DHerr(DH_F_DH_GENERATE_PARAMETERS, DH_R_BAD_GENERATOR); + goto err; + } if (generator == DH_GENERATOR_2) { - BN_set_word(t1,24); - BN_set_word(t2,11); + if (!BN_set_word(t1,24)) goto err; + if (!BN_set_word(t2,11)) goto err; g=2; } -#ifdef undef /* does not work for strong primes */ +#if 0 /* does not work for safe primes */ else if (generator == DH_GENERATOR_3) { - BN_set_word(t1,12); - BN_set_word(t2,5); + if (!BN_set_word(t1,12)) goto err; + if (!BN_set_word(t2,5)) goto err; g=3; } #endif else if (generator == DH_GENERATOR_5) { - BN_set_word(t1,10); - BN_set_word(t2,3); + if (!BN_set_word(t1,10)) goto err; + if (!BN_set_word(t2,3)) goto err; /* BN_set_word(t3,7); just have to miss * out on these ones :-( */ g=5; } else + { + /* in the general case, don't worry if 'generator' is a + * generator or not: since we are using safe primes, + * it will generate either an order-q or an order-2q group, + * which both is OK */ + if (!BN_set_word(t1,2)) goto err; + if (!BN_set_word(t2,1)) goto err; g=generator; + } - p=BN_generate_prime(prime_len,1,t1,t2,callback,cb_arg); + 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; @@ -140,7 +155,11 @@ err: ok=0; } - if (ctx != NULL) BN_CTX_free(ctx); + if (ctx != NULL) + { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } if (!ok && (ret != NULL)) { DH_free(ret); diff --git a/src/lib/libcrypto/dh/dh_key.c b/src/lib/libcrypto/dh/dh_key.c index 7576772bcd..1a0efca2c4 100644 --- a/src/lib/libcrypto/dh/dh_key.c +++ b/src/lib/libcrypto/dh/dh_key.c @@ -58,32 +58,63 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rand.h" -#include "dh.h" +#include +#include +#include +#include -int DH_generate_key(dh) -DH *dh; +static int generate_key(DH *dh); +static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, + const 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, const 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 +}; + +const DH_METHOD *DH_OpenSSL(void) +{ + return &dh_ossl; +} + +static int generate_key(DH *dh) { int ok=0; - unsigned int i; - BN_CTX *ctx=NULL; + int generate_new_key=0; + unsigned l; + BN_CTX *ctx; + BN_MONT_CTX *mont; BIGNUM *pub_key=NULL,*priv_key=NULL; - ctx=BN_CTX_new(); + ctx = BN_CTX_new(); if (ctx == NULL) goto err; if (dh->priv_key == NULL) { - i=dh->length; - if (i == 0) - { - /* Make the number p-1 bits long */ - i=BN_num_bits(dh->p)-1; - } priv_key=BN_new(); if (priv_key == NULL) goto err; - if (!BN_rand(priv_key,i,0,0)) goto err; + generate_new_key=1; } else priv_key=dh->priv_key; @@ -96,7 +127,21 @@ DH *dh; else pub_key=dh->pub_key; - if (!BN_mod_exp(pub_key,dh->g,priv_key,dh->p,ctx)) 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 (generate_new_key) + { + l = dh->length ? dh->length : BN_num_bits(dh->p)-1; /* secret exponent length */ + if (!BN_rand(priv_key, l, 0, 0)) goto err; + } + 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; @@ -107,29 +152,36 @@ err: if ((pub_key != NULL) && (dh->pub_key == NULL)) BN_free(pub_key); if ((priv_key != NULL) && (dh->priv_key == NULL)) BN_free(priv_key); - if (ctx != NULL) BN_CTX_free(ctx); + BN_CTX_free(ctx); return(ok); } -int DH_compute_key(key,pub_key,dh) -unsigned char *key; -BIGNUM *pub_key; -DH *dh; +static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) { BN_CTX *ctx; + BN_MONT_CTX *mont; BIGNUM *tmp; int ret= -1; - ctx=BN_CTX_new(); + ctx = BN_CTX_new(); if (ctx == NULL) goto err; - tmp=ctx->bn[ctx->tos++]; + 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 (!BN_mod_exp(tmp,pub_key,dh->priv_key,dh->p,ctx)) + 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; @@ -137,6 +189,35 @@ DH *dh; ret=BN_bn2bin(tmp,key); err: - if (ctx != NULL) BN_CTX_free(ctx); + BN_CTX_end(ctx); + BN_CTX_free(ctx); return(ret); } + +static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, + const 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/src/lib/libcrypto/dh/dh_lib.c b/src/lib/libcrypto/dh/dh_lib.c index a300b38396..ba5fd41057 100644 --- a/src/lib/libcrypto/dh/dh_lib.c +++ b/src/lib/libcrypto/dh/dh_lib.c @@ -58,21 +58,84 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "dh.h" +#include +#include +#include -char *DH_version="Diffie-Hellman part of SSLeay 0.9.0b 29-Jun-1998"; +const char *DH_version="Diffie-Hellman" OPENSSL_VERSION_PTEXT; -DH *DH_new() +static const DH_METHOD *default_DH_method = NULL; + +void DH_set_default_method(const DH_METHOD *meth) + { + default_DH_method = meth; + } + +const DH_METHOD *DH_get_default_method(void) + { + if(!default_DH_method) + default_DH_method = DH_OpenSSL(); + return default_DH_method; + } + +int DH_set_method(DH *dh, const DH_METHOD *meth) + { + /* NB: The caller is specifically setting a method, so it's not up to us + * to deal with which ENGINE it comes from. */ + const DH_METHOD *mtmp; + mtmp = dh->meth; + if (mtmp->finish) mtmp->finish(dh); + if (dh->engine) + { + ENGINE_finish(dh->engine); + dh->engine = NULL; + } + dh->meth = meth; + if (meth->init) meth->init(dh); + return 1; + } + +DH *DH_new(void) + { + return DH_new_method(NULL); + } + +DH *DH_new_method(ENGINE *engine) { DH *ret; - ret=(DH *)Malloc(sizeof(DH)); + ret=(DH *)OPENSSL_malloc(sizeof(DH)); if (ret == NULL) { - DHerr(DH_F_DH_NEW,ERR_R_MALLOC_FAILURE); + DHerr(DH_F_DH_NEW_METHOD,ERR_R_MALLOC_FAILURE); return(NULL); } + + ret->meth = DH_get_default_method(); + if (engine) + { + if (!ENGINE_init(engine)) + { + DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB); + OPENSSL_free(ret); + return NULL; + } + ret->engine = engine; + } + else + ret->engine = ENGINE_get_default_DH(); + if(ret->engine) + { + ret->meth = ENGINE_get_DH(ret->engine); + if(!ret->meth) + { + DHerr(DH_F_DH_NEW_METHOD,ERR_R_ENGINE_LIB); + ENGINE_finish(ret->engine); + OPENSSL_free(ret); + return NULL; + } + } + ret->pad=0; ret->version=0; ret->p=NULL; @@ -80,21 +143,95 @@ DH *DH_new() 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(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data); + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + if (ret->engine) + ENGINE_finish(ret->engine); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data); + OPENSSL_free(ret); + ret=NULL; + } return(ret); } -void DH_free(r) -DH *r; +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); + if (r->engine) + ENGINE_finish(r->engine); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, 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) OPENSSL_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); + OPENSSL_free(r); + } + +int DH_up_ref(DH *r) + { + int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH); +#ifdef REF_PRINT + REF_PRINT("DH",r); +#endif +#ifdef REF_CHECK + if (i < 2) + { + fprintf(stderr, "DH_up, bad reference count\n"); + abort(); + } +#endif + return ((i > 1) ? 1 : 0); + } + +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) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, 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 *dh; +int DH_size(const DH *dh) { return(BN_num_bytes(dh->p)); } diff --git a/src/lib/libcrypto/doc/DH_set_method.pod b/src/lib/libcrypto/doc/DH_set_method.pod index dca41d8dbc..d990bf8786 100644 --- a/src/lib/libcrypto/doc/DH_set_method.pod +++ b/src/lib/libcrypto/doc/DH_set_method.pod @@ -2,20 +2,21 @@ =head1 NAME -DH_set_default_method, DH_get_default_method, DH_set_method, -DH_new_method, DH_OpenSSL - select DH method +DH_set_default_openssl_method, DH_get_default_openssl_method, +DH_set_method, DH_new_method, DH_OpenSSL - select DH method =head1 SYNOPSIS #include + #include - void DH_set_default_method(DH_METHOD *meth); + void DH_set_default_openssl_method(DH_METHOD *meth); - DH_METHOD *DH_get_default_method(void); + DH_METHOD *DH_get_default_openssl_method(void); - DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth); + int DH_set_method(DH *dh, ENGINE *engine); - DH *DH_new_method(DH_METHOD *meth); + DH *DH_new_method(ENGINE *engine); DH_METHOD *DH_OpenSSL(void); @@ -28,20 +29,26 @@ such as hardware accelerators may be used. Initially, the default is to use the OpenSSL internal implementation. DH_OpenSSL() returns a pointer to that method. -DH_set_default_method() makes B the default method for all B -structures created later. +DH_set_default_openssl_method() makes B the default method for all DH +structures created later. B This is true only whilst the default engine +for Diffie-Hellman operations remains as "openssl". ENGINEs provide an +encapsulation for implementations of one or more algorithms, and all the DH +functions mentioned here operate within the scope of the default +"openssl" engine. -DH_get_default_method() returns a pointer to the current default -method. +DH_get_default_openssl_method() returns a pointer to the current default +method for the "openssl" engine. -DH_set_method() selects B for all operations using the structure B. +DH_set_method() selects B as the engine that will be responsible for +all operations using the structure B. If this function completes successfully, +then the B structure will have its own functional reference of B, so +the caller should remember to free their own reference to B when they are +finished with it. NB: An ENGINE's DH_METHOD can be retrieved (or set) by +ENGINE_get_DH() or ENGINE_set_DH(). -DH_get_method() returns a pointer to the method currently selected -for B. - -DH_new_method() allocates and initializes a B structure so that -B will be used for the DH operations. If B is B, -the default method is used. +DH_new_method() allocates and initializes a DH structure so that +B will be used for the DH operations. If B is NULL, +the default engine for Diffie-Hellman opertaions is used. =head1 THE DH_METHOD STRUCTURE @@ -56,7 +63,7 @@ the default method is used. /* compute shared secret */ int (*compute_key)(unsigned char *key, BIGNUM *pub_key, DH *dh); - /* compute r = a ^ p mod m. May be NULL */ + /* compute r = a ^ p mod m (May be NULL for some implementations) */ int (*bn_mod_exp)(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); @@ -75,17 +82,17 @@ the default method is used. =head1 RETURN VALUES -DH_OpenSSL(), DH_get_default_method() and DH_get_method() return -pointers to the respective Bs. +DH_OpenSSL() and DH_get_default_openssl_method() return pointers to the +respective Bs. -DH_set_default_method() returns no value. +DH_set_default_openssl_method() returns no value. -DH_set_method() returns a pointer to the B previously -associated with B. +DH_set_method() returns non-zero if the ENGINE associated with B +was successfully changed to B. -DH_new_method() returns B and sets an error code that can be -obtained by L if the allocation fails. Otherwise it -returns a pointer to the newly allocated structure. +DH_new_method() returns NULL and sets an error code that can be +obtained by L if the allocation fails. +Otherwise it returns a pointer to the newly allocated structure. =head1 SEE ALSO @@ -96,4 +103,9 @@ L, L DH_set_default_method(), DH_get_default_method(), DH_set_method(), DH_new_method() and DH_OpenSSL() were added in OpenSSL 0.9.4. +DH_set_default_openssl_method() and DH_get_default_openssl_method() +replaced DH_set_default_method() and DH_get_default_method() respectively, +and DH_set_method() and DH_new_method() were altered to use Bs +rather than Bs during development of OpenSSL 0.9.6. + =cut diff --git a/src/lib/libcrypto/doc/DSA_set_method.pod b/src/lib/libcrypto/doc/DSA_set_method.pod index 0b13ec9237..36a1052d27 100644 --- a/src/lib/libcrypto/doc/DSA_set_method.pod +++ b/src/lib/libcrypto/doc/DSA_set_method.pod @@ -2,20 +2,21 @@ =head1 NAME -DSA_set_default_method, DSA_get_default_method, DSA_set_method, -DSA_new_method, DSA_OpenSSL - select RSA method +DSA_set_default_openssl_method, DSA_get_default_openssl_method, +DSA_set_method, DSA_new_method, DSA_OpenSSL - select DSA method =head1 SYNOPSIS - #include + #include + #include - void DSA_set_default_method(DSA_METHOD *meth); + void DSA_set_default_openssl_method(DSA_METHOD *meth); - DSA_METHOD *DSA_get_default_method(void); + DSA_METHOD *DSA_get_default_openssl_method(void); - DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *meth); + int DSA_set_method(DSA *dsa, ENGINE *engine); - DSA *DSA_new_method(DSA_METHOD *meth); + DSA *DSA_new_method(ENGINE *engine); DSA_METHOD *DSA_OpenSSL(void); @@ -28,20 +29,21 @@ such as hardware accelerators may be used. Initially, the default is to use the OpenSSL internal implementation. DSA_OpenSSL() returns a pointer to that method. -DSA_set_default_method() makes B the default method for all B -structures created later. +DSA_set_default_openssl_method() makes B the default method for +all DSA structures created later. B This is true only whilst the +default engine for DSA operations remains as "openssl". ENGINEs +provide an encapsulation for implementations of one or more algorithms at a +time, and all the DSA functions mentioned here operate within the scope +of the default "openssl" engine. -DSA_get_default_method() returns a pointer to the current default -method. +DSA_get_default_openssl_method() returns a pointer to the current default +method for the "openssl" engine. -DSA_set_method() selects B for all operations using the structure B. +DSA_set_method() selects B for all operations using the structure B. -DSA_get_method() returns a pointer to the method currently selected -for B. - -DSA_new_method() allocates and initializes a B structure so that -B will be used for the DSA operations. If B is B, -the default method is used. +DSA_new_method() allocates and initializes a DSA structure so that +B will be used for the DSA operations. If B is NULL, +the default engine for DSA operations is used. =head1 THE DSA_METHOD STRUCTURE @@ -62,12 +64,13 @@ struct int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa); - /* compute rr = a1^p1 * a2^p2 mod m. May be NULL */ + /* compute rr = a1^p1 * a2^p2 mod m (May be NULL for some + implementations) */ 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); - /* compute r = a ^ p mod m. May be NULL */ + /* compute r = a ^ p mod m (May be NULL for some implementations) */ int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); @@ -86,18 +89,17 @@ struct =head1 RETURN VALUES -DSA_OpenSSL(), DSA_get_default_method() and DSA_get_method() return -pointers to the respective Bs. +DSA_OpenSSL() and DSA_get_default_openssl_method() return pointers to the +respective Bs. -DSA_set_default_method() returns no value. +DSA_set_default_openssl_method() returns no value. -DSA_set_method() returns a pointer to the B previously -associated with B. +DSA_set_method() returns non-zero if the ENGINE associated with B +was successfully changed to B. -DSA_new_method() returns B and sets an error code that can be +DSA_new_method() returns NULL and sets an error code that can be obtained by L if the allocation -fails. Otherwise it returns a pointer to the newly allocated -structure. +fails. Otherwise it returns a pointer to the newly allocated structure. =head1 SEE ALSO @@ -108,4 +110,9 @@ L, L DSA_set_default_method(), DSA_get_default_method(), DSA_set_method(), DSA_new_method() and DSA_OpenSSL() were added in OpenSSL 0.9.4. +DSA_set_default_openssl_method() and DSA_get_default_openssl_method() +replaced DSA_set_default_method() and DSA_get_default_method() respectively, +and DSA_set_method() and DSA_new_method() were altered to use Bs +rather than Bs during development of OpenSSL 0.9.6. + =cut diff --git a/src/lib/libcrypto/doc/ERR_error_string.pod b/src/lib/libcrypto/doc/ERR_error_string.pod index 0d2417599c..e01beb817a 100644 --- a/src/lib/libcrypto/doc/ERR_error_string.pod +++ b/src/lib/libcrypto/doc/ERR_error_string.pod @@ -2,13 +2,16 @@ =head1 NAME -ERR_error_string - obtain human-readable error message +ERR_error_string, ERR_error_string_n, ERR_lib_error_string, +ERR_func_error_string, ERR_reason_error_string - obtain human-readable +error message =head1 SYNOPSIS #include char *ERR_error_string(unsigned long e, char *buf); + char *ERR_error_string_n(unsigned long e, char *buf, size_t len); const char *ERR_lib_error_string(unsigned long e); const char *ERR_func_error_string(unsigned long e); @@ -17,9 +20,13 @@ ERR_error_string - obtain human-readable error message =head1 DESCRIPTION ERR_error_string() generates a human-readable string representing the -error code B, and places it at B. B must be at least 120 -bytes long. If B is B, the error string is placed in a +error code I, and places it at I. I must be at least 120 +bytes long. If I is B, the error string is placed in a static buffer. +ERR_error_string_n() is a variant of ERR_error_string() that writes +at most I characters (including the terminating 0) +and truncates the string if necessary. +For ERR_error_string_n(), I may not be B. The string will have the following format: @@ -45,7 +52,7 @@ all error codes currently in the queue. =head1 RETURN VALUES ERR_error_string() returns a pointer to a static buffer containing the -string if B, B otherwise. +string if I B<== NULL>, I otherwise. ERR_lib_error_string(), ERR_func_error_string() and ERR_reason_error_string() return the strings, and B if @@ -61,5 +68,6 @@ L =head1 HISTORY ERR_error_string() is available in all versions of SSLeay and OpenSSL. +ERR_error_string_n() was added in OpenSSL 0.9.6. =cut diff --git a/src/lib/libcrypto/doc/ERR_get_error.pod b/src/lib/libcrypto/doc/ERR_get_error.pod index 75ece00d97..9fdedbcb91 100644 --- a/src/lib/libcrypto/doc/ERR_get_error.pod +++ b/src/lib/libcrypto/doc/ERR_get_error.pod @@ -2,7 +2,10 @@ =head1 NAME -ERR_get_error, ERR_peek_error - obtain error code +ERR_get_error, ERR_peek_error, ERR_peek_last_error, +ERR_get_error_line, ERR_peek_error_line, ERR_peek_last_error_line, +ERR_get_error_line_data, ERR_peek_error_line_data, +ERR_peek_error_line_data - obtain error code and data =head1 SYNOPSIS @@ -10,22 +13,29 @@ ERR_get_error, ERR_peek_error - obtain error code unsigned long ERR_get_error(void); unsigned long ERR_peek_error(void); + unsigned long ERR_peek_last_error(void); unsigned long ERR_get_error_line(const char **file, int *line); unsigned long ERR_peek_error_line(const char **file, int *line); + unsigned long ERR_peek_last_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_line_data(const char **file, int *line, const char **data, int *flags); + unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags); =head1 DESCRIPTION -ERR_get_error() returns the last error code from the thread's error +ERR_get_error() returns the earliest error code from the thread's error queue and removes the entry. This function can be called repeatedly until there are no more error codes to return. -ERR_peek_error() returns the last error code from the thread's +ERR_peek_error() returns the earliest error code from the thread's +error queue without modifying it. + +ERR_peek_last_error() returns the latest error code from the thread's error queue without modifying it. See L for obtaining information about @@ -33,14 +43,16 @@ location and reason of the error, and L for human-readable error messages. -ERR_get_error_line() and ERR_peek_error_line() are the same as the -above, but they additionally store the file name and line number where +ERR_get_error_line(), ERR_peek_error_line() and +ERR_peek_last_error_line() are the same as the above, but they +additionally store the file name and line number where the error occurred in *B and *B, unless these are B. -ERR_get_error_line_data() and ERR_peek_error_line_data() store -additional data and flags associated with the error code in *B +ERR_get_error_line_data(), ERR_peek_error_line_data() and +ERR_get_last_error_line_data() store additional data and flags +associated with the error code in *B and *B, unless these are B. *B contains a string -if *B&B. If it has been allocated by Malloc(), +if *B&B. If it has been allocated by OPENSSL_malloc(), *B&B is true. =head1 RETURN VALUES @@ -58,5 +70,7 @@ ERR_get_error(), ERR_peek_error(), ERR_get_error_line() and ERR_peek_error_line() are available in all versions of SSLeay and OpenSSL. ERR_get_error_line_data() and ERR_peek_error_line_data() were added in SSLeay 0.9.0. +ERR_peek_last_error(), ERR_peek_last_error_line() and +ERR_peek_last_error_line_data() were added in OpenSSL 0.9.7. =cut diff --git a/src/lib/libcrypto/doc/ERR_remove_state.pod b/src/lib/libcrypto/doc/ERR_remove_state.pod index ebcdc0f5a5..72925fb9f4 100644 --- a/src/lib/libcrypto/doc/ERR_remove_state.pod +++ b/src/lib/libcrypto/doc/ERR_remove_state.pod @@ -16,7 +16,7 @@ ERR_remove_state() frees the error queue associated with thread B. If B == 0, the current thread will have its error queue removed. Since error queue data structures are allocated automatically for new -threads, they must be freed when threads are terminated in oder to +threads, they must be freed when threads are terminated in order to avoid memory leaks. =head1 RETURN VALUE diff --git a/src/lib/libcrypto/doc/EVP_DigestInit.pod b/src/lib/libcrypto/doc/EVP_DigestInit.pod index 345b1ddfa7..b3a61f1c5d 100644 --- a/src/lib/libcrypto/doc/EVP_DigestInit.pod +++ b/src/lib/libcrypto/doc/EVP_DigestInit.pod @@ -2,21 +2,40 @@ =head1 NAME -EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal - EVP digest routines +EVP_MD_CTX_init, EVP_MD_CTX_create, EVP_DigestInit_ex, EVP_DigestUpdate, +EVP_DigestFinal_ex, EVP_MD_CTX_cleanup, EVP_MD_CTX_destroy, EVP_MAX_MD_SIZE, +EVP_MD_CTX_copy_ex EVP_MD_CTX_copy, EVP_MD_type, EVP_MD_pkey_type, EVP_MD_size, +EVP_MD_block_size, EVP_MD_CTX_md, EVP_MD_CTX_size, EVP_MD_CTX_block_size, EVP_MD_CTX_type, +EVP_md_null, EVP_md2, EVP_md5, EVP_sha, EVP_sha1, EVP_dss, EVP_dss1, EVP_mdc2, +EVP_ripemd160, EVP_get_digestbyname, EVP_get_digestbynid, EVP_get_digestbyobj - +EVP digest routines =head1 SYNOPSIS #include - 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, + void EVP_MD_CTX_init(EVP_MD_CTX *ctx); + EVP_MD_CTX *EVP_MD_CTX_create(void); + + int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); + int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); + int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); - #define EVP_MAX_MD_SIZE (16+20) /* The SSLv3 md5+sha1 type */ + int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); + void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); + + int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in); + + int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); + int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, + unsigned int *s); int EVP_MD_CTX_copy(EVP_MD_CTX *out,EVP_MD_CTX *in); + #define EVP_MAX_MD_SIZE (16+20) /* The SSLv3 md5+sha1 type */ + + #define EVP_MD_type(e) ((e)->type) #define EVP_MD_pkey_type(e) ((e)->pkey_type) #define EVP_MD_size(e) ((e)->md_size) @@ -27,15 +46,15 @@ EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal - EVP digest routines #define EVP_MD_CTX_block_size(e) EVP_MD_block_size((e)->digest) #define EVP_MD_CTX_type(e) EVP_MD_type((e)->digest) - 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); + const EVP_MD *EVP_md_null(void); + const EVP_MD *EVP_md2(void); + const EVP_MD *EVP_md5(void); + const EVP_MD *EVP_sha(void); + const EVP_MD *EVP_sha1(void); + const EVP_MD *EVP_dss(void); + const EVP_MD *EVP_dss1(void); + const EVP_MD *EVP_mdc2(void); + const EVP_MD *EVP_ripemd160(void); const EVP_MD *EVP_get_digestbyname(const char *name); #define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) @@ -45,25 +64,48 @@ EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal - EVP digest routines The EVP digest routines are a high level interface to message digests. -EVP_DigestInit() initialises a digest context B to use a digest -B: this will typically be supplied by a function such as -EVP_sha1(). +EVP_MD_CTX_init() initializes digest contet B. + +EVP_MD_CTX_create() allocates, initializes and returns a digest contet. + +EVP_DigestInit_ex() sets up digest context B to use a digest +B from ENGINE B. B must be initialized before calling this +function. B will typically be supplied by a functionsuch as EVP_sha1(). +If B is NULL then the default implementation of digest B is used. EVP_DigestUpdate() hashes B bytes of data at B into the -digest context B. This funtion can be called several times on the +digest context B. This function can be called several times on the same B to hash additional data. -EVP_DigestFinal() retrieves the digest value from B and places +EVP_DigestFinal_ex() retrieves the digest value from B and places it in B. If the B parameter is not NULL then the number of bytes of data written (i.e. the length of the digest) will be written to the integer at B, at most B bytes will be written. -After calling EVP_DigestFinal() no additional calls to EVP_DigestUpdate() -can be made, but EVP_DigestInit() can be called to initialiase a new +After calling EVP_DigestFinal_ex() no additional calls to EVP_DigestUpdate() +can be made, but EVP_DigestInit_ex() can be called to initialize a new digest operation. -EVP_MD_CTX_copy() can be used to copy the message digest state from +EVP_MD_CTX_cleanup() cleans up digest context B, it should be called +after a digest context is no longer needed. + +EVP_MD_CTX_destroy() cleans up digest context B and frees up the +space allocated to it, it should be called only on a context created +using EVP_MD_CTX_create(). + +EVP_MD_CTX_copy_ex() can be used to copy the message digest state from B to B. This is useful if large amounts of data are to be -hashed which only differ in the last few bytes. +hashed which only differ in the last few bytes. B must be initialized +before calling this function. + +EVP_DigestInit() behaves in the same way as EVP_DigestInit_ex() except +the passed context B does not have to be initialized, and it always +uses the default digest implementation. + +EVP_DigestFinal() is similar to EVP_DigestFinal_ex() except the digest +contet B is automatically cleaned up. + +EVP_MD_CTX_copy() is similar to EVP_MD_CTX_copy_ex() except the destination +B does not have to be initialized. EVP_MD_size() and EVP_MD_CTX_size() return the size of the message digest when passed an B or an B structure, i.e. the size of the @@ -97,14 +139,15 @@ returns is of zero length. EVP_get_digestbyname(), EVP_get_digestbynid() and EVP_get_digestbyobj() return an B structure when passed a digest name, a digest NID or -an ASN1_OBJECT structure respectively. The digest table must be initialised +an ASN1_OBJECT structure respectively. The digest table must be initialized using, for example, OpenSSL_add_all_digests() for these functions to work. =head1 RETURN VALUES -EVP_DigestInit(), EVP_DigestUpdate() and EVP_DigestFinal() do not return values. +EVP_DigestInit_ex(), EVP_DigestUpdate() and EVP_DigestFinal_ex() return 1 for +success and 0 for failure. -EVP_MD_CTX_copy() returns 1 if successful or 0 for failure. +EVP_MD_CTX_copy_ex() returns 1 if successful or 0 for failure. EVP_MD_type(), EVP_MD_pkey_type() and EVP_MD_type() return the NID of the corresponding OBJECT IDENTIFIER or NID_undef if none exists. @@ -129,6 +172,19 @@ transparent to the digest used and much more flexible. SHA1 is the digest of choice for new applications. The other digest algorithms are still in common use. +For most applications the B parameter to EVP_DigestInit_ex() will be +set to NULL to use the default digest implementation. + +The functions EVP_DigestInit(), EVP_DigestFinal() and EVP_MD_CTX_copy() are +obsolete but are retained to maintain compatibility with existing code. New +applications should use EVP_DigestInit_ex(), EVP_DigestFinal_ex() and +EVP_MD_CTX_copy_ex() because they can efficiently reuse a digest context +instead of initializing and cleaning it up on each call and allow non default +implementations of digests to be specified. + +In OpenSSL 0.9.7 and later if digest contexts are not cleaned up after use +memory leaks will occur. + =head1 EXAMPLE This example digests the data "Test Message\n" and "Hello World\n", using the @@ -160,10 +216,12 @@ digest name passed on the command line. exit(1); } - EVP_DigestInit(&mdctx, md); + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, md, NULL); EVP_DigestUpdate(&mdctx, mess1, strlen(mess1)); EVP_DigestUpdate(&mdctx, mess2, strlen(mess2)); - EVP_DigestFinal(&mdctx, md_value, &md_len); + EVP_DigestFinal_ex(&mdctx, md_value, &md_len); + EVP_MD_CTX_cleanup(&mdctx); printf("Digest is: "); for(i = 0; i < md_len; i++) printf("%02x", md_value[i]); @@ -172,17 +230,10 @@ digest name passed on the command line. =head1 BUGS -Several of the functions do not return values: maybe they should. Although the -internal digest operations will never fail some future hardware based operations -might. - The link between digests and signing algorithms results in a situation where EVP_sha1() must be used with RSA and EVP_dss1() must be used with DSS even though they are identical digests. -The size of an B structure is determined at compile time: this results -in code that must be recompiled if the size of B increases. - =head1 SEE ALSO L, L, L, @@ -194,4 +245,7 @@ L, L EVP_DigestInit(), EVP_DigestUpdate() and EVP_DigestFinal() are available in all versions of SSLeay and OpenSSL. +EVP_DigestInit_ex(), EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex() +were added in OpenSSL 0.9.7. + =cut diff --git a/src/lib/libcrypto/doc/EVP_EncryptInit.pod b/src/lib/libcrypto/doc/EVP_EncryptInit.pod index 77ed4ccdba..371b6a2287 100644 --- a/src/lib/libcrypto/doc/EVP_EncryptInit.pod +++ b/src/lib/libcrypto/doc/EVP_EncryptInit.pod @@ -2,34 +2,68 @@ =head1 NAME -EVP_EncryptInit, EVP_EncryptUpdate, EVP_EncryptFinal - EVP cipher routines +EVP_CIPHER_CTX_init, EVP_EncryptInit_ex, EVP_EncryptUpdate, +EVP_EncryptFinal_ex, EVP_DecryptInit_ex, EVP_DecryptUpdate, +EVP_DecryptFinal_ex, EVP_CipherInit_ex, EVP_CipherUpdate, +EVP_CipherFinal_ex, EVP_CIPHER_CTX_set_key_length, +EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX_cleanup, EVP_EncryptInit, +EVP_EncryptFinal, EVP_DecryptInit, EVP_DecryptFinal, +EVP_CipherInit, EVP_CipherFinal, EVP_get_cipherbyname, +EVP_get_cipherbynid, EVP_get_cipherbyobj, EVP_CIPHER_nid, +EVP_CIPHER_block_size, EVP_CIPHER_key_length, EVP_CIPHER_iv_length, +EVP_CIPHER_flags, EVP_CIPHER_mode, EVP_CIPHER_type, EVP_CIPHER_CTX_cipher, +EVP_CIPHER_CTX_nid, EVP_CIPHER_CTX_block_size, EVP_CIPHER_CTX_key_length, +EVP_CIPHER_CTX_iv_length, EVP_CIPHER_CTX_get_app_data, +EVP_CIPHER_CTX_set_app_data, EVP_CIPHER_CTX_type, EVP_CIPHER_CTX_flags, +EVP_CIPHER_CTX_mode, EVP_CIPHER_param_to_asn1, EVP_CIPHER_asn1_to_param, +EVP_CIPHER_CTX_set_padding - EVP cipher routines =head1 SYNOPSIS #include - 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 EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); + + int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + ENGINE *impl, unsigned char *key, unsigned char *iv); + int 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 EVP_EncryptFinal_ex(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 EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + ENGINE *impl, unsigned char *key, unsigned char *iv); + int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl); + int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + + int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + ENGINE *impl, unsigned char *key, unsigned char *iv, int enc); + int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, unsigned char *in, int inl); + int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + + int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char *key, unsigned char *iv); + int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl); + + int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char *key, unsigned char *iv); int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); - void EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + int 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); - void EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); + int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding); + int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); + int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); + int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); const EVP_CIPHER *EVP_get_cipherbyname(const char *name); #define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) @@ -38,15 +72,21 @@ EVP_EncryptInit, EVP_EncryptUpdate, EVP_EncryptFinal - EVP cipher routines #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_iv_length(e) ((e)->iv_len) + #define EVP_CIPHER_flags(e) ((e)->flags) + #define EVP_CIPHER_mode(e) ((e)->flags) & EVP_CIPH_MODE) int EVP_CIPHER_type(const EVP_CIPHER *ctx); + #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_key_length(e) ((e)->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_CIPHER_CTX_flags(e) ((e)->cipher->flags) + #define EVP_CIPHER_CTX_mode(e) ((e)->cipher->flags & EVP_CIPH_MODE) 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); @@ -56,16 +96,19 @@ EVP_EncryptInit, EVP_EncryptUpdate, EVP_EncryptFinal - EVP cipher routines The EVP cipher routines are a high level interface to certain symmetric ciphers. -EVP_EncryptInit() initialises a cipher context B for encryption -with cipher B. B is normally supplied by a function such -as EVP_des_cbc() . B is the symmetric key to use and B is the -IV to use (if necessary), the actual number of bytes used for the -key and IV depends on the cipher. It is possible to set all parameters -to NULL except B in an initial call and supply the remaining -parameters in subsequent calls. This is normally done when the -EVP_CIPHER_asn1_to_param() function is called to set the cipher -parameters from an ASN1 AlgorithmIdentifier and the key from a -different source. +EVP_CIPHER_CTX_init() initializes cipher contex B. + +EVP_EncryptInit_ex() sets up cipher context B for encryption +with cipher B from ENGINE B. B must be initialized +before calling this function. B is normally supplied +by a function such as EVP_des_cbc(). If B is NULL then the +default implementation is used. B is the symmetric key to use +and B is the IV to use (if necessary), the actual number of bytes +used for the key and IV depends on the cipher. It is possible to set +all parameters to NULL except B in an initial call and supply +the remaining parameters in subsequent calls, all of which have B +set to NULL. This is done when the default cipher parameters are not +appropriate. EVP_EncryptUpdate() encrypts B bytes from the buffer B and writes the encrypted version to B. This function can be called @@ -73,31 +116,49 @@ multiple times to encrypt successive blocks of data. The amount of data written depends on the block alignment of the encrypted data: as a result the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1) so B should contain sufficient -room. The actual number of bytes written is placed in B. +room. The actual number of bytes written is placed in B. -EVP_EncryptFinal() encrypts the "final" data, that is any data that -remains in a partial block. It uses L (aka PKCS -padding). The encrypted final data is written to B which should -have sufficient space for one cipher block. The number of bytes written -is placed in B. After this function is called the encryption operation -is finished and no further calls to EVP_EncryptUpdate() should be made. - -EVP_DecryptInit(), EVP_DecryptUpdate() and EVP_DecryptFinal() are the -corresponding decryption operations. EVP_DecryptFinal() will return an -error code if the final block is not correctly formatted. The parameters -and restrictions are identical to the encryption operations except that -the decrypted data buffer B passed to EVP_DecryptUpdate() should -have sufficient room for (B + cipher_block_size) bytes unless the -cipher block size is 1 in which case B bytes is sufficient. +If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts +the "final" data, that is any data that remains in a partial block. +It uses L (aka PKCS padding). The encrypted +final data is written to B which should have sufficient space for +one cipher block. The number of bytes written is placed in B. After +this function is called the encryption operation is finished and no further +calls to EVP_EncryptUpdate() should be made. -EVP_CipherInit(), EVP_CipherUpdate() and EVP_CipherFinal() are functions -that can be used for decryption or encryption. The operation performed -depends on the value of the B parameter. It should be set to 1 for -encryption and 0 for decryption. +If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more +data and it will return an error if any data remains in a partial block: +that is if the total data length is not a multiple of the block size. -EVP_CIPHER_CTX_cleanup() clears all information from a cipher context. -It should be called after all operations using a cipher are complete -so sensitive information does not remain in memory. +EVP_DecryptInit_ex(), EVP_DecryptUpdate() and EVP_DecryptFinal_ex() are the +corresponding decryption operations. EVP_DecryptFinal() will return an +error code if padding is enabled and the final block is not correctly +formatted. The parameters and restrictions are identical to the encryption +operations except that if padding is enabled the decrypted data buffer B +passed to EVP_DecryptUpdate() should have sufficient room for +(B + cipher_block_size) bytes unless the cipher block size is 1 in +which case B bytes is sufficient. + +EVP_CipherInit_ex(), EVP_CipherUpdate() and EVP_CipherFinal_ex() are +functions that can be used for decryption or encryption. The operation +performed depends on the value of the B parameter. It should be set +to 1 for encryption, 0 for decryption and -1 to leave the value unchanged +(the actual value of 'enc' being supplied in a previous call). + +EVP_CIPHER_CTX_cleanup() clears all information from a cipher context +and free up any allocated memory associate with it. It should be called +after all operations using a cipher are complete so sensitive information +does not remain in memory. + +EVP_EncryptInit(), EVP_DecryptInit() and EVP_CipherInit() behave in a +similar way to EVP_EncryptInit_ex(), EVP_DecryptInit_ex and +EVP_CipherInit_ex() except the B paramter does not need to be +initialized and they always use the default cipher implementation. + +EVP_EncryptFinal(), EVP_DecryptFinal() and EVP_CipherFinal() behave in a +similar way to EVP_EncryptFinal_ex(), EVP_DecryptFinal_ex() and +EVP_CipherFinal_ex() except B is automatically cleaned up +after the call. EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj() return an EVP_CIPHER structure when passed a cipher name, a NID or an @@ -108,10 +169,23 @@ passed an B or B structure. The actual NID value is an internal value which may not have a corresponding OBJECT IDENTIFIER. +EVP_CIPHER_CTX_set_padding() enables or disables padding. By default +encryption operations are padded using standard block padding and the +padding is checked and removed when decrypting. If the B parameter +is zero then no padding is performed, the total amount of data encrypted +or decrypted must then be a multiple of the block size or an error will +occur. + EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key length of a cipher when passed an B or B structure. The constant B is the maximum key length -for all ciphers. +for all ciphers. Note: although EVP_CIPHER_key_length() is fixed for a +given cipher, the value of EVP_CIPHER_CTX_key_length() may be different +for variable key length ciphers. + +EVP_CIPHER_CTX_set_key_length() sets the key length of the cipher ctx. +If the cipher is a fixed length cipher then attempting to set the key +length to any value other than the fixed value is an error. EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV length of a cipher when passed an B or B. @@ -133,6 +207,11 @@ B. EVP_CIPHER_CTX_cipher() returns the B structure when passed an B structure. +EVP_CIPHER_mode() and EVP_CIPHER_CTX_mode() return the block cipher mode: +EVP_CIPH_ECB_MODE, EVP_CIPH_CBC_MODE, EVP_CIPH_CFB_MODE or +EVP_CIPH_OFB_MODE. If the cipher is a stream cipher then +EVP_CIPH_STREAM_CIPHER is returned. + EVP_CIPHER_param_to_asn1() sets the AlgorithmIdentifier "parameter" based on the passed cipher. This will typically include any parameters and an IV. The cipher IV (if any) must be set when this call is made. This call @@ -149,21 +228,24 @@ key set to NULL, EVP_CIPHER_asn1_to_param() will be called and finally EVP_CipherInit() again with all parameters except the key set to NULL. It is possible for this function to fail if the cipher does not have any ASN1 support or the parameters cannot be set (for example the RC2 effective key length -does not have an B structure). +is not supported. + +EVP_CIPHER_CTX_ctrl() allows various cipher specific parameters to be determined +and set. Currently only the RC2 effective key length and the number of rounds of +RC5 can be set. =head1 RETURN VALUES -EVP_EncryptInit(), EVP_EncryptUpdate() and EVP_EncryptFinal() do not return -values. +EVP_CIPHER_CTX_init, EVP_EncryptInit_ex(), EVP_EncryptUpdate() and +EVP_EncryptFinal_ex() return 1 for success and 0 for failure. -EVP_DecryptInit() and EVP_DecryptUpdate() do not return values. -EVP_DecryptFinal() returns 0 if the decrypt failed or 1 for success. +EVP_DecryptInit_ex() and EVP_DecryptUpdate() return 1 for success and 0 for failure. +EVP_DecryptFinal_ex() returns 0 if the decrypt failed or 1 for success. -EVP_CipherInit() and EVP_CipherUpdate() do not return values. -EVP_CipherFinal() returns 1 for a decryption failure or 1 for success, if -the operation is encryption then it always returns 1. +EVP_CipherInit_ex() and EVP_CipherUpdate() return 1 for success and 0 for failure. +EVP_CipherFinal_ex() returns 0 for a decryption failure or 1 for success. -EVP_CIPHER_CTX_cleanup() does not return a value. +EVP_CIPHER_CTX_cleanup() returns 1 for success and 0 for failure. EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj() return an B structure or NULL on error. @@ -176,6 +258,8 @@ size. EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key length. +EVP_CIPHER_CTX_set_padding() always returns 1. + EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV length or zero if the cipher does not use an IV. @@ -187,6 +271,75 @@ EVP_CIPHER_CTX_cipher() returns an B structure. EVP_CIPHER_param_to_asn1() and EVP_CIPHER_asn1_to_param() return 1 for success or zero for failure. +=head1 CIPHER LISTING + +All algorithms have a fixed key length unless otherwise stated. + +=over 4 + +=item EVP_enc_null() + +Null cipher: does nothing. + +=item EVP_des_cbc(void), EVP_des_ecb(void), EVP_des_cfb(void), EVP_des_ofb(void) + +DES in CBC, ECB, CFB and OFB modes respectively. + +=item EVP_des_ede_cbc(void), EVP_des_ede(), EVP_des_ede_ofb(void), EVP_des_ede_cfb(void) + +Two key triple DES in CBC, ECB, CFB and OFB modes respectively. + +=item EVP_des_ede3_cbc(void), EVP_des_ede3(), EVP_des_ede3_ofb(void), EVP_des_ede3_cfb(void) + +Three key triple DES in CBC, ECB, CFB and OFB modes respectively. + +=item EVP_desx_cbc(void) + +DESX algorithm in CBC mode. + +=item EVP_rc4(void) + +RC4 stream cipher. This is a variable key length cipher with default key length 128 bits. + +=item EVP_rc4_40(void) + +RC4 stream cipher with 40 bit key length. This is obsolete and new code should use EVP_rc4() +and the EVP_CIPHER_CTX_set_key_length() function. + +=item EVP_idea_cbc() EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void), EVP_idea_cbc(void) + +IDEA encryption algorithm in CBC, ECB, CFB and OFB modes respectively. + +=item EVP_rc2_cbc(void), EVP_rc2_ecb(void), EVP_rc2_cfb(void), EVP_rc2_ofb(void) + +RC2 encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key +length cipher with an additional parameter called "effective key bits" or "effective key length". +By default both are set to 128 bits. + +=item EVP_rc2_40_cbc(void), EVP_rc2_64_cbc(void) + +RC2 algorithm in CBC mode with a default key length and effective key length of 40 and 64 bits. +These are obsolete and new code should use EVP_rc2_cbc(), EVP_CIPHER_CTX_set_key_length() and +EVP_CIPHER_CTX_ctrl() to set the key length and effective key length. + +=item EVP_bf_cbc(void), EVP_bf_ecb(void), EVP_bf_cfb(void), EVP_bf_ofb(void); + +Blowfish encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key +length cipher. + +=item EVP_cast5_cbc(void), EVP_cast5_ecb(void), EVP_cast5_cfb(void), EVP_cast5_ofb(void) + +CAST encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key +length cipher. + +=item EVP_rc5_32_12_16_cbc(void), EVP_rc5_32_12_16_ecb(void), EVP_rc5_32_12_16_cfb(void), EVP_rc5_32_12_16_ofb(void) + +RC5 encryption algorithm in CBC, ECB, CFB and OFB modes respectively. This is a variable key length +cipher with an additional "number of rounds" parameter. By default the key length is set to 128 +bits and 12 rounds. + +=back + =head1 NOTES Where possible the B interface to symmetric ciphers should be used in @@ -201,19 +354,146 @@ encrypted then 5 padding bytes of value 5 will be added. When decrypting the final block is checked to see if it has the correct form. -Although the decryption operation can produce an error, it is not a strong -test that the input data or key is correct. A random block has better than -1 in 256 chance of being of the correct format and problems with the -input data earlier on will not produce a final decrypt error. +Although the decryption operation can produce an error if padding is enabled, +it is not a strong test that the input data or key is correct. A random block +has better than 1 in 256 chance of being of the correct format and problems with +the input data earlier on will not produce a final decrypt error. + +If padding is disabled then the decryption operation will always succeed if +the total amount of data decrypted is a multiple of the block size. + +The functions EVP_EncryptInit(), EVP_EncryptFinal(), EVP_DecryptInit(), +EVP_CipherInit() and EVP_CipherFinal() are obsolete but are retained for +compatibility with existing code. New code should use EVP_EncryptInit_ex(), +EVP_EncryptFinal_ex(), EVP_DecryptInit_ex(), EVP_DecryptFinal_ex(), +EVP_CipherInit_ex() and EVP_CipherFinal_ex() because they can reuse an +existing context without allocating and freeing it up on each call. =head1 BUGS -The current B cipher interface is not as flexible as it should be. Only -certain "spot" encryption algorithms can be used for ciphers which have various -parameters associated with them (RC2, RC5 for example) this is inadequate. +For RC5 the number of rounds can currently only be set to 8, 12 or 16. This is +a limitation of the current RC5 code rather than the EVP interface. + +EVP_MAX_KEY_LENGTH and EVP_MAX_IV_LENGTH only refer to the internal ciphers with +default key lengths. If custom ciphers exceed these values the results are +unpredictable. This is because it has become standard practice to define a +generic key as a fixed unsigned char array containing EVP_MAX_KEY_LENGTH bytes. + +The ASN1 code is incomplete (and sometimes inaccurate) it has only been tested +for certain common S/MIME ciphers (RC2, DES, triple DES) in CBC mode. + +=head1 EXAMPLES + +Get the number of rounds used in RC5: + + int nrounds; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC5_ROUNDS, 0, &nrounds); + +Get the RC2 effective key length: + + int key_bits; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC2_KEY_BITS, 0, &key_bits); + +Set the number of rounds used in RC5: + + int nrounds; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC5_ROUNDS, nrounds, NULL); + +Set the effective key length used in RC2: + + int key_bits; + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL); + +Encrypt a string using blowfish: + + int do_crypt(char *outfile) + { + unsigned char outbuf[1024]; + int outlen, tmplen; + /* Bogus key and IV: we'd normally set these from + * another source. + */ + unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + unsigned char iv[] = {1,2,3,4,5,6,7,8}; + char intext[] = "Some Crypto Text"; + EVP_CIPHER_CTX ctx; + FILE *out; + EVP_CIPHER_CTX_init(&ctx); + EVP_EncryptInit_ex(&ctx, NULL, EVP_bf_cbc(), key, iv); + + if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, intext, strlen(intext))) + { + /* Error */ + return 0; + } + /* Buffer passed to EVP_EncryptFinal() must be after data just + * encrypted to avoid overwriting it. + */ + if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen)) + { + /* Error */ + return 0; + } + outlen += tmplen; + EVP_CIPHER_CTX_cleanup(&ctx); + /* Need binary mode for fopen because encrypted data is + * binary data. Also cannot use strlen() on it because + * it wont be null terminated and may contain embedded + * nulls. + */ + out = fopen(outfile, "wb"); + fwrite(outbuf, 1, outlen, out); + fclose(out); + return 1; + } + +The ciphertext from the above example can be decrypted using the B +utility with the command line: + + S + +General encryption, decryption function example using FILE I/O and RC2 with an +80 bit key: + + int do_crypt(FILE *in, FILE *out, int do_encrypt) + { + /* Allow enough space in output buffer for additional block */ + inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH]; + int inlen, outlen; + /* Bogus key and IV: we'd normally set these from + * another source. + */ + unsigned char key[] = "0123456789"; + unsigned char iv[] = "12345678"; + /* Don't set key or IV because we will modify the parameters */ + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, EVP_rc2(), NULL, NULL, NULL, do_encrypt); + EVP_CIPHER_CTX_set_key_length(&ctx, 10); + /* We finished modifying parameters so now we can set key and IV */ + EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt); + + for(;;) + { + inlen = fread(inbuf, 1, 1024, in); + if(inlen <= 0) break; + if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) + { + /* Error */ + return 0; + } + fwrite(outbuf, 1, outlen, out); + } + if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) + { + /* Error */ + return 0; + } + fwrite(outbuf, 1, outlen, out); + + EVP_CIPHER_CTX_cleanup(&ctx); + return 1; + } -Several of the functions do not return error codes because the software versions -can never fail. This is not true of hardware versions. =head1 SEE ALSO diff --git a/src/lib/libcrypto/doc/EVP_OpenInit.pod b/src/lib/libcrypto/doc/EVP_OpenInit.pod index 9707a4b399..2e710da945 100644 --- a/src/lib/libcrypto/doc/EVP_OpenInit.pod +++ b/src/lib/libcrypto/doc/EVP_OpenInit.pod @@ -10,9 +10,9 @@ EVP_OpenInit, EVP_OpenUpdate, EVP_OpenFinal - EVP envelope decryption int EVP_OpenInit(EVP_CIPHER_CTX *ctx,EVP_CIPHER *type,unsigned char *ek, int ekl,unsigned char *iv,EVP_PKEY *priv); - void EVP_OpenUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int EVP_OpenUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl); - void EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); =head1 DESCRIPTION @@ -21,7 +21,7 @@ The EVP envelope routines are a high level interface to envelope decryption. They decrypt a public key encrypted symmetric key and then decrypt data using it. -EVP_OpenInit() initialises a cipher context B for decryption +EVP_OpenInit() initializes a cipher context B for decryption with cipher B. It decrypts the encrypted symmetric key of length B bytes passed in the B parameter using the private key B. The IV is supplied in the B parameter. @@ -29,20 +29,32 @@ The IV is supplied in the B parameter. EVP_OpenUpdate() and EVP_OpenFinal() have exactly the same properties as the EVP_DecryptUpdate() and EVP_DecryptFinal() routines, as documented on the L manual -page. +page. + +=head1 NOTES + +It is possible to call EVP_OpenInit() twice in the same way as +EVP_DecryptInit(). The first call should have B set to NULL +and (after setting any cipher parameters) it should be called again +with B set to NULL. + +If the cipher passed in the B parameter is a variable length +cipher then the key length will be set to the value of the recovered +key length. If the cipher is a fixed length cipher then the recovered +key length must match the fixed cipher length. =head1 RETURN VALUES -EVP_OpenInit() returns -1 on error or an non zero integer (actually the +EVP_OpenInit() returns 0 on error or a non zero integer (actually the recovered secret key size) if successful. -EVP_SealUpdate() does not return a value. +EVP_OpenUpdate() returns 1 for success or 0 for failure. -EVP_SealFinal() returns 0 if the decrypt failed or 1 for success. +EVP_OpenFinal() returns 0 if the decrypt failed or 1 for success. =head1 SEE ALSO -L,L +L, L, L, L diff --git a/src/lib/libcrypto/doc/EVP_SealInit.pod b/src/lib/libcrypto/doc/EVP_SealInit.pod index 1579d110fa..0451eb648a 100644 --- a/src/lib/libcrypto/doc/EVP_SealInit.pod +++ b/src/lib/libcrypto/doc/EVP_SealInit.pod @@ -10,9 +10,9 @@ EVP_SealInit, EVP_SealUpdate, EVP_SealFinal - EVP envelope encryption 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_SealUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int EVP_SealUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl); - void EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, + int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); =head1 DESCRIPTION @@ -22,7 +22,7 @@ encryption. They generate a random key and then "envelope" it by using public key encryption. Data can then be encrypted using this key. -EVP_SealInit() initialises a cipher context B for encryption +EVP_SealInit() initializes a cipher context B for encryption with cipher B using a random secret key and IV supplied in the B parameter. B is normally supplied by a function such as EVP_des_cbc(). The secret key is encrypted using one or more public @@ -41,9 +41,10 @@ page. =head1 RETURN VALUES -EVP_SealInit() returns -1 on error or B if successful. +EVP_SealInit() returns 0 on error or B if successful. -EVP_SealUpdate() and EVP_SealFinal() do not return values. +EVP_SealUpdate() and EVP_SealFinal() return 1 for success and 0 for +failure. =head1 NOTES @@ -59,9 +60,14 @@ but symmetric encryption is fast. So symmetric encryption is used for bulk encryption and the small random symmetric key used is transferred using public key encryption. +It is possible to call EVP_SealInit() twice in the same way as +EVP_EncryptInit(). The first call should have B set to 0 +and (after setting any cipher parameters) it should be called again +with B set to NULL. + =head1 SEE ALSO -L,L +L, L, L, L diff --git a/src/lib/libcrypto/doc/EVP_SignInit.pod b/src/lib/libcrypto/doc/EVP_SignInit.pod index bbc9203c9c..32e9d54809 100644 --- a/src/lib/libcrypto/doc/EVP_SignInit.pod +++ b/src/lib/libcrypto/doc/EVP_SignInit.pod @@ -8,10 +8,12 @@ EVP_SignInit, EVP_SignUpdate, EVP_SignFinal - EVP signing functions #include - void EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type); - void EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); + int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); + int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *sig,unsigned int *s, EVP_PKEY *pkey); + void EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type); + int EVP_PKEY_size(EVP_PKEY *pkey); =head1 DESCRIPTION @@ -19,30 +21,30 @@ EVP_SignInit, EVP_SignUpdate, EVP_SignFinal - EVP signing functions The EVP signature routines are a high level interface to digital signatures. -EVP_SignInit() initialises a signing context B to using digest -B: this will typically be supplied by a function such as -EVP_sha1(). +EVP_SignInit_ex() sets up signing context B to use digest +B from ENGINE B. B must be initialized with +EVP_MD_CTX_init() before calling this function. EVP_SignUpdate() hashes B bytes of data at B into the -signature context B. This funtion can be called several times on the +signature context B. This function can be called several times on the same B to include additional data. EVP_SignFinal() signs the data in B using the private key B and places the signature in B. If the B parameter is not NULL then the number of bytes of data written (i.e. the length of the signature) will be written to the integer at B, at most EVP_PKEY_size(pkey) bytes -will be written. After calling EVP_SignFinal() no additional calls to -EVP_SignUpdate() can be made, but EVP_SignInit() can be called to initialiase -a new signature operation. +will be written. + +EVP_SignInit() initializes a signing context B to use the default +implementation of digest B. EVP_PKEY_size() returns the maximum size of a signature in bytes. The actual signature returned by EVP_SignFinal() may be smaller. =head1 RETURN VALUES -EVP_SignInit() and EVP_SignUpdate() do not return values. - -EVP_SignFinal() returns 1 for success and 0 for failure. +EVP_SignInit_ex(), EVP_SignUpdate() and EVP_SignFinal() return 1 +for success and 0 for failure. EVP_PKEY_size() returns the maximum size of a signature in bytes. @@ -63,11 +65,18 @@ When signing with DSA private keys the random number generator must be seeded or the operation will fail. The random number generator does not need to be seeded for RSA signatures. +The call to EVP_SignFinal() internally finalizes a copy of the digest context. +This means that calls to EVP_SignUpdate() and EVP_SignFinal() can be called +later to digest and sign additional data. + +Since only a copy of the digest context is ever finalized the context must +be cleaned up after use by calling EVP_MD_CTX_cleanup() or a memory leak +will occur. + =head1 BUGS -Several of the functions do not return values: maybe they should. Although the -internal digest operations will never fail some future hardware based operations -might. +Older versions of this documentation wrongly stated that calls to +EVP_SignUpdate() could not be made after calling EVP_SignFinal(). =head1 SEE ALSO @@ -82,4 +91,6 @@ L, L EVP_SignInit(), EVP_SignUpdate() and EVP_SignFinal() are available in all versions of SSLeay and OpenSSL. +EVP_SignInit_ex() was added in OpenSSL 0.9.7 + =cut diff --git a/src/lib/libcrypto/doc/EVP_VerifyInit.pod b/src/lib/libcrypto/doc/EVP_VerifyInit.pod index 3b5e07f4ad..80c656fde8 100644 --- a/src/lib/libcrypto/doc/EVP_VerifyInit.pod +++ b/src/lib/libcrypto/doc/EVP_VerifyInit.pod @@ -8,30 +8,35 @@ EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal - EVP signature verification f #include - void EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); - void EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); + int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); + int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); int EVP_VerifyFinal(EVP_MD_CTX *ctx,unsigned char *sigbuf, unsigned int siglen,EVP_PKEY *pkey); + int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); + =head1 DESCRIPTION The EVP signature verification routines are a high level interface to digital signatures. -EVP_VerifyInit() initialises a verification context B to using digest -B: this will typically be supplied by a function such as EVP_sha1(). +EVP_VerifyInit_ex() sets up verification context B to use digest +B from ENGINE B. B must be initialized by calling +EVP_MD_CTX_init() before calling this function. EVP_VerifyUpdate() hashes B bytes of data at B into the -verification context B. This funtion can be called several times on the +verification context B. This function can be called several times on the same B to include additional data. EVP_VerifyFinal() verifies the data in B using the public key B -and against the B bytes at B. After calling EVP_VerifyFinal() -no additional calls to EVP_VerifyUpdate() can be made, but EVP_VerifyInit() -can be called to initialiase a new verification operation. +and against the B bytes at B. + +EVP_VerifyInit() initializes verification context B to use the default +implementation of digest B. =head1 RETURN VALUES -EVP_VerifyInit() and EVP_VerifyUpdate() do not return values. +EVP_VerifyInit_ex() and EVP_VerifyUpdate() return 1 for success and 0 for +failure. EVP_VerifyFinal() returns 1 for a correct signature, 0 for failure and -1 if some other error occurred. @@ -49,14 +54,22 @@ digest algorithm must be used with the correct public key type. A list of algorithms and associated public key algorithms appears in L. +The call to EVP_VerifyFinal() internally finalizes a copy of the digest context. +This means that calls to EVP_VerifyUpdate() and EVP_VerifyFinal() can be called +later to digest and verify additional data. + +Since only a copy of the digest context is ever finalized the context must +be cleaned up after use by calling EVP_MD_CTX_cleanup() or a memory leak +will occur. + =head1 BUGS -Several of the functions do not return values: maybe they should. Although the -internal digest operations will never fail some future hardware based operations -might. +Older versions of this documentation wrongly stated that calls to +EVP_VerifyUpdate() could not be made after calling EVP_VerifyFinal(). =head1 SEE ALSO +L, L, L, L, L, L, L, @@ -68,4 +81,6 @@ L, L EVP_VerifyInit(), EVP_VerifyUpdate() and EVP_VerifyFinal() are available in all versions of SSLeay and OpenSSL. +EVP_VerifyInit_ex() was added in OpenSSL 0.9.7 + =cut diff --git a/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod b/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod index b0b1058d19..c39ac35e78 100644 --- a/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod +++ b/src/lib/libcrypto/doc/OPENSSL_VERSION_NUMBER.pod @@ -2,7 +2,7 @@ =head1 NAME -OPENSSL_VERSION_NUMBER, SSLeay - get OpenSSL version number +OPENSSL_VERSION_NUMBER, SSLeay, SSLeay_version - get OpenSSL version number =head1 SYNOPSIS @@ -11,11 +11,27 @@ OPENSSL_VERSION_NUMBER, SSLeay - get OpenSSL version number #include long SSLeay(void); + const char *SSLeay_version(int t); =head1 DESCRIPTION OPENSSL_VERSION_NUMBER is a 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. + +for example + + 0x000906000 == 0.9.6 dev + 0x000906023 == 0.9.6b beta 3 + 0x00090605f == 0.9.6e release + +Versions prior to 0.9.3 have identifiers E 0x0930. +Versions between 0.9.3 and 0.9.5 had a version identifier with this +interpretation: + MMNNFFRBB major minor fix final beta/patch for example @@ -23,13 +39,51 @@ for example 0x000904100 == 0.9.4 release 0x000905000 == 0.9.5 dev -Versions prior to 0.9.3 have identifiers E 0x0930. +Version 0.9.5a had an interim interpretation that is like the current one, +except the patch level got the highest bit set, to keep continuity. The +number was therefore 0x0090581f. + + For backward compatibility, SSLEAY_VERSION_NUMBER is also defined. SSLeay() returns this number. The return value can be compared to the macro to make sure that the correct version of the library has been loaded, especially when using DLLs on Windows systems. +SSLeay_version() returns different strings depending on B: + +=over 4 + +=item SSLEAY_VERSION + +The text variant of the version number and the release date. For example, +"OpenSSL 0.9.5a 1 Apr 2000". + +=item SSLEAY_CFLAGS + +The compiler flags set for the compilation process in the form +"compiler: ..." if available or "compiler: information not available" +otherwise. + +=item SSLEAY_BUILT_ON + +The date of the build process in the form "built on: ..." if available +or "built on: date not available" otherwise. + +=item SSLEAY_PLATFORM + +The "Configure" target of the library build in the form "platform: ..." +if available or "platform: information not available" otherwise. + +=item SSLEAY_DIR + +The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" +if available or "OPENSSLDIR: N/A" otherwise. + +=back + +For an unknown B, the text "not available" is returned. + =head1 RETURN VALUE The version number. @@ -42,5 +96,6 @@ L SSLeay() and SSLEAY_VERSION_NUMBER are available in all versions of SSLeay and OpenSSL. OPENSSL_VERSION_NUMBER is available in all versions of OpenSSL. +B was added in OpenSSL 0.9.7. =cut diff --git a/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod b/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod index 1300fe190c..486c903430 100644 --- a/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod +++ b/src/lib/libcrypto/doc/OpenSSL_add_all_algorithms.pod @@ -2,7 +2,8 @@ =head1 NAME -OpenSSL_add_all_algorithms() - add algorithms to internal table +OpenSSL_add_all_algorithms, OpenSSL_add_all_ciphers, OpenSSL_add_all_digests - +add algorithms to internal table =head1 SYNOPSIS @@ -43,7 +44,7 @@ by EVP_sha1(). It just needs to add them if it (or any of the functions it calls needs to lookup algorithms. The cipher and digest lookup functions are used in many parts of the library. If -the table is not initialised several functions will misbehave and complain they +the table is not initialized several functions will misbehave and complain they cannot find algorithms. This includes the PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in the OpenSSL mailing lists. diff --git a/src/lib/libcrypto/doc/RAND_add.pod b/src/lib/libcrypto/doc/RAND_add.pod index 0a13ec2a92..67c66f3e0c 100644 --- a/src/lib/libcrypto/doc/RAND_add.pod +++ b/src/lib/libcrypto/doc/RAND_add.pod @@ -2,7 +2,8 @@ =head1 NAME -RAND_add, RAND_seed, RAND_screen - add entropy to the PRNG +RAND_add, RAND_seed, RAND_status, RAND_event, RAND_screen - add +entropy to the PRNG =head1 SYNOPSIS @@ -14,6 +15,7 @@ RAND_add, RAND_seed, RAND_screen - add entropy to the PRNG int RAND_status(void); + int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam); void RAND_screen(void); =head1 DESCRIPTION @@ -40,17 +42,24 @@ or L. RAND_seed() is equivalent to RAND_add() when B. +RAND_event() collects the entropy from Windows events such as mouse +movements and other user interaction. It should be called with the +B, B and B arguments of I messages sent to +the window procedure. It will estimate the entropy contained in the +event message (if any), and add it to the PRNG. The program can then +process the messages as usual. + The RAND_screen() function is available for the convenience of Windows programmers. It adds the current contents of the screen to the PRNG. -For applications that can catch Windows events, seeding the PRNG with -the parameters of B events is a significantly better -source of randomness. It should be noted that both methods cannot be -used on servers that run without user interaction. +For applications that can catch Windows events, seeding the PRNG by +calling RAND_event() is a significantly better source of +randomness. It should be noted that both methods cannot be used on +servers that run without user interaction. =head1 RETURN VALUES -RAND_status() returns 1 if the PRNG has been seeded with enough data, -0 otherwise. +RAND_status() and RAND_event() return 1 if the PRNG has been seeded +with enough data, 0 otherwise. The other functions do not return values. @@ -63,6 +72,6 @@ L, L RAND_seed() and RAND_screen() are available in all versions of SSLeay and OpenSSL. RAND_add() and RAND_status() have been added in OpenSSL -0.9.5. +0.9.5, RAND_event() in OpenSSL 0.9.5a. =cut diff --git a/src/lib/libcrypto/doc/RAND_load_file.pod b/src/lib/libcrypto/doc/RAND_load_file.pod index 8dd700ca3d..d8c134e621 100644 --- a/src/lib/libcrypto/doc/RAND_load_file.pod +++ b/src/lib/libcrypto/doc/RAND_load_file.pod @@ -8,7 +8,7 @@ RAND_load_file, RAND_write_file, RAND_file_name - PRNG seed file #include - const char *RAND_file_name(char *buf, int num); + const char *RAND_file_name(char *buf, size_t num); int RAND_load_file(const char *filename, long max_bytes); diff --git a/src/lib/libcrypto/doc/RAND_set_rand_method.pod b/src/lib/libcrypto/doc/RAND_set_rand_method.pod index 466e9b8767..464eba416d 100644 --- a/src/lib/libcrypto/doc/RAND_set_rand_method.pod +++ b/src/lib/libcrypto/doc/RAND_set_rand_method.pod @@ -34,10 +34,12 @@ RAND_get_rand_method() returns a pointer to the current method. void (*cleanup)(void); void (*add)(const void *buf, int num, int entropy); int (*pseudorand)(unsigned char *buf, int num); + int (*status)(void); } RAND_METHOD; The components point to the implementation of RAND_seed(), -RAND_bytes(), RAND_cleanup(), RAND_add() and RAND_pseudo_rand(). +RAND_bytes(), RAND_cleanup(), RAND_add(), RAND_pseudo_rand() +and RAND_status(). Each component may be NULL if the function is not implemented. =head1 RETURN VALUES diff --git a/src/lib/libcrypto/doc/RSA_generate_key.pod b/src/lib/libcrypto/doc/RSA_generate_key.pod index fdaddbcb13..8714f7179d 100644 --- a/src/lib/libcrypto/doc/RSA_generate_key.pod +++ b/src/lib/libcrypto/doc/RSA_generate_key.pod @@ -19,7 +19,7 @@ be seeded prior to calling RSA_generate_key(). The modulus size will be B bits, and the public exponent will be B. Key sizes with B E 1024 should be considered insecure. -The exponent is an odd number, typically 3 or 65535. +The exponent is an odd number, typically 3, 17 or 65537. A callback function may be used to provide feedback about the progress of the key generation. If B is not B, it diff --git a/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod b/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod index 920dc76325..46cc8f5359 100644 --- a/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod +++ b/src/lib/libcrypto/doc/RSA_get_ex_new_index.pod @@ -17,14 +17,12 @@ RSA_get_ex_new_index, RSA_set_ex_data, RSA_get_ex_data - add application specifi void *RSA_get_ex_data(RSA *r, int idx); - int new_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, - int idx, long argl, void *argp); - - void free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, - int idx, long argl, void *argp); - - int dup_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, - int idx, long argl, void *argp); + typedef int new_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); + typedef void free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); + typedef int dup_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, + int idx, long argl, void *argp); =head1 DESCRIPTION diff --git a/src/lib/libcrypto/doc/RSA_print.pod b/src/lib/libcrypto/doc/RSA_print.pod index dd968a5274..67876facc5 100644 --- a/src/lib/libcrypto/doc/RSA_print.pod +++ b/src/lib/libcrypto/doc/RSA_print.pod @@ -2,8 +2,9 @@ =head1 NAME -RSA_print, RSA_print_fp, DHparams_print, DHparams_print_fp - print -cryptographic parameters +RSA_print, RSA_print_fp, DHparams_print, DHparams_print_fp, DSA_print, +DSA_print_fp, DHparams_print, DHparams_print_fp - print cryptographic +parameters =head1 SYNOPSIS diff --git a/src/lib/libcrypto/doc/RSA_public_encrypt.pod b/src/lib/libcrypto/doc/RSA_public_encrypt.pod index 910c4752b8..e20dfcb551 100644 --- a/src/lib/libcrypto/doc/RSA_public_encrypt.pod +++ b/src/lib/libcrypto/doc/RSA_public_encrypt.pod @@ -47,7 +47,7 @@ Encrypting user data directly with RSA is insecure. =back B must be less than RSA_size(B) - 11 for the PKCS #1 v1.5 -based padding modes, and less than RSA_size(B) - 21 for +based padding modes, and less than RSA_size(B) - 41 for RSA_PKCS1_OAEP_PADDING. The random number generator must be seeded prior to calling RSA_public_encrypt(). @@ -74,10 +74,6 @@ SSL, PKCS #1 v2.0 L, L, L, L -=head1 NOTES - -The L method supports only the RSA_PKCS1_PADDING mode. - =head1 HISTORY The B argument was added in SSLeay 0.8. RSA_NO_PADDING is diff --git a/src/lib/libcrypto/doc/RSA_set_method.pod b/src/lib/libcrypto/doc/RSA_set_method.pod index deb1183a23..14917dd35f 100644 --- a/src/lib/libcrypto/doc/RSA_set_method.pod +++ b/src/lib/libcrypto/doc/RSA_set_method.pod @@ -3,30 +3,29 @@ =head1 NAME RSA_set_default_method, RSA_get_default_method, RSA_set_method, -RSA_get_method, RSA_PKCS1_SSLeay, RSA_PKCS1_RSAref, -RSA_PKCS1_null_method, RSA_flags, RSA_new_method - select RSA method +RSA_get_method, RSA_PKCS1_SSLeay, +RSA_null_method, RSA_flags, RSA_new_method - select RSA method =head1 SYNOPSIS #include + #include - void RSA_set_default_method(RSA_METHOD *meth); + void RSA_set_default_openssl_method(RSA_METHOD *meth); - RSA_METHOD *RSA_get_default_method(void); + RSA_METHOD *RSA_get_default_openssl_method(void); - RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth); + int RSA_set_method(RSA *rsa, ENGINE *engine); RSA_METHOD *RSA_get_method(RSA *rsa); RSA_METHOD *RSA_PKCS1_SSLeay(void); - RSA_METHOD *RSA_PKCS1_RSAref(void); - RSA_METHOD *RSA_null_method(void); int RSA_flags(RSA *rsa); - RSA *RSA_new_method(RSA_METHOD *method); + RSA *RSA_new_method(ENGINE *engine); =head1 DESCRIPTION @@ -34,35 +33,30 @@ An B specifies the functions that OpenSSL uses for RSA operations. By modifying the method, alternative implementations such as hardware accelerators may be used. -Initially, the default is to use the OpenSSL internal implementation, -unless OpenSSL was configured with the C or C<-DRSA_NULL> -options. RSA_PKCS1_SSLeay() returns a pointer to that method. - -RSA_PKCS1_RSAref() returns a pointer to a method that uses the RSAref -library. This is the default method in the C configuration; -the function is not available in other configurations. -RSA_null_method() returns a pointer to a method that does not support -the RSA transformation. It is the default if OpenSSL is compiled with -C<-DRSA_NULL>. These methods may be useful in the USA because of a -patent on the RSA cryptosystem. +Initially, the default is to use the OpenSSL internal implementation. +RSA_PKCS1_SSLeay() returns a pointer to that method. -RSA_set_default_method() makes B the default method for all B -structures created later. +RSA_set_default_openssl_method() makes B the default method for all B +structures created later. B This is true only whilst the default engine +for RSA operations remains as "openssl". ENGINEs provide an +encapsulation for implementations of one or more algorithms at a time, and all +the RSA functions mentioned here operate within the scope of the default +"openssl" engine. -RSA_get_default_method() returns a pointer to the current default -method. +RSA_get_default_openssl_method() returns a pointer to the current default +method for the "openssl" engine. -RSA_set_method() selects B for all operations using the key +RSA_set_method() selects B for all operations using the key B. -RSA_get_method() returns a pointer to the method currently selected -for B. +RSA_get_method() returns a pointer to the RSA_METHOD from the currently +selected ENGINE for B. RSA_flags() returns the B that are set for B's current method. -RSA_new_method() allocates and initializes an B structure so that -B will be used for the RSA operations. If B is B, -the default method is used. +RSA_new_method() allocates and initializes an RSA structure so that +B will be used for the RSA operations. If B is NULL, +the default engine for RSA operations is used. =head1 THE RSA_METHOD STRUCTURE @@ -87,10 +81,11 @@ the default method is used. int (*rsa_priv_dec)(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding); - /* compute r0 = r0 ^ I mod rsa->n. May be NULL */ + /* compute r0 = r0 ^ I mod rsa->n (May be NULL for some + implementations) */ int (*rsa_mod_exp)(BIGNUM *r0, BIGNUM *I, RSA *rsa); - /* compute r = a ^ p mod m. May be NULL */ + /* compute r = a ^ p mod m (May be NULL for some implementations) */ int (*bn_mod_exp)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); @@ -126,18 +121,21 @@ the default method is used. =head1 RETURN VALUES -RSA_PKCS1_SSLeay(), RSA_PKCS1_RSAref(), RSA_PKCS1_null_method(), -RSA_get_default_method() and RSA_get_method() return pointers to the -respective Bs. +RSA_PKCS1_SSLeay(), RSA_PKCS1_null_method(), RSA_get_default_openssl_method() +and RSA_get_method() return pointers to the respective RSA_METHODs. -RSA_set_default_method() returns no value. +RSA_set_default_openssl_method() returns no value. -RSA_set_method() returns a pointer to the B previously -associated with B. +RSA_set_method() selects B as the engine that will be responsible for +all operations using the structure B. If this function completes successfully, +then the B structure will have its own functional reference of B, so +the caller should remember to free their own reference to B when they are +finished with it. NB: An ENGINE's RSA_METHOD can be retrieved (or set) by +ENGINE_get_RSA() or ENGINE_set_RSA(). -RSA_new_method() returns B and sets an error code that can be -obtained by L if the allocation fails. Otherwise it -returns a pointer to the newly allocated structure. +RSA_new_method() returns NULL and sets an error code that can be +obtained by L if the allocation fails. Otherwise +it returns a pointer to the newly allocated structure. =head1 SEE ALSO @@ -150,4 +148,9 @@ RSA_get_default_method(), RSA_set_method() and RSA_get_method() as well as the rsa_sign and rsa_verify components of RSA_METHOD were added in OpenSSL 0.9.4. +RSA_set_default_openssl_method() and RSA_get_default_openssl_method() +replaced RSA_set_default_method() and RSA_get_default_method() respectively, +and RSA_set_method() and RSA_new_method() were altered to use Bs +rather than Bs during development of OpenSSL 0.9.6. + =cut diff --git a/src/lib/libcrypto/doc/bn.pod b/src/lib/libcrypto/doc/bn.pod index 1504a1c92d..210dfeac08 100644 --- a/src/lib/libcrypto/doc/bn.pod +++ b/src/lib/libcrypto/doc/bn.pod @@ -21,19 +21,27 @@ bn - multiprecision integer arithmetics BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); BIGNUM *BN_dup(const BIGNUM *a); + BIGNUM *BN_swap(BIGNUM *a, BIGNUM *b); + int BN_num_bytes(const BIGNUM *a); int BN_num_bits(const BIGNUM *a); int BN_num_bits_word(BN_ULONG w); - int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b); + int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); + int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx); int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, BN_CTX *ctx); - int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx); int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); + int BN_nnmod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); + int BN_mod_add(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); + int BN_mod_sub(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); + int BN_mod_sqr(BIGNUM *ret, BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); 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); @@ -54,12 +62,14 @@ bn - multiprecision integer arithmetics int BN_zero(BIGNUM *a); int BN_one(BIGNUM *a); - BIGNUM *BN_value_one(void); + const BIGNUM *BN_value_one(void); int BN_set_word(BIGNUM *a, unsigned long w); unsigned long BN_get_word(BIGNUM *a); 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_pseudo_rand_range(BIGNUM *rnd, BIGNUM *range); BIGNUM *BN_generate_prime(BIGNUM *ret, int bits,int safe, BIGNUM *add, BIGNUM *rem, void (*callback)(int, int, void *), void *cb_arg); @@ -137,7 +147,7 @@ of Bs to external formats is described in L. L, L, L, L, L, L, L, -L, L, +L, L, L, L, L, L, L, L, L, L, diff --git a/src/lib/libcrypto/doc/dh.pod b/src/lib/libcrypto/doc/dh.pod index 0a9b7c03a2..b4be4be405 100644 --- a/src/lib/libcrypto/doc/dh.pod +++ b/src/lib/libcrypto/doc/dh.pod @@ -7,6 +7,7 @@ dh - Diffie-Hellman key agreement =head1 SYNOPSIS #include + #include DH * DH_new(void); void DH_free(DH *dh); @@ -20,10 +21,10 @@ dh - Diffie-Hellman key agreement int DH_generate_key(DH *dh); int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh); - 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); + void DH_set_default_openssl_method(DH_METHOD *meth); + DH_METHOD *DH_get_default_openssl_method(void); + int DH_set_method(DH *dh, ENGINE *engine); + DH *DH_new_method(ENGINE *engine); DH_METHOD *DH_OpenSSL(void); int DH_get_ex_new_index(long argl, char *argp, int (*new_func)(), diff --git a/src/lib/libcrypto/doc/dsa.pod b/src/lib/libcrypto/doc/dsa.pod index 2c09244899..82d7fb77cd 100644 --- a/src/lib/libcrypto/doc/dsa.pod +++ b/src/lib/libcrypto/doc/dsa.pod @@ -7,6 +7,7 @@ dsa - Digital Signature Algorithm =head1 SYNOPSIS #include + #include DSA * DSA_new(void); void DSA_free(DSA *dsa); @@ -28,10 +29,10 @@ dsa - Digital Signature Algorithm int DSA_verify(int dummy, const unsigned char *dgst, int len, unsigned char *sigbuf, int siglen, DSA *dsa); - void DSA_set_default_method(DSA_METHOD *meth); - DSA_METHOD *DSA_get_default_method(void); - DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *meth); - DSA *DSA_new_method(DSA_METHOD *meth); + void DSA_set_default_openssl_method(DSA_METHOD *meth); + DSA_METHOD *DSA_get_default_openssl_method(void); + int DSA_set_method(DSA *dsa, ENGINE *engine); + DSA *DSA_new_method(ENGINE *engine); DSA_METHOD *DSA_OpenSSL(void); int DSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), diff --git a/src/lib/libcrypto/doc/evp.pod b/src/lib/libcrypto/doc/evp.pod index f089dd49a2..edf47dbde6 100644 --- a/src/lib/libcrypto/doc/evp.pod +++ b/src/lib/libcrypto/doc/evp.pod @@ -10,7 +10,7 @@ evp - high-level cryptographic functions =head1 DESCRIPTION -The EVP library provided a high-level interface to cryptographic +The EVP library provides a high-level interface to cryptographic functions. BI<...> and BI<...> provide public key encryption diff --git a/src/lib/libcrypto/doc/rsa.pod b/src/lib/libcrypto/doc/rsa.pod index 0486c044a6..09ad30cab1 100644 --- a/src/lib/libcrypto/doc/rsa.pod +++ b/src/lib/libcrypto/doc/rsa.pod @@ -7,6 +7,7 @@ rsa - RSA public key cryptosystem =head1 SYNOPSIS #include + #include RSA * RSA_new(void); void RSA_free(RSA *rsa); @@ -31,15 +32,14 @@ rsa - RSA public key cryptosystem int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); void RSA_blinding_off(RSA *rsa); - void RSA_set_default_method(RSA_METHOD *meth); - RSA_METHOD *RSA_get_default_method(void); - RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth); + void RSA_set_default_openssl_method(RSA_METHOD *meth); + RSA_METHOD *RSA_get_default_openssl_method(void); + int RSA_set_method(RSA *rsa, ENGINE *engine); RSA_METHOD *RSA_get_method(RSA *rsa); RSA_METHOD *RSA_PKCS1_SSLeay(void); - RSA_METHOD *RSA_PKCS1_RSAref(void); RSA_METHOD *RSA_null_method(void); int RSA_flags(RSA *rsa); - RSA *RSA_new_method(RSA_METHOD *method); + RSA *RSA_new_method(ENGINE *engine); int RSA_print(BIO *bp, RSA *x, int offset); int RSA_print_fp(FILE *fp, RSA *x, int offset); @@ -86,8 +86,9 @@ contain public as well as private RSA keys: In public keys, the private exponent and the related secret values are B. -B, B and B may be B in private keys, but the -RSA operations are much faster when these values are available. +B

, B, B, B and B may be B in private +keys, but the RSA operations are much faster when these values are +available. =head1 CONFORMING TO @@ -95,7 +96,7 @@ SSL, PKCS #1 v2.0 =head1 PATENTS -RSA is covered by a US patent which expires in September 2000. +RSA was covered by a US patent which expired in September 2000. =head1 SEE ALSO diff --git a/src/lib/libcrypto/dsa/dsa.h b/src/lib/libcrypto/dsa/dsa.h index 1ca87c1cbe..9b3baadf2c 100644 --- a/src/lib/libcrypto/dsa/dsa.h +++ b/src/lib/libcrypto/dsa/dsa.h @@ -65,18 +65,59 @@ #ifndef HEADER_DSA_H #define HEADER_DSA_H +#ifdef OPENSSL_NO_DSA +#error DSA is disabled. +#endif + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include +#ifndef OPENSSL_NO_DH +# include +#endif + +#define DSA_FLAG_CACHE_MONT_P 0x01 + #ifdef __cplusplus extern "C" { #endif -#include "bn.h" +typedef struct dsa_st DSA; -typedef struct dsa_st +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; + long version; int write_params; BIGNUM *p; BIGNUM *q; /* == 20 */ @@ -88,8 +129,15 @@ typedef struct dsa_st BIGNUM *kinv; /* Signing pre-calc */ BIGNUM *r; /* Signing pre-calc */ + int flags; + /* Normally used to cache montgomery values */ + char *method_mont_p; int references; - } DSA; + CRYPTO_EX_DATA ex_data; + const DSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; + }; #define DSAparams_dup(x) (DSA *)ASN1_dup((int (*)())i2d_DSAparams, \ (char *(*)())d2i_DSAparams,(char *)(x)) @@ -102,93 +150,101 @@ typedef struct dsa_st #define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio(i2d_DSAparams,(bp), \ (unsigned char *)(x)) -#ifndef NOPROTO + +DSA_SIG * DSA_SIG_new(void); +void DSA_SIG_free(DSA_SIG *a); +int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp); +DSA_SIG * d2i_DSA_SIG(DSA_SIG **v, const 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); +int DSA_set_method(DSA *dsa, const DSA_METHOD *); DSA * DSA_new(void); -int DSA_size(DSA *); +DSA * DSA_new_method(ENGINE *engine); +void DSA_free (DSA *r); +/* "up" the DSA object's reference count */ +int DSA_up_ref(DSA *r); +int DSA_size(const 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,unsigned char *dgst,int dlen, +int DSA_sign(int type,const unsigned char *dgst,int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa); -int DSA_verify(int type,unsigned char *dgst,int dgst_len, - unsigned char *sigbuf, int siglen, DSA *dsa); -void DSA_free (DSA *r); - -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 DSA_verify(int type,const unsigned char *dgst,int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa); +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); + +DSA * d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length); +DSA * d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length); +DSA * d2i_DSAparams(DSA **a, const 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)(),char *cb_arg); + (*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); +int i2d_DSAPublicKey(const DSA *a, unsigned char **pp); +int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); +int i2d_DSAparams(const 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); +#ifndef OPENSSL_NO_BIO +int DSAparams_print(BIO *bp, const DSA *x); +int DSA_print(BIO *bp, const 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); +#ifndef OPENSSL_NO_FP_API +int DSAparams_print_fp(FILE *fp, const DSA *x); +int DSA_print_fp(FILE *bp, const DSA *x, int off); #endif -int DSA_is_prime(BIGNUM *q,void (*callback)(),char *cb_arg); - -#else - -DSA * DSA_new(); -int DSA_size(); -int DSA_sign_setup(); -int DSA_sign(); -int DSA_verify(); -void DSA_free (); - -void ERR_load_DSA_strings(); - -DSA * d2i_DSAPublicKey(); -DSA * d2i_DSAPrivateKey(); -DSA * d2i_DSAparams(); -DSA * DSA_generate_parameters(); -int DSA_generate_key(); -int i2d_DSAPublicKey(); -int i2d_DSAPrivateKey(); -int i2d_DSAparams(); - -int DSA_is_prime(); - -int DSAparams_print(); -int DSA_print(); - -#ifndef NO_FP_API -int DSAparams_print_fp(); -int DSA_print_fp(); -#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 OPENSSL_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(const 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. + */ +void ERR_load_DSA_strings(void); + /* 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_IS_PRIME 102 -#define DSA_F_DSA_NEW 103 +#define DSA_F_DSA_DO_SIGN 112 +#define DSA_F_DSA_DO_VERIFY 113 +#define DSA_F_DSA_NEW_METHOD 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 +#define DSA_F_SIG_CB 114 /* Reason codes. */ #define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100 - +#define DSA_R_MISSING_PARAMETERS 101 + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/dsa/dsa_asn1.c b/src/lib/libcrypto/dsa/dsa_asn1.c index 7523b21654..23fce555aa 100644 --- a/src/lib/libcrypto/dsa/dsa_asn1.c +++ b/src/lib/libcrypto/dsa/dsa_asn1.c @@ -1,96 +1,140 @@ -/* crypto/dsa/dsa_asn1.c */ +/* dsa_asn1.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 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 + * 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 +#include -DSA_SIG *DSA_SIG_new(void) +/* Override the default new methods */ +static int sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) { - 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); + if(operation == ASN1_OP_NEW_PRE) { + DSA_SIG *sig; + sig = OPENSSL_malloc(sizeof(DSA_SIG)); + sig->r = NULL; + sig->s = NULL; + *pval = (ASN1_VALUE *)sig; + if(sig) return 2; + DSAerr(DSA_F_SIG_CB, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; } -void DSA_SIG_free(DSA_SIG *r) +ASN1_SEQUENCE_cb(DSA_SIG, sig_cb) = { + ASN1_SIMPLE(DSA_SIG, r, CBIGNUM), + ASN1_SIMPLE(DSA_SIG, s, CBIGNUM) +} ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG) + +IMPLEMENT_ASN1_FUNCTIONS_const(DSA_SIG) + +/* Override the default free and new methods */ +static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) { - if (r == NULL) return; - if (r->r) BN_clear_free(r->r); - if (r->s) BN_clear_free(r->s); - Free(r); + if(operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)DSA_new(); + if(*pval) return 2; + return 0; + } else if(operation == ASN1_OP_FREE_PRE) { + DSA_free((DSA *)*pval); + *pval = NULL; + return 2; + } + return 1; } -int i2d_DSA_SIG(DSA_SIG *v, unsigned char **pp) -{ - int t=0,len; - ASN1_INTEGER rbs,sbs; - unsigned char *p; +ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = { + ASN1_SIMPLE(DSA, version, LONG), + ASN1_SIMPLE(DSA, p, BIGNUM), + ASN1_SIMPLE(DSA, q, BIGNUM), + ASN1_SIMPLE(DSA, g, BIGNUM), + ASN1_SIMPLE(DSA, pub_key, BIGNUM), + ASN1_SIMPLE(DSA, priv_key, BIGNUM) +} ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey) - 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); +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey) - len=i2d_ASN1_INTEGER(&rbs,NULL); - len+=i2d_ASN1_INTEGER(&sbs,NULL); +ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = { + ASN1_SIMPLE(DSA, p, BIGNUM), + ASN1_SIMPLE(DSA, q, BIGNUM), + ASN1_SIMPLE(DSA, g, BIGNUM), +} ASN1_SEQUENCE_END_cb(DSA, DSAparams) - 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); -} +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams) -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); +/* DSA public key is a bit trickier... its effectively a CHOICE type + * decided by a field called write_params which can either write out + * just the public key as an INTEGER or the parameters and public key + * in a SEQUENCE + */ - 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; - ASN1_BIT_STRING_free(bs); - M_ASN1_D2I_Finish_2(a); +ASN1_SEQUENCE(dsa_pub_internal) = { + ASN1_SIMPLE(DSA, pub_key, BIGNUM), + ASN1_SIMPLE(DSA, p, BIGNUM), + ASN1_SIMPLE(DSA, q, BIGNUM), + ASN1_SIMPLE(DSA, g, BIGNUM) +} ASN1_SEQUENCE_END_name(DSA, dsa_pub_internal) -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) ASN1_BIT_STRING_free(bs); - return(NULL); -} +ASN1_CHOICE_cb(DSAPublicKey, dsa_cb) = { + ASN1_SIMPLE(DSA, pub_key, BIGNUM), + ASN1_EX_COMBINE(0, 0, dsa_pub_internal) +} ASN1_CHOICE_END_cb(DSA, DSAPublicKey, write_params) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey) diff --git a/src/lib/libcrypto/dsa/dsa_err.c b/src/lib/libcrypto/dsa/dsa_err.c index 318e9f31aa..79aa4ff526 100644 --- a/src/lib/libcrypto/dsa/dsa_err.c +++ b/src/lib/libcrypto/dsa/dsa_err.c @@ -1,96 +1,105 @@ -/* lib/dsa/dsa_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/dsa/dsa_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "dsa.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_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_IS_PRIME,0), "DSA_is_prime"}, -{ERR_PACK(0,DSA_F_DSA_NEW,0), "DSA_new"}, +{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_METHOD,0), "DSA_new_method"}, {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"}, -{0,NULL}, +{ERR_PACK(0,DSA_F_I2D_DSA_SIG,0), "i2d_DSA_SIG"}, +{ERR_PACK(0,DSA_F_SIG_CB,0), "SIG_CB"}, +{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}, +{DSA_R_MISSING_PARAMETERS ,"missing parameters"}, +{0,NULL} }; #endif -void ERR_load_DSA_strings() +void ERR_load_DSA_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_DSA,DSA_str_functs); ERR_load_strings(ERR_LIB_DSA,DSA_str_reasons); #endif diff --git a/src/lib/libcrypto/dsa/dsa_gen.c b/src/lib/libcrypto/dsa/dsa_gen.c index d7d30bf90a..dc9c249310 100644 --- a/src/lib/libcrypto/dsa/dsa_gen.c +++ b/src/lib/libcrypto/dsa/dsa_gen.c @@ -59,28 +59,32 @@ #undef GENUINE_DSA #ifdef GENUINE_DSA -#define HASH SHA +/* 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 EVP_sha() #else -#define HASH SHA1 +/* 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 EVP_sha1() #endif +#ifndef OPENSSL_NO_SHA + #include #include #include "cryptlib.h" -#include "sha.h" -#include "bn.h" -#include "dsa.h" -#include "rand.h" - -DSA *DSA_generate_parameters(bits,seed_in,seed_len,counter_ret,h_ret,callback, - cb_arg) -int bits; -unsigned char *seed_in; -int seed_len; -int *counter_ret; -unsigned long *h_ret; -void (*callback)(); -char *cb_arg; +#include +#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]; @@ -88,49 +92,66 @@ char *cb_arg; 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; - BN_CTX *ctx=NULL,*ctx2=NULL; + 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); - ctx=BN_CTX_new(); - if (ctx == NULL) goto err; - ctx2=BN_CTX_new(); - if (ctx2 == NULL) goto err; - ret=DSA_new(); - if (ret == NULL) goto err; - r0=ctx2->bn[0]; - g=ctx2->bn[1]; - W=ctx2->bn[2]; - q=ctx2->bn[3]; - X=ctx2->bn[4]; - c=ctx2->bn[5]; - p=ctx2->bn[6]; - test=ctx2->bn[7]; + 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 (;;) + for (;;) /* find q */ { + int seed_is_random; + /* step 1 */ if (callback != NULL) callback(0,m++,cb_arg); if (!seed_len) - RAND_bytes(seed,SHA_DIGEST_LENGTH); + { + RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH); + seed_is_random = 1; + } else - seed_len=0; - + { + 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]++; @@ -138,18 +159,23 @@ char *cb_arg; } /* step 2 */ - HASH(seed,SHA_DIGEST_LENGTH,md); - HASH(buf,SHA_DIGEST_LENGTH,buf2); + EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL); + EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL); for (i=0; i 0) break; + r = BN_is_prime_fasttest(q, DSS_prime_checks, callback, ctx3, cb_arg, seed_is_random); + if (r > 0) + break; + if (r != 0) + goto err; + /* do a callback call */ /* step 5 */ } @@ -159,26 +185,33 @@ char *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); + EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL); /* step 8 */ - if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0)) abort(); + if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0)) + goto err; BN_lshift(r0,r0,160*k); BN_add(W,W,r0); } @@ -198,32 +231,36 @@ char *cb_arg; if (BN_cmp(p,test) >= 0) { /* step 11 */ - if (DSA_is_prime(p,callback,cb_arg) > 0) - goto end; + 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; - - if (callback != NULL) callback(0,counter,cb_arg); } } end: if (callback != NULL) callback(2,1,cb_arg); - /* We now need to gernerate g */ + /* 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_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(g,test,r0,p,ctx); + BN_mod_exp_mont(g,test,r0,p,ctx,mont); if (!BN_is_one(g)) break; BN_add(test,test,BN_value_one()); h++; @@ -246,83 +283,14 @@ err: if (counter_ret != NULL) *counter_ret=counter; if (h_ret != NULL) *h_ret=h; } - BN_CTX_free(ctx); - BN_CTX_free(ctx2); - return(ok?ret:NULL); - } - -int DSA_is_prime(w, callback,cb_arg) -BIGNUM *w; -void (*callback)(); -char *cb_arg; - { - int ok= -1,j,i,n; - BN_CTX *ctx=NULL,*ctx2=NULL; - BIGNUM *w_1,*b,*m,*z; - int a; - - if (!BN_is_bit_set(w,0)) return(0); - - ctx=BN_CTX_new(); - if (ctx == NULL) goto err; - ctx2=BN_CTX_new(); - if (ctx2 == NULL) goto err; - - m= ctx2->bn[2]; - b= ctx2->bn[3]; - z= ctx2->bn[4]; - w_1=ctx2->bn[5]; - - /* step 1 */ - n=50; - - /* step 2 */ - if (!BN_sub(w_1,w,BN_value_one())) goto err; - for (a=1; !BN_is_bit_set(w_1,a); a++) - ; - if (!BN_rshift(m,w_1,a)) goto err; - - for (i=1; i < n; i++) + if (ctx != NULL) BN_CTX_free(ctx); + if (ctx2 != NULL) { - /* step 3 */ - BN_rand(b,BN_num_bits(w)-2/*-1*/,0,0); - BN_set_word(b,0x10001L); - - /* step 4 */ - j=0; - if (!BN_mod_exp(z,b,m,w,ctx)) goto err; - - /* step 5 */ - for (;;) - { - if (((j == 0) && BN_is_one(z)) || (BN_cmp(z,w_1) == 0)) - break; - - /* step 6 */ - if ((j > 0) && BN_is_one(z)) - { - ok=0; - goto err; - } - - j++; - if (j >= a) - { - ok=0; - goto err; - } - - if (!BN_mod_mul(z,z,z,w,ctx)) goto err; - if (callback != NULL) callback(1,j,cb_arg); - } + BN_CTX_end(ctx2); + BN_CTX_free(ctx2); } - - ok=1; -err: - if (ok == -1) DSAerr(DSA_F_DSA_IS_PRIME,ERR_R_BN_LIB); - BN_CTX_free(ctx); - BN_CTX_free(ctx2); - - return(ok); + if (ctx3 != NULL) BN_CTX_free(ctx3); + if (mont != NULL) BN_MONT_CTX_free(mont); + return(ok?ret:NULL); } - +#endif diff --git a/src/lib/libcrypto/dsa/dsa_key.c b/src/lib/libcrypto/dsa/dsa_key.c index d51ed9395f..ef87c3e637 100644 --- a/src/lib/libcrypto/dsa/dsa_key.c +++ b/src/lib/libcrypto/dsa/dsa_key.c @@ -56,19 +56,17 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_SHA #include #include #include "cryptlib.h" -#include "sha.h" -#include "bn.h" -#include "dsa.h" -#include "rand.h" +#include +#include +#include -int DSA_generate_key(dsa) -DSA *dsa; +int DSA_generate_key(DSA *dsa) { int ok=0; - unsigned int i; BN_CTX *ctx=NULL; BIGNUM *pub_key=NULL,*priv_key=NULL; @@ -81,14 +79,9 @@ DSA *dsa; else priv_key=dsa->priv_key; - i=BN_num_bits(dsa->q); - for (;;) - { - BN_rand(priv_key,i,1,0); - if (BN_cmp(priv_key,dsa->q) >= 0) - BN_sub(priv_key,priv_key,dsa->q); - if (!BN_is_zero(priv_key)) break; - } + do + if (!BN_rand_range(priv_key,dsa->q)) goto err; + while (BN_is_zero(priv_key)); if (dsa->pub_key == NULL) { @@ -109,4 +102,4 @@ err: if (ctx != NULL) BN_CTX_free(ctx); return(ok); } - +#endif diff --git a/src/lib/libcrypto/dsa/dsa_lib.c b/src/lib/libcrypto/dsa/dsa_lib.c index b647257f9f..da2cdfa3d6 100644 --- a/src/lib/libcrypto/dsa/dsa_lib.c +++ b/src/lib/libcrypto/dsa/dsa_lib.c @@ -56,26 +56,89 @@ * [including the GNU Public Licence.] */ -/* Origional version from Steven Schoch */ +/* Original version from Steven Schoch */ #include #include "cryptlib.h" -#include "bn.h" -#include "dsa.h" -#include "asn1.h" +#include +#include +#include +#include -char *DSA_version="\0DSA part of SSLeay 0.9.0b 29-Jun-1998"; +const char *DSA_version="DSA" OPENSSL_VERSION_PTEXT; -DSA *DSA_new() +static const DSA_METHOD *default_DSA_method = 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); + } + +int DSA_set_method(DSA *dsa, const DSA_METHOD *meth) + { + /* NB: The caller is specifically setting a method, so it's not up to us + * to deal with which ENGINE it comes from. */ + const DSA_METHOD *mtmp; + mtmp = dsa->meth; + if (mtmp->finish) mtmp->finish(dsa); + if (dsa->engine) + { + ENGINE_finish(dsa->engine); + dsa->engine = NULL; + } + dsa->meth = meth; + if (meth->init) meth->init(dsa); + return 1; + } + +DSA *DSA_new_method(ENGINE *engine) { DSA *ret; - ret=(DSA *)Malloc(sizeof(DSA)); + ret=(DSA *)OPENSSL_malloc(sizeof(DSA)); if (ret == NULL) { - DSAerr(DSA_F_DSA_NEW,ERR_R_MALLOC_FAILURE); + DSAerr(DSA_F_DSA_NEW_METHOD,ERR_R_MALLOC_FAILURE); return(NULL); } + ret->meth = DSA_get_default_method(); + if (engine) + { + if (!ENGINE_init(engine)) + { + DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB); + OPENSSL_free(ret); + return NULL; + } + ret->engine = engine; + } + else + ret->engine = ENGINE_get_default_DSA(); + if(ret->engine) + { + ret->meth = ENGINE_get_DSA(ret->engine); + if(!ret->meth) + { + DSAerr(DSA_F_DSA_NEW_METHOD, + ERR_R_ENGINE_LIB); + ENGINE_finish(ret->engine); + OPENSSL_free(ret); + return NULL; + } + } + ret->pad=0; ret->version=0; ret->write_params=1; @@ -88,13 +151,24 @@ DSA *DSA_new() ret->kinv=NULL; ret->r=NULL; + ret->method_mont_p=NULL; ret->references=1; + ret->flags=ret->meth->flags; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data); + if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + { + if (ret->engine) + ENGINE_finish(ret->engine); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data); + OPENSSL_free(ret); + ret=NULL; + } + return(ret); } -void DSA_free(r) -DSA *r; +void DSA_free(DSA *r) { int i; @@ -113,6 +187,13 @@ DSA *r; } #endif + if(r->meth->finish) + r->meth->finish(r); + if(r->engine) + ENGINE_finish(r->engine); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data); + 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); @@ -120,11 +201,26 @@ DSA *r; 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); + OPENSSL_free(r); + } + +int DSA_up_ref(DSA *r) + { + int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DSA); +#ifdef REF_PRINT + REF_PRINT("DSA",r); +#endif +#ifdef REF_CHECK + if (i < 2) + { + fprintf(stderr, "DSA_up_ref, bad reference count\n"); + abort(); + } +#endif + return ((i > 1) ? 1 : 0); } -int DSA_size(r) -DSA *r; +int DSA_size(const DSA *r) { int ret,i; ASN1_INTEGER bs; @@ -143,3 +239,57 @@ DSA *r; return(ret); } +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) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, 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 OPENSSL_NO_DH +DH *DSA_dup_DH(const 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/src/lib/libcrypto/dsa/dsa_ossl.c b/src/lib/libcrypto/dsa/dsa_ossl.c index b51cf6ad8d..37dd5fc994 100644 --- a/src/lib/libcrypto/dsa/dsa_ossl.c +++ b/src/lib/libcrypto/dsa/dsa_ossl.c @@ -64,6 +64,7 @@ #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); @@ -91,7 +92,7 @@ dsa_finish, NULL }; -DSA_METHOD *DSA_OpenSSL(void) +const DSA_METHOD *DSA_OpenSSL(void) { return &openssl_dsa_meth; } @@ -105,6 +106,11 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) int i,reason=ERR_R_BN_LIB; DSA_SIG *ret=NULL; + if (!dsa->p || !dsa->q || !dsa->g) + { + reason=DSA_R_MISSING_PARAMETERS; + goto err; + } BN_init(&m); BN_init(&xr); s=BN_new(); @@ -167,6 +173,11 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) BIGNUM k,*kinv=NULL,*r=NULL; int ret=0; + if (!dsa->p || !dsa->q || !dsa->g) + { + DSAerr(DSA_F_DSA_SIGN_SETUP,DSA_R_MISSING_PARAMETERS); + return 0; + } if (ctx_in == NULL) { if ((ctx=BN_CTX_new()) == NULL) goto err; @@ -179,13 +190,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) 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; - } + do + if (!BN_rand_range(&k, dsa->q)) goto err; + while (BN_is_zero(&k)); if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P)) { @@ -228,12 +235,28 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, BIGNUM u1,u2,t1; BN_MONT_CTX *mont=NULL; int ret = -1; + if (!dsa->p || !dsa->q || !dsa->g) + { + DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS); + return -1; + } if ((ctx=BN_CTX_new()) == NULL) goto err; BN_init(&u1); BN_init(&u2); BN_init(&t1); + if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) + { + ret = 0; + goto err; + } + if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) + { + ret = 0; + goto err; + } + /* Calculate W = inv(S) mod Q * save W in u2 */ if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err; diff --git a/src/lib/libcrypto/dsa/dsa_sign.c b/src/lib/libcrypto/dsa/dsa_sign.c index 6ca1c318f2..e9469ca62f 100644 --- a/src/lib/libcrypto/dsa/dsa_sign.c +++ b/src/lib/libcrypto/dsa/dsa_sign.c @@ -56,160 +56,38 @@ * [including the GNU Public Licence.] */ -/* Origional version from Steven Schoch */ +/* Original version from Steven Schoch */ #include #include "cryptlib.h" -#include "bn.h" -#include "dsa.h" -#include "rand.h" -#include "asn1.h" +#include +#include +#include +#include +#include -/* data has already been hashed (probably with SHA or SHA-1). */ -/* DSAerr(DSA_F_DSA_SIGN,DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); */ - -int DSA_sign(type,dgst,dlen,sig,siglen,dsa) -int type; -unsigned char *dgst; -int dlen; -unsigned char *sig; /* out */ -unsigned int *siglen; /* out */ -DSA *dsa; +DSA_SIG * DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { - BIGNUM *kinv=NULL,*r=NULL; - BIGNUM *m=NULL; - BIGNUM *xr=NULL,*s=NULL; - BN_CTX *ctx=NULL; - unsigned char *p; - int i,len=0,ret=0,reason=ERR_R_BN_LIB; - ASN1_INTEGER rbs,sbs; - MS_STATIC unsigned char rbuf[50]; /* assuming r is 20 bytes +extra */ - MS_STATIC unsigned char sbuf[50]; /* assuming s is 20 bytes +extra */ - - 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; - } - - m=BN_new(); - xr=BN_new(); - s=BN_new(); - if (m == NULL || xr == NULL || s == NULL) goto err; - - if (BN_bin2bn(dgst,dlen,m) == NULL) goto err; - - /* Compute s = inv(k) (m + xr) mod q */ - if (!BN_mul(xr, dsa->priv_key, r)) goto err; /* s = xr */ - if (!BN_add(s, xr, m)) goto err; /* s = m + xr */ - if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err; - - /* - * Now create a ASN.1 sequence of the integers R and S. - */ - rbs.data=rbuf; - sbs.data=sbuf; - rbs.type = V_ASN1_INTEGER; - sbs.type = V_ASN1_INTEGER; - rbs.length=BN_bn2bin(r,rbs.data); - sbs.length=BN_bn2bin(s,sbs.data); - - len =i2d_ASN1_INTEGER(&rbs,NULL); - len+=i2d_ASN1_INTEGER(&sbs,NULL); - - p=sig; - ASN1_put_object(&p,1,len,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); - i2d_ASN1_INTEGER(&rbs,&p); - i2d_ASN1_INTEGER(&sbs,&p); - *siglen=(p-sig); - ret=1; -err: - if (!ret) DSAerr(DSA_F_DSA_SIGN,reason); - -#if 1 /* do the right thing :-) */ - if (kinv != NULL) BN_clear_free(kinv); - if (r != NULL) BN_clear_free(r); -#endif - if (ctx != NULL) BN_CTX_free(ctx); - if (m != NULL) BN_clear_free(m); - if (xr != NULL) BN_clear_free(xr); - if (s != NULL) BN_clear_free(s); - return(ret); + return dsa->meth->dsa_do_sign(dgst, dlen, dsa); } -int DSA_sign_setup(dsa,ctx_in,kinvp,rp) -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) { - BN_CTX *ctx; - BIGNUM *k=NULL,*kinv=NULL,*r=NULL; - int ret=0; - - if (ctx_in == NULL) - { - if ((ctx=BN_CTX_new()) == NULL) goto err; - } - else - ctx=ctx_in; - - r=BN_new(); - k=BN_new(); - if ((r == NULL) || (k == NULL)) - goto err; - kinv=NULL; - - if (r == NULL) goto err; - - /* Get random k */ - for (;;) + DSA_SIG *s; + s=DSA_do_sign(dgst,dlen,dsa); + if (s == NULL) { - 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; + *siglen=0; + return(0); } + *siglen=i2d_DSA_SIG(s,&sig); + DSA_SIG_free(s); + return(1); + } - /* Compute r = (g^k mod p) mod q */ - if (!BN_mod_exp(r,dsa->g,k,dsa->p,ctx)) 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(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 (k != NULL) BN_clear_free(k); - if (kinv != NULL) BN_clear_free(kinv); - return(ret); +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/src/lib/libcrypto/dsa/dsa_vrf.c b/src/lib/libcrypto/dsa/dsa_vrf.c index 0f860984ed..066c6b5b28 100644 --- a/src/lib/libcrypto/dsa/dsa_vrf.c +++ b/src/lib/libcrypto/dsa/dsa_vrf.c @@ -56,97 +56,40 @@ * [including the GNU Public Licence.] */ -/* Origional version from Steven Schoch */ +/* Original version from Steven Schoch */ #include #include "cryptlib.h" -#include "bn.h" -#include "dsa.h" -#include "rand.h" -#include "asn1.h" -#include "asn1_mac.h" +#include +#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 + * 1: correct signature + * 0: incorrect signature + * -1: error */ -int DSA_verify(type,dgst,dgst_len,sigbuf,siglen, dsa) -int type; -unsigned char *dgst; -int dgst_len; -unsigned char *sigbuf; -int siglen; -DSA *dsa; +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa) { - /* The next 3 are used by the M_ASN1 macros */ - long length=siglen; - ASN1_CTX c; - unsigned char **pp= &sigbuf; - BN_CTX *ctx; - BIGNUM *r=NULL; - BIGNUM *t1=NULL,*t2=NULL; - BIGNUM *u1=NULL,*u2=NULL; - ASN1_INTEGER *bs=NULL; - int ret = -1; - - ctx=BN_CTX_new(); - if (ctx == NULL) goto err; - - t1=BN_new(); - t2=BN_new(); - if (t1 == NULL || t2 == NULL) goto err; - - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER); - if ((r=BN_bin2bn(bs->data,bs->length,NULL)) == NULL) goto err_bn; - M_ASN1_D2I_get(bs,d2i_ASN1_INTEGER); - if ((u1=BN_bin2bn(bs->data,bs->length,NULL)) == NULL) goto err_bn; - if (!asn1_Finish(&c)) goto err; - - /* Calculate W = inv(S) mod Q - * save W in u2 */ - if ((u2=BN_mod_inverse(u1,dsa->q,ctx)) == NULL) goto err_bn; - - /* save M in u1 */ - if (BN_bin2bn(dgst,dgst_len,u1) == NULL) goto err_bn; - - /* u1 = M * w mod q */ - if (!BN_mod_mul(u1,u1,u2,dsa->q,ctx)) goto err_bn; - - /* u2 = r * w mod q */ - if (!BN_mod_mul(u2,r,u2,dsa->q,ctx)) goto err_bn; + DSA_SIG *s; + int ret=-1; - /* v = ( g^u1 * y^u2 mod p ) mod q */ - /* let t1 = g ^ u1 mod p */ - if (!BN_mod_exp(t1,dsa->g,u1,dsa->p,ctx)) goto err_bn; - /* let t2 = y ^ u2 mod p */ - if (!BN_mod_exp(t2,dsa->pub_key,u2,dsa->p,ctx)) goto err_bn; - /* let u1 = t1 * t2 mod p */ - if (!BN_mod_mul(u1,t1,t2,dsa->p,ctx)) goto err_bn; - /* let u1 = u1 mod q */ - if (!BN_mod(u1,u1,dsa->q,ctx)) goto err_bn; - /* V is now in u1. If the signature is correct, it will be - * equal to R. */ - ret=(BN_ucmp(u1, r) == 0); - if (0) - { -err: /* ASN1 error */ - DSAerr(DSA_F_DSA_VERIFY,c.error); - } - if (0) - { -err_bn: /* BN error */ - DSAerr(DSA_F_DSA_VERIFY,ERR_R_BN_LIB); - } - if (ctx != NULL) BN_CTX_free(ctx); - if (r != NULL) BN_free(r); - if (t1 != NULL) BN_free(t1); - if (t2 != NULL) BN_free(t2); - if (u1 != NULL) BN_free(u1); - if (u2 != NULL) BN_free(u2); - if (bs != NULL) ASN1_BIT_STRING_free(bs); + 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); } diff --git a/src/lib/libcrypto/dso/dso.h b/src/lib/libcrypto/dso/dso.h index bed7c464a6..aa721f7feb 100644 --- a/src/lib/libcrypto/dso/dso.h +++ b/src/lib/libcrypto/dso/dso.h @@ -70,31 +70,51 @@ extern "C" { #define DSO_CTRL_SET_FLAGS 2 #define DSO_CTRL_OR_FLAGS 3 -/* These flags control the translation of file-names from canonical to - * native. Eg. in the CryptoSwift support, the "dl" and "dlfcn" - * methods will translate "swift" -> "libswift.so" whereas the "win32" - * method will translate "swift" -> "swift.dll". NB: Until I can figure - * out how to be more "conventional" with this, the methods will only - * honour this flag if it looks like it was passed a file without any - * path and if the filename is small enough. - */ -#define DSO_FLAG_NAME_TRANSLATION 0x01 +/* By default, DSO_load() will translate the provided filename into a form + * typical for the platform (more specifically the DSO_METHOD) using the + * dso_name_converter function of the method. Eg. win32 will transform "blah" + * into "blah.dll", and dlfcn will transform it into "libblah.so". The + * behaviour can be overriden by setting the name_converter callback in the DSO + * object (using DSO_set_name_converter()). This callback could even utilise + * the DSO_METHOD's converter too if it only wants to override behaviour for + * one or two possible DSO methods. However, the following flag can be set in a + * DSO to prevent *any* native name-translation at all - eg. if the caller has + * prompted the user for a path to a driver library so the filename should be + * interpreted as-is. */ +#define DSO_FLAG_NO_NAME_TRANSLATION 0x01 +/* An extra flag to give if only the extension should be added as + * translation. This is obviously only of importance on Unix and + * other operating systems where the translation also may prefix + * the name with something, like 'lib', and ignored everywhere else. + * This flag is also ignored if DSO_FLAG_NO_NAME_TRANSLATION is used + * at the same time. */ +#define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02 /* The following flag controls the translation of symbol names to upper * case. This is currently only being implemented for OpenVMS. */ -#define DSO_FLAG_UPCASE_SYMBOL 0x02 +#define DSO_FLAG_UPCASE_SYMBOL 0x10 typedef void (*DSO_FUNC_TYPE)(void); typedef struct dso_st DSO; +/* The function prototype used for method functions (or caller-provided + * callbacks) that transform filenames. They are passed a DSO structure pointer + * (or NULL if they are to be used independantly of a DSO object) and a + * filename to transform. They should either return NULL (if there is an error + * condition) or a newly allocated string containing the transformed form that + * the caller will need to free with OPENSSL_free() when done. */ +typedef char* (*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *); + typedef struct dso_meth_st { const char *name; - /* Loads a shared library */ - int (*dso_load)(DSO *dso, const char *filename); + /* Loads a shared library, NB: new DSO_METHODs must ensure that a + * successful load populates the loaded_filename field, and likewise a + * successful unload OPENSSL_frees and NULLs it out. */ + int (*dso_load)(DSO *dso); /* Unloads a shared library */ int (*dso_unload)(DSO *dso); /* Binds a variable */ @@ -117,6 +137,9 @@ typedef struct dso_meth_st /* The generic (yuck) "ctrl()" function. NB: Negative return * values (rather than zero) indicate errors. */ long (*dso_ctrl)(DSO *dso, int cmd, long larg, void *parg); + /* The default DSO_METHOD-specific function for converting filenames to + * a canonical native form. */ + DSO_NAME_CONVERTER_FUNC dso_name_converter; /* [De]Initialisation handlers. */ int (*init)(DSO *dso); @@ -140,6 +163,23 @@ struct dso_st /* For use by applications etc ... use this for your bits'n'pieces, * don't touch meth_data! */ CRYPTO_EX_DATA ex_data; + /* If this callback function pointer is set to non-NULL, then it will + * be used on DSO_load() in place of meth->dso_name_converter. NB: This + * should normally set using DSO_set_name_converter(). */ + DSO_NAME_CONVERTER_FUNC name_converter; + /* This is populated with (a copy of) the platform-independant + * filename used for this DSO. */ + char *filename; + /* This is populated with (a copy of) the translated filename by which + * the DSO was actually loaded. It is NULL iff the DSO is not currently + * loaded. NB: This is here because the filename translation process + * may involve a callback being invoked more than once not only to + * convert to a platform-specific form, but also to try different + * filenames in the process of trying to perform a load. As such, this + * variable can be used to indicate (a) whether this DSO structure + * corresponds to a loaded library or not, and (b) the filename with + * which it was actually loaded. */ + char *loaded_filename; }; @@ -147,10 +187,38 @@ DSO * DSO_new(void); DSO * DSO_new_method(DSO_METHOD *method); int DSO_free(DSO *dso); int DSO_flags(DSO *dso); -int DSO_up(DSO *dso); +int DSO_up_ref(DSO *dso); long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg); -void DSO_set_default_method(DSO_METHOD *meth); +/* This function sets the DSO's name_converter callback. If it is non-NULL, + * then it will be used instead of the associated DSO_METHOD's function. If + * oldcb is non-NULL then it is set to the function pointer value being + * replaced. Return value is non-zero for success. */ +int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb, + DSO_NAME_CONVERTER_FUNC *oldcb); +/* These functions can be used to get/set the platform-independant filename + * used for a DSO. NB: set will fail if the DSO is already loaded. */ +const char *DSO_get_filename(DSO *dso); +int DSO_set_filename(DSO *dso, const char *filename); +/* This function will invoke the DSO's name_converter callback to translate a + * filename, or if the callback isn't set it will instead use the DSO_METHOD's + * converter. If "filename" is NULL, the "filename" in the DSO itself will be + * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is + * simply duplicated. NB: This function is usually called from within a + * DSO_METHOD during the processing of a DSO_load() call, and is exposed so that + * caller-created DSO_METHODs can do the same thing. A non-NULL return value + * will need to be OPENSSL_free()'d. */ +char *DSO_convert_filename(DSO *dso, const char *filename); +/* If the DSO is currently loaded, this returns the filename that it was loaded + * under, otherwise it returns NULL. So it is also useful as a test as to + * whether the DSO is currently loaded. NB: This will not necessarily return + * the same value as DSO_convert_filename(dso, dso->filename), because the + * DSO_METHOD's load function may have tried a variety of filenames (with + * and/or without the aid of the converters) before settling on the one it + * actually loaded. */ +const char *DSO_get_loaded_filename(DSO *dso); + +void DSO_set_default_method(DSO_METHOD *meth); DSO_METHOD *DSO_get_default_method(void); DSO_METHOD *DSO_get_method(DSO *dso); DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth); @@ -159,8 +227,7 @@ DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth); * for the first and third parameters. Use DSO_up and DSO_free for * subsequent reference count handling. Any flags passed in will be set * in the constructed DSO after its init() function but before the - * load operation. This will be done with; - * DSO_ctrl(dso, DSO_CTRL_SET_FLAGS, flags, NULL); */ + * load operation. If 'dso' is non-NULL, 'flags' is ignored. */ DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags); /* This function binds to a variable inside a shared library. */ @@ -194,52 +261,58 @@ DSO_METHOD *DSO_METHOD_win32(void); /* If VMS is defined, use shared images. If not, return NULL. */ DSO_METHOD *DSO_METHOD_vms(void); -void ERR_load_DSO_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. */ +void ERR_load_DSO_strings(void); /* Error codes for the DSO functions. */ /* Function codes. */ #define DSO_F_DLFCN_BIND_FUNC 100 #define DSO_F_DLFCN_BIND_VAR 101 -#define DSO_F_DLFCN_CTRL 102 -#define DSO_F_DLFCN_LOAD 103 -#define DSO_F_DLFCN_UNLOAD 104 -#define DSO_F_DL_BIND_FUNC 105 -#define DSO_F_DL_BIND_VAR 106 -#define DSO_F_DL_CTRL 107 -#define DSO_F_DL_LOAD 108 -#define DSO_F_DL_UNLOAD 109 -#define DSO_F_DSO_BIND_FUNC 110 -#define DSO_F_DSO_BIND_VAR 111 -#define DSO_F_DSO_CTRL 112 -#define DSO_F_DSO_FREE 113 -#define DSO_F_DSO_LOAD 114 -#define DSO_F_DSO_NEW_METHOD 115 -#define DSO_F_DSO_UP 116 -#define DSO_F_VMS_BIND_VAR 122 -#define DSO_F_VMS_CTRL 123 -#define DSO_F_VMS_LOAD 124 -#define DSO_F_VMS_UNLOAD 125 -#define DSO_F_WIN32_BIND_FUNC 117 -#define DSO_F_WIN32_BIND_VAR 118 -#define DSO_F_WIN32_CTRL 119 +#define DSO_F_DLFCN_LOAD 102 +#define DSO_F_DLFCN_NAME_CONVERTER 123 +#define DSO_F_DLFCN_UNLOAD 103 +#define DSO_F_DL_BIND_FUNC 104 +#define DSO_F_DL_BIND_VAR 105 +#define DSO_F_DL_LOAD 106 +#define DSO_F_DL_NAME_CONVERTER 124 +#define DSO_F_DL_UNLOAD 107 +#define DSO_F_DSO_BIND_FUNC 108 +#define DSO_F_DSO_BIND_VAR 109 +#define DSO_F_DSO_CONVERT_FILENAME 126 +#define DSO_F_DSO_CTRL 110 +#define DSO_F_DSO_FREE 111 +#define DSO_F_DSO_GET_FILENAME 127 +#define DSO_F_DSO_GET_LOADED_FILENAME 128 +#define DSO_F_DSO_LOAD 112 +#define DSO_F_DSO_NEW_METHOD 113 +#define DSO_F_DSO_SET_FILENAME 129 +#define DSO_F_DSO_SET_NAME_CONVERTER 122 +#define DSO_F_DSO_UP_REF 114 +#define DSO_F_VMS_BIND_VAR 115 +#define DSO_F_VMS_LOAD 116 +#define DSO_F_VMS_UNLOAD 117 +#define DSO_F_WIN32_BIND_FUNC 118 +#define DSO_F_WIN32_BIND_VAR 119 #define DSO_F_WIN32_LOAD 120 +#define DSO_F_WIN32_NAME_CONVERTER 125 #define DSO_F_WIN32_UNLOAD 121 /* Reason codes. */ #define DSO_R_CTRL_FAILED 100 -#define DSO_R_FILENAME_TOO_BIG 109 -#define DSO_R_FINISH_FAILED 101 -#define DSO_R_LOAD_FAILED 102 -#define DSO_R_NULL_HANDLE 103 -#define DSO_R_STACK_ERROR 104 -#define DSO_R_SYM_FAILURE 105 -#define DSO_R_UNKNOWN_COMMAND 106 +#define DSO_R_DSO_ALREADY_LOADED 110 +#define DSO_R_FILENAME_TOO_BIG 101 +#define DSO_R_FINISH_FAILED 102 +#define DSO_R_LOAD_FAILED 103 +#define DSO_R_NAME_TRANSLATION_FAILED 109 +#define DSO_R_NO_FILENAME 111 +#define DSO_R_NULL_HANDLE 104 +#define DSO_R_SET_FILENAME_FAILED 112 +#define DSO_R_STACK_ERROR 105 +#define DSO_R_SYM_FAILURE 106 #define DSO_R_UNLOAD_FAILED 107 #define DSO_R_UNSUPPORTED 108 @@ -247,4 +320,3 @@ void ERR_load_DSO_strings(void); } #endif #endif - diff --git a/src/lib/libcrypto/dso/dso_dlfcn.c b/src/lib/libcrypto/dso/dso_dlfcn.c index e709c721cc..906b4703de 100644 --- a/src/lib/libcrypto/dso/dso_dlfcn.c +++ b/src/lib/libcrypto/dso/dso_dlfcn.c @@ -74,7 +74,7 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) /* Part of the hack in "dlfcn_load" ... */ #define DSO_MAX_TRANSLATED_SIZE 256 -static int dlfcn_load(DSO *dso, const char *filename); +static int dlfcn_load(DSO *dso); static int dlfcn_unload(DSO *dso); static void *dlfcn_bind_var(DSO *dso, const char *symname); static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); @@ -82,8 +82,9 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); static int dlfcn_unbind(DSO *dso, char *symname, void *symptr); static int dlfcn_init(DSO *dso); static int dlfcn_finish(DSO *dso); -#endif static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); +#endif +static char *dlfcn_name_converter(DSO *dso, const char *filename); static DSO_METHOD dso_meth_dlfcn = { "OpenSSL 'dlfcn' shared library method", @@ -96,7 +97,8 @@ static DSO_METHOD dso_meth_dlfcn = { NULL, /* unbind_var */ NULL, /* unbind_func */ #endif - dlfcn_ctrl, + NULL, /* ctrl */ + dlfcn_name_converter, NULL, /* init */ NULL /* finish */ }; @@ -112,7 +114,7 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) * as we don't have autoconf yet, I'm implementing a hack that could * be hacked further relatively easily to deal with cases as we find * them. Initially this is to cope with OpenBSD. */ -#ifdef __OpenBSD__ +#if defined(__OpenBSD__) || defined(__NetBSD__) # ifdef DL_LAZY # define DLOPEN_FLAG DL_LAZY # else @@ -130,41 +132,40 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) * (i) the handle (void*) returned from dlopen(). */ -static int dlfcn_load(DSO *dso, const char *filename) +static int dlfcn_load(DSO *dso) { - void *ptr; - char translated[DSO_MAX_TRANSLATED_SIZE]; - int len; + void *ptr = NULL; + /* See applicable comments in dso_dl.c */ + char *filename = DSO_convert_filename(dso, NULL); - /* NB: This is a hideous hack, but I'm not yet sure what - * to replace it with. This attempts to convert any filename, - * that looks like it has no path information, into a - * translated form, e. "blah" -> "libblah.so" */ - len = strlen(filename); - if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && - (len + 6 < DSO_MAX_TRANSLATED_SIZE) && - (strstr(filename, "/") == NULL)) + if(filename == NULL) { - sprintf(translated, "lib%s.so", filename); - ptr = dlopen(translated, DLOPEN_FLAG); - } - else - { - ptr = dlopen(filename, DLOPEN_FLAG); + DSOerr(DSO_F_DLFCN_LOAD,DSO_R_NO_FILENAME); + goto err; } + ptr = dlopen(filename, DLOPEN_FLAG); if(ptr == NULL) { DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); - return(0); + ERR_add_error_data(4, "filename(", filename, "): ", dlerror()); + goto err; } if(!sk_push(dso->meth_data, (char *)ptr)) { DSOerr(DSO_F_DLFCN_LOAD,DSO_R_STACK_ERROR); - dlclose(ptr); - return(0); + goto err; } + /* Success */ + dso->loaded_filename = filename; return(1); - } +err: + /* Cleanup! */ + if(filename != NULL) + OPENSSL_free(filename); + if(ptr != NULL) + dlclose(ptr); + return(0); +} static int dlfcn_unload(DSO *dso) { @@ -214,6 +215,7 @@ static void *dlfcn_bind_var(DSO *dso, const char *symname) if(sym == NULL) { DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_SYM_FAILURE); + ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); return(NULL); } return(sym); @@ -244,33 +246,44 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) if(sym == NULL) { DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); + ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); return(NULL); } return(sym); } -static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg) +static char *dlfcn_name_converter(DSO *dso, const char *filename) { - if(dso == NULL) + char *translated; + int len, rsize, transform; + + len = strlen(filename); + rsize = len + 1; + transform = (strstr(filename, "/") == NULL); + if(transform) { - DSOerr(DSO_F_DLFCN_CTRL,ERR_R_PASSED_NULL_PARAMETER); - return(-1); + /* We will convert this to "%s.so" or "lib%s.so" */ + rsize += 3; /* The length of ".so" */ + if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) + rsize += 3; /* The length of "lib" */ } - switch(cmd) + translated = OPENSSL_malloc(rsize); + if(translated == NULL) { - case DSO_CTRL_GET_FLAGS: - return dso->flags; - case DSO_CTRL_SET_FLAGS: - dso->flags = (int)larg; - return(0); - case DSO_CTRL_OR_FLAGS: - dso->flags |= (int)larg; - return(0); - default: - break; + DSOerr(DSO_F_DLFCN_NAME_CONVERTER, + DSO_R_NAME_TRANSLATION_FAILED); + return(NULL); } - DSOerr(DSO_F_DLFCN_CTRL,DSO_R_UNKNOWN_COMMAND); - return(-1); + if(transform) + { + if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) + sprintf(translated, "lib%s.so", filename); + else + sprintf(translated, "%s.so", filename); + } + else + sprintf(translated, "%s", filename); + return(translated); } #endif /* DSO_DLFCN */ diff --git a/src/lib/libcrypto/dso/dso_err.c b/src/lib/libcrypto/dso/dso_err.c index a3d7321c9b..cf452de1aa 100644 --- a/src/lib/libcrypto/dso/dso_err.c +++ b/src/lib/libcrypto/dso/dso_err.c @@ -63,34 +63,38 @@ #include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA DSO_str_functs[]= { {ERR_PACK(0,DSO_F_DLFCN_BIND_FUNC,0), "DLFCN_BIND_FUNC"}, {ERR_PACK(0,DSO_F_DLFCN_BIND_VAR,0), "DLFCN_BIND_VAR"}, -{ERR_PACK(0,DSO_F_DLFCN_CTRL,0), "DLFCN_CTRL"}, {ERR_PACK(0,DSO_F_DLFCN_LOAD,0), "DLFCN_LOAD"}, +{ERR_PACK(0,DSO_F_DLFCN_NAME_CONVERTER,0), "DLFCN_NAME_CONVERTER"}, {ERR_PACK(0,DSO_F_DLFCN_UNLOAD,0), "DLFCN_UNLOAD"}, {ERR_PACK(0,DSO_F_DL_BIND_FUNC,0), "DL_BIND_FUNC"}, {ERR_PACK(0,DSO_F_DL_BIND_VAR,0), "DL_BIND_VAR"}, -{ERR_PACK(0,DSO_F_DL_CTRL,0), "DL_CTRL"}, {ERR_PACK(0,DSO_F_DL_LOAD,0), "DL_LOAD"}, +{ERR_PACK(0,DSO_F_DL_NAME_CONVERTER,0), "DL_NAME_CONVERTER"}, {ERR_PACK(0,DSO_F_DL_UNLOAD,0), "DL_UNLOAD"}, {ERR_PACK(0,DSO_F_DSO_BIND_FUNC,0), "DSO_bind_func"}, {ERR_PACK(0,DSO_F_DSO_BIND_VAR,0), "DSO_bind_var"}, +{ERR_PACK(0,DSO_F_DSO_CONVERT_FILENAME,0), "DSO_convert_filename"}, {ERR_PACK(0,DSO_F_DSO_CTRL,0), "DSO_ctrl"}, {ERR_PACK(0,DSO_F_DSO_FREE,0), "DSO_free"}, +{ERR_PACK(0,DSO_F_DSO_GET_FILENAME,0), "DSO_get_filename"}, +{ERR_PACK(0,DSO_F_DSO_GET_LOADED_FILENAME,0), "DSO_get_loaded_filename"}, {ERR_PACK(0,DSO_F_DSO_LOAD,0), "DSO_load"}, {ERR_PACK(0,DSO_F_DSO_NEW_METHOD,0), "DSO_new_method"}, -{ERR_PACK(0,DSO_F_DSO_UP,0), "DSO_up"}, +{ERR_PACK(0,DSO_F_DSO_SET_FILENAME,0), "DSO_set_filename"}, +{ERR_PACK(0,DSO_F_DSO_SET_NAME_CONVERTER,0), "DSO_set_name_converter"}, +{ERR_PACK(0,DSO_F_DSO_UP_REF,0), "DSO_up_ref"}, {ERR_PACK(0,DSO_F_VMS_BIND_VAR,0), "VMS_BIND_VAR"}, -{ERR_PACK(0,DSO_F_VMS_CTRL,0), "VMS_CTRL"}, {ERR_PACK(0,DSO_F_VMS_LOAD,0), "VMS_LOAD"}, {ERR_PACK(0,DSO_F_VMS_UNLOAD,0), "VMS_UNLOAD"}, {ERR_PACK(0,DSO_F_WIN32_BIND_FUNC,0), "WIN32_BIND_FUNC"}, {ERR_PACK(0,DSO_F_WIN32_BIND_VAR,0), "WIN32_BIND_VAR"}, -{ERR_PACK(0,DSO_F_WIN32_CTRL,0), "WIN32_CTRL"}, {ERR_PACK(0,DSO_F_WIN32_LOAD,0), "WIN32_LOAD"}, +{ERR_PACK(0,DSO_F_WIN32_NAME_CONVERTER,0), "WIN32_NAME_CONVERTER"}, {ERR_PACK(0,DSO_F_WIN32_UNLOAD,0), "WIN32_UNLOAD"}, {0,NULL} }; @@ -98,13 +102,16 @@ static ERR_STRING_DATA DSO_str_functs[]= static ERR_STRING_DATA DSO_str_reasons[]= { {DSO_R_CTRL_FAILED ,"control command failed"}, +{DSO_R_DSO_ALREADY_LOADED ,"dso already loaded"}, {DSO_R_FILENAME_TOO_BIG ,"filename too big"}, {DSO_R_FINISH_FAILED ,"cleanup method function failed"}, {DSO_R_LOAD_FAILED ,"could not load the shared library"}, +{DSO_R_NAME_TRANSLATION_FAILED ,"name translation failed"}, +{DSO_R_NO_FILENAME ,"no filename"}, {DSO_R_NULL_HANDLE ,"a null shared library handle was used"}, +{DSO_R_SET_FILENAME_FAILED ,"set filename failed"}, {DSO_R_STACK_ERROR ,"the meth_data stack is corrupt"}, {DSO_R_SYM_FAILURE ,"could not bind to the requested symbol name"}, -{DSO_R_UNKNOWN_COMMAND ,"unknown control command"}, {DSO_R_UNLOAD_FAILED ,"could not unload the shared library"}, {DSO_R_UNSUPPORTED ,"functionality not supported"}, {0,NULL} @@ -119,7 +126,7 @@ void ERR_load_DSO_strings(void) if (init) { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_DSO,DSO_str_functs); ERR_load_strings(ERR_LIB_DSO,DSO_str_reasons); #endif diff --git a/src/lib/libcrypto/dso/dso_lib.c b/src/lib/libcrypto/dso/dso_lib.c index acd166697e..556069b9b8 100644 --- a/src/lib/libcrypto/dso/dso_lib.c +++ b/src/lib/libcrypto/dso/dso_lib.c @@ -108,7 +108,7 @@ DSO *DSO_new_method(DSO_METHOD *meth) } memset(ret, 0, sizeof(DSO)); ret->meth_data = sk_new_null(); - if((ret->meth_data = sk_new_null()) == NULL) + if(ret->meth_data == NULL) { /* sk_new doesn't generate any errors so we do */ DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE); @@ -164,6 +164,10 @@ int DSO_free(DSO *dso) } sk_free(dso->meth_data); + if(dso->filename != NULL) + OPENSSL_free(dso->filename); + if(dso->loaded_filename != NULL) + OPENSSL_free(dso->loaded_filename); OPENSSL_free(dso); return(1); @@ -175,11 +179,11 @@ int DSO_flags(DSO *dso) } -int DSO_up(DSO *dso) +int DSO_up_ref(DSO *dso) { if (dso == NULL) { - DSOerr(DSO_F_DSO_UP,ERR_R_PASSED_NULL_PARAMETER); + DSOerr(DSO_F_DSO_UP_REF,ERR_R_PASSED_NULL_PARAMETER); return(0); } @@ -192,48 +196,60 @@ DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags) DSO *ret; int allocated = 0; - if(filename == NULL) - { - DSOerr(DSO_F_DSO_LOAD,ERR_R_PASSED_NULL_PARAMETER); - return(NULL); - } if(dso == NULL) { ret = DSO_new_method(meth); if(ret == NULL) { DSOerr(DSO_F_DSO_LOAD,ERR_R_MALLOC_FAILURE); - return(NULL); + goto err; } allocated = 1; + /* Pass the provided flags to the new DSO object */ + if(DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_CTRL_FAILED); + goto err; + } } else ret = dso; - /* Bleurgh ... have to check for negative return values for - * errors. */ - if(DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) + /* Don't load if we're currently already loaded */ + if(ret->filename != NULL) { - DSOerr(DSO_F_DSO_LOAD,DSO_R_CTRL_FAILED); - if(allocated) - DSO_free(ret); - return(NULL); + DSOerr(DSO_F_DSO_LOAD,DSO_R_DSO_ALREADY_LOADED); + goto err; + } + /* filename can only be NULL if we were passed a dso that already has + * one set. */ + if(filename != NULL) + if(!DSO_set_filename(ret, filename)) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_SET_FILENAME_FAILED); + goto err; + } + filename = ret->filename; + if(filename == NULL) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_NO_FILENAME); + goto err; } if(ret->meth->dso_load == NULL) { DSOerr(DSO_F_DSO_LOAD,DSO_R_UNSUPPORTED); - if(allocated) - DSO_free(ret); - return(NULL); + goto err; } - if(!ret->meth->dso_load(ret, filename)) + if(!ret->meth->dso_load(ret)) { DSOerr(DSO_F_DSO_LOAD,DSO_R_LOAD_FAILED); - if(allocated) - DSO_free(ret); - return(NULL); + goto err; } /* Load succeeded */ return(ret); +err: + if(allocated) + DSO_free(ret); + return(NULL); } void *DSO_bind_var(DSO *dso, const char *symname) @@ -297,6 +313,22 @@ long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg) DSOerr(DSO_F_DSO_CTRL,ERR_R_PASSED_NULL_PARAMETER); return(-1); } + /* We should intercept certain generic commands and only pass control + * to the method-specific ctrl() function if it's something we don't + * handle. */ + switch(cmd) + { + case DSO_CTRL_GET_FLAGS: + return dso->flags; + case DSO_CTRL_SET_FLAGS: + dso->flags = (int)larg; + return(0); + case DSO_CTRL_OR_FLAGS: + dso->flags |= (int)larg; + return(0); + default: + break; + } if((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) { DSOerr(DSO_F_DSO_CTRL,DSO_R_UNSUPPORTED); @@ -304,3 +336,104 @@ long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg) } return(dso->meth->dso_ctrl(dso,cmd,larg,parg)); } + +int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb, + DSO_NAME_CONVERTER_FUNC *oldcb) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_SET_NAME_CONVERTER, + ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if(oldcb) + *oldcb = dso->name_converter; + dso->name_converter = cb; + return(1); + } + +const char *DSO_get_filename(DSO *dso) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_GET_FILENAME,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + return(dso->filename); + } + +int DSO_set_filename(DSO *dso, const char *filename) + { + char *copied; + + if((dso == NULL) || (filename == NULL)) + { + DSOerr(DSO_F_DSO_SET_FILENAME,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if(dso->loaded_filename) + { + DSOerr(DSO_F_DSO_SET_FILENAME,DSO_R_DSO_ALREADY_LOADED); + return(0); + } + /* We'll duplicate filename */ + copied = OPENSSL_malloc(strlen(filename) + 1); + if(copied == NULL) + { + DSOerr(DSO_F_DSO_SET_FILENAME,ERR_R_MALLOC_FAILURE); + return(0); + } + strcpy(copied, filename); + if(dso->filename) + OPENSSL_free(dso->filename); + dso->filename = copied; + return(1); + } + +char *DSO_convert_filename(DSO *dso, const char *filename) + { + char *result = NULL; + + if(dso == NULL) + { + DSOerr(DSO_F_DSO_CONVERT_FILENAME,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(filename == NULL) + filename = dso->filename; + if(filename == NULL) + { + DSOerr(DSO_F_DSO_CONVERT_FILENAME,DSO_R_NO_FILENAME); + return(NULL); + } + if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) + { + if(dso->name_converter != NULL) + result = dso->name_converter(dso, filename); + else if(dso->meth->dso_name_converter != NULL) + result = dso->meth->dso_name_converter(dso, filename); + } + if(result == NULL) + { + result = OPENSSL_malloc(strlen(filename) + 1); + if(result == NULL) + { + DSOerr(DSO_F_DSO_CONVERT_FILENAME, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(result, filename); + } + return(result); + } + +const char *DSO_get_loaded_filename(DSO *dso) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_GET_LOADED_FILENAME, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + return(dso->loaded_filename); + } diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c index e0d78d67fb..0cf485de60 100644 --- a/src/lib/libcrypto/ec/ec_lib.c +++ b/src/lib/libcrypto/ec/ec_lib.c @@ -106,6 +106,8 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) void EC_GROUP_free(EC_GROUP *group) { + if (!group) return; + if (group->meth->group_finish != 0) group->meth->group_finish(group); @@ -117,6 +119,8 @@ void EC_GROUP_free(EC_GROUP *group) void EC_GROUP_clear_free(EC_GROUP *group) { + if (!group) return; + if (group->meth->group_clear_finish != 0) group->meth->group_clear_finish(group); else if (group->meth != NULL && group->meth->group_finish != 0) @@ -337,6 +341,8 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group) void EC_POINT_free(EC_POINT *point) { + if (!point) return; + if (point->meth->point_finish != 0) point->meth->point_finish(point); OPENSSL_free(point); @@ -345,6 +351,8 @@ void EC_POINT_free(EC_POINT *point) void EC_POINT_clear_free(EC_POINT *point) { + if (!point) return; + if (point->meth->point_clear_finish != 0) point->meth->point_clear_finish(point); else if (point->meth != NULL && point->meth->point_finish != 0) diff --git a/src/lib/libcrypto/engine/README b/src/lib/libcrypto/engine/README index 96595e6f35..6b69b70f57 100644 --- a/src/lib/libcrypto/engine/README +++ b/src/lib/libcrypto/engine/README @@ -1,278 +1,211 @@ -NOTES, THOUGHTS, and EVERYTHING -------------------------------- - -(1) Concurrency and locking ... I made a change to the ENGINE_free code - because I spotted a potential hold-up in proceedings (doing too - much inside a lock including calling a callback), there may be - other bits like this. What do the speed/optimisation freaks think - of this aspect of the code and design? There's lots of locking for - manipulation functions and I need that to keep things nice and - solid, but this manipulation is mostly (de)initialisation, I would - think that most run-time locking is purely in the ENGINE_init and - ENGINE_finish calls that might be made when getting handles for - RSA (and friends') structures. These would be mostly reference - count operations as the functional references should always be 1 - or greater at run-time to prevent init/deinit thrashing. - -(2) nCipher support, via the HWCryptoHook API, is now in the code. - Apparently this hasn't been tested too much yet, but it looks - good. :-) Atalla support has been added too, but shares a lot in - common with Ben's original hooks in bn_exp.c (although it has been - ENGINE-ified, and error handling wrapped around it) and it's also - had some low-volume testing, so it should be usable. - -(3) Of more concern, we need to work out (a) how to put together usable - RAND_METHODs for units that just have one "get n or less random - bytes" function, (b) we also need to determine how to hook the code - in crypto/rand/ to use the ENGINE defaults in a way similar to what - has been done in crypto/rsa/, crypto/dsa/, etc. - -(4) ENGINE should really grow to encompass more than 3 public key - algorithms and randomness gathering. The structure/data level of - the engine code is hidden from code outside the crypto/engine/ - directory so change shouldn't be too viral. More important though - is how things should evolve ... this needs thought and discussion. - - ------------------------------------==*==----------------------------------- - -More notes 2000-08-01 ---------------------- - -Geoff Thorpe, who designed the engine part, wrote a pretty good description -of the thoughts he had when he built it, good enough to include verbatim here -(with his permission) -- Richard Levitte - - -Date: Tue, 1 Aug 2000 16:54:08 +0100 (BST) -From: Geoff Thorpe -Subject: Re: The thoughts to merge BRANCH_engine into the main trunk are - emerging - -Hi there, - -I'm going to try and do some justice to this, but I'm a little short on -time and the there is an endless amount that could be discussed on this -subject. sigh ... please bear with me :-) - -> The changes in BRANCH_engine dig deep into the core of OpenSSL, for example -> into the RSA and RAND routines, adding a level of indirection which is needed -> to keep the abstraction, as far as I understand. It would be a good thing if -> those who do play with those things took a look at the changes that have been -> done in the branch and say out loud how much (or hopefully little) we've made -> fools of ourselves. - -The point here is that the code that has emerged in the BRANCH_engine -branch was based on some initial requirements of mine that I went in and -addressed, and Richard has picked up the ball and run with it too. It -would be really useful to get some review of the approach we've taken, but -first I think I need to describe as best I can the reasons behind what has -been done so far, in particular what issues we have tried to address when -doing this, and what issues we have intentionally (or necessarily) tried -to avoid. - -methods, engines, and evps --------------------------- - -There has been some dicussion, particularly with Steve, about where this -ENGINE stuff might fit into the conceptual picture as/when we start to -abstract algorithms a little bit to make the library more extensible. In -particular, it would desirable to have algorithms (symmetric, hash, pkc, -etc) abstracted in some way that allows them to be just objects sitting in -a list (or database) ... it'll just happen that the "DSA" object doesn't -support encryption whereas the "RSA" object does. This requires a lot of -consideration to begin to know how to tackle it; in particular how -encapsulated should these things be? If the objects also understand their -own ASN1 encodings and what-not, then it would for example be possible to -add support for elliptic-curve DSA in as a new algorithm and automatically -have ECC-DSA certificates supported in SSL applications. Possible, but not -easy. :-) - -Whatever, it seems that the way to go (if I've grok'd Steve's comments on -this in the past) is to amalgamate these things in EVP as is already done -(I think) for ciphers or hashes (Steve, please correct/elaborate). I -certainly think something should be done in this direction because right -now we have different source directories, types, functions, and methods -for each algorithm - even when conceptually they are very much different -feathers of the same bird. (This is certainly all true for the public-key -stuff, and may be partially true for the other parts.) - -ENGINE was *not* conceived as a way of solving this, far from it. Nor was -it conceived as a way of replacing the various "***_METHOD"s. It was -conceived as an abstraction of a sort of "virtual crypto device". If we -lived in a world where "EVP_ALGO"s (or something like them) encapsulated -particular algorithms like RSA,DSA,MD5,RC4,etc, and "***_METHOD"s -encapsulated interfaces to algorithms (eg. some algo's might support a -PKC_METHOD, a HASH_METHOD, or a CIPHER_METHOD, who knows?), then I would -think that ENGINE would encapsulate an implementation of arbitrarily many -of those algorithms - perhaps as alternatives to existing algorithms -and/or perhaps as new previously unimplemented algorithms. An ENGINE could -be used to contain an alternative software implementation, a wrapper for a -hardware acceleration and/or key-management unit, a comms-wrapper for -distributing cryptographic operations to remote machines, or any other -"devices" your imagination can dream up. - -However, what has been done in the ENGINE branch so far is nothing more -than starting to get our toes wet. I had a couple of self-imposed -requirements when putting the initial abstraction together, and I may have -already posed these in one form or another on the list, but briefly; - - (i) only bother with public key algorithms for now, and maybe RAND too - (motivated by the need to get hardware support going and the fact - this was a comparitively easy subset to address to begin with). - - (ii) don't change (if at all possible) the existing crypto code, ie. the - implementations, the way the ***_METHODs work, etc. - - (iii) ensure that if no function from the ENGINE code is ever called then - things work the way they always did, and there is no memory - allocation (otherwise the failure to cleanup would be a problem - - this is part of the reason no STACKs were used, the other part of - the reason being I found them inappropriate). - - (iv) ensure that all the built-in crypto was encapsulated by one of - these "ENGINE"s and that this engine was automatically selected as - the default. - - (v) provide the minimum hooking possible in the existing crypto code - so that global functions (eg. RSA_public_encrypt) do not need any - extra parameter, yet will use whatever the current default ENGINE - for that RSA key is, and that the default can be set "per-key" - and globally (new keys will assume the global default, and keys - without their own default will be operated on using the global - default). NB: Try and make (v) conflict as little as possible with - (ii). :-) - - (vi) wrap the ENGINE code up in duct tape so you can't even see the - corners. Ie. expose no structures at all, just black-box pointers. - - (v) maintain internally a list of ENGINEs on which a calling - application can iterate, interrogate, etc. Allow a calling - application to hook in new ENGINEs, remove ENGINEs from the list, - and enforce uniqueness within the global list of each ENGINE's - "unique id". - - (vi) keep reference counts for everything - eg. this includes storing a - reference inside each RSA structure to the ENGINE that it uses. - This is freed when the RSA structure is destroyed, or has its - ENGINE explicitly changed. The net effect needs to be that at any - time, it is deterministic to know whether an ENGINE is in use or - can be safely removed (or unloaded in the case of the other type - of reference) without invalidating function pointers that may or - may not be used indavertently in the future. This was actually - one of the biggest problems to overcome in the existing OpenSSL - code - implementations had always been assumed to be ever-present, - so there was no trivial way to get round this. - - (vii) distinguish between structural references and functional - references. - -A *little* detail +Notes: 2001-09-24 ----------------- -While my mind is on it; I'll illustrate the bit in item (vii). This idea -turned out to be very handy - the ENGINEs themselves need to be operated -on and manipulated simply as objects without necessarily trying to -"enable" them for use. Eg. most host machines will not have the necessary -hardware or software to support all the engines one might compile into -OpenSSL, yet it needs to be possible to iterate across the ENGINEs, -querying their names, properties, etc - all happening in a thread-safe -manner that uses reference counts (if you imagine two threads iterating -through a list and one thread removing the ENGINE the other is currently -looking at - you can see the gotcha waiting to happen). For all of this, -*structural references* are used and operate much like the other reference -counts in OpenSSL. - -The other kind of reference count is for *functional* references - these -indicate a reference on which the caller can actually assume the -particular ENGINE to be initialised and usable to perform the operations -it implements. Any increment or decrement of the functional reference -count automatically invokes a corresponding change in the structural -reference count, as it is fairly obvious that a functional reference is a -restricted case of a structural reference. So struct_ref >= funct_ref at -all times. NB: functional references are usually obtained by a call to -ENGINE_init(), but can also be created implicitly by calls that require a -new functional reference to be created, eg. ENGINE_set_default(). Either -way the only time the underlying ENGINE's "init" function is really called -is when the (functional) reference count increases to 1, similarly the -underlying "finish" handler is only called as the count goes down to 0. -The effect of this, for example, is that if you set the default ENGINE for -RSA operations to be "cswift", then its functional reference count will -already be at least 1 so the CryptoSwift shared-library and the card will -stay loaded and initialised until such time as all RSA keys using the -cswift ENGINE are changed or destroyed and the default ENGINE for RSA -operations has been changed. This prevents repeated thrashing of init and -finish handling if the count keeps getting down as far as zero. - -Otherwise, the way the ENGINE code has been put together I think pretty -much reflects the above points. The reason for the ENGINE structure having -individual RSA_METHOD, DSA_METHOD, etc pointers is simply that it was the -easiest way to go about things for now, to hook it all into the raw -RSA,DSA,etc code, and I was trying to the keep the structure invisible -anyway so that the way this is internally managed could be easily changed -later on when we start to work out what's to be done about these other -abstractions. - -Down the line, if some EVP-based technique emerges for adequately -encapsulating algorithms and all their various bits and pieces, then I can -imagine that "ENGINE" would turn into a reference-counting database of -these EVP things, of which the default "openssl" ENGINE would be the -library's own object database of pre-built software implemented algorithms -(and such). It would also be cool to see the idea of "METHOD"s detached -from the algorithms themselves ... so RSA, DSA, ElGamal, etc can all -expose essentially the same METHOD (aka interface), which would include -any querying/flagging stuff to identify what the algorithm can/can't do, -its name, and other stuff like max/min block sizes, key sizes, etc. This -would result in ENGINE similarly detaching its internal database of -algorithm implementations from the function definitions that return -interfaces to them. I think ... - -As for DSOs etc. Well the DSO code is pretty handy (but could be made much -more so) for loading vendor's driver-libraries and talking to them in some -generic way, but right now there's still big problems associated with -actually putting OpenSSL code (ie. new ENGINEs, or anything else for that -matter) in dynamically loadable libraries. These problems won't go away in -a hurry so I don't think we should expect to have any kind of -shared-library extensions any time soon - but solving the problems is a -good thing to aim for, and would as a side-effect probably help make -OpenSSL more usable as a shared-library itself (looking at the things -needed to do this will show you why). - -One of the problems is that if you look at any of the ENGINE -implementations, eg. hw_cswift.c or hw_ncipher.c, you'll see how it needs -a variety of functionality and definitions from various areas of OpenSSL, -including crypto/bn/, crypto/err/, crypto/ itself (locking for example), -crypto/dso/, crypto/engine/, crypto/rsa, etc etc etc. So if similar code -were to be suctioned off into shared libraries, the shared libraries would -either have to duplicate all the definitions and code and avoid loader -conflicts, or OpenSSL would have to somehow expose all that functionality -to the shared-library. If this isn't a big enough problem, the issue of -binary compatibility will be - anyone writing Apache modules can tell you -that (Ralf? Ben? :-). However, I don't think OpenSSL would need to be -quite so forgiving as Apache should be, so OpenSSL could simply tell its -version to the DSO and leave the DSO with the problem of deciding whether -to proceed or bail out for fear of binary incompatibilities. - -Certainly one thing that would go a long way to addressing this is to -embark on a bit of an opaqueness mission. I've set the ENGINE code up with -this in mind - it's so draconian that even to declare your own ENGINE, you -have to get the engine code to create the underlying ENGINE structure, and -then feed in the new ENGINE's function/method pointers through various -"set" functions. The more of the code that takes on such a black-box -approach, the more of the code that will be (a) easy to expose to shared -libraries that need it, and (b) easy to expose to applications wanting to -use OpenSSL itself as a shared-library. From my own explorations in -OpenSSL, the biggest leviathan I've seen that is a problem in this respect -is the BIGNUM code. Trying to "expose" the bignum code through any kind of -organised "METHODs", let alone do all the necessary bignum operations -solely through functions rather than direct access to the structures and -macros, will be a massive pain in the "r"s. - -Anyway, I'm done for now - hope it was readable. Thoughts? - -Cheers, -Geoff - - ------------------------------------==*==----------------------------------- +This "description" (if one chooses to call it that) needed some major updating +so here goes. This update addresses a change being made at the same time to +OpenSSL, and it pretty much completely restructures the underlying mechanics of +the "ENGINE" code. So it serves a double purpose of being a "ENGINE internals +for masochists" document *and* a rather extensive commit log message. (I'd get +lynched for sticking all this in CHANGES or the commit mails :-). + +ENGINE_TABLE underlies this restructuring, as described in the internal header +"eng_int.h", implemented in eng_table.c, and used in each of the "class" files; +tb_rsa.c, tb_dsa.c, etc. + +However, "EVP_CIPHER" underlies the motivation and design of ENGINE_TABLE so +I'll mention a bit about that first. EVP_CIPHER (and most of this applies +equally to EVP_MD for digests) is both a "method" and a algorithm/mode +identifier that, in the current API, "lingers". These cipher description + +implementation structures can be defined or obtained directly by applications, +or can be loaded "en masse" into EVP storage so that they can be catalogued and +searched in various ways, ie. two ways of encrypting with the "des_cbc" +algorithm/mode pair are; + +(i) directly; + const EVP_CIPHER *cipher = EVP_des_cbc(); + EVP_EncryptInit(&ctx, cipher, key, iv); + [ ... use EVP_EncryptUpdate() and EVP_EncryptFinal() ...] + +(ii) indirectly; + OpenSSL_add_all_ciphers(); + cipher = EVP_get_cipherbyname("des_cbc"); + EVP_EncryptInit(&ctx, cipher, key, iv); + [ ... etc ... ] + +The latter is more generally used because it also allows ciphers/digests to be +looked up based on other identifiers which can be useful for automatic cipher +selection, eg. in SSL/TLS, or by user-controllable configuration. + +The important point about this is that EVP_CIPHER definitions and structures are +passed around with impunity and there is no safe way, without requiring massive +rewrites of many applications, to assume that EVP_CIPHERs can be reference +counted. One an EVP_CIPHER is exposed to the caller, neither it nor anything it +comes from can "safely" be destroyed. Unless of course the way of getting to +such ciphers is via entirely distinct API calls that didn't exist before. +However existing API usage cannot be made to understand when an EVP_CIPHER +pointer, that has been passed to the caller, is no longer being used. + +The other problem with the existing API w.r.t. to hooking EVP_CIPHER support +into ENGINE is storage - the OBJ_NAME-based storage used by EVP to register +ciphers simultaneously registers cipher *types* and cipher *implementations* - +they are effectively the same thing, an "EVP_CIPHER" pointer. The problem with +hooking in ENGINEs is that multiple ENGINEs may implement the same ciphers. The +solution is necessarily that ENGINE-provided ciphers simply are not registered, +stored, or exposed to the caller in the same manner as existing ciphers. This is +especially necessary considering the fact ENGINE uses reference counts to allow +for cleanup, modularity, and DSO support - yet EVP_CIPHERs, as exposed to +callers in the current API, support no such controls. + +Another sticking point for integrating cipher support into ENGINE is linkage. +Already there is a problem with the way ENGINE supports RSA, DSA, etc whereby +they are available *because* they're part of a giant ENGINE called "openssl". +Ie. all implementations *have* to come from an ENGINE, but we get round that by +having a giant ENGINE with all the software support encapsulated. This creates +linker hassles if nothing else - linking a 1-line application that calls 2 basic +RSA functions (eg. "RSA_free(RSA_new());") will result in large quantities of +ENGINE code being linked in *and* because of that DSA, DH, and RAND also. If we +continue with this approach for EVP_CIPHER support (even if it *was* possible) +we would lose our ability to link selectively by selectively loading certain +implementations of certain functionality. Touching any part of any kind of +crypto would result in massive static linkage of everything else. So the +solution is to change the way ENGINE feeds existing "classes", ie. how the +hooking to ENGINE works from RSA, DSA, DH, RAND, as well as adding new hooking +for EVP_CIPHER, and EVP_MD. + +The way this is now being done is by mostly reverting back to how things used to +work prior to ENGINE :-). Ie. RSA now has a "RSA_METHOD" pointer again - this +was previously replaced by an "ENGINE" pointer and all RSA code that required +the RSA_METHOD would call ENGINE_get_RSA() each time on its ENGINE handle to +temporarily get and use the ENGINE's RSA implementation. Apart from being more +efficient, switching back to each RSA having an RSA_METHOD pointer also allows +us to conceivably operate with *no* ENGINE. As we'll see, this removes any need +for a fallback ENGINE that encapsulates default implementations - we can simply +have our RSA structure pointing its RSA_METHOD pointer to the software +implementation and have its ENGINE pointer set to NULL. + +A look at the EVP_CIPHER hooking is most explanatory, the RSA, DSA (etc) cases +turn out to be degenerate forms of the same thing. The EVP storage of ciphers, +and the existing EVP API functions that return "software" implementations and +descriptions remain untouched. However, the storage takes more meaning in terms +of "cipher description" and less meaning in terms of "implementation". When an +EVP_CIPHER_CTX is actually initialised with an EVP_CIPHER method and is about to +begin en/decryption, the hooking to ENGINE comes into play. What happens is that +cipher-specific ENGINE code is asked for an ENGINE pointer (a functional +reference) for any ENGINE that is registered to perform the algo/mode that the +provided EVP_CIPHER structure represents. Under normal circumstances, that +ENGINE code will return NULL because no ENGINEs will have had any cipher +implementations *registered*. As such, a NULL ENGINE pointer is stored in the +EVP_CIPHER_CTX context, and the EVP_CIPHER structure is left hooked into the +context and so is used as the implementation. Pretty much how things work now +except we'd have a redundant ENGINE pointer set to NULL and doing nothing. + +Conversely, if an ENGINE *has* been registered to perform the algorithm/mode +combination represented by the provided EVP_CIPHER, then a functional reference +to that ENGINE will be returned to the EVP_CIPHER_CTX during initialisation. +That functional reference will be stored in the context (and released on +cleanup) - and having that reference provides a *safe* way to use an EVP_CIPHER +definition that is private to the ENGINE. Ie. the EVP_CIPHER provided by the +application will actually be replaced by an EVP_CIPHER from the registered +ENGINE - it will support the same algorithm/mode as the original but will be a +completely different implementation. Because this EVP_CIPHER isn't stored in the +EVP storage, nor is it returned to applications from traditional API functions, +there is no associated problem with it not having reference counts. And of +course, when one of these "private" cipher implementations is hooked into +EVP_CIPHER_CTX, it is done whilst the EVP_CIPHER_CTX holds a functional +reference to the ENGINE that owns it, thus the use of the ENGINE's EVP_CIPHER is +safe. + +The "cipher-specific ENGINE code" I mentioned is implemented in tb_cipher.c but +in essence it is simply an instantiation of "ENGINE_TABLE" code for use by +EVP_CIPHER code. tb_digest.c is virtually identical but, of course, it is for +use by EVP_MD code. Ditto for tb_rsa.c, tb_dsa.c, etc. These instantiations of +ENGINE_TABLE essentially provide linker-separation of the classes so that even +if ENGINEs implement *all* possible algorithms, an application using only +EVP_CIPHER code will link at most code relating to EVP_CIPHER, tb_cipher.c, core +ENGINE code that is independant of class, and of course the ENGINE +implementation that the application loaded. It will *not* however link any +class-specific ENGINE code for digests, RSA, etc nor will it bleed over into +other APIs, such as the RSA/DSA/etc library code. + +ENGINE_TABLE is a little more complicated than may seem necessary but this is +mostly to avoid a lot of "init()"-thrashing on ENGINEs (that may have to load +DSOs, and other expensive setup that shouldn't be thrashed unnecessarily) *and* +to duplicate "default" behaviour. Basically an ENGINE_TABLE instantiation, for +example tb_cipher.c, implements a hash-table keyed by integer "nid" values. +These nids provide the uniquenness of an algorithm/mode - and each nid will hash +to a potentially NULL "ENGINE_PILE". An ENGINE_PILE is essentially a list of +pointers to ENGINEs that implement that particular 'nid'. Each "pile" uses some +caching tricks such that requests on that 'nid' will be cached and all future +requests will return immediately (well, at least with minimal operation) unless +a change is made to the pile, eg. perhaps an ENGINE was unloaded. The reason is +that an application could have support for 10 ENGINEs statically linked +in, and the machine in question may not have any of the hardware those 10 +ENGINEs support. If each of those ENGINEs has a "des_cbc" implementation, we +want to avoid every EVP_CIPHER_CTX setup from trying (and failing) to initialise +each of those 10 ENGINEs. Instead, the first such request will try to do that +and will either return (and cache) a NULL ENGINE pointer or will return a +functional reference to the first that successfully initialised. In the latter +case it will also cache an extra functional reference to the ENGINE as a +"default" for that 'nid'. The caching is acknowledged by a 'uptodate' variable +that is unset only if un/registration takes place on that pile. Ie. if +implementations of "des_cbc" are added or removed. This behaviour can be +tweaked; the ENGINE_TABLE_FLAG_NOINIT value can be passed to +ENGINE_set_table_flags(), in which case the only ENGINEs that tb_cipher.c will +try to initialise from the "pile" will be those that are already initialised +(ie. it's simply an increment of the functional reference count, and no real +"initialisation" will take place). + +RSA, DSA, DH, and RAND all have their own ENGINE_TABLE code as well, and the +difference is that they all use an implicit 'nid' of 1. Whereas EVP_CIPHERs are +actually qualitatively different depending on 'nid' (the "des_cbc" EVP_CIPHER is +not an interoperable implementation of "aes_256_cbc"), RSA_METHODs are +necessarily interoperable and don't have different flavours, only different +implementations. In other words, the ENGINE_TABLE for RSA will either be empty, +or will have a single ENGING_PILE hashed to by the 'nid' 1 and that pile +represents ENGINEs that implement the single "type" of RSA there is. + +Cleanup - the registration and unregistration may pose questions about how +cleanup works with the ENGINE_PILE doing all this caching nonsense (ie. when the +application or EVP_CIPHER code releases its last reference to an ENGINE, the +ENGINE_PILE code may still have references and thus those ENGINEs will stay +hooked in forever). The way this is handled is via "unregistration". With these +new ENGINE changes, an abstract ENGINE can be loaded and initialised, but that +is an algorithm-agnostic process. Even if initialised, it will not have +registered any of its implementations (to do so would link all class "table" +code despite the fact the application may use only ciphers, for example). This +is deliberately a distinct step. Moreover, registration and unregistration has +nothing to do with whether an ENGINE is *functional* or not (ie. you can even +register an ENGINE and its implementations without it being operational, you may +not even have the drivers to make it operate). What actually happens with +respect to cleanup is managed inside eng_lib.c with the "engine_cleanup_***" +functions. These functions are internal-only and each part of ENGINE code that +could require cleanup will, upon performing its first allocation, register a +callback with the "engine_cleanup" code. The other part of this that makes it +tick is that the ENGINE_TABLE instantiations (tb_***.c) use NULL as their +initialised state. So if RSA code asks for an ENGINE and no ENGINE has +registered an implementation, the code will simply return NULL and the tb_rsa.c +state will be unchanged. Thus, no cleanup is required unless registration takes +place. ENGINE_cleanup() will simply iterate across a list of registered cleanup +callbacks calling each in turn, and will then internally delete its own storage +(a STACK). When a cleanup callback is next registered (eg. if the cleanup() is +part of a gracefull restart and the application wants to cleanup all state then +start again), the internal STACK storage will be freshly allocated. This is much +the same as the situation in the ENGINE_TABLE instantiations ... NULL is the +initialised state, so only modification operations (not queries) will cause that +code to have to register a cleanup. + +What else? The bignum callbacks and associated ENGINE functions have been +removed for two obvious reasons; (i) there was no way to generalise them to the +mechanism now used by RSA/DSA/..., because there's no such thing as a BIGNUM +method, and (ii) because of (i), there was no meaningful way for library or +application code to automatically hook and use ENGINE supplied bignum functions +anyway. Also, ENGINE_cpy() has been removed (although an internal-only version +exists) - the idea of providing an ENGINE_cpy() function probably wasn't a good +one and now certainly doesn't make sense in any generalised way. Some of the +RSA, DSA, DH, and RAND functions that were fiddled during the original ENGINE +changes have now, as a consequence, been reverted back. This is because the +hooking of ENGINE is now automatic (and passive, it can interally use a NULL +ENGINE pointer to simply ignore ENGINE from then on). + +Hell, that should be enough for now ... comments welcome: geoff@openssl.org diff --git a/src/lib/libcrypto/engine/eng_all.c b/src/lib/libcrypto/engine/eng_all.c index a35b3db9e8..b3030fe505 100644 --- a/src/lib/libcrypto/engine/eng_all.c +++ b/src/lib/libcrypto/engine/eng_all.c @@ -60,10 +60,6 @@ #include #include "eng_int.h" -#ifdef __OpenBSD__ -static int openbsd_default_loaded = 0; -#endif - void ENGINE_load_builtin_engines(void) { /* There's no longer any need for an "openssl" ENGINE unless, one day, @@ -96,23 +92,11 @@ void ENGINE_load_builtin_engines(void) #ifndef OPENSSL_NO_HW_SUREWARE ENGINE_load_sureware(); #endif +#ifndef OPENSSL_NO_HW_4758_CCA + ENGINE_load_4758cca(); +#endif #ifdef OPENSSL_OPENBSD_DEV_CRYPTO ENGINE_load_openbsd_dev_crypto(); #endif -#ifdef __OpenBSD__ - ENGINE_load_cryptodev(); -#endif #endif } - -#ifdef __OpenBSD__ -void ENGINE_setup_openbsd(void) { - if (!openbsd_default_loaded) { - ENGINE_load_cryptodev(); - ENGINE_register_all_complete(); - } - openbsd_default_loaded=1; -} -#endif - - diff --git a/src/lib/libcrypto/engine/eng_fat.c b/src/lib/libcrypto/engine/eng_fat.c index af918b1499..d49aa7ed40 100644 --- a/src/lib/libcrypto/engine/eng_fat.c +++ b/src/lib/libcrypto/engine/eng_fat.c @@ -141,8 +141,7 @@ int ENGINE_register_all_complete(void) { ENGINE *e; - for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) { + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) ENGINE_register_complete(e); - } return 1; } diff --git a/src/lib/libcrypto/engine/eng_init.c b/src/lib/libcrypto/engine/eng_init.c index cc9396e863..98caa21e32 100644 --- a/src/lib/libcrypto/engine/eng_init.c +++ b/src/lib/libcrypto/engine/eng_init.c @@ -93,7 +93,7 @@ int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) * there's a chance that both threads will together take the count from * 2 to 0 without either calling finish(). */ e->funct_ref--; - engine_ref_debug(e, 1, -1); + engine_ref_debug(e, 1, -1) if((e->funct_ref == 0) && e->finish) { if(unlock_for_handlers) @@ -155,4 +155,3 @@ int ENGINE_finish(ENGINE *e) } return to_return; } - diff --git a/src/lib/libcrypto/engine/eng_list.c b/src/lib/libcrypto/engine/eng_list.c index ce48d2255a..0c220558e7 100644 --- a/src/lib/libcrypto/engine/eng_list.c +++ b/src/lib/libcrypto/engine/eng_list.c @@ -348,7 +348,7 @@ ENGINE *ENGINE_by_id(const char *id) } CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); iterator = engine_list_head; - while(iterator && (strcmp(id, iterator->id) != 0)) + while(iterator && (strcmp(id, iterator->id) != 0)) iterator = iterator->next; if(iterator) { diff --git a/src/lib/libcrypto/engine/engine.h b/src/lib/libcrypto/engine/engine.h index 2983f47034..cf06618286 100644 --- a/src/lib/libcrypto/engine/engine.h +++ b/src/lib/libcrypto/engine/engine.h @@ -3,7 +3,7 @@ * project 2000. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2001 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 @@ -59,36 +59,171 @@ #ifndef HEADER_ENGINE_H #define HEADER_ENGINE_H +#include #include +#ifndef OPENSSL_NO_RSA #include +#endif +#ifndef OPENSSL_NO_DSA #include +#endif +#ifndef OPENSSL_NO_DH #include +#endif #include -#include +#include #include +#include #ifdef __cplusplus extern "C" { #endif +/* Fixups for missing algorithms */ +#ifdef OPENSSL_NO_RSA +typedef void RSA_METHOD; +#endif +#ifdef OPENSSL_NO_DSA +typedef void DSA_METHOD; +#endif +#ifdef OPENSSL_NO_DH +typedef void DH_METHOD; +#endif + /* These flags are used to control combinations of algorithm (methods) * by bitwise "OR"ing. */ #define ENGINE_METHOD_RSA (unsigned int)0x0001 #define ENGINE_METHOD_DSA (unsigned int)0x0002 #define ENGINE_METHOD_DH (unsigned int)0x0004 #define ENGINE_METHOD_RAND (unsigned int)0x0008 -#define ENGINE_METHOD_BN_MOD_EXP (unsigned int)0x0010 -#define ENGINE_METHOD_BN_MOD_EXP_CRT (unsigned int)0x0020 +#define ENGINE_METHOD_CIPHERS (unsigned int)0x0040 +#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080 /* Obvious all-or-nothing cases. */ #define ENGINE_METHOD_ALL (unsigned int)0xFFFF #define ENGINE_METHOD_NONE (unsigned int)0x0000 +/* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used + * internally to control registration of ENGINE implementations, and can be set + * by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to + * initialise registered ENGINEs if they are not already initialised. */ +#define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001 + +/* ENGINE flags that can be set by ENGINE_set_flags(). */ +/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ /* Not used */ + +/* This flag is for ENGINEs that wish to handle the various 'CMD'-related + * control commands on their own. Without this flag, ENGINE_ctrl() handles these + * control commands on behalf of the ENGINE using their "cmd_defns" data. */ +#define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002 + +/* This flag is for ENGINEs who return new duplicate structures when found via + * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl() + * commands are called in sequence as part of some stateful process like + * key-generation setup and execution), it can set this flag - then each attempt + * to obtain the ENGINE will result in it being copied into a new structure. + * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments + * the existing ENGINE's structural reference count. */ +#define ENGINE_FLAGS_BY_ID_COPY (int)0x0004 + +/* ENGINEs can support their own command types, and these flags are used in + * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each + * command expects. Currently only numeric and string input is supported. If a + * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options, + * then it is regarded as an "internal" control command - and not for use in + * config setting situations. As such, they're not available to the + * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to + * this list of 'command types' should be reflected carefully in + * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */ + +/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */ +#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 +/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to + * ENGINE_ctrl) */ +#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 +/* Indicates that the control command takes *no* input. Ie. the control command + * is unparameterised. */ +#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 +/* Indicates that the control command is internal. This control command won't + * be shown in any output, and is only usable through the ENGINE_ctrl_cmd() + * function. */ +#define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 + +/* NB: These 3 control commands are deprecated and should not be used. ENGINEs + * relying on these commands should compile conditional support for + * compatibility (eg. if these symbols are defined) but should also migrate the + * same functionality to their own ENGINE-specific control functions that can be + * "discovered" by calling applications. The fact these control commands + * wouldn't be "executable" (ie. usable by text-based config) doesn't change the + * fact that application code can find and use them without requiring per-ENGINE + * hacking. */ + /* These flags are used to tell the ctrl function what should be done. * All command numbers are shared between all engines, even if some don't * make sense to some engines. In such a case, they do nothing but return * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */ #define ENGINE_CTRL_SET_LOGSTREAM 1 #define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +#define ENGINE_CTRL_HUP 3 /* Close and reinitialise any + handles/connections etc. */ +#define ENGINE_CTRL_SET_USER_INTERFACE 4 /* Alternative to callback */ +#define ENGINE_CTRL_SET_CALLBACK_DATA 5 /* User-specific data, used + when calling the password + callback and the user + interface */ + +/* These control commands allow an application to deal with an arbitrary engine + * in a dynamic way. Warn: Negative return values indicate errors FOR THESE + * COMMANDS because zero is used to indicate 'end-of-list'. Other commands, + * including ENGINE-specific command types, return zero for an error. + * + * An ENGINE can choose to implement these ctrl functions, and can internally + * manage things however it chooses - it does so by setting the + * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the + * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns + * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl() + * handler need only implement its own commands - the above "meta" commands will + * be taken care of. */ + +/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then + * all the remaining control commands will return failure, so it is worth + * checking this first if the caller is trying to "discover" the engine's + * capabilities and doesn't want errors generated unnecessarily. */ +#define ENGINE_CTRL_HAS_CTRL_FUNCTION 10 +/* Returns a positive command number for the first command supported by the + * engine. Returns zero if no ctrl commands are supported. */ +#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 +/* The 'long' argument specifies a command implemented by the engine, and the + * return value is the next command supported, or zero if there are no more. */ +#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 +/* The 'void*' argument is a command name (cast from 'const char *'), and the + * return value is the command that corresponds to it. */ +#define ENGINE_CTRL_GET_CMD_FROM_NAME 13 +/* The next two allow a command to be converted into its corresponding string + * form. In each case, the 'long' argument supplies the command. In the NAME_LEN + * case, the return value is the length of the command name (not counting a + * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer + * large enough, and it will be populated with the name of the command (WITH a + * trailing EOL). */ +#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 +#define ENGINE_CTRL_GET_NAME_FROM_CMD 15 +/* The next two are similar but give a "short description" of a command. */ +#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 +#define ENGINE_CTRL_GET_DESC_FROM_CMD 17 +/* With this command, the return value is the OR'd combination of + * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given + * engine-specific ctrl command expects. */ +#define ENGINE_CTRL_GET_CMD_FLAGS 18 + +/* ENGINE implementations should start the numbering of their own control + * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */ +#define ENGINE_CMD_BASE 200 + +/* NB: These 2 nCipher "chil" control commands are deprecated, and their + * functionality is now available through ENGINE-specific control commands + * (exposed through the above-mentioned 'CMD'-handling). Code using these 2 + * commands should be migrated to the more general command handling before these + * are removed. */ + /* Flags specific to the nCipher "chil" engine */ #define ENGINE_CTRL_CHIL_SET_FORKCHECK 100 /* Depending on the value of the (long)i argument, this sets or @@ -99,45 +234,55 @@ extern "C" { /* This prevents the initialisation function from providing mutex * callbacks to the nCipher library. */ -/* As we're missing a BIGNUM_METHOD, we need a couple of locally - * defined function types that engines can implement. */ - -#ifndef HEADER_ENGINE_INT_H -/* mod_exp operation, calculates; r = a ^ p mod m - * NB: ctx can be NULL, but if supplied, the implementation may use - * it if it wishes. */ -typedef int (*BN_MOD_EXP)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx); - -/* private key operation for RSA, provided seperately in case other - * RSA implementations wish to use it. */ -typedef int (*BN_MOD_EXP_CRT)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, - const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, - const BIGNUM *iqmp, BN_CTX *ctx); +/* If an ENGINE supports its own specific control commands and wishes the + * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its + * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries + * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that + * supports the stated commands (ie. the "cmd_num" entries as described by the + * array). NB: The array must be ordered in increasing order of cmd_num. + * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set + * to zero and/or cmd_name set to NULL. */ +typedef struct ENGINE_CMD_DEFN_st + { + unsigned int cmd_num; /* The command number */ + const char *cmd_name; /* The command name itself */ + const char *cmd_desc; /* A short description of the command */ + unsigned int cmd_flags; /* The input the command expects */ + } ENGINE_CMD_DEFN; /* Generic function pointer */ -typedef void (*ENGINE_GEN_FUNC_PTR)(); +typedef int (*ENGINE_GEN_FUNC_PTR)(); /* Generic function pointer taking no arguments */ -typedef void (*ENGINE_GEN_INT_FUNC_PTR)(void); +typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *); /* Specific control function pointer */ -typedef int (*ENGINE_CTRL_FUNC_PTR)(int cmd, long i, void *p, void (*f)()); - -/* The list of "engine" types is a static array of (const ENGINE*) - * pointers (not dynamic because static is fine for now and we otherwise - * have to hook an appropriate load/unload function in to initialise and - * cleanup). */ -typedef struct engine_st ENGINE; -#endif +typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)()); +/* Generic load_key function pointer */ +typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, + UI_METHOD *ui_method, void *callback_data); +/* These callback types are for an ENGINE's handler for cipher and digest logic. + * These handlers have these prototypes; + * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); + * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid); + * Looking at how to implement these handlers in the case of cipher support, if + * the framework wants the EVP_CIPHER for 'nid', it will call; + * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure) + * If the framework wants a list of supported 'nid's, it will call; + * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error) + */ +/* Returns to a pointer to the array of supported cipher 'nid's. If the second + * parameter is non-NULL it is set to the size of the returned array. */ +typedef int (*ENGINE_CIPHERS_PTR)(ENGINE *, const EVP_CIPHER **, const int **, int); +typedef int (*ENGINE_DIGESTS_PTR)(ENGINE *, const EVP_MD **, const int **, int); -/* STRUCTURE functions ... all of these functions deal with pointers to - * ENGINE structures where the pointers have a "structural reference". - * This means that their reference is to allow access to the structure - * but it does not imply that the structure is functional. To simply - * increment or decrement the structural reference count, use ENGINE_new - * and ENGINE_free. NB: This is not required when iterating using - * ENGINE_get_next as it will automatically decrement the structural - * reference count of the "current" ENGINE and increment the structural - * reference count of the ENGINE it returns (unless it is NULL). */ +/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE + * structures where the pointers have a "structural reference". This means that + * their reference is to allowed access to the structure but it does not imply + * that the structure is functional. To simply increment or decrement the + * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not + * required when iterating using ENGINE_get_next as it will automatically + * decrement the structural reference count of the "current" ENGINE and + * increment the structural reference count of the ENGINE it returns (unless it + * is NULL). */ /* Get the first/last "ENGINE" type available. */ ENGINE *ENGINE_get_first(void); @@ -151,67 +296,167 @@ int ENGINE_add(ENGINE *e); int ENGINE_remove(ENGINE *e); /* Retrieve an engine from the list by its unique "id" value. */ ENGINE *ENGINE_by_id(const char *id); +/* Add all the built-in engines. */ +void ENGINE_load_openssl(void); +void ENGINE_load_dynamic(void); +void ENGINE_load_cswift(void); +void ENGINE_load_chil(void); +void ENGINE_load_atalla(void); +void ENGINE_load_nuron(void); +void ENGINE_load_ubsec(void); +void ENGINE_load_aep(void); +void ENGINE_load_sureware(void); +void ENGINE_load_4758cca(void); +void ENGINE_load_openbsd_dev_crypto(void); +void ENGINE_load_builtin_engines(void); -/* These functions are useful for manufacturing new ENGINE - * structures. They don't address reference counting at all - - * one uses them to populate an ENGINE structure with personalised - * implementations of things prior to using it directly or adding - * it to the builtin ENGINE list in OpenSSL. These are also here - * so that the ENGINE structure doesn't have to be exposed and - * break binary compatibility! - * - * NB: I'm changing ENGINE_new to force the ENGINE structure to - * be allocated from within OpenSSL. See the comment for - * ENGINE_get_struct_size(). - */ -#if 0 -ENGINE *ENGINE_new(ENGINE *e); -#else +/* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation + * "registry" handling. */ +unsigned int ENGINE_get_table_flags(void); +void ENGINE_set_table_flags(unsigned int flags); + +/* Manage registration of ENGINEs per "table". For each type, there are 3 + * functions; + * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one) + * ENGINE_unregister_***(e) - unregister the implementation from 'e' + * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list + * Cleanup is automatically registered from each table when required, so + * ENGINE_cleanup() will reverse any "register" operations. */ + +int ENGINE_register_RSA(ENGINE *e); +void ENGINE_unregister_RSA(ENGINE *e); +void ENGINE_register_all_RSA(void); + +int ENGINE_register_DSA(ENGINE *e); +void ENGINE_unregister_DSA(ENGINE *e); +void ENGINE_register_all_DSA(void); + +int ENGINE_register_DH(ENGINE *e); +void ENGINE_unregister_DH(ENGINE *e); +void ENGINE_register_all_DH(void); + +int ENGINE_register_RAND(ENGINE *e); +void ENGINE_unregister_RAND(ENGINE *e); +void ENGINE_register_all_RAND(void); + +int ENGINE_register_ciphers(ENGINE *e); +void ENGINE_unregister_ciphers(ENGINE *e); +void ENGINE_register_all_ciphers(void); + +int ENGINE_register_digests(ENGINE *e); +void ENGINE_unregister_digests(ENGINE *e); +void ENGINE_register_all_digests(void); + +/* These functions register all support from the above categories. Note, use of + * these functions can result in static linkage of code your application may not + * need. If you only need a subset of functionality, consider using more + * selective initialisation. */ +int ENGINE_register_complete(ENGINE *e); +int ENGINE_register_all_complete(void); + +/* Send parametrised control commands to the engine. The possibilities to send + * down an integer, a pointer to data or a function pointer are provided. Any of + * the parameters may or may not be NULL, depending on the command number. In + * actuality, this function only requires a structural (rather than functional) + * reference to an engine, but many control commands may require the engine be + * functional. The caller should be aware of trying commands that require an + * operational ENGINE, and only use functional references in such situations. */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); + +/* This function tests if an ENGINE-specific command is usable as a "setting". + * Eg. in an application's config file that gets processed through + * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to + * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */ +int ENGINE_cmd_is_executable(ENGINE *e, int cmd); + +/* This function works like ENGINE_ctrl() with the exception of taking a + * command name instead of a command number, and can handle optional commands. + * See the comment on ENGINE_ctrl_cmd_string() for an explanation on how to + * use the cmd_name and cmd_optional. */ +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f)(), int cmd_optional); + +/* This function passes a command-name and argument to an ENGINE. The cmd_name + * is converted to a command number and the control command is called using + * 'arg' as an argument (unless the ENGINE doesn't support such a command, in + * which case no control command is called). The command is checked for input + * flags, and if necessary the argument will be converted to a numeric value. If + * cmd_optional is non-zero, then if the ENGINE doesn't support the given + * cmd_name the return value will be success anyway. This function is intended + * for applications to use so that users (or config files) can supply + * engine-specific config data to the ENGINE at run-time to control behaviour of + * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl() + * functions that return data, deal with binary data, or that are otherwise + * supposed to be used directly through ENGINE_ctrl() in application code. Any + * "return" data from an ENGINE_ctrl() operation in this function will be lost - + * the return value is interpreted as failure if the return value is zero, + * success otherwise, and this function returns a boolean value as a result. In + * other words, vendors of 'ENGINE'-enabled devices should write ENGINE + * implementations with parameterisations that work in this scheme, so that + * compliant ENGINE-based applications can work consistently with the same + * configuration for the same ENGINE-enabled devices, across applications. */ +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional); + +/* These functions are useful for manufacturing new ENGINE structures. They + * don't address reference counting at all - one uses them to populate an ENGINE + * structure with personalised implementations of things prior to using it + * directly or adding it to the builtin ENGINE list in OpenSSL. These are also + * here so that the ENGINE structure doesn't have to be exposed and break binary + * compatibility! */ ENGINE *ENGINE_new(void); -#endif int ENGINE_free(ENGINE *e); int ENGINE_set_id(ENGINE *e, const char *id); int ENGINE_set_name(ENGINE *e, const char *name); -int ENGINE_set_RSA(ENGINE *e, RSA_METHOD *rsa_meth); -int ENGINE_set_DSA(ENGINE *e, DSA_METHOD *dsa_meth); -int ENGINE_set_DH(ENGINE *e, DH_METHOD *dh_meth); -int ENGINE_set_RAND(ENGINE *e, RAND_METHOD *rand_meth); -int ENGINE_set_BN_mod_exp(ENGINE *e, BN_MOD_EXP bn_mod_exp); -int ENGINE_set_BN_mod_exp_crt(ENGINE *e, BN_MOD_EXP_CRT bn_mod_exp_crt); +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth); +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth); +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f); int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); +int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f); +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f); +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f); +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f); +int ENGINE_set_flags(ENGINE *e, int flags); +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); +/* These functions (and the "get" function lower down) allow control over any + * per-structure ENGINE data. */ +int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); -/* These return values from within the ENGINE structure. These can - * be useful with functional references as well as structural - * references - it depends which you obtained. Using the result - * for functional purposes if you only obtained a structural - * reference may be problematic! */ -const char *ENGINE_get_id(ENGINE *e); -const char *ENGINE_get_name(ENGINE *e); -RSA_METHOD *ENGINE_get_RSA(ENGINE *e); -DSA_METHOD *ENGINE_get_DSA(ENGINE *e); -DH_METHOD *ENGINE_get_DH(ENGINE *e); -RAND_METHOD *ENGINE_get_RAND(ENGINE *e); -BN_MOD_EXP ENGINE_get_BN_mod_exp(ENGINE *e); -BN_MOD_EXP_CRT ENGINE_get_BN_mod_exp_crt(ENGINE *e); -ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(ENGINE *e); -ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(ENGINE *e); -ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(ENGINE *e); - -/* ENGINE_new is normally passed a NULL in the first parameter because - * the calling code doesn't have access to the definition of the ENGINE - * structure (for good reason). However, if the caller wishes to use - * its own memory allocation or use a static array, the following call - * should be used to check the amount of memory the ENGINE structure - * will occupy. This will make the code more future-proof. - * - * NB: I'm "#if 0"-ing this out because it's better to force the use of - * internally allocated memory. See similar change in ENGINE_new(). - */ -#if 0 -int ENGINE_get_struct_size(void); -#endif +/* This function cleans up anything that needs it. Eg. the ENGINE_add() function + * automatically ensures the list cleanup function is registered to be called + * from ENGINE_cleanup(). Similarly, all ENGINE_register_*** functions ensure + * ENGINE_cleanup() will clean up after them. */ +void ENGINE_cleanup(void); + +/* These return values from within the ENGINE structure. These can be useful + * with functional references as well as structural references - it depends + * which you obtained. Using the result for functional purposes if you only + * obtained a structural reference may be problematic! */ +const char *ENGINE_get_id(const ENGINE *e); +const char *ENGINE_get_name(const ENGINE *e); +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e); +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e); +const DH_METHOD *ENGINE_get_DH(const ENGINE *e); +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e); +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e); +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid); +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid); +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); +int ENGINE_get_flags(const ENGINE *e); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); /* FUNCTIONAL functions. These functions deal with ENGINE structures * that have (or will) be initialised for use. Broadly speaking, the @@ -233,20 +478,14 @@ int ENGINE_init(ENGINE *e); * a corresponding call to ENGINE_free as it also releases a structural * reference. */ int ENGINE_finish(ENGINE *e); -/* Send control parametrised commands to the engine. The possibilities - * to send down an integer, a pointer to data or a function pointer are - * provided. Any of the parameters may or may not be NULL, depending - * on the command number */ -/* WARNING: This is currently experimental and may change radically! */ -int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); /* The following functions handle keys that are stored in some secondary * location, handled by the engine. The storage may be on a card or * whatever. */ EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, - const char *passphrase); + UI_METHOD *ui_method, void *callback_data); EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, - const char *passphrase); + UI_METHOD *ui_method, void *callback_data); /* This returns a pointer for the current ENGINE structure that * is (by default) performing any RSA operations. The value returned @@ -257,117 +496,192 @@ ENGINE *ENGINE_get_default_RSA(void); ENGINE *ENGINE_get_default_DSA(void); ENGINE *ENGINE_get_default_DH(void); ENGINE *ENGINE_get_default_RAND(void); -ENGINE *ENGINE_get_default_BN_mod_exp(void); -ENGINE *ENGINE_get_default_BN_mod_exp_crt(void); +/* These functions can be used to get a functional reference to perform + * ciphering or digesting corresponding to "nid". */ +ENGINE *ENGINE_get_cipher_engine(int nid); +ENGINE *ENGINE_get_digest_engine(int nid); /* This sets a new default ENGINE structure for performing RSA * operations. If the result is non-zero (success) then the ENGINE * structure will have had its reference count up'd so the caller * should still free their own reference 'e'. */ int ENGINE_set_default_RSA(ENGINE *e); +int ENGINE_set_default_string(ENGINE *e, const char *list); /* Same for the other "methods" */ int ENGINE_set_default_DSA(ENGINE *e); int ENGINE_set_default_DH(ENGINE *e); int ENGINE_set_default_RAND(ENGINE *e); -int ENGINE_set_default_BN_mod_exp(ENGINE *e); -int ENGINE_set_default_BN_mod_exp_crt(ENGINE *e); +int ENGINE_set_default_ciphers(ENGINE *e); +int ENGINE_set_default_digests(ENGINE *e); /* The combination "set" - the flags are bitwise "OR"d from the - * ENGINE_METHOD_*** defines above. */ + * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()" + * function, this function can result in unnecessary static linkage. If your + * application requires only specific functionality, consider using more + * selective functions. */ int ENGINE_set_default(ENGINE *e, unsigned int flags); -/* Obligatory error function. */ -void ERR_load_ENGINE_strings(void); +void ENGINE_add_conf_module(void); -/* - * Error codes for all engine functions. NB: We use "generic" - * function names instead of per-implementation ones because this - * levels the playing field for externally implemented bootstrapped - * support code. As the filename and line number is included, it's - * more important to indicate the type of function, so that - * bootstrapped code (that can't easily add its own errors in) can - * use the same error codes too. - */ +/* Deprecated functions ... */ +/* int ENGINE_clear_defaults(void); */ + +/**************************/ +/* DYNAMIC ENGINE SUPPORT */ +/**************************/ + +/* Binary/behaviour compatibility levels */ +#define OSSL_DYNAMIC_VERSION (unsigned long)0x00010100 +/* Binary versions older than this are too old for us (whether we're a loader or + * a loadee) */ +#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00010100 + +/* When compiling an ENGINE entirely as an external shared library, loadable by + * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure + * type provides the calling application's (or library's) error functionality + * and memory management function pointers to the loaded library. These should + * be used/set in the loaded library code so that the loading application's + * 'state' will be used/changed in all operations. */ +typedef void *(*dyn_MEM_malloc_cb)(size_t); +typedef void *(*dyn_MEM_realloc_cb)(void *, size_t); +typedef void (*dyn_MEM_free_cb)(void *); +typedef struct st_dynamic_MEM_fns { + dyn_MEM_malloc_cb malloc_cb; + dyn_MEM_realloc_cb realloc_cb; + dyn_MEM_free_cb free_cb; + } dynamic_MEM_fns; +/* FIXME: Perhaps the memory and locking code (crypto.h) should declare and use + * these types so we (and any other dependant code) can simplify a bit?? */ +typedef void (*dyn_lock_locking_cb)(int,int,const char *,int); +typedef int (*dyn_lock_add_lock_cb)(int*,int,int,const char *,int); +typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb)( + const char *,int); +typedef void (*dyn_dynlock_lock_cb)(int,struct CRYPTO_dynlock_value *, + const char *,int); +typedef void (*dyn_dynlock_destroy_cb)(struct CRYPTO_dynlock_value *, + const char *,int); +typedef struct st_dynamic_LOCK_fns { + dyn_lock_locking_cb lock_locking_cb; + dyn_lock_add_lock_cb lock_add_lock_cb; + dyn_dynlock_create_cb dynlock_create_cb; + dyn_dynlock_lock_cb dynlock_lock_cb; + dyn_dynlock_destroy_cb dynlock_destroy_cb; + } dynamic_LOCK_fns; +/* The top-level structure */ +typedef struct st_dynamic_fns { + const ERR_FNS *err_fns; + const CRYPTO_EX_DATA_IMPL *ex_data_fns; + dynamic_MEM_fns mem_fns; + dynamic_LOCK_fns lock_fns; + } dynamic_fns; + +/* The version checking function should be of this prototype. NB: The + * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code. + * If this function returns zero, it indicates a (potential) version + * incompatibility and the loaded library doesn't believe it can proceed. + * Otherwise, the returned value is the (latest) version supported by the + * loading library. The loader may still decide that the loaded code's version + * is unsatisfactory and could veto the load. The function is expected to + * be implemented with the symbol name "v_check", and a default implementation + * can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */ +typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version); +#define IMPLEMENT_DYNAMIC_CHECK_FN() \ + unsigned long v_check(unsigned long v) { \ + if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \ + return 0; } + +/* This function is passed the ENGINE structure to initialise with its own + * function and command settings. It should not adjust the structural or + * functional reference counts. If this function returns zero, (a) the load will + * be aborted, (b) the previous ENGINE state will be memcpy'd back onto the + * structure, and (c) the shared library will be unloaded. So implementations + * should do their own internal cleanup in failure circumstances otherwise they + * could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that + * the loader is looking for. If this is NULL, the shared library can choose to + * return failure or to initialise a 'default' ENGINE. If non-NULL, the shared + * library must initialise only an ENGINE matching the passed 'id'. The function + * is expected to be implemented with the symbol name "bind_engine". A standard + * implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where + * the parameter 'fn' is a callback function that populates the ENGINE structure + * and returns an int value (zero for failure). 'fn' should have prototype; + * [static] int fn(ENGINE *e, const char *id); */ +typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id, + const dynamic_fns *fns); +#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \ + if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \ + fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \ + return 0; \ + CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \ + CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \ + CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \ + CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \ + CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \ + if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \ + return 0; \ + if(!ERR_set_implementation(fns->err_fns)) return 0; \ + if(!fn(e,id)) return 0; \ + return 1; } /* 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. */ +void ERR_load_ENGINE_strings(void); /* Error codes for the ENGINE functions. */ /* Function codes. */ -#define ENGINE_F_ATALLA_FINISH 135 -#define ENGINE_F_ATALLA_INIT 136 -#define ENGINE_F_ATALLA_MOD_EXP 137 -#define ENGINE_F_ATALLA_RSA_MOD_EXP 138 -#define ENGINE_F_CSWIFT_DSA_SIGN 133 -#define ENGINE_F_CSWIFT_DSA_VERIFY 134 -#define ENGINE_F_CSWIFT_FINISH 100 -#define ENGINE_F_CSWIFT_INIT 101 -#define ENGINE_F_CSWIFT_MOD_EXP 102 -#define ENGINE_F_CSWIFT_MOD_EXP_CRT 103 -#define ENGINE_F_CSWIFT_RSA_MOD_EXP 104 +#define ENGINE_F_DYNAMIC_CTRL 180 +#define ENGINE_F_DYNAMIC_GET_DATA_CTX 181 +#define ENGINE_F_DYNAMIC_LOAD 182 #define ENGINE_F_ENGINE_ADD 105 #define ENGINE_F_ENGINE_BY_ID 106 +#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170 #define ENGINE_F_ENGINE_CTRL 142 +#define ENGINE_F_ENGINE_CTRL_CMD 178 +#define ENGINE_F_ENGINE_CTRL_CMD_STRING 171 #define ENGINE_F_ENGINE_FINISH 107 #define ENGINE_F_ENGINE_FREE 108 -#define ENGINE_F_ENGINE_GET_BN_MOD_EXP 109 -#define ENGINE_F_ENGINE_GET_BN_MOD_EXP_CRT 110 -#define ENGINE_F_ENGINE_GET_CTRL_FUNCTION 144 -#define ENGINE_F_ENGINE_GET_DH 111 -#define ENGINE_F_ENGINE_GET_DSA 112 -#define ENGINE_F_ENGINE_GET_FINISH_FUNCTION 145 -#define ENGINE_F_ENGINE_GET_ID 113 -#define ENGINE_F_ENGINE_GET_INIT_FUNCTION 146 -#define ENGINE_F_ENGINE_GET_NAME 114 +#define ENGINE_F_ENGINE_GET_CIPHER 185 +#define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177 +#define ENGINE_F_ENGINE_GET_DIGEST 186 #define ENGINE_F_ENGINE_GET_NEXT 115 #define ENGINE_F_ENGINE_GET_PREV 116 -#define ENGINE_F_ENGINE_GET_RAND 117 -#define ENGINE_F_ENGINE_GET_RSA 118 #define ENGINE_F_ENGINE_INIT 119 #define ENGINE_F_ENGINE_LIST_ADD 120 #define ENGINE_F_ENGINE_LIST_REMOVE 121 #define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 #define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +#define ENGINE_F_ENGINE_MODULE_INIT 187 #define ENGINE_F_ENGINE_NEW 122 #define ENGINE_F_ENGINE_REMOVE 123 -#define ENGINE_F_ENGINE_SET_BN_MOD_EXP 124 -#define ENGINE_F_ENGINE_SET_BN_MOD_EXP_CRT 125 -#define ENGINE_F_ENGINE_SET_CTRL_FUNCTION 147 +#define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189 #define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126 -#define ENGINE_F_ENGINE_SET_DH 127 -#define ENGINE_F_ENGINE_SET_DSA 128 -#define ENGINE_F_ENGINE_SET_FINISH_FUNCTION 148 #define ENGINE_F_ENGINE_SET_ID 129 -#define ENGINE_F_ENGINE_SET_INIT_FUNCTION 149 #define ENGINE_F_ENGINE_SET_NAME 130 -#define ENGINE_F_ENGINE_SET_RAND 131 -#define ENGINE_F_ENGINE_SET_RSA 132 +#define ENGINE_F_ENGINE_TABLE_REGISTER 184 #define ENGINE_F_ENGINE_UNLOAD_KEY 152 -#define ENGINE_F_HWCRHK_CTRL 143 -#define ENGINE_F_HWCRHK_FINISH 135 -#define ENGINE_F_HWCRHK_GET_PASS 155 -#define ENGINE_F_HWCRHK_INIT 136 -#define ENGINE_F_HWCRHK_LOAD_PRIVKEY 153 -#define ENGINE_F_HWCRHK_LOAD_PUBKEY 154 -#define ENGINE_F_HWCRHK_MOD_EXP 137 -#define ENGINE_F_HWCRHK_MOD_EXP_CRT 138 -#define ENGINE_F_HWCRHK_RAND_BYTES 139 -#define ENGINE_F_HWCRHK_RSA_MOD_EXP 140 +#define ENGINE_F_INT_CTRL_HELPER 172 +#define ENGINE_F_INT_ENGINE_CONFIGURE 188 #define ENGINE_F_LOG_MESSAGE 141 +#define ENGINE_F_SET_DATA_CTX 183 /* Reason codes. */ #define ENGINE_R_ALREADY_LOADED 100 -#define ENGINE_R_BIO_WAS_FREED 121 -#define ENGINE_R_BN_CTX_FULL 101 -#define ENGINE_R_BN_EXPAND_FAIL 102 -#define ENGINE_R_CHIL_ERROR 123 +#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133 +#define ENGINE_R_CMD_NOT_EXECUTABLE 134 +#define ENGINE_R_COMMAND_TAKES_INPUT 135 +#define ENGINE_R_COMMAND_TAKES_NO_INPUT 136 #define ENGINE_R_CONFLICTING_ENGINE_ID 103 #define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +#define ENGINE_R_DH_NOT_IMPLEMENTED 139 +#define ENGINE_R_DSA_NOT_IMPLEMENTED 140 #define ENGINE_R_DSO_FAILURE 104 +#define ENGINE_R_DSO_NOT_FOUND 132 +#define ENGINE_R_ENGINES_SECTION_ERROR 148 #define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +#define ENGINE_R_ENGINE_SECTION_ERROR 149 #define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 #define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 #define ENGINE_R_FINISH_FAILED 106 @@ -375,24 +689,26 @@ void ERR_load_ENGINE_strings(void); #define ENGINE_R_ID_OR_NAME_MISSING 108 #define ENGINE_R_INIT_FAILED 109 #define ENGINE_R_INTERNAL_LIST_ERROR 110 -#define ENGINE_R_MISSING_KEY_COMPONENTS 111 +#define ENGINE_R_INVALID_ARGUMENT 143 +#define ENGINE_R_INVALID_CMD_NAME 137 +#define ENGINE_R_INVALID_CMD_NUMBER 138 +#define ENGINE_R_INVALID_INIT_VALUE 151 +#define ENGINE_R_INVALID_STRING 150 #define ENGINE_R_NOT_INITIALISED 117 #define ENGINE_R_NOT_LOADED 112 -#define ENGINE_R_NO_CALLBACK 127 #define ENGINE_R_NO_CONTROL_FUNCTION 120 -#define ENGINE_R_NO_KEY 124 +#define ENGINE_R_NO_INDEX 144 #define ENGINE_R_NO_LOAD_FUNCTION 125 #define ENGINE_R_NO_REFERENCE 130 #define ENGINE_R_NO_SUCH_ENGINE 116 #define ENGINE_R_NO_UNLOAD_FUNCTION 126 #define ENGINE_R_PROVIDE_PARAMETERS 113 -#define ENGINE_R_REQUEST_FAILED 114 -#define ENGINE_R_REQUEST_FALLBACK 118 -#define ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL 122 -#define ENGINE_R_UNIT_FAILURE 115 +#define ENGINE_R_RSA_NOT_IMPLEMENTED 141 +#define ENGINE_R_UNIMPLEMENTED_CIPHER 146 +#define ENGINE_R_UNIMPLEMENTED_DIGEST 147 +#define ENGINE_R_VERSION_INCOMPATIBILITY 145 #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/err/err.c b/src/lib/libcrypto/err/err.c index 5aef6a1259..04773d65a6 100644 --- a/src/lib/libcrypto/err/err.c +++ b/src/lib/libcrypto/err/err.c @@ -55,37 +55,74 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "lhash.h" -#include "crypto.h" +#include +#include +#include +#include #include "cryptlib.h" -#include "buffer.h" -#include "err.h" -#include "crypto.h" +#include +#include +#include +static void err_load_strings(int lib, ERR_STRING_DATA *str); -static LHASH *error_hash=NULL; -static LHASH *thread_hash=NULL; - -#ifndef NOPROTO -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,char **file,int *line, - char **data,int *flags); static void ERR_STATE_free(ERR_STATE *s); -#else -static unsigned long err_hash(); -static int err_cmp(); -static unsigned long pid_hash(); -static int pid_cmp(); -static void ERR_STATE_free(); -ERR_STATE *s; -#endif - -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA ERR_str_libraries[]= { {ERR_PACK(ERR_LIB_NONE,0,0) ,"unknown library"}, @@ -95,18 +132,23 @@ static ERR_STRING_DATA ERR_str_libraries[]= {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_DSA,0,0) ,"dsa routines"}, {ERR_PACK(ERR_LIB_X509,0,0) ,"x509 certificate routines"}, -{ERR_PACK(ERR_LIB_CONF,0,0) ,"configuation file routines"}, -{ERR_PACK(ERR_LIB_METH,0,0) ,"X509 lookup 'method' routines"}, +{ERR_PACK(ERR_LIB_ASN1,0,0) ,"asn1 encoding routines"}, +{ERR_PACK(ERR_LIB_CONF,0,0) ,"configuration file routines"}, +{ERR_PACK(ERR_LIB_CRYPTO,0,0) ,"common libcrypto routines"}, +{ERR_PACK(ERR_LIB_EC,0,0) ,"elliptic curve 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"}, +{ERR_PACK(ERR_LIB_DSO,0,0) ,"DSO support routines"}, +{ERR_PACK(ERR_LIB_ENGINE,0,0) ,"engine routines"}, +{ERR_PACK(ERR_LIB_OCSP,0,0) ,"OCSP routines"}, {0,NULL}, }; @@ -120,132 +162,480 @@ static ERR_STRING_DATA ERR_str_functs[]= {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 +#ifdef OPENSSL_SYS_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_DSA_LIB ,"DSA 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_CRYPTO_LIB ,"CRYPTO lib"}, +{ERR_R_EC_LIB ,"EC 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_MALLOC_FAILURE ,"Malloc failure"}, -{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED ,"called a fuction you should not call"}, +{ERR_R_X509V3_LIB ,"X509V3 lib"}, +{ERR_R_PKCS12_LIB ,"PKCS12 lib"}, +{ERR_R_RAND_LIB ,"RAND lib"}, +{ERR_R_DSO_LIB ,"DSO lib"}, +{ERR_R_ENGINE_LIB ,"ENGINE lib"}, +{ERR_R_OCSP_LIB ,"OCSP lib"}, + +{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"}, + +{ERR_R_FATAL ,"fatal"}, +{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_INTERNAL_ERROR ,"internal error"}, + {0,NULL}, }; + + +/* Define the predeclared (but externally opaque) "ERR_FNS" type */ +struct st_ERR_FNS + { + /* Works on the "error_hash" string table */ + LHASH *(*cb_err_get)(int create); + void (*cb_err_del)(void); + ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *); + ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *); + ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *); + /* Works on the "thread_hash" error-state table */ + LHASH *(*cb_thread_get)(int create); + ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *); + ERR_STATE *(*cb_thread_set_item)(ERR_STATE *); + void (*cb_thread_del_item)(const ERR_STATE *); + /* Returns the next available error "library" numbers */ + int (*cb_get_next_lib)(void); + }; + +/* Predeclarations of the "err_defaults" functions */ +static LHASH *int_err_get(int create); +static void int_err_del(void); +static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); +static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *); +static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *); +static LHASH *int_thread_get(int create); +static ERR_STATE *int_thread_get_item(const ERR_STATE *); +static ERR_STATE *int_thread_set_item(ERR_STATE *); +static void int_thread_del_item(const ERR_STATE *); +static int int_err_get_next_lib(void); +/* The static ERR_FNS table using these defaults functions */ +static const ERR_FNS err_defaults = + { + int_err_get, + int_err_del, + int_err_get_item, + int_err_set_item, + int_err_del_item, + int_thread_get, + int_thread_get_item, + int_thread_set_item, + int_thread_del_item, + int_err_get_next_lib + }; + +/* The replacable table of ERR_FNS functions we use at run-time */ +static const ERR_FNS *err_fns = NULL; + +/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */ +#define ERRFN(a) err_fns->cb_##a + +/* The internal state used by "err_defaults" - as such, the setting, reading, + * creating, and deleting of this data should only be permitted via the + * "err_defaults" functions. This way, a linked module can completely defer all + * ERR state operation (together with requisite locking) to the implementations + * and state in the loading application. */ +static LHASH *int_error_hash = NULL; +static LHASH *int_thread_hash = NULL; +static int int_err_library_number= ERR_LIB_USER; + +/* Internal function that checks whether "err_fns" is set and if not, sets it to + * the defaults. */ +static void err_fns_check(void) + { + if (err_fns) return; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + if (!err_fns) + err_fns = &err_defaults; + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + } + +/* API functions to get or set the underlying ERR functions. */ + +const ERR_FNS *ERR_get_implementation(void) + { + err_fns_check(); + return err_fns; + } + +int ERR_set_implementation(const ERR_FNS *fns) + { + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + /* It's too late if 'err_fns' is non-NULL. BTW: not much point setting + * an error is there?! */ + if (!err_fns) + { + err_fns = fns; + ret = 1; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + return ret; + } + +/* These are the callbacks provided to "lh_new()" when creating the LHASH tables + * internal to the "err_defaults" implementation. */ + +/* static unsigned long err_hash(ERR_STRING_DATA *a); */ +static unsigned long err_hash(const void *a_void); +/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */ +static int err_cmp(const void *a_void, const void *b_void); +/* static unsigned long pid_hash(ERR_STATE *pid); */ +static unsigned long pid_hash(const void *pid_void); +/* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */ +static int pid_cmp(const void *a_void,const void *pid_void); +static unsigned long get_error_values(int inc,int top,const char **file,int *line, + const char **data,int *flags); + +/* The internal functions used in the "err_defaults" implementation */ + +static LHASH *int_err_get(int create) + { + LHASH *ret = NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + if (!int_error_hash && create) + { + CRYPTO_push_info("int_err_get (err.c)"); + int_error_hash = lh_new(err_hash, err_cmp); + CRYPTO_pop_info(); + } + if (int_error_hash) + ret = int_error_hash; + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + return ret; + } + +static void int_err_del(void) + { + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + if (int_error_hash) + { + lh_free(int_error_hash); + int_error_hash = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + } + +static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) + { + ERR_STRING_DATA *p; + LHASH *hash; + + err_fns_check(); + hash = ERRFN(err_get)(0); + if (!hash) + return NULL; + + CRYPTO_r_lock(CRYPTO_LOCK_ERR); + p = (ERR_STRING_DATA *)lh_retrieve(hash, d); + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + + return p; + } + +static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d) + { + ERR_STRING_DATA *p; + LHASH *hash; + + err_fns_check(); + hash = ERRFN(err_get)(1); + if (!hash) + return NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + p = (ERR_STRING_DATA *)lh_insert(hash, d); + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + return p; + } + +static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d) + { + ERR_STRING_DATA *p; + LHASH *hash; + + err_fns_check(); + hash = ERRFN(err_get)(0); + if (!hash) + return NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + p = (ERR_STRING_DATA *)lh_delete(hash, d); + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + return p; + } + +static LHASH *int_thread_get(int create) + { + LHASH *ret = NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + if (!int_thread_hash && create) + { + CRYPTO_push_info("int_thread_get (err.c)"); + int_thread_hash = lh_new(pid_hash, pid_cmp); + CRYPTO_pop_info(); + } + if (int_thread_hash) + ret = int_thread_hash; + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + return ret; + } + +static ERR_STATE *int_thread_get_item(const ERR_STATE *d) + { + ERR_STATE *p; + LHASH *hash; + + err_fns_check(); + hash = ERRFN(thread_get)(0); + if (!hash) + return NULL; + + CRYPTO_r_lock(CRYPTO_LOCK_ERR); + p = (ERR_STATE *)lh_retrieve(hash, d); + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + + return p; + } + +static ERR_STATE *int_thread_set_item(ERR_STATE *d) + { + ERR_STATE *p; + LHASH *hash; + + err_fns_check(); + hash = ERRFN(thread_get)(1); + if (!hash) + return NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + p = (ERR_STATE *)lh_insert(hash, d); + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + return p; + } + +static void int_thread_del_item(const ERR_STATE *d) + { + ERR_STATE *p; + LHASH *hash; + + err_fns_check(); + hash = ERRFN(thread_get)(0); + if (!hash) + return; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + p = (ERR_STATE *)lh_delete(hash, d); + /* make sure we don't leak memory */ + if (int_thread_hash && (lh_num_items(int_thread_hash) == 0)) + { + lh_free(int_thread_hash); + int_thread_hash = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + if (p) + ERR_STATE_free(p); + } + +static int int_err_get_next_lib(void) + { + int ret; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + ret = int_err_library_number++; + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + + return ret; + } + + +#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() + { + /* OPENSSL_malloc cannot be used here, use static storage instead */ + static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON]; + int i; + static int init = 1; + + if (!init) return; + + CRYPTO_w_lock(CRYPTO_LOCK_ERR); + + 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. */ + + init = 0; + + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + } #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]); \ + OPENSSL_free((p)->err_data[i]); \ (p)->err_data[i]=NULL; \ } \ (p)->err_data_flags[i]=0; -static void ERR_STATE_free(s) -ERR_STATE *s; +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,(char *)str); + ERRFN(err_set_item)(str); str++; } - CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH); } -void ERR_free_strings() +void ERR_load_strings(int lib, ERR_STRING_DATA *str) { - CRYPTO_w_lock(CRYPTO_LOCK_ERR); + ERR_load_ERR_strings(); + err_load_strings(lib, str); + } - if (error_hash != NULL) +void ERR_unload_strings(int lib, ERR_STRING_DATA *str) + { + while (str->error) { - lh_free(error_hash); - error_hash=NULL; + str->error|=ERR_PACK(lib,0,0); + ERRFN(err_del_item)(str); + str++; } + } - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); +void ERR_free_strings(void) + { + err_fns_check(); + ERRFN(err_del)(); } /********************************************************/ -void ERR_put_error(lib,func,reason,file,line) -int lib,func,reason; -char *file; -int line; +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; @@ -257,62 +647,60 @@ int line; err_clear_data(es,es->top); } -void ERR_clear_error() +void ERR_clear_error(void) { + int i; ERR_STATE *es; es=ERR_get_state(); -#if 0 - /* hmm... is this needed */ for (i=0; ierr_buffer[i]=0; + err_clear_data(es,i); 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() - { return(get_error_values(1,NULL,NULL,NULL,NULL)); } +unsigned long ERR_get_error(void) + { return(get_error_values(1,0,NULL,NULL,NULL,NULL)); } + +unsigned long ERR_get_error_line(const char **file, + int *line) + { return(get_error_values(1,0,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,0,file,line,data,flags)); } + -unsigned long ERR_get_error_line(file,line) -char **file; -int *line; - { return(get_error_values(1,file,line,NULL,NULL)); } +unsigned long ERR_peek_error(void) + { return(get_error_values(0,0,NULL,NULL,NULL,NULL)); } -unsigned long ERR_get_error_line_data(file,line,data,flags) -char **file; -int *line; -char **data; -int *flags; - { return(get_error_values(1,file,line,data,flags)); } +unsigned long ERR_peek_error_line(const char **file, int *line) + { return(get_error_values(0,0,file,line,NULL,NULL)); } -unsigned long ERR_peek_error() - { return(get_error_values(0,NULL,NULL,NULL,NULL)); } +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) + { return(get_error_values(0,0,file,line,data,flags)); } -unsigned long ERR_peek_error_line(file,line) -char **file; -int *line; - { return(get_error_values(0,file,line,NULL,NULL)); } -unsigned long ERR_peek_error_line_data(file,line,data,flags) -char **file; -int *line; -char **data; -int *flags; - { return(get_error_values(0,file,line,data,flags)); } +unsigned long ERR_peek_last_error(void) + { return(get_error_values(0,1,NULL,NULL,NULL,NULL)); } -static unsigned long get_error_values(inc,file,line,data,flags) -int inc; -char **file; -int *line; -char **data; -int *flags; +unsigned long ERR_peek_last_error_line(const char **file, int *line) + { return(get_error_values(0,1,file,line,NULL,NULL)); } + +unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags) + { return(get_error_values(0,1,file,line,data,flags)); } + + +static unsigned long get_error_values(int inc, int top, const char **file, int *line, + const char **data, int *flags) { int i=0; ERR_STATE *es; @@ -320,8 +708,21 @@ int *flags; es=ERR_get_state(); - if (es->bottom == es->top) return(0); - i=(es->bottom+1)%ERR_NUM_ERRORS; + if (inc && top) + { + if (file) *file = ""; + if (line) *line = 0; + if (data) *data = ""; + if (flags) *flags = 0; + + return ERR_R_INTERNAL_ERROR; + } + + if (es->bottom == es->top) return 0; + if (top) + i=es->top; /* last error */ + else + i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */ ret=es->err_buffer[i]; if (inc) @@ -344,7 +745,14 @@ int *flags; } } - if (data != NULL) + if (data == NULL) + { + if (inc) + { + err_clear_data(es, i); + } + } + else { if (es->err_data[i] == NULL) { @@ -357,18 +765,14 @@ int *flags; if (flags != NULL) *flags=es->err_data_flags[i]; } } - return(ret); + return ret; } -/* BAD for multi-threaded, uses a local buffer if ret == NULL */ -char *ERR_error_string(e,ret) -unsigned long e; -char *ret; +void ERR_error_string_n(unsigned long e, char *buf, size_t len) { - static char buf[256]; - char *ls,*fs,*rs; + char lsbuf[64], fsbuf[64], rsbuf[64]; + const char *ls,*fs,*rs; unsigned long l,f,r; - int i; l=ERR_GET_LIB(e); f=ERR_GET_FUNC(e); @@ -378,185 +782,168 @@ char *ret; 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 (ls == NULL) + BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l); if (fs == NULL) - sprintf(&(ret[i]),":func(%lu) ",f); - else sprintf(&(ret[i]),":%s",fs); - i=strlen(ret); + BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f); if (rs == NULL) - sprintf(&(ret[i]),":reason(%lu)",r); - else sprintf(&(ret[i]),":%s",rs); + BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r); + + BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf, + fs?fs:fsbuf, rs?rs:rsbuf); + if (strlen(buf) == len-1) + { + /* output may be truncated; make sure we always have 5 + * colon-separated fields, i.e. 4 colons ... */ +#define NUM_COLONS 4 + if (len > NUM_COLONS) /* ... if possible */ + { + int i; + char *s = buf; + + for (i = 0; i < NUM_COLONS; i++) + { + char *colon = strchr(s, ':'); + if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i) + { + /* set colon no. i at last possible position + * (buf[len-1] is the terminating 0)*/ + colon = &buf[len-1] - NUM_COLONS + i; + *colon = ':'; + } + s = colon + 1; + } + } + } + } + +/* BAD for multi-threading: uses a local buffer if ret == NULL */ +/* ERR_error_string_n should be used instead for ret != NULL + * as ERR_error_string cannot know how large the buffer is */ +char *ERR_error_string(unsigned long e, char *ret) + { + static char buf[256]; + + if (ret == NULL) ret=buf; + ERR_error_string_n(e, ret, 256); - return(ret); + return ret; } -LHASH *ERR_get_string_table() +LHASH *ERR_get_string_table(void) { - return(error_hash); + err_fns_check(); + return ERRFN(err_get)(0); } -LHASH *ERR_get_err_state_table() +LHASH *ERR_get_err_state_table(void) { - return(thread_hash); + err_fns_check(); + return ERRFN(thread_get)(0); } -char *ERR_lib_error_string(e) -unsigned long e; +const char *ERR_lib_error_string(unsigned long e) { - ERR_STRING_DATA d,*p=NULL; + ERR_STRING_DATA d,*p; unsigned long l; + err_fns_check(); 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,(char *)&d); - } - - CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); - + d.error=ERR_PACK(l,0,0); + p=ERRFN(err_get_item)(&d); return((p == NULL)?NULL:p->string); } -char *ERR_func_error_string(e) -unsigned long e; +const char *ERR_func_error_string(unsigned long e) { - ERR_STRING_DATA d,*p=NULL; + ERR_STRING_DATA d,*p; unsigned long l,f; + err_fns_check(); 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,(char *)&d); - } - - CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); - + d.error=ERR_PACK(l,f,0); + p=ERRFN(err_get_item)(&d); return((p == NULL)?NULL:p->string); } -char *ERR_reason_error_string(e) -unsigned long e; +const char *ERR_reason_error_string(unsigned long e) { ERR_STRING_DATA d,*p=NULL; unsigned long l,r; + err_fns_check(); 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=ERRFN(err_get_item)(&d); + if (!p) { - d.error=ERR_PACK(l,0,r); - p=(ERR_STRING_DATA *)lh_retrieve(error_hash,(char *)&d); - if (p == NULL) - { - d.error=ERR_PACK(0,0,r); - p=(ERR_STRING_DATA *)lh_retrieve(error_hash, - (char *)&d); - } + d.error=ERR_PACK(0,0,r); + p=ERRFN(err_get_item)(&d); } - - CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); - return((p == NULL)?NULL:p->string); } -static unsigned long err_hash(a) -ERR_STRING_DATA *a; +/* static unsigned long err_hash(ERR_STRING_DATA *a) */ +static unsigned long err_hash(const void *a_void) { unsigned long ret,l; - l=a->error; + l=((ERR_STRING_DATA *)a_void)->error; ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l); return(ret^ret%19*13); } -static int err_cmp(a,b) -ERR_STRING_DATA *a,*b; +/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */ +static int err_cmp(const void *a_void, const void *b_void) { - return((int)(a->error-b->error)); + return((int)(((ERR_STRING_DATA *)a_void)->error - + ((ERR_STRING_DATA *)b_void)->error)); } -static unsigned long pid_hash(a) -ERR_STATE *a; +/* static unsigned long pid_hash(ERR_STATE *a) */ +static unsigned long pid_hash(const void *a_void) { - return(a->pid*13); + return(((ERR_STATE *)a_void)->pid*13); } -static int pid_cmp(a,b) -ERR_STATE *a,*b; +/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */ +static int pid_cmp(const void *a_void, const void *b_void) { - return((int)((long)a->pid - (long)b->pid)); + return((int)((long)((ERR_STATE *)a_void)->pid - + (long)((ERR_STATE *)b_void)->pid)); } -void ERR_remove_state(pid) -unsigned long pid; +void ERR_remove_state(unsigned long pid) { - ERR_STATE *p,tmp; + ERR_STATE tmp; - if (thread_hash == NULL) - return; + err_fns_check(); 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,(char *)&tmp); - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - - if (p != NULL) ERR_STATE_free(p); + /* thread_del_item automatically destroys the LHASH if the number of + * items reaches zero. */ + ERRFN(thread_del_item)(&tmp); } -ERR_STATE *ERR_get_state() +ERR_STATE *ERR_get_state(void) { static ERR_STATE fallback; - ERR_STATE *ret=NULL,tmp,*tmpp; + ERR_STATE *ret,tmp,*tmpp=NULL; int i; unsigned long pid; + err_fns_check(); 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) - { - thread_hash=lh_new(pid_hash,pid_cmp); - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - if (thread_hash == NULL) return(&fallback); - } - else - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - } - else - { - tmp.pid=pid; - ret=(ERR_STATE *)lh_retrieve(thread_hash,(char *)&tmp); - CRYPTO_r_unlock(CRYPTO_LOCK_ERR); - } + tmp.pid=pid; + ret=ERRFN(thread_get_item)(&tmp); /* ret == the error state, if NULL, make a new one */ if (ret == NULL) { - ret=(ERR_STATE *)Malloc(sizeof(ERR_STATE)); + ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE)); if (ret == NULL) return(&fallback); ret->pid=pid; ret->top=0; @@ -566,27 +953,28 @@ ERR_STATE *ERR_get_state() ret->err_data[i]=NULL; ret->err_data_flags[i]=0; } - CRYPTO_w_lock(CRYPTO_LOCK_ERR); - tmpp=(ERR_STATE *)lh_insert(thread_hash,(char *)ret); - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - if (tmpp != NULL) /* old entry - should not happen */ + tmpp = ERRFN(thread_set_item)(ret); + /* To check if insertion failed, do a get. */ + if (ERRFN(thread_get_item)(ret) != ret) { - ERR_STATE_free(tmpp); + ERR_STATE_free(ret); /* could not insert it */ + return(&fallback); } + /* If a race occured in this function and we came second, tmpp + * is the first one that we just replaced. */ + if (tmpp) + ERR_STATE_free(tmpp); } - return(ret); + return ret; } -int ERR_get_next_error_library() +int ERR_get_next_error_library(void) { - static int value=ERR_LIB_USER; - - return(value++); + err_fns_check(); + return ERRFN(get_next_lib)(); } -void ERR_set_error_data(data,flags) -char *data; -int flags; +void ERR_set_error_data(char *data, int flags) { ERR_STATE *es; int i; @@ -597,37 +985,39 @@ int flags; if (i == 0) i=ERR_NUM_ERRORS-1; + err_clear_data(es,i); es->err_data[i]=data; - es->err_data_flags[es->top]=flags; + es->err_data_flags[i]=flags; } -void ERR_add_error_data( VAR_PLIST(int , num)) -VAR_ALIST - { - VAR_BDEFN(args, int, num); +void ERR_add_error_data(int num, ...) + { + va_list args; int i,n,s; char *str,*p,*a; - s=64; - str=Malloc(s+1); + s=80; + str=OPENSSL_malloc(s+1); if (str == NULL) return; str[0]='\0'; - VAR_INIT(args,int,num); + 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); + p=OPENSSL_realloc(str,s+1); if (p == NULL) { - Free(str); - return; + OPENSSL_free(str); + goto err; } else str=p; @@ -637,6 +1027,6 @@ VAR_ALIST } ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING); - VAR_END( args ); +err: + va_end(args); } - diff --git a/src/lib/libcrypto/err/err.h b/src/lib/libcrypto/err/err.h index 75f931be11..cc9bb649ea 100644 --- a/src/lib/libcrypto/err/err.h +++ b/src/lib/libcrypto/err/err.h @@ -59,17 +59,23 @@ #ifndef HEADER_ERR_H #define HEADER_ERR_H -#ifdef __cplusplus -extern "C" { +#ifndef OPENSSL_NO_FP_API +#include +#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. */ +#ifndef OPENSSL_NO_BIO +#include +#endif +#ifndef OPENSSL_NO_LHASH +#include +#endif -#define ERR_file_name __FILE__ +#ifdef __cplusplus +extern "C" { +#endif -#ifndef NO_ERR +#ifndef OPENSSL_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) @@ -87,7 +93,7 @@ typedef struct err_state_st unsigned long err_buffer[ERR_NUM_ERRORS]; char *err_data[ERR_NUM_ERRORS]; int err_data_flags[ERR_NUM_ERRORS]; - char *err_file[ERR_NUM_ERRORS]; + const char *err_file[ERR_NUM_ERRORS]; int err_line[ERR_NUM_ERRORS]; int top,bottom; } ERR_STATE; @@ -104,43 +110,55 @@ typedef struct err_state_st #define ERR_LIB_PEM 9 #define ERR_LIB_DSA 10 #define ERR_LIB_X509 11 -#define ERR_LIB_METH 12 +/* #define ERR_LIB_METH 12 */ #define ERR_LIB_ASN1 13 #define ERR_LIB_CONF 14 #define ERR_LIB_CRYPTO 15 +#define ERR_LIB_EC 16 #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_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_DSO 37 +#define ERR_LIB_ENGINE 38 +#define ERR_LIB_OCSP 39 +#define ERR_LIB_UI 40 +#define ERR_LIB_COMP 41 #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 SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__) +#define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__) +#define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__) +#define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__) +#define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__) +#define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__) +#define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__) +#define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__) +#define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__) +#define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__) +#define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__) +#define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__) +#define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__) +#define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__) +#define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__) +#define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__) +#define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__) +#define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__) +#define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__) +#define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__) +#define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__) +#define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__) +#define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__) +#define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__) +#define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__) /* Borland C seems too stupid to be able to shift and do longs in * the pre-processor :-( */ @@ -152,7 +170,8 @@ typedef struct err_state_st #define ERR_GET_REASON(l) (int)((l)&0xfffL) #define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL) -/* OS fuctions */ + +/* OS functions */ #define SYS_F_FOPEN 1 #define SYS_F_CONNECT 2 #define SYS_F_GETSERVBYNAME 3 @@ -162,123 +181,114 @@ typedef struct err_state_st #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_SYS_LIB ERR_LIB_SYS /* 2 */ +#define ERR_R_BN_LIB ERR_LIB_BN /* 3 */ +#define ERR_R_RSA_LIB ERR_LIB_RSA /* 4 */ +#define ERR_R_DH_LIB ERR_LIB_DH /* 5 */ +#define ERR_R_EVP_LIB ERR_LIB_EVP /* 6 */ +#define ERR_R_BUF_LIB ERR_LIB_BUF /* 7 */ +#define ERR_R_OBJ_LIB ERR_LIB_OBJ /* 8 */ +#define ERR_R_PEM_LIB ERR_LIB_PEM /* 9 */ +#define ERR_R_DSA_LIB ERR_LIB_DSA /* 10 */ +#define ERR_R_X509_LIB ERR_LIB_X509 /* 11 */ +#define ERR_R_ASN1_LIB ERR_LIB_ASN1 /* 13 */ +#define ERR_R_CONF_LIB ERR_LIB_CONF /* 14 */ +#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO /* 15 */ +#define ERR_R_EC_LIB ERR_LIB_EC /* 16 */ +#define ERR_R_SSL_LIB ERR_LIB_SSL /* 20 */ +#define ERR_R_BIO_LIB ERR_LIB_BIO /* 32 */ +#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 /* 33 */ +#define ERR_R_X509V3_LIB ERR_LIB_X509V3 /* 34 */ +#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12 /* 35 */ +#define ERR_R_RAND_LIB ERR_LIB_RAND /* 36 */ +#define ERR_R_DSO_LIB ERR_LIB_DSO /* 37 */ +#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE /* 38 */ +#define ERR_R_OCSP_LIB ERR_LIB_OCSP /* 39 */ +#define ERR_R_UI_LIB ERR_LIB_UI /* 40 */ +#define ERR_R_COMP_LIB ERR_LIB_COMP /* 41 */ + +#define ERR_R_NESTED_ASN1_ERROR 58 +#define ERR_R_BAD_ASN1_OBJECT_HEADER 59 +#define ERR_R_BAD_GET_ASN1_OBJECT_CALL 60 +#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE 61 +#define ERR_R_ASN1_LENGTH_MISMATCH 62 +#define ERR_R_MISSING_ASN1_EOS 63 /* fatal error */ +#define ERR_R_FATAL 64 #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_INTERNAL_ERROR (4|ERR_R_FATAL) + +/* 99 is the maximum possible ERR_R_... code, higher values + * are reserved for the individual libraries */ + typedef struct ERR_string_data_st { unsigned long error; - char *string; + const char *string; } ERR_STRING_DATA; -#ifndef NOPROTO -void ERR_put_error(int lib, int func,int reason,char *file,int line); +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(char **file,int *line); -unsigned long ERR_get_error_line_data(char **file,int *line, - char **data, int *flags); -unsigned long ERR_peek_error(void ); -unsigned long ERR_peek_error_line(char **file,int *line); -unsigned long ERR_peek_error_line_data(char **file,int *line, - 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); +unsigned long ERR_peek_last_error(void); +unsigned long ERR_peek_last_error_line(const char **file,int *line); +unsigned long ERR_peek_last_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); -char *ERR_lib_error_string(unsigned long e); -char *ERR_func_error_string(unsigned long e); -char *ERR_reason_error_string(unsigned long e); -#ifndef NO_FP_API +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +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); +void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), + void *u); +#ifndef OPENSSL_NO_FP_API void ERR_print_errors_fp(FILE *fp); #endif -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO void ERR_print_errors(BIO *bp); -void ERR_add_error_data( VAR_PLIST( int, num ) ); +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_unload_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 ); - -#else - -void ERR_put_error(); -void ERR_set_error_data(); - -unsigned long ERR_get_error(); -unsigned long ERR_get_error_line(); -unsigned long ERR_peek_error(); -unsigned long ERR_peek_error_line(); -void ERR_clear_error(); -char *ERR_error_string(); -char *ERR_lib_error_string(); -char *ERR_func_error_string(); -char *ERR_reason_error_string(); -#ifndef NO_FP_API -void ERR_print_errors_fp(); -#endif -void ERR_print_errors(); -void ERR_add_error_data(); -void ERR_load_strings(); -void ERR_load_ERR_strings(); -void ERR_load_crypto_strings(); -void ERR_free_strings(); - -void ERR_remove_state(); -ERR_STATE *ERR_get_state(); - -#ifdef HEADER_LHASH_H -LHASH *ERR_get_string_table(); -LHASH *ERR_get_err_state_table(); -#else -char *ERR_get_string_table(); -char *ERR_get_err_state_table(); +#ifndef OPENSSL_NO_LHASH +LHASH *ERR_get_string_table(void); +LHASH *ERR_get_err_state_table(void); #endif -int ERR_get_next_error_library(); +int ERR_get_next_error_library(void); -#endif +/* This opaque type encapsulates the low-level error-state functions */ +typedef struct st_ERR_FNS ERR_FNS; +/* An application can use this function and provide the return value to loaded + * modules that should use the application's ERR state/functionality */ +const ERR_FNS *ERR_get_implementation(void); +/* A loaded module should call this function prior to any ERR operations using + * the application's "ERR_FNS". */ +int ERR_set_implementation(const ERR_FNS *fns); #ifdef __cplusplus } diff --git a/src/lib/libcrypto/err/err_all.c b/src/lib/libcrypto/err/err_all.c index f874268e1a..90029fd159 100644 --- a/src/lib/libcrypto/err/err_all.c +++ b/src/lib/libcrypto/err/err_all.c @@ -57,60 +57,73 @@ */ #include -#include "asn1.h" -#include "bn.h" -#include "buffer.h" -#include "bio.h" -#ifndef NO_RSA -#include "rsa.h" +#include +#include +#ifndef OPENSSL_NO_EC +#include #endif -#ifdef RSAref -#include "rsaref.h" +#include +#include +#ifndef OPENSSL_NO_RSA +#include #endif -#ifndef NO_DH -#include "dh.h" +#ifndef OPENSSL_NO_DH +#include #endif -#ifndef NO_DSA -#include "dsa.h" +#ifndef OPENSSL_NO_DSA +#include #endif -#include "evp.h" -#include "objects.h" -#include "pem.h" -#include "x509.h" -#include "conf.h" -#include "err.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -void ERR_load_crypto_strings() +void ERR_load_crypto_strings(void) { static int done=0; if (done) return; done=1; -#ifndef NO_ERR - ERR_load_ASN1_strings(); +#ifndef OPENSSL_NO_ERR + ERR_load_ERR_strings(); /* include error strings for SYSerr */ ERR_load_BN_strings(); - ERR_load_BUF_strings(); - ERR_load_BIO_strings(); - ERR_load_CONF_strings(); -#ifndef NO_RSA -#ifdef RSAref - ERR_load_RSAREF_strings(); -#else +#ifndef OPENSSL_NO_RSA ERR_load_RSA_strings(); #endif -#endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH ERR_load_DH_strings(); #endif -#ifndef NO_DSA - ERR_load_DSA_strings(); -#endif - ERR_load_ERR_strings(); ERR_load_EVP_strings(); + ERR_load_BUF_strings(); ERR_load_OBJ_strings(); ERR_load_PEM_strings(); +#ifndef OPENSSL_NO_DSA + ERR_load_DSA_strings(); +#endif ERR_load_X509_strings(); + ERR_load_ASN1_strings(); + ERR_load_CONF_strings(); ERR_load_CRYPTO_strings(); - ERR_load_PKCS7_strings(); +#ifndef OPENSSL_NO_EC + ERR_load_EC_strings(); +#endif + /* skip ERR_load_SSL_strings() because it is not in this library */ + ERR_load_BIO_strings(); + ERR_load_PKCS7_strings(); + ERR_load_X509V3_strings(); + ERR_load_PKCS12_strings(); + ERR_load_RAND_strings(); + ERR_load_DSO_strings(); + ERR_load_ENGINE_strings(); + ERR_load_OCSP_strings(); + ERR_load_UI_strings(); #endif } diff --git a/src/lib/libcrypto/err/err_prn.c b/src/lib/libcrypto/err/err_prn.c index ecd0e7c4fa..c156663f0e 100644 --- a/src/lib/libcrypto/err/err_prn.c +++ b/src/lib/libcrypto/err/err_prn.c @@ -57,51 +57,51 @@ */ #include -#include "lhash.h" -#include "crypto.h" +#include +#include #include "cryptlib.h" -#include "buffer.h" -#include "err.h" -#include "crypto.h" +#include +#include +#include -#ifndef NO_FP_API -void ERR_print_errors_fp(fp) -FILE *fp; +void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), + void *u) { unsigned long l; - char buf[200]; - char *file,*data; + char buf[256]; + char buf2[4096]; + 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:""); + ERR_error_string_n(l, buf, sizeof buf); + BIO_snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", es, buf, + file, line, (flags & ERR_TXT_STRING) ? data : ""); + cb(buf2, strlen(buf2), u); } } -#endif -void ERR_print_errors(bp) -BIO *bp; +#ifndef OPENSSL_NO_FP_API +static int print_fp(const char *str, size_t len, void *fp) { - unsigned long l; - char buf[256]; - char buf2[256]; - char *file,*data; - int line,flags; - unsigned long es; + return fprintf((FILE *)fp, "%s", str); + } +void ERR_print_errors_fp(FILE *fp) + { + ERR_print_errors_cb(print_fp, fp); + } +#endif - 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); - } +static int print_bio(const char *str, size_t len, void *bp) + { + return BIO_write((BIO *)bp, str, len); + } +void ERR_print_errors(BIO *bp) + { + ERR_print_errors_cb(print_bio, bp); } + diff --git a/src/lib/libcrypto/err/openssl.ec b/src/lib/libcrypto/err/openssl.ec index c2a8acff0c..29a69dfdd4 100644 --- a/src/lib/libcrypto/err/openssl.ec +++ b/src/lib/libcrypto/err/openssl.ec @@ -1,26 +1,36 @@ +# crypto/err/openssl.ec + +# configuration file for util/mkerr.pl + +# files that may have to be rewritten by util/mkerr.pl L ERR NONE NONE -L CRYPTO crypto/crypto.h crypto/cpt_err.c L BN crypto/bn/bn.h crypto/bn/bn_err.c L RSA crypto/rsa/rsa.h crypto/rsa/rsa_err.c -L DSA crypto/dsa/dsa.h crypto/dsa/dsa_err.c L DH crypto/dh/dh.h crypto/dh/dh_err.c L EVP crypto/evp/evp.h crypto/evp/evp_err.c L BUF crypto/buffer/buffer.h crypto/buffer/buf_err.c -L BIO crypto/bio/bio.h crypto/bio/bio_err.c L OBJ crypto/objects/objects.h crypto/objects/obj_err.c L PEM crypto/pem/pem.h crypto/pem/pem_err.c +L DSA crypto/dsa/dsa.h crypto/dsa/dsa_err.c L X509 crypto/x509/x509.h crypto/x509/x509_err.c -L NONE crypto/x509/x509_vfy.h NONE -L X509V3 crypto/x509v3/x509v3.h crypto/x509v3/v3err.c -#L METH crypto/meth/meth.h crypto/meth/meth_err.c L ASN1 crypto/asn1/asn1.h crypto/asn1/asn1_err.c L CONF crypto/conf/conf.h crypto/conf/conf_err.c -#L PROXY crypto/proxy/proxy.h crypto/proxy/proxy_err.c +L CRYPTO crypto/crypto.h crypto/cpt_err.c +L EC crypto/ec/ec.h crypto/ec/ec_err.c +L SSL ssl/ssl.h ssl/ssl_err.c +L BIO crypto/bio/bio.h crypto/bio/bio_err.c L PKCS7 crypto/pkcs7/pkcs7.h crypto/pkcs7/pkcs7err.c +L X509V3 crypto/x509v3/x509v3.h crypto/x509v3/v3err.c L PKCS12 crypto/pkcs12/pkcs12.h crypto/pkcs12/pk12err.c -L RSAREF rsaref/rsaref.h rsaref/rsar_err.c -L SSL ssl/ssl.h ssl/ssl_err.c -L COMP crypto/comp/comp.h crypto/comp/comp_err.c +L RAND crypto/rand/rand.h crypto/rand/rand_err.c +L DSO crypto/dso/dso.h crypto/dso/dso_err.c +L ENGINE crypto/engine/engine.h crypto/engine/eng_err.c +L OCSP crypto/ocsp/ocsp.h crypto/ocsp/ocsp_err.c +L UI crypto/ui/ui.h crypto/ui/ui_err.c + +# additional header files to be scanned for function names +L NONE crypto/x509/x509_vfy.h NONE +L NONE crypto/ec/ec_lcl.h NONE F RSAREF_F_RSA_BN2BIN @@ -47,11 +57,11 @@ R SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 R SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 R SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 R SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 -R SSL_R_TLSV1_ALERT_EXPORT_RESTRICION 1060 +R SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 R SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 R SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 R SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 -R SSL_R_TLSV1_ALERT_USER_CANCLED 1090 +R SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 R SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 R RSAREF_R_CONTENT_ENCODING 0x0400 diff --git a/src/lib/libcrypto/evp/bio_b64.c b/src/lib/libcrypto/evp/bio_b64.c index 73172b9a07..f12eac1b55 100644 --- a/src/lib/libcrypto/evp/bio_b64.c +++ b/src/lib/libcrypto/evp/bio_b64.c @@ -59,27 +59,17 @@ #include #include #include "cryptlib.h" -#include "buffer.h" -#include "evp.h" - -#ifndef NOPROTO -static int b64_write(BIO *h,char *buf,int num); -static int b64_read(BIO *h,char *buf,int size); -/*static int b64_puts(BIO *h,char *str); */ -/*static int b64_gets(BIO *h,char *str,int size); */ -static long b64_ctrl(BIO *h,int cmd,long arg1,char *arg2); +#include +#include + +static int b64_write(BIO *h, const char *buf, int num); +static int b64_read(BIO *h, char *buf, int size); +/*static int b64_puts(BIO *h, const char *str); */ +/*static int b64_gets(BIO *h, char *str, int size); */ +static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int b64_new(BIO *h); static int b64_free(BIO *data); -#else -static int b64_write(); -static int b64_read(); -/*static int b64_puts(); */ -/*static int b64_gets(); */ -static long b64_ctrl(); -static int b64_new(); -static int b64_free(); -#endif - +static long b64_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp); #define B64_BLOCK_SIZE 1024 #define B64_BLOCK_SIZE2 768 #define B64_NONE 0 @@ -111,19 +101,19 @@ static BIO_METHOD methods_b64= b64_ctrl, b64_new, b64_free, + b64_callback_ctrl, }; -BIO_METHOD *BIO_f_base64() +BIO_METHOD *BIO_f_base64(void) { return(&methods_b64); } -static int b64_new(bi) -BIO *bi; +static int b64_new(BIO *bi) { BIO_B64_CTX *ctx; - ctx=(BIO_B64_CTX *)Malloc(sizeof(BIO_B64_CTX)); + ctx=(BIO_B64_CTX *)OPENSSL_malloc(sizeof(BIO_B64_CTX)); if (ctx == NULL) return(0); ctx->buf_len=0; @@ -140,21 +130,17 @@ BIO *bi; return(1); } -static int b64_free(a) -BIO *a; +static int b64_free(BIO *a) { if (a == NULL) return(0); - Free(a->ptr); + OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } -static int b64_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int b64_read(BIO *b, char *out, int outl) { int ret=0,i,ii,j,k,x,n,num,ret_code=0; BIO_B64_CTX *ctx; @@ -253,8 +239,8 @@ int outl; &(ctx->tmp[0])); for (x=0; x < i; x++) ctx->tmp[x]=p[x]; - EVP_DecodeInit(&ctx->base64); } + EVP_DecodeInit(&ctx->base64); ctx->start=0; break; } @@ -354,10 +340,7 @@ int outl; return((ret == 0)?ret_code:ret); } -static int b64_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int b64_write(BIO *b, const char *in, int inl) { int ret=inl,n,i; BIO_B64_CTX *ctx; @@ -387,10 +370,11 @@ int inl; n-=i; } /* at this point all pending data has been written */ + ctx->buf_off=0; + ctx->buf_len=0; if ((in == NULL) || (inl <= 0)) return(0); - ctx->buf_off=0; while (inl > 0) { n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl; @@ -400,14 +384,20 @@ int inl; if (ctx->tmp_len > 0) { n=3-ctx->tmp_len; + /* There's a teoretical possibility for this */ + if (n > inl) + n=inl; memcpy(&(ctx->tmp[ctx->tmp_len]),in,n); ctx->tmp_len+=n; - n=ctx->tmp_len; - if (n < 3) + if (ctx->tmp_len < 3) break; ctx->buf_len=EVP_EncodeBlock( (unsigned char *)ctx->buf, - (unsigned char *)ctx->tmp,n); + (unsigned char *)ctx->tmp, + ctx->tmp_len); + /* Since we're now done using the temporary + buffer, the length should be 0'd */ + ctx->tmp_len=0; } else { @@ -451,11 +441,7 @@ int inl; return(ret); } -static long b64_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO_B64_CTX *ctx; long ret=1; @@ -479,7 +465,8 @@ char *ptr; break; case BIO_CTRL_WPENDING: /* More to write in buffer */ ret=ctx->buf_len-ctx->buf_off; - if ((ret == 0) && (ctx->base64.num != 0)) + if ((ret == 0) && (ctx->encode != B64_NONE) + && (ctx->base64.num != 0)) ret=1; else if (ret <= 0) ret=BIO_ctrl(b->next_bio,cmd,num,ptr); @@ -514,7 +501,7 @@ again: goto again; } } - else if (ctx->base64.num != 0) + else if (ctx->encode != B64_NONE && ctx->base64.num != 0) { ctx->buf_off=0; EVP_EncodeFinal(&(ctx->base64), @@ -545,3 +532,17 @@ again: return(ret); } +static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + diff --git a/src/lib/libcrypto/evp/bio_enc.c b/src/lib/libcrypto/evp/bio_enc.c index 6c30ddfc54..64fb2353af 100644 --- a/src/lib/libcrypto/evp/bio_enc.c +++ b/src/lib/libcrypto/evp/bio_enc.c @@ -59,28 +59,19 @@ #include #include #include "cryptlib.h" -#include "buffer.h" -#include "evp.h" - -#ifndef NOPROTO -static int enc_write(BIO *h,char *buf,int num); -static int enc_read(BIO *h,char *buf,int size); -/*static int enc_puts(BIO *h,char *str); */ -/*static int enc_gets(BIO *h,char *str,int size); */ -static long enc_ctrl(BIO *h,int cmd,long arg1,char *arg2); +#include +#include + +static int enc_write(BIO *h, const char *buf, int num); +static int enc_read(BIO *h, char *buf, int size); +/*static int enc_puts(BIO *h, const char *str); */ +/*static int enc_gets(BIO *h, char *str, int size); */ +static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int enc_new(BIO *h); static int enc_free(BIO *data); -#else -static int enc_write(); -static int enc_read(); -/*static int enc_puts(); */ -/*static int enc_gets(); */ -static long enc_ctrl(); -static int enc_new(); -static int enc_free(); -#endif - +static long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); #define ENC_BLOCK_SIZE (1024*4) +#define BUF_OFFSET EVP_MAX_BLOCK_LENGTH typedef struct enc_struct { @@ -90,7 +81,10 @@ typedef struct enc_struct int finished; int ok; /* bad decrypt */ EVP_CIPHER_CTX cipher; - char buf[ENC_BLOCK_SIZE+10]; + /* buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate + * can return up to a block more data than is presented to it + */ + char buf[ENC_BLOCK_SIZE+BUF_OFFSET+2]; } BIO_ENC_CTX; static BIO_METHOD methods_enc= @@ -103,21 +97,21 @@ static BIO_METHOD methods_enc= enc_ctrl, enc_new, enc_free, + enc_callback_ctrl, }; -BIO_METHOD *BIO_f_cipher() +BIO_METHOD *BIO_f_cipher(void) { return(&methods_enc); } -static int enc_new(bi) -BIO *bi; +static int enc_new(BIO *bi) { BIO_ENC_CTX *ctx; - ctx=(BIO_ENC_CTX *)Malloc(sizeof(BIO_ENC_CTX)); - EVP_CIPHER_CTX_init(&ctx->cipher); + ctx=(BIO_ENC_CTX *)OPENSSL_malloc(sizeof(BIO_ENC_CTX)); if (ctx == NULL) return(0); + EVP_CIPHER_CTX_init(&ctx->cipher); ctx->buf_len=0; ctx->buf_off=0; @@ -131,8 +125,7 @@ BIO *bi; return(1); } -static int enc_free(a) -BIO *a; +static int enc_free(BIO *a) { BIO_ENC_CTX *b; @@ -140,17 +133,14 @@ BIO *a; b=(BIO_ENC_CTX *)a->ptr; EVP_CIPHER_CTX_cleanup(&(b->cipher)); memset(a->ptr,0,sizeof(BIO_ENC_CTX)); - Free(a->ptr); + OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } -static int enc_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int enc_read(BIO *b, char *out, int outl) { int ret=0,i; BIO_ENC_CTX *ctx; @@ -184,9 +174,9 @@ int outl; { if (ctx->cont <= 0) break; - /* read in at offset 8, read the EVP_Cipher + /* read in at IV offset, read the EVP_Cipher * documentation about why */ - i=BIO_read(b->next_bio,&(ctx->buf[8]),ENC_BLOCK_SIZE); + i=BIO_read(b->next_bio,&(ctx->buf[BUF_OFFSET]),ENC_BLOCK_SIZE); if (i <= 0) { @@ -194,29 +184,37 @@ int outl; if (!BIO_should_retry(b->next_bio)) { ctx->cont=i; - i=EVP_CipherFinal(&(ctx->cipher), + i=EVP_CipherFinal_ex(&(ctx->cipher), (unsigned char *)ctx->buf, &(ctx->buf_len)); ctx->ok=i; ctx->buf_off=0; } - else + else + { ret=(ret == 0)?i:ret; - break; + break; + } } else { EVP_CipherUpdate(&(ctx->cipher), (unsigned char *)ctx->buf,&ctx->buf_len, - (unsigned char *)&(ctx->buf[8]),i); + (unsigned char *)&(ctx->buf[BUF_OFFSET]),i); ctx->cont=1; + /* Note: it is possible for EVP_CipherUpdate to + * decrypt zero bytes because this is or looks like + * the final block: if this happens we should retry + * and either read more data or decrypt the final + * block + */ + if(ctx->buf_len == 0) continue; } if (ctx->buf_len <= outl) i=ctx->buf_len; else i=outl; - if (i <= 0) break; memcpy(out,ctx->buf,i); ret+=i; @@ -230,10 +228,7 @@ int outl; return((ret == 0)?ctx->cont:ret); } -static int enc_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int enc_write(BIO *b, const char *in, int inl) { int ret=0,n,i; BIO_ENC_CTX *ctx; @@ -288,16 +283,13 @@ int inl; return(ret); } -static long enc_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; BIO_ENC_CTX *ctx,*dctx; long ret=1; int i; + EVP_CIPHER_CTX **c_ctx; ctx=(BIO_ENC_CTX *)b->ptr; @@ -306,7 +298,7 @@ char *ptr; case BIO_CTRL_RESET: ctx->ok=1; ctx->finished=0; - EVP_CipherInit(&(ctx->cipher),NULL,NULL,NULL, + EVP_CipherInit_ex(&(ctx->cipher),NULL,NULL,NULL,NULL, ctx->cipher.encrypt); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; @@ -343,7 +335,7 @@ again: { ctx->finished=1; ctx->buf_off=0; - ret=EVP_CipherFinal(&(ctx->cipher), + ret=EVP_CipherFinal_ex(&(ctx->cipher), (unsigned char *)ctx->buf, &(ctx->buf_len)); ctx->ok=(int)ret; @@ -364,7 +356,11 @@ again: ret=BIO_ctrl(b->next_bio,cmd,num,ptr); BIO_copy_next_retry(b); break; - + case BIO_C_GET_CIPHER_CTX: + c_ctx=(EVP_CIPHER_CTX **)ptr; + (*c_ctx)= &(ctx->cipher); + b->init=1; + break; case BIO_CTRL_DUP: dbio=(BIO *)ptr; dctx=(BIO_ENC_CTX *)dbio->ptr; @@ -378,6 +374,20 @@ again: return(ret); } +static long enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + /* void BIO_set_cipher_ctx(b,c) BIO *b; @@ -398,26 +408,22 @@ EVP_CIPHER_ctx *c; } */ -void BIO_set_cipher(b,c,k,i,e) -BIO *b; -EVP_CIPHER *c; -unsigned char *k; -unsigned char *i; -int e; +void BIO_set_cipher(BIO *b, const EVP_CIPHER *c, unsigned char *k, + unsigned char *i, int e) { BIO_ENC_CTX *ctx; if (b == NULL) return; if ((b->callback != NULL) && - (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) + (b->callback(b,BIO_CB_CTRL,(const char *)c,BIO_CTRL_SET,e,0L) <= 0)) return; b->init=1; ctx=(BIO_ENC_CTX *)b->ptr; - EVP_CipherInit(&(ctx->cipher),c,k,i,e); + EVP_CipherInit_ex(&(ctx->cipher),c,NULL, k,i,e); if (b->callback != NULL) - b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); + b->callback(b,BIO_CB_CTRL,(const char *)c,BIO_CTRL_SET,e,1L); } diff --git a/src/lib/libcrypto/evp/bio_md.c b/src/lib/libcrypto/evp/bio_md.c index fa5fdc055b..c632dfb202 100644 --- a/src/lib/libcrypto/evp/bio_md.c +++ b/src/lib/libcrypto/evp/bio_md.c @@ -59,29 +59,20 @@ #include #include #include "cryptlib.h" -#include "buffer.h" -#include "evp.h" +#include +#include /* BIO_put and BIO_get both add to the digest, * BIO_gets returns the digest */ -#ifndef NOPROTO -static int md_write(BIO *h,char *buf,int num); -static int md_read(BIO *h,char *buf,int size); -/*static int md_puts(BIO *h,char *str); */ -static int md_gets(BIO *h,char *str,int size); -static long md_ctrl(BIO *h,int cmd,long arg1,char *arg2); +static int md_write(BIO *h, char const *buf, int num); +static int md_read(BIO *h, char *buf, int size); +/*static int md_puts(BIO *h, const char *str); */ +static int md_gets(BIO *h, char *str, int size); +static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int md_new(BIO *h); static int md_free(BIO *data); -#else -static int md_write(); -static int md_read(); -/*static int md_puts(); */ -static int md_gets(); -static long md_ctrl(); -static int md_new(); -static int md_free(); -#endif +static long md_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp); static BIO_METHOD methods_md= { @@ -93,19 +84,19 @@ static BIO_METHOD methods_md= md_ctrl, md_new, md_free, + md_callback_ctrl, }; -BIO_METHOD *BIO_f_md() +BIO_METHOD *BIO_f_md(void) { return(&methods_md); } -static int md_new(bi) -BIO *bi; +static int md_new(BIO *bi) { EVP_MD_CTX *ctx; - ctx=(EVP_MD_CTX *)Malloc(sizeof(EVP_MD_CTX)); + ctx=EVP_MD_CTX_create(); if (ctx == NULL) return(0); bi->init=0; @@ -114,27 +105,23 @@ BIO *bi; return(1); } -static int md_free(a) -BIO *a; +static int md_free(BIO *a) { if (a == NULL) return(0); - Free(a->ptr); + EVP_MD_CTX_destroy(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } -static int md_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int md_read(BIO *b, char *out, int outl) { int ret=0; EVP_MD_CTX *ctx; if (out == NULL) return(0); - ctx=(EVP_MD_CTX *)b->ptr; + ctx=b->ptr; if ((ctx == NULL) || (b->next_bio == NULL)) return(0); @@ -152,16 +139,13 @@ int outl; return(ret); } -static int md_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int md_write(BIO *b, const char *in, int inl) { int ret=0; EVP_MD_CTX *ctx; if ((in == NULL) || (inl <= 0)) return(0); - ctx=(EVP_MD_CTX *)b->ptr; + ctx=b->ptr; if ((ctx != NULL) && (b->next_bio != NULL)) ret=BIO_write(b->next_bio,in,inl); @@ -178,25 +162,21 @@ int inl; return(ret); } -static long md_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long md_ctrl(BIO *b, int cmd, long num, void *ptr) { EVP_MD_CTX *ctx,*dctx,**pctx; - EVP_MD **ppmd; + const EVP_MD **ppmd; EVP_MD *md; long ret=1; BIO *dbio; - ctx=(EVP_MD_CTX *)b->ptr; + ctx=b->ptr; switch (cmd) { case BIO_CTRL_RESET: if (b->init) - EVP_DigestInit(ctx,ctx->digest); + EVP_DigestInit_ex(ctx,ctx->digest, NULL); else ret=0; ret=BIO_ctrl(b->next_bio,cmd,num,ptr); @@ -204,7 +184,7 @@ char *ptr; case BIO_C_GET_MD: if (b->init) { - ppmd=(EVP_MD **)ptr; + ppmd=ptr; *ppmd=ctx->digest; } else @@ -213,7 +193,7 @@ char *ptr; case BIO_C_GET_MD_CTX: if (b->init) { - pctx=(EVP_MD_CTX **)ptr; + pctx=ptr; *pctx=ctx; } else @@ -226,14 +206,14 @@ char *ptr; break; case BIO_C_SET_MD: - md=(EVP_MD *)ptr; - EVP_DigestInit(ctx,md); + md=ptr; + EVP_DigestInit_ex(ctx,md, NULL); b->init=1; break; case BIO_CTRL_DUP: - dbio=(BIO *)ptr; - dctx=(EVP_MD_CTX *)dbio->ptr; - memcpy(dctx,ctx,sizeof(ctx)); + dbio=ptr; + dctx=dbio->ptr; + EVP_MD_CTX_copy_ex(dctx,ctx); b->init=1; break; default: @@ -243,19 +223,30 @@ char *ptr; return(ret); } -static int md_gets(bp,buf,size) -BIO *bp; -char *buf; -int size; +static long md_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } + +static int md_gets(BIO *bp, char *buf, int size) { EVP_MD_CTX *ctx; unsigned int ret; - ctx=(EVP_MD_CTX *)bp->ptr; + ctx=bp->ptr; if (size < ctx->digest->md_size) return(0); - EVP_DigestFinal(ctx,(unsigned char *)buf,&ret); + EVP_DigestFinal_ex(ctx,(unsigned char *)buf,&ret); return((int)ret); } diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c index e77d1c896b..5ffd352ea0 100644 --- a/src/lib/libcrypto/evp/c_all.c +++ b/src/lib/libcrypto/evp/c_all.c @@ -58,133 +58,17 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" +#include -void SSLeay_add_all_algorithms() - { - SSLeay_add_all_ciphers(); - SSLeay_add_all_digests(); - } +#undef OpenSSL_add_all_algorithms -void SSLeay_add_all_ciphers() +void OpenSSL_add_all_algorithms(void) { -#ifndef NO_DES - EVP_add_cipher(EVP_des_cfb()); - EVP_add_cipher(EVP_des_ede_cfb()); - EVP_add_cipher(EVP_des_ede3_cfb()); - - EVP_add_cipher(EVP_des_ofb()); - EVP_add_cipher(EVP_des_ede_ofb()); - EVP_add_cipher(EVP_des_ede3_ofb()); - - EVP_add_cipher(EVP_desx_cbc()); - EVP_add_alias(SN_desx_cbc,"DESX"); - EVP_add_alias(SN_desx_cbc,"desx"); - - EVP_add_cipher(EVP_des_cbc()); - EVP_add_alias(SN_des_cbc,"DES"); - EVP_add_alias(SN_des_cbc,"des"); - EVP_add_cipher(EVP_des_ede_cbc()); - EVP_add_cipher(EVP_des_ede3_cbc()); - EVP_add_alias(SN_des_ede3_cbc,"DES3"); - EVP_add_alias(SN_des_ede3_cbc,"des3"); - - EVP_add_cipher(EVP_des_ecb()); - EVP_add_cipher(EVP_des_ede()); - EVP_add_cipher(EVP_des_ede3()); -#endif - -#ifndef NO_RC4 - EVP_add_cipher(EVP_rc4()); - EVP_add_cipher(EVP_rc4_40()); -#endif - -#ifndef NO_IDEA - EVP_add_cipher(EVP_idea_ecb()); - EVP_add_cipher(EVP_idea_cfb()); - EVP_add_cipher(EVP_idea_ofb()); - EVP_add_cipher(EVP_idea_cbc()); - EVP_add_alias(SN_idea_cbc,"IDEA"); - EVP_add_alias(SN_idea_cbc,"idea"); -#endif - -#ifndef NO_RC2 - EVP_add_cipher(EVP_rc2_ecb()); - EVP_add_cipher(EVP_rc2_cfb()); - EVP_add_cipher(EVP_rc2_ofb()); - EVP_add_cipher(EVP_rc2_cbc()); - EVP_add_cipher(EVP_rc2_40_cbc()); - EVP_add_alias(SN_rc2_cbc,"RC2"); - EVP_add_alias(SN_rc2_cbc,"rc2"); -#endif - -#ifndef NO_BLOWFISH - EVP_add_cipher(EVP_bf_ecb()); - EVP_add_cipher(EVP_bf_cfb()); - EVP_add_cipher(EVP_bf_ofb()); - EVP_add_cipher(EVP_bf_cbc()); - EVP_add_alias(SN_bf_cbc,"BF"); - EVP_add_alias(SN_bf_cbc,"bf"); - EVP_add_alias(SN_bf_cbc,"blowfish"); -#endif - -#ifndef NO_CAST - EVP_add_cipher(EVP_cast5_ecb()); - EVP_add_cipher(EVP_cast5_cfb()); - EVP_add_cipher(EVP_cast5_ofb()); - EVP_add_cipher(EVP_cast5_cbc()); - EVP_add_alias(SN_cast5_cbc,"CAST"); - EVP_add_alias(SN_cast5_cbc,"cast"); - EVP_add_alias(SN_cast5_cbc,"CAST-cbc"); - EVP_add_alias(SN_cast5_cbc,"cast-cbc"); -#endif - -#ifndef NO_RC5 - EVP_add_cipher(EVP_rc5_32_12_16_ecb()); - EVP_add_cipher(EVP_rc5_32_12_16_cfb()); - EVP_add_cipher(EVP_rc5_32_12_16_ofb()); - EVP_add_cipher(EVP_rc5_32_12_16_cbc()); - EVP_add_alias(SN_rc5_cbc,"rc5"); - EVP_add_alias(SN_rc5_cbc,"RC5"); - EVP_add_alias(SN_rc5_cbc,"rc5-cbc"); - EVP_add_alias(SN_rc5_cbc,"RC5-cbc"); -#endif + OPENSSL_add_all_algorithms_noconf(); } - -void SSLeay_add_all_digests() +void OPENSSL_add_all_algorithms_noconf(void) { -#ifndef NO_MD2 - EVP_add_digest(EVP_md2()); -#endif -#ifndef NO_MD5 - EVP_add_digest(EVP_md5()); - EVP_add_alias(SN_md5,"ssl2-md5"); - EVP_add_alias(SN_md5,"ssl3-md5"); -#endif -#ifndef NO_SHA - EVP_add_digest(EVP_sha()); -#ifndef NO_DSA - EVP_add_digest(EVP_dss()); -#endif -#endif -#ifndef NO_SHA1 - EVP_add_digest(EVP_sha1()); - EVP_add_alias(SN_sha1,"ssl3-sha1"); -#ifndef NO_DSA - EVP_add_digest(EVP_dss1()); - EVP_add_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2); - EVP_add_alias(SN_dsaWithSHA1,"DSS1"); - EVP_add_alias(SN_dsaWithSHA1,"dss1"); -#endif -#endif -#if !defined(NO_MDC2) && !defined(NO_DES) - EVP_add_digest(EVP_mdc2()); -#endif -#ifndef NO_RIPEMD160 - EVP_add_digest(EVP_ripemd160()); - EVP_add_alias(SN_ripemd160,"ripemd"); - EVP_add_alias(SN_ripemd160,"rmd160"); -#endif + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); } diff --git a/src/lib/libcrypto/evp/digest.c b/src/lib/libcrypto/evp/digest.c index d65f0036f7..a969ac69ed 100644 --- a/src/lib/libcrypto/evp/digest.c +++ b/src/lib/libcrypto/evp/digest.c @@ -55,35 +55,258 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "objects.h" -#include "evp.h" +#include +#include +#include + +void EVP_MD_CTX_init(EVP_MD_CTX *ctx) + { + memset(ctx,'\0',sizeof *ctx); + } + +EVP_MD_CTX *EVP_MD_CTX_create(void) + { + EVP_MD_CTX *ctx=OPENSSL_malloc(sizeof *ctx); + + EVP_MD_CTX_init(ctx); + + return ctx; + } -void EVP_DigestInit(ctx,type) -EVP_MD_CTX *ctx; -EVP_MD *type; +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) { - ctx->digest=type; - type->init(&(ctx->md)); + EVP_MD_CTX_init(ctx); + return EVP_DigestInit_ex(ctx, type, NULL); } -void EVP_DigestUpdate(ctx,data,count) -EVP_MD_CTX *ctx; -unsigned char *data; -unsigned int count; +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { - ctx->digest->update(&(ctx->md.base[0]),data,(unsigned long)count); + EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED); + /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts + * so this context may already have an ENGINE! Try to avoid releasing + * the previous handle, re-querying for an ENGINE, and having a + * reinitialisation, when it may all be unecessary. */ + if (ctx->engine && ctx->digest && (!type || + (type && (type->type == ctx->digest->type)))) + goto skip_to_init; + if (type) + { + /* Ensure an ENGINE left lying around from last time is cleared + * (the previous check attempted to avoid this if the same + * ENGINE and EVP_MD could be used). */ + if(ctx->engine) + ENGINE_finish(ctx->engine); + if(impl) + { + if (!ENGINE_init(impl)) + { + EVPerr(EVP_F_EVP_DIGESTINIT, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } + else + /* Ask if an ENGINE is reserved for this job */ + impl = ENGINE_get_digest_engine(type->type); + if(impl) + { + /* There's an ENGINE for this job ... (apparently) */ + const EVP_MD *d = ENGINE_get_digest(impl, type->type); + if(!d) + { + /* Same comment from evp_enc.c */ + EVPerr(EVP_F_EVP_DIGESTINIT, EVP_R_INITIALIZATION_ERROR); + return 0; + } + /* We'll use the ENGINE's private digest definition */ + type = d; + /* Store the ENGINE functional reference so we know + * 'type' came from an ENGINE and we need to release + * it when done. */ + ctx->engine = impl; + } + else + ctx->engine = NULL; + } + else if(!ctx->digest) + { + EVPerr(EVP_F_EVP_DIGESTINIT, EVP_R_NO_DIGEST_SET); + return 0; + } + if (ctx->digest != type) + { + if (ctx->digest && ctx->digest->ctx_size) + OPENSSL_free(ctx->md_data); + ctx->digest=type; + if (type->ctx_size) + ctx->md_data=OPENSSL_malloc(type->ctx_size); + } +skip_to_init: + return ctx->digest->init(ctx); } -void EVP_DigestFinal(ctx,md,size) -EVP_MD_CTX *ctx; -unsigned char *md; -unsigned int *size; +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, + unsigned int count) { - ctx->digest->final(md,&(ctx->md.base[0])); + return ctx->digest->update(ctx,data,(unsigned long)count); + } + +/* The caller can assume that this removes any secret data from the context */ +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) + { + int ret; + ret = EVP_DigestFinal_ex(ctx, md, size); + EVP_MD_CTX_cleanup(ctx); + return ret; + } + +/* The caller can assume that this removes any secret data from the context */ +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) + { + int ret; + ret=ctx->digest->final(ctx,md); if (size != NULL) *size=ctx->digest->md_size; - memset(&(ctx->md),0,sizeof(ctx->md)); + if (ctx->digest->cleanup) + { + ctx->digest->cleanup(ctx); + EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED); + } + memset(ctx->md_data,0,ctx->digest->ctx_size); + return ret; + } + +int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) + { + EVP_MD_CTX_init(out); + return EVP_MD_CTX_copy_ex(out, in); + } + +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) + { + if ((in == NULL) || (in->digest == NULL)) + { + EVPerr(EVP_F_EVP_MD_CTX_COPY,EVP_R_INPUT_NOT_INITIALIZED); + return 0; + } + /* Make sure it's safe to copy a digest context using an ENGINE */ + if (in->engine && !ENGINE_init(in->engine)) + { + EVPerr(EVP_F_EVP_MD_CTX_COPY,ERR_R_ENGINE_LIB); + return 0; + } + + EVP_MD_CTX_cleanup(out); + memcpy(out,in,sizeof *out); + + if (out->digest->ctx_size) + { + out->md_data=OPENSSL_malloc(out->digest->ctx_size); + memcpy(out->md_data,in->md_data,out->digest->ctx_size); + } + + if (out->digest->copy) + return out->digest->copy(out,in); + + return 1; + } + +int EVP_Digest(void *data, unsigned int count, + unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl) + { + EVP_MD_CTX ctx; + int ret; + + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_set_flags(&ctx,EVP_MD_CTX_FLAG_ONESHOT); + ret=EVP_DigestInit_ex(&ctx, type, impl) + && EVP_DigestUpdate(&ctx, data, count) + && EVP_DigestFinal_ex(&ctx, md, size); + EVP_MD_CTX_cleanup(&ctx); + + return ret; + } + +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) + { + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } + +/* This call frees resources associated with the context */ +int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) + { + /* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, + * because sometimes only copies of the context are ever finalised. + */ + if (ctx->digest && ctx->digest->cleanup + && !EVP_MD_CTX_test_flags(ctx,EVP_MD_CTX_FLAG_CLEANED)) + ctx->digest->cleanup(ctx); + if (ctx->digest && ctx->digest->ctx_size && ctx->md_data) + { + memset(ctx->md_data,0,ctx->digest->ctx_size); + OPENSSL_free(ctx->md_data); + } + if(ctx->engine) + /* The EVP_MD we used belongs to an ENGINE, release the + * functional reference we held for this reason. */ + ENGINE_finish(ctx->engine); + memset(ctx,'\0',sizeof *ctx); + + return 1; } diff --git a/src/lib/libcrypto/evp/e_aes.c b/src/lib/libcrypto/evp/e_aes.c index 9d03a9602f..c323fa2892 100644 --- a/src/lib/libcrypto/evp/e_aes.c +++ b/src/lib/libcrypto/evp/e_aes.c @@ -88,7 +88,9 @@ IMPLEMENT_BLOCK_CIPHER(aes_256, ks, AES, EVP_AES_KEY, static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - if (enc) + if ((ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_CFB_MODE + || (ctx->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_OFB_MODE + || enc) AES_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data); else AES_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data); diff --git a/src/lib/libcrypto/evp/e_bf.c b/src/lib/libcrypto/evp/e_bf.c index 72047f64da..e74337567b 100644 --- a/src/lib/libcrypto/evp/e_bf.c +++ b/src/lib/libcrypto/evp/e_bf.c @@ -56,24 +56,32 @@ * [including the GNU Public Licence.] */ -#ifndef NO_BF +#ifndef OPENSSL_NO_BF #include #include "cryptlib.h" #include #include "evp_locl.h" #include +#include static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); -IMPLEMENT_BLOCK_CIPHER(bf, bf_ks, BF, bf_ks, NID_bf, 8, 16, 8, - 0, bf_init_key, NULL, +typedef struct + { + BF_KEY ks; + } EVP_BF_KEY; + +#define data(ctx) EVP_C_DATA(EVP_BF_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(bf, ks, BF, EVP_BF_KEY, NID_bf, 8, 16, 8, 64, + EVP_CIPH_VARIABLE_LENGTH, bf_init_key, NULL, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - BF_set_key(&(ctx->c.bf_ks),EVP_CIPHER_CTX_key_length(ctx),key); + BF_set_key(&data(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),key); return 1; } diff --git a/src/lib/libcrypto/evp/e_cast.c b/src/lib/libcrypto/evp/e_cast.c index e5af7fb4ed..3400fef187 100644 --- a/src/lib/libcrypto/evp/e_cast.c +++ b/src/lib/libcrypto/evp/e_cast.c @@ -56,26 +56,34 @@ * [including the GNU Public Licence.] */ -#ifndef NO_CAST +#ifndef OPENSSL_NO_CAST #include #include "cryptlib.h" #include #include #include "evp_locl.h" +#include static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv,int enc); -IMPLEMENT_BLOCK_CIPHER(cast5, cast_ks, CAST, cast_ks, - NID_cast5, 8, EVP_CAST5_KEY_SIZE, 8, +typedef struct + { + CAST_KEY ks; + } EVP_CAST_KEY; + +#define data(ctx) EVP_C_DATA(EVP_CAST_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(cast5, ks, CAST, EVP_CAST_KEY, + NID_cast5, 8, CAST_KEY_LENGTH, 8, 64, EVP_CIPH_VARIABLE_LENGTH, cast_init_key, NULL, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - CAST_set_key(&(ctx->c.cast_ks),EVP_CIPHER_CTX_key_length(ctx),key); + CAST_set_key(&data(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),key); return 1; } diff --git a/src/lib/libcrypto/evp/e_des.c b/src/lib/libcrypto/evp/e_des.c index f4e998b81c..105266a4b3 100644 --- a/src/lib/libcrypto/evp/e_des.c +++ b/src/lib/libcrypto/evp/e_des.c @@ -56,12 +56,13 @@ * [including the GNU Public Licence.] */ -#ifndef NO_DES +#ifndef OPENSSL_NO_DES #include #include "cryptlib.h" #include #include #include "evp_locl.h" +#include static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); @@ -72,34 +73,34 @@ static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { BLOCK_CIPHER_ecb_loop() - des_ecb_encrypt((des_cblock *)(in + i), (des_cblock *)(out + i), ctx->c.des_ks, ctx->encrypt); + DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i), ctx->cipher_data, ctx->encrypt); return 1; } static int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { - des_ofb64_encrypt(in, out, (long)inl, ctx->c.des_ks, (des_cblock *)ctx->iv, &ctx->num); + DES_ofb64_encrypt(in, out, (long)inl, ctx->cipher_data, (DES_cblock *)ctx->iv, &ctx->num); return 1; } static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { - des_ncbc_encrypt(in, out, (long)inl, ctx->c.des_ks, - (des_cblock *)ctx->iv, ctx->encrypt); + DES_ncbc_encrypt(in, out, (long)inl, ctx->cipher_data, + (DES_cblock *)ctx->iv, ctx->encrypt); return 1; } static int des_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { - des_cfb64_encrypt(in, out, (long)inl, ctx->c.des_ks, - (des_cblock *)ctx->iv, &ctx->num, ctx->encrypt); + DES_cfb64_encrypt(in, out, (long)inl, ctx->cipher_data, + (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt); return 1; } -BLOCK_CIPHER_defs(des, des_ks, NID_des, 8, 8, 8, +BLOCK_CIPHER_defs(des, DES_key_schedule, NID_des, 8, 8, 8, 64, 0, des_init_key, NULL, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, @@ -109,9 +110,9 @@ BLOCK_CIPHER_defs(des, des_ks, NID_des, 8, 8, 8, static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - des_cblock *deskey = (des_cblock *)key; + DES_cblock *deskey = (DES_cblock *)key; - des_set_key_unchecked(deskey,ctx->c.des_ks); + DES_set_key_unchecked(deskey,ctx->cipher_data); return 1; } diff --git a/src/lib/libcrypto/evp/e_des3.c b/src/lib/libcrypto/evp/e_des3.c index a9aba4ae70..077860e7b6 100644 --- a/src/lib/libcrypto/evp/e_des3.c +++ b/src/lib/libcrypto/evp/e_des3.c @@ -56,12 +56,13 @@ * [including the GNU Public Licence.] */ -#ifndef NO_DES +#ifndef OPENSSL_NO_DES #include #include "cryptlib.h" #include #include #include "evp_locl.h" +#include static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv,int enc); @@ -69,60 +70,78 @@ static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv,int enc); +typedef 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_KEY; + +#define data(ctx) ((DES_EDE_KEY *)(ctx)->cipher_data) + /* Because of various casts and different args can't use IMPLEMENT_BLOCK_CIPHER */ static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { BLOCK_CIPHER_ecb_loop() - des_ecb3_encrypt((des_cblock *)(in + i), (des_cblock *)(out + i), - ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, - ctx->encrypt); + DES_ecb3_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i), + &data(ctx)->ks1, &data(ctx)->ks2, + &data(ctx)->ks3, + ctx->encrypt); return 1; } static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { - des_ede3_ofb64_encrypt(in, out, (long)inl, - ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, - (des_cblock *)ctx->iv, &ctx->num); + DES_ede3_ofb64_encrypt(in, out, (long)inl, + &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3, + (DES_cblock *)ctx->iv, &ctx->num); return 1; } static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { - des_ede3_cbc_encrypt(in, out, (long)inl, - ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, - (des_cblock *)ctx->iv, ctx->encrypt); +#ifdef KSSL_DEBUG + { + int i; + char *cp; + printf("des_ede_cbc_cipher(ctx=%lx, buflen=%d)\n", ctx, ctx->buf_len); + printf("\t iv= "); + for(i=0;i<8;i++) + printf("%02X",ctx->iv[i]); + printf("\n"); + } +#endif /* KSSL_DEBUG */ + DES_ede3_cbc_encrypt(in, out, (long)inl, + &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3, + (DES_cblock *)ctx->iv, ctx->encrypt); return 1; } static int des_ede_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { - des_ede3_cfb64_encrypt(in, out, (long)inl, - ctx->c.des_ede.ks1, ctx->c.des_ede.ks2, ctx->c.des_ede.ks3, - (des_cblock *)ctx->iv, &ctx->num, ctx->encrypt); + DES_ede3_cfb64_encrypt(in, out, (long)inl, + &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3, + (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt); return 1; } -#define NID_des_ede_ecb NID_des_ede - -BLOCK_CIPHER_defs(des_ede, des_ede, NID_des_ede, 8, 16, 8, +BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64, 0, des_ede_init_key, NULL, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) -#define NID_des_ede3_ecb NID_des_ede3 #define des_ede3_cfb_cipher des_ede_cfb_cipher #define des_ede3_ofb_cipher des_ede_ofb_cipher #define des_ede3_cbc_cipher des_ede_cbc_cipher #define des_ede3_ecb_cipher des_ede_ecb_cipher -BLOCK_CIPHER_defs(des_ede3, des_ede, NID_des_ede3, 8, 24, 8, +BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64, 0, des_ede3_init_key, NULL, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, @@ -131,34 +150,43 @@ BLOCK_CIPHER_defs(des_ede3, des_ede, NID_des_ede3, 8, 24, 8, static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - des_cblock *deskey = (des_cblock *)key; + DES_cblock *deskey = (DES_cblock *)key; - des_set_key_unchecked(&deskey[0],ctx->c.des_ede.ks1); - des_set_key_unchecked(&deskey[1],ctx->c.des_ede.ks2); - memcpy( (char *)ctx->c.des_ede.ks3, - (char *)ctx->c.des_ede.ks1, - sizeof(ctx->c.des_ede.ks1)); + DES_set_key_unchecked(&deskey[0],&data(ctx)->ks1); + DES_set_key_unchecked(&deskey[1],&data(ctx)->ks2); + memcpy(&data(ctx)->ks3,&data(ctx)->ks1, + sizeof(data(ctx)->ks1)); return 1; } static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - des_cblock *deskey = (des_cblock *)key; + DES_cblock *deskey = (DES_cblock *)key; +#ifdef KSSL_DEBUG + { + int i; + printf("des_ede3_init_key(ctx=%lx)\n", ctx); + printf("\tKEY= "); + for(i=0;i<24;i++) printf("%02X",key[i]); printf("\n"); + printf("\t IV= "); + for(i=0;i<8;i++) printf("%02X",iv[i]); printf("\n"); + } +#endif /* KSSL_DEBUG */ - des_set_key_unchecked(&deskey[0],ctx->c.des_ede.ks1); - des_set_key_unchecked(&deskey[1],ctx->c.des_ede.ks2); - des_set_key_unchecked(&deskey[2],ctx->c.des_ede.ks3); + DES_set_key_unchecked(&deskey[0],&data(ctx)->ks1); + DES_set_key_unchecked(&deskey[1],&data(ctx)->ks2); + DES_set_key_unchecked(&deskey[2],&data(ctx)->ks3); return 1; } -EVP_CIPHER *EVP_des_ede(void) +const EVP_CIPHER *EVP_des_ede(void) { return &des_ede_ecb; } -EVP_CIPHER *EVP_des_ede3(void) +const EVP_CIPHER *EVP_des_ede3(void) { return &des_ede3_ecb; } diff --git a/src/lib/libcrypto/evp/e_idea.c b/src/lib/libcrypto/evp/e_idea.c index 8d3c88deb7..ed838d3e62 100644 --- a/src/lib/libcrypto/evp/e_idea.c +++ b/src/lib/libcrypto/evp/e_idea.c @@ -56,13 +56,14 @@ * [including the GNU Public Licence.] */ -#ifndef NO_IDEA +#ifndef OPENSSL_NO_IDEA #include #include "cryptlib.h" #include #include #include "evp_locl.h" +#include static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv,int enc); @@ -75,17 +76,22 @@ static int idea_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { BLOCK_CIPHER_ecb_loop() - idea_ecb_encrypt(in + i, out + i, &ctx->c.idea_ks); + idea_ecb_encrypt(in + i, out + i, ctx->cipher_data); return 1; } /* Can't use IMPLEMENT_BLOCK_CIPHER because idea_ecb_encrypt is different */ -BLOCK_CIPHER_func_cbc(idea, idea, idea_ks) -BLOCK_CIPHER_func_ofb(idea, idea, idea_ks) -BLOCK_CIPHER_func_cfb(idea, idea, idea_ks) +typedef struct + { + IDEA_KEY_SCHEDULE ks; + } EVP_IDEA_KEY; + +BLOCK_CIPHER_func_cbc(idea, idea, EVP_IDEA_KEY, ks) +BLOCK_CIPHER_func_ofb(idea, idea, 64, EVP_IDEA_KEY, ks) +BLOCK_CIPHER_func_cfb(idea, idea, 64, EVP_IDEA_KEY, ks) -BLOCK_CIPHER_defs(idea, idea_ks, NID_idea, 8, 16, 8, +BLOCK_CIPHER_defs(idea, IDEA_KEY_SCHEDULE, NID_idea, 8, 16, 8, 64, 0, idea_init_key, NULL, EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) @@ -96,13 +102,13 @@ static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) enc = 1; else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) enc = 1; } - if (enc) idea_set_encrypt_key(key,&(ctx->c.idea_ks)); + if (enc) idea_set_encrypt_key(key,ctx->cipher_data); else { IDEA_KEY_SCHEDULE tmp; idea_set_encrypt_key(key,&tmp); - idea_set_decrypt_key(&tmp,&(ctx->c.idea_ks)); + idea_set_decrypt_key(&tmp,ctx->cipher_data); memset((unsigned char *)&tmp,0, sizeof(IDEA_KEY_SCHEDULE)); } diff --git a/src/lib/libcrypto/evp/e_null.c b/src/lib/libcrypto/evp/e_null.c index e4e7ca7606..2420d7e5af 100644 --- a/src/lib/libcrypto/evp/e_null.c +++ b/src/lib/libcrypto/evp/e_null.c @@ -58,52 +58,44 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" +#include +#include -#ifndef NOPROTO -static void null_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key, - unsigned char *iv,int enc); -static void null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - unsigned char *in, unsigned int inl); -#else -static void null_init_key(); -static void null_cipher(); -#endif - -static EVP_CIPHER n_cipher= +static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); +static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +static const EVP_CIPHER n_cipher= { NID_undef, 1,0,0, + 0, null_init_key, null_cipher, NULL, 0, NULL, NULL, + NULL }; -EVP_CIPHER *EVP_enc_null() +const EVP_CIPHER *EVP_enc_null(void) { return(&n_cipher); } -static void null_init_key(ctx,key,iv,enc) -EVP_CIPHER_CTX *ctx; -unsigned char *key; -unsigned char *iv; -int enc; +static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) { - memset(&(ctx->c),0,sizeof(ctx->c)); + /* memset(&(ctx->c),0,sizeof(ctx->c));*/ + return 1; } -static void null_cipher(ctx,out,in,inl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -unsigned char *in; -unsigned int inl; +static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) { if (in != out) memcpy((char *)out,(char *)in,(int)inl); + return 1; } diff --git a/src/lib/libcrypto/evp/e_rc2.c b/src/lib/libcrypto/evp/e_rc2.c index 3955c3ef84..4685198e2e 100644 --- a/src/lib/libcrypto/evp/e_rc2.c +++ b/src/lib/libcrypto/evp/e_rc2.c @@ -56,13 +56,14 @@ * [including the GNU Public Licence.] */ -#ifndef NO_RC2 +#ifndef OPENSSL_NO_RC2 #include #include "cryptlib.h" #include #include #include "evp_locl.h" +#include static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv,int enc); @@ -72,9 +73,17 @@ static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); -IMPLEMENT_BLOCK_CIPHER(rc2, rc2.ks, RC2, rc2, NID_rc2, +typedef struct + { + int key_bits; /* effective key bits */ + RC2_KEY ks; /* key schedule */ + } EVP_RC2_KEY; + +#define data(ctx) ((EVP_RC2_KEY *)(ctx)->cipher_data) + +IMPLEMENT_BLOCK_CIPHER(rc2, ks, RC2, EVP_RC2_KEY, NID_rc2, 8, - EVP_RC2_KEY_SIZE, 8, + RC2_KEY_LENGTH, 8, 64, EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, rc2_init_key, NULL, rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, @@ -84,7 +93,7 @@ IMPLEMENT_BLOCK_CIPHER(rc2, rc2.ks, RC2, rc2, NID_rc2, #define RC2_64_MAGIC 0x78 #define RC2_128_MAGIC 0x3a -static EVP_CIPHER r2_64_cbc_cipher= +static const EVP_CIPHER r2_64_cbc_cipher= { NID_rc2_64_cbc, 8,8 /* 64 bit */,8, @@ -92,15 +101,14 @@ static EVP_CIPHER r2_64_cbc_cipher= rc2_init_key, rc2_cbc_cipher, NULL, - sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+ - sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)), + sizeof(EVP_RC2_KEY), rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, rc2_ctrl, NULL }; -static EVP_CIPHER r2_40_cbc_cipher= +static const EVP_CIPHER r2_40_cbc_cipher= { NID_rc2_40_cbc, 8,5 /* 40 bit */,8, @@ -108,20 +116,19 @@ static EVP_CIPHER r2_40_cbc_cipher= rc2_init_key, rc2_cbc_cipher, NULL, - sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+ - sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)), + sizeof(EVP_RC2_KEY), rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, rc2_ctrl, NULL }; -EVP_CIPHER *EVP_rc2_64_cbc(void) +const EVP_CIPHER *EVP_rc2_64_cbc(void) { return(&r2_64_cbc_cipher); } -EVP_CIPHER *EVP_rc2_40_cbc(void) +const EVP_CIPHER *EVP_rc2_40_cbc(void) { return(&r2_40_cbc_cipher); } @@ -129,8 +136,8 @@ EVP_CIPHER *EVP_rc2_40_cbc(void) static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - RC2_set_key(&(ctx->c.rc2.ks),EVP_CIPHER_CTX_key_length(ctx), - key,ctx->c.rc2.key_bits); + RC2_set_key(&data(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx), + key,data(ctx)->key_bits); return 1; } @@ -173,7 +180,7 @@ static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) key_bits =rc2_magic_to_meth((int)num); if (!key_bits) return(-1); - if(i > 0) EVP_CipherInit(c, NULL, NULL, iv, -1); + if(i > 0) EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1); EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL); EVP_CIPHER_CTX_set_key_length(c, key_bits / 8); } @@ -196,26 +203,26 @@ static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { - switch(type) { - - case EVP_CTRL_INIT: - c->c.rc2.key_bits = EVP_CIPHER_CTX_key_length(c) * 8; - return 1; + switch(type) + { + case EVP_CTRL_INIT: + data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8; + return 1; - case EVP_CTRL_GET_RC2_KEY_BITS: - *(int *)ptr = c->c.rc2.key_bits; - return 1; + case EVP_CTRL_GET_RC2_KEY_BITS: + *(int *)ptr = data(c)->key_bits; + return 1; - - case EVP_CTRL_SET_RC2_KEY_BITS: - if(arg > 0) { - c->c.rc2.key_bits = arg; - return 1; + case EVP_CTRL_SET_RC2_KEY_BITS: + if(arg > 0) + { + data(c)->key_bits = arg; + return 1; } - return 0; + return 0; - default: - return -1; + default: + return -1; } } diff --git a/src/lib/libcrypto/evp/e_rc4.c b/src/lib/libcrypto/evp/e_rc4.c index 7e9790a94c..4064cc5fa0 100644 --- a/src/lib/libcrypto/evp/e_rc4.c +++ b/src/lib/libcrypto/evp/e_rc4.c @@ -56,72 +56,81 @@ * [including the GNU Public Licence.] */ -#ifndef NO_RC4 +#ifndef OPENSSL_NO_RC4 #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" +#include +#include +#include -#ifndef NOPROTO -static void rc4_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key, - unsigned char *iv,int enc); -static void rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - unsigned char *in, unsigned int inl); -#else -static void rc4_init_key(); -static void rc4_cipher(); -#endif +/* FIXME: surely this is available elsewhere? */ +#define EVP_RC4_KEY_SIZE 16 + +typedef struct + { + /* FIXME: what is the key for? */ + unsigned char key[EVP_RC4_KEY_SIZE]; + RC4_KEY ks; /* working key */ + } EVP_RC4_KEY; + +#define data(ctx) ((EVP_RC4_KEY *)(ctx)->cipher_data) -static EVP_CIPHER r4_cipher= +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); +static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +static const EVP_CIPHER r4_cipher= { NID_rc4, 1,EVP_RC4_KEY_SIZE,0, + EVP_CIPH_VARIABLE_LENGTH, rc4_init_key, rc4_cipher, NULL, - sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+ - sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc4)), + sizeof(EVP_RC4_KEY), NULL, NULL, + NULL }; -static EVP_CIPHER r4_40_cipher= +static const EVP_CIPHER r4_40_cipher= { NID_rc4_40, 1,5 /* 40 bit */,0, + EVP_CIPH_VARIABLE_LENGTH, rc4_init_key, rc4_cipher, + NULL, + sizeof(EVP_RC4_KEY), + NULL, + NULL, + NULL }; -EVP_CIPHER *EVP_rc4() +const EVP_CIPHER *EVP_rc4(void) { return(&r4_cipher); } -EVP_CIPHER *EVP_rc4_40() +const EVP_CIPHER *EVP_rc4_40(void) { return(&r4_40_cipher); } -static void rc4_init_key(ctx,key,iv,enc) -EVP_CIPHER_CTX *ctx; -unsigned char *key; -unsigned char *iv; -int enc; +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) { - if (key != NULL) - memcpy(&(ctx->c.rc4.key[0]),key,EVP_CIPHER_CTX_key_length(ctx)); - RC4_set_key(&(ctx->c.rc4.ks),EVP_CIPHER_CTX_key_length(ctx), - ctx->c.rc4.key); + memcpy(&data(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx)); + RC4_set_key(&data(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx), + data(ctx)->key); + return 1; } -static void rc4_cipher(ctx,out,in,inl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -unsigned char *in; -unsigned int inl; +static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) { - RC4(&(ctx->c.rc4.ks),inl,in,out); + RC4(&data(ctx)->ks,inl,in,out); + return 1; } #endif diff --git a/src/lib/libcrypto/evp/e_xcbc_d.c b/src/lib/libcrypto/evp/e_xcbc_d.c index 0d7fda0c47..a6f849e93d 100644 --- a/src/lib/libcrypto/evp/e_xcbc_d.c +++ b/src/lib/libcrypto/evp/e_xcbc_d.c @@ -56,67 +56,67 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_DES #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" +#include +#include +#include -#ifndef NOPROTO -static void desx_cbc_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key, - unsigned char *iv,int enc); -static void desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - unsigned char *in, unsigned int inl); -#else -static void desx_cbc_init_key(); -static void desx_cbc_cipher(); -#endif +static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv,int enc); +static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); + + +typedef struct + { + DES_key_schedule ks;/* key schedule */ + DES_cblock inw; + DES_cblock outw; + } DESX_CBC_KEY; + +#define data(ctx) ((DESX_CBC_KEY *)(ctx)->cipher_data) -static EVP_CIPHER d_xcbc_cipher= +static const EVP_CIPHER d_xcbc_cipher= { NID_desx_cbc, 8,24,8, + EVP_CIPH_CBC_MODE, desx_cbc_init_key, desx_cbc_cipher, NULL, - sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+ - sizeof((((EVP_CIPHER_CTX *)NULL)->c.desx_cbc)), + sizeof(DESX_CBC_KEY), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, + NULL }; -EVP_CIPHER *EVP_desx_cbc() +const EVP_CIPHER *EVP_desx_cbc(void) { return(&d_xcbc_cipher); } -static void desx_cbc_init_key(ctx,key,iv,enc) -EVP_CIPHER_CTX *ctx; -unsigned char *key; -unsigned char *iv; -int enc; +static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) { - if (iv != NULL) - memcpy(&(ctx->oiv[0]),iv,8); - memcpy(&(ctx->iv[0]),&(ctx->oiv[0]),8); - if (key != NULL) - { - des_set_key((des_cblock *)key,ctx->c.desx_cbc.ks); - memcpy(&(ctx->c.desx_cbc.inw[0]),&(key[8]),8); - memcpy(&(ctx->c.desx_cbc.outw[0]),&(key[16]),8); - } + DES_cblock *deskey = (DES_cblock *)key; + + DES_set_key_unchecked(deskey,&data(ctx)->ks); + memcpy(&data(ctx)->inw[0],&key[8],8); + memcpy(&data(ctx)->outw[0],&key[16],8); + + return 1; } -static void desx_cbc_cipher(ctx,out,in,inl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -unsigned char *in; -unsigned int inl; +static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) { - des_xcbc_encrypt( - (des_cblock *)in,(des_cblock *)out, - (long)inl, ctx->c.desx_cbc.ks, - (des_cblock *)&(ctx->iv[0]), - (des_cblock *)&(ctx->c.desx_cbc.inw[0]), - (des_cblock *)&(ctx->c.desx_cbc.outw[0]), - ctx->encrypt); + DES_xcbc_encrypt(in,out,inl,&data(ctx)->ks, + (DES_cblock *)&(ctx->iv[0]), + &data(ctx)->inw, + &data(ctx)->outw, + ctx->encrypt); + return 1; } +#endif diff --git a/src/lib/libcrypto/evp/encode.c b/src/lib/libcrypto/evp/encode.c index 14d47c1eed..12c6379df1 100644 --- a/src/lib/libcrypto/evp/encode.c +++ b/src/lib/libcrypto/evp/encode.c @@ -58,10 +58,21 @@ #include #include "cryptlib.h" -#include "evp.h" +#include +#ifndef CHARSET_EBCDIC #define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) #define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f]) +#else +/* We assume that PEM encoded files are EBCDIC files + * (i.e., printable text files). Convert them here while decoding. + * When encoding, output is EBCDIC (text) format again. + * (No need for conversion in the conv_bin2ascii macro, as the + * underlying textstring data_bin2ascii[] is already EBCDIC) + */ +#define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) +#define conv_ascii2bin(a) (data_ascii2bin[os_toascii[a]&0x7f]) +#endif /* 64 char lines * pad input with 0 @@ -110,20 +121,15 @@ static unsigned char data_ascii2bin[128]={ 0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF, }; -void EVP_EncodeInit(ctx) -EVP_ENCODE_CTX *ctx; +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { ctx->length=48; ctx->num=0; ctx->line_num=0; } -void EVP_EncodeUpdate(ctx,out,outl,in,inl) -EVP_ENCODE_CTX *ctx; -unsigned char *out; -int *outl; -unsigned char *in; -int inl; +void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + unsigned char *in, int inl) { int i,j; unsigned int total=0; @@ -165,10 +171,7 @@ int inl; *outl=total; } -void EVP_EncodeFinal(ctx,out,outl) -EVP_ENCODE_CTX *ctx; -unsigned char *out; -int *outl; +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) { unsigned int ret=0; @@ -182,9 +185,7 @@ int *outl; *outl=ret; } -int EVP_EncodeBlock(t,f,dlen) -unsigned char *t,*f; -int dlen; +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) { int i,ret=0; unsigned long l; @@ -218,8 +219,7 @@ int dlen; return(ret); } -void EVP_DecodeInit(ctx) -EVP_ENCODE_CTX *ctx; +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { ctx->length=30; ctx->num=0; @@ -231,12 +231,8 @@ EVP_ENCODE_CTX *ctx; * 0 for last line * 1 for full line */ -int EVP_DecodeUpdate(ctx,out,outl,in,inl) -EVP_ENCODE_CTX *ctx; -unsigned char *out; -int *outl; -unsigned char *in; -int inl; +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + unsigned char *in, int inl) { int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2,exp_nl; unsigned char *d; @@ -281,6 +277,13 @@ int inl; eof++; } + if (v == B64_CR) + { + ln = 0; + if (exp_nl) + continue; + } + /* eoln */ if (v == B64_EOLN) { @@ -296,7 +299,17 @@ int inl; /* If we are at the end of input and it looks like a * line, process it. */ if (((i+1) == inl) && (((n&3) == 0) || eof)) + { v=B64_EOF; + /* In case things were given us in really small + records (so two '=' were given in separate + updates), eof may contain the incorrect number + of ending bytes to skip, so let's redo the count */ + eof = 0; + if (d[n-1] == '=') eof++; + if (d[n-2] == '=') eof++; + /* There will never be more than two '=' */ + } if ((v == B64_EOF) || (n >= 64)) { @@ -341,9 +354,7 @@ end: return(rv); } -int EVP_DecodeBlock(t,f,n) -unsigned char *t,*f; -int n; +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) { int i,ret=0,a,b,c,d; unsigned long l; @@ -383,10 +394,7 @@ int n; return(ret); } -int EVP_DecodeFinal(ctx,out,outl) -EVP_ENCODE_CTX *ctx; -unsigned char *out; -int *outl; +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) { int i; @@ -404,9 +412,7 @@ int *outl; } #ifdef undef -int EVP_DecodeValid(buf,len) -unsigned char *buf; -int len; +int EVP_DecodeValid(unsigned char *buf, int len) { int i,num=0,bad=0; diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h index b39fad93a4..fb16de6852 100644 --- a/src/lib/libcrypto/evp/evp.h +++ b/src/lib/libcrypto/evp/evp.h @@ -59,75 +59,39 @@ #ifndef HEADER_ENVELOPE_H #define HEADER_ENVELOPE_H -#ifdef __cplusplus -extern "C" { +#ifdef OPENSSL_ALGORITHM_DEFINES +# include +#else +# define OPENSSL_ALGORITHM_DEFINES +# include +# undef OPENSSL_ALGORITHM_DEFINES #endif -#ifndef NO_MD2 -#include "md2.h" -#endif -#ifndef NO_MD5 -#include "md5.h" -#endif -#if !defined(NO_SHA) || !defined(NO_SHA1) -#include "sha.h" -#endif -#ifndef NO_RIPEMD -#include "ripemd.h" -#endif -#ifndef NO_DES -#include "des.h" -#endif -#ifndef NO_RC4 -#include "rc4.h" -#endif -#ifndef NO_RC2 -#include "rc2.h" -#endif -#ifndef NO_RC5 -#include "rc5.h" -#endif -#ifndef NO_BLOWFISH -#include "blowfish.h" -#endif -#ifndef NO_CAST -#include "cast.h" -#endif -#ifndef NO_IDEA -#include "idea.h" -#endif -#ifndef NO_MDC2 -#include "mdc2.h" +#include + +#include + +#ifndef OPENSSL_NO_BIO +#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 - -#ifndef NO_RSA -#include "rsa.h" -#else -#define RSA long -#endif - -#ifndef NO_DSA -#include "dsa.h" -#else -#define DSA long -#endif +#define EVP_MAX_KEY_LENGTH 32 +#define EVP_MAX_IV_LENGTH 16 +#define EVP_MAX_BLOCK_LENGTH 32 -#ifndef NO_DH -#include "dh.h" -#else -#define DH long -#endif +#define PKCS5_SALT_LEN 8 +/* Default PKCS#5 iteration count */ +#define PKCS5_DEFAULT_ITER 2048 -#include "objects.h" +#include #define EVP_PK_RSA 0x0001 #define EVP_PK_DSA 0x0002 @@ -149,27 +113,33 @@ extern "C" { #define EVP_PKEY_DSA4 NID_dsaWithSHA1_2 #define EVP_PKEY_DH NID_dhKeyAgreement +#ifdef __cplusplus +extern "C" { +#endif + /* Type needs to be a bit field * Sub-type needs to be for variations on the method, as in, can it do - * arbitary encryption.... */ -typedef struct evp_pkey_st + * arbitrary encryption.... */ +struct evp_pkey_st { int type; int save_type; int references; union { char *ptr; +#ifndef OPENSSL_NO_RSA struct rsa_st *rsa; /* RSA */ +#endif +#ifndef OPENSSL_NO_DSA struct dsa_st *dsa; /* DSA */ +#endif +#ifndef OPENSSL_NO_DH struct dh_st *dh; /* DH */ +#endif } pkey; int save_parameters; -#ifdef HEADER_STACK_H - STACK /* X509_ATTRIBUTE */ *attributes; /* [ 0 ] */ -#else - char /* X509_ATTRIBUTE */ *attributes; /* [ 0 ] */ -#endif - } EVP_PKEY; + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ + } /* EVP_PKEY */; #define EVP_PKEY_MO_SIGN 0x0001 #define EVP_PKEY_MO_VERIFY 0x0002 @@ -183,7 +153,7 @@ typedef struct evp_pkey_st * 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 ossociated with it. + * 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. */ @@ -194,28 +164,28 @@ typedef struct evp_pkey_md_st EVP_PKEY_METHOD *pkey; } EVP_PKEY_MD; -#define EVP_rsa_md2() +#define EVP_rsa_md2() \ EVP_PKEY_MD_add(NID_md2WithRSAEncryption,\ EVP_rsa_pkcs1(),EVP_md2()) -#define EVP_rsa_md5() +#define EVP_rsa_md5() \ EVP_PKEY_MD_add(NID_md5WithRSAEncryption,\ EVP_rsa_pkcs1(),EVP_md5()) -#define EVP_rsa_sha0() +#define EVP_rsa_sha0() \ EVP_PKEY_MD_add(NID_shaWithRSAEncryption,\ EVP_rsa_pkcs1(),EVP_sha()) -#define EVP_rsa_sha1() +#define EVP_rsa_sha1() \ EVP_PKEY_MD_add(NID_sha1WithRSAEncryption,\ EVP_rsa_pkcs1(),EVP_sha1()) -#define EVP_rsa_ripemd160() +#define EVP_rsa_ripemd160() \ EVP_PKEY_MD_add(NID_ripemd160WithRSA,\ EVP_rsa_pkcs1(),EVP_ripemd160()) -#define EVP_rsa_mdc2() +#define EVP_rsa_mdc2() \ EVP_PKEY_MD_add(NID_mdc2WithRSA,\ EVP_rsa_octet_string(),EVP_mdc2()) -#define EVP_dsa_sha() +#define EVP_dsa_sha() \ EVP_PKEY_MD_add(NID_dsaWithSHA,\ - EVP_dsa(),EVP_mdc2()) -#define EVP_dsa_sha1() + EVP_dsa(),EVP_sha()) +#define EVP_dsa_sha1() \ EVP_PKEY_MD_add(NID_dsaWithSHA1,\ EVP_dsa(),EVP_sha1()) @@ -230,7 +200,6 @@ typedef struct evp_pkey_method_st int (*sign)(); int (*verify)(); struct { - int int (*set)(); /* get and/or set the underlying type */ int (*get)(); int (*encrypt)(); @@ -245,25 +214,32 @@ typedef struct evp_pkey_method_st #endif #ifndef EVP_MD -typedef struct env_md_st +struct env_md_st { int type; int pkey_type; int md_size; - void (*init)(); - void (*update)(); - void (*final)(); - + unsigned long flags; + int (*init)(EVP_MD_CTX *ctx); + int (*update)(EVP_MD_CTX *ctx,const void *data,unsigned long count); + int (*final)(EVP_MD_CTX *ctx,unsigned char *md); + int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from); + int (*cleanup)(EVP_MD_CTX *ctx); + + /* FIXME: prototype these some day */ 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; + int ctx_size; /* how big does the ctx->md_data need to be */ + } /* EVP_MD */; + +#define EVP_MD_FLAG_ONESHOT 0x0001 /* digest can only handle a single + * block */ #define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA #define EVP_PKEY_DSA_method DSA_sign,DSA_verify, \ {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \ EVP_PKEY_DSA4,0} @@ -271,7 +247,7 @@ typedef struct env_md_st #define EVP_PKEY_DSA_method EVP_PKEY_NULL_method #endif -#ifndef NO_RSA +#ifndef OPENSSL_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 \ @@ -285,103 +261,98 @@ typedef struct env_md_st #endif /* !EVP_MD */ -typedef struct env_md_ctx_st +struct env_md_ctx_st { - EVP_MD *digest; - union { - unsigned char base[4]; -#ifndef NO_MD2 - MD2_CTX md2; -#endif -#ifndef NO_MD5 - MD5_CTX md5; -#endif -#ifndef NO_MD5 - RIPEMD160_CTX ripemd160; -#endif -#if !defined(NO_SHA) || !defined(NO_SHA1) - SHA_CTX sha; -#endif -#ifndef NO_MDC2 - MDC2_CTX mdc2; -#endif - } md; - } EVP_MD_CTX; + const EVP_MD *digest; + ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */ + unsigned long flags; + void *md_data; + } /* EVP_MD_CTX */; + +/* values for EVP_MD_CTX flags */ -typedef struct evp_cipher_st +#define EVP_MD_CTX_FLAG_ONESHOT 0x0001 /* digest update will be called + * once only */ +#define EVP_MD_CTX_FLAG_CLEANED 0x0002 /* context has already been + * cleaned */ + +struct evp_cipher_st { int nid; int block_size; - int key_len; + int key_len; /* Default value for variable length ciphers */ 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; + unsigned long flags; /* Various flags */ + int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); /* init key */ + int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */ + int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */ + int ctx_size; /* how big ctx->cipher_data needs to be */ + int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */ + int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */ + int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */ + void *app_data; /* Application data */ + } /* EVP_CIPHER */; + +/* Values for cipher flags */ + +/* Modes for ciphers */ + +#define EVP_CIPH_STREAM_CIPHER 0x0 +#define EVP_CIPH_ECB_MODE 0x1 +#define EVP_CIPH_CBC_MODE 0x2 +#define EVP_CIPH_CFB_MODE 0x3 +#define EVP_CIPH_OFB_MODE 0x4 +#define EVP_CIPH_MODE 0x7 +/* Set if variable length cipher */ +#define EVP_CIPH_VARIABLE_LENGTH 0x8 +/* Set if the iv handling should be done by the cipher itself */ +#define EVP_CIPH_CUSTOM_IV 0x10 +/* Set if the cipher's init() function should be called if key is NULL */ +#define EVP_CIPH_ALWAYS_CALL_INIT 0x20 +/* Call ctrl() to init cipher parameters */ +#define EVP_CIPH_CTRL_INIT 0x40 +/* Don't use standard key length function */ +#define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 +/* Don't use standard block padding */ +#define EVP_CIPH_NO_PADDING 0x100 + +/* ctrl() values */ + +#define EVP_CTRL_INIT 0x0 +#define EVP_CTRL_SET_KEY_LENGTH 0x1 +#define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +#define EVP_CTRL_GET_RC5_ROUNDS 0x4 +#define EVP_CTRL_SET_RC5_ROUNDS 0x5 typedef struct evp_cipher_info_st { - EVP_CIPHER *cipher; + const EVP_CIPHER *cipher; unsigned char iv[EVP_MAX_IV_LENGTH]; } EVP_CIPHER_INFO; -typedef struct evp_cipher_ctx_st +struct evp_cipher_ctx_st { - EVP_CIPHER *cipher; + const EVP_CIPHER *cipher; + ENGINE *engine; /* functional reference if 'cipher' is ENGINE-provided */ 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 */ + unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */ int num; /* used by cfb/ofb mode */ - char *app_data; /* aplication 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 */ - C_Block inw; - C_Block 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_BLOWFISH - BF_KEY bf_ks;/* key schedule */ -#endif -#ifndef NO_CAST - CAST_KEY cast_ks;/* key schedule */ -#endif - } c; - } EVP_CIPHER_CTX; + void *app_data; /* application stuff */ + int key_len; /* May change for variable length cipher */ + unsigned long flags; /* Various flags */ + void *cipher_data; /* per EVP data */ + int final_used; + int block_mask; + unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */ + } /* EVP_CIPHER_CTX */; typedef struct evp_Encode_Ctx_st { @@ -396,12 +367,25 @@ typedef struct evp_Encode_Ctx_st 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, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); + +#ifndef OPENSSL_NO_RSA #define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ (char *)(rsa)) +#endif + +#ifndef OPENSSL_NO_DSA #define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ (char *)(dsa)) +#endif + +#ifndef OPENSSL_NO_DH #define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\ (char *)(dh)) +#endif /* Add some extra combinations */ #define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) @@ -410,77 +394,124 @@ typedef struct evp_Encode_Ctx_st #define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) #define EVP_MD_type(e) ((e)->type) +#define EVP_MD_nid(e) EVP_MD_type(e) +#define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e)) #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) ((e)->digest) +#define EVP_MD_CTX_type(e) EVP_MD_type((e)->digest) #define EVP_CIPHER_nid(e) ((e)->nid) +#define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) #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_flags(e) ((e)->flags) +#define EVP_CIPHER_mode(e) (((e)->flags) & EVP_CIPH_MODE) #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_key_length(e) ((e)->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_CIPHER_CTX_flags(e) ((e)->cipher->flags) +#define EVP_CIPHER_CTX_mode(e) ((e)->cipher->flags & EVP_CIPH_MODE) #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_ex(a,b,c) EVP_DigestInit_ex(a,b,c) #define EVP_SignInit(a,b) EVP_DigestInit(a,b) #define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(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) -#define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md) +#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)) -#ifndef NOPROTO - -void EVP_DigestInit(EVP_MD_CTX *ctx, EVP_MD *type); -void EVP_DigestUpdate(EVP_MD_CTX *ctx,unsigned char *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,char *prompt,int verify); +#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); + +void EVP_MD_CTX_init(EVP_MD_CTX *ctx); +int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); +EVP_MD_CTX *EVP_MD_CTX_create(void); +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in); +#define EVP_MD_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs)) +#define EVP_MD_CTX_clear_flags(ctx,flgs) ((ctx)->flags&=~(flgs)) +#define EVP_MD_CTX_test_flags(ctx,flgs) ((ctx)->flags&(flgs)) +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); +int EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d, + unsigned int cnt); +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s); +int EVP_Digest(void *data, unsigned int count, + unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl); + +int EVP_MD_CTX_copy(EVP_MD_CTX *out,const EVP_MD_CTX *in); +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +int 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(EVP_CIPHER *type,EVP_MD *md,unsigned char *salt, - unsigned char *data, int datal, int count, - unsigned char *key,unsigned char *iv); - -EVP_CIPHER *EVP_get_cipherbyname(char *name); - -void EVP_EncryptInit(EVP_CIPHER_CTX *ctx,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,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_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md, + const unsigned char *salt, const unsigned char *data, + int datal, int count, unsigned char *key,unsigned char *iv); + +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, const unsigned char *iv); +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, const unsigned char *iv); +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); - -void EVP_CipherInit(EVP_CIPHER_CTX *ctx,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_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, + const unsigned char *key,const unsigned char *iv, + int enc); +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key,const unsigned char *iv, + int enc); +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, + int *outl, const unsigned char *in, int inl); int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +int EVP_CipherFinal_ex(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); @@ -488,100 +519,171 @@ int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s, 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 EVP_OpenInit(EVP_CIPHER_CTX *ctx,const 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 EVP_SealInit(EVP_CIPHER_CTX *ctx, const 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); +int 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, unsigned char *f, int n); +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, unsigned - char *f, int n); - -void ERR_load_EVP_strings(void ); +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); -void EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad); +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO BIO_METHOD *BIO_f_md(void); BIO_METHOD *BIO_f_base64(void); BIO_METHOD *BIO_f_cipher(void); -void BIO_set_cipher(BIO *b,EVP_CIPHER *c,unsigned char *k, +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_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 SSLeay_add_all_algorithms(void); -void SSLeay_add_all_ciphers(void); -void SSLeay_add_all_digests(void); - -int EVP_add_cipher(EVP_CIPHER *cipher); -int EVP_add_digest(EVP_MD *digest); -int EVP_add_alias(char *name,char *alias); -int EVP_delete_alias(char *name); - -EVP_CIPHER *EVP_get_cipherbyname(char *name); -EVP_MD *EVP_get_digestbyname(char *name); +const EVP_MD *EVP_md_null(void); +#ifndef OPENSSL_NO_MD2 +const EVP_MD *EVP_md2(void); +#endif +#ifndef OPENSSL_NO_MD4 +const EVP_MD *EVP_md4(void); +#endif +#ifndef OPENSSL_NO_MD5 +const EVP_MD *EVP_md5(void); +#endif +#ifndef OPENSSL_NO_SHA +const EVP_MD *EVP_sha(void); +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_dss(void); +const EVP_MD *EVP_dss1(void); +#endif +#ifndef OPENSSL_NO_MDC2 +const EVP_MD *EVP_mdc2(void); +#endif +#ifndef OPENSSL_NO_RIPEMD +const EVP_MD *EVP_ripemd160(void); +#endif +const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ +#ifndef OPENSSL_NO_DES +const EVP_CIPHER *EVP_des_ecb(void); +const EVP_CIPHER *EVP_des_ede(void); +const EVP_CIPHER *EVP_des_ede3(void); +const EVP_CIPHER *EVP_des_cfb(void); +const EVP_CIPHER *EVP_des_ede_cfb(void); +const EVP_CIPHER *EVP_des_ede3_cfb(void); +const EVP_CIPHER *EVP_des_ofb(void); +const EVP_CIPHER *EVP_des_ede_ofb(void); +const EVP_CIPHER *EVP_des_ede3_ofb(void); +const EVP_CIPHER *EVP_des_cbc(void); +const EVP_CIPHER *EVP_des_ede_cbc(void); +const EVP_CIPHER *EVP_des_ede3_cbc(void); +const EVP_CIPHER *EVP_desx_cbc(void); +/* This should now be supported through the dev_crypto ENGINE. But also, why are + * rc4 and md5 declarations made here inside a "NO_DES" precompiler branch? */ +#if 0 +# ifdef OPENSSL_OPENBSD_DEV_CRYPTO +const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void); +const EVP_CIPHER *EVP_dev_crypto_rc4(void); +const EVP_MD *EVP_dev_crypto_md5(void); +# endif +#endif +#endif +#ifndef OPENSSL_NO_RC4 +const EVP_CIPHER *EVP_rc4(void); +const EVP_CIPHER *EVP_rc4_40(void); +#endif +#ifndef OPENSSL_NO_IDEA +const EVP_CIPHER *EVP_idea_ecb(void); +const EVP_CIPHER *EVP_idea_cfb(void); +const EVP_CIPHER *EVP_idea_ofb(void); +const EVP_CIPHER *EVP_idea_cbc(void); +#endif +#ifndef OPENSSL_NO_RC2 +const EVP_CIPHER *EVP_rc2_ecb(void); +const EVP_CIPHER *EVP_rc2_cbc(void); +const EVP_CIPHER *EVP_rc2_40_cbc(void); +const EVP_CIPHER *EVP_rc2_64_cbc(void); +const EVP_CIPHER *EVP_rc2_cfb(void); +const EVP_CIPHER *EVP_rc2_ofb(void); +#endif +#ifndef OPENSSL_NO_BF +const EVP_CIPHER *EVP_bf_ecb(void); +const EVP_CIPHER *EVP_bf_cbc(void); +const EVP_CIPHER *EVP_bf_cfb(void); +const EVP_CIPHER *EVP_bf_ofb(void); +#endif +#ifndef OPENSSL_NO_CAST +const EVP_CIPHER *EVP_cast5_ecb(void); +const EVP_CIPHER *EVP_cast5_cbc(void); +const EVP_CIPHER *EVP_cast5_cfb(void); +const EVP_CIPHER *EVP_cast5_ofb(void); +#endif +#ifndef OPENSSL_NO_RC5 +const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void); +const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void); +#endif +#ifndef OPENSSL_NO_AES +const EVP_CIPHER *EVP_aes_128_ecb(void); +const EVP_CIPHER *EVP_aes_128_cbc(void); +const EVP_CIPHER *EVP_aes_128_cfb(void); +const EVP_CIPHER *EVP_aes_128_ofb(void); +#if 0 +const EVP_CIPHER *EVP_aes_128_ctr(void); +#endif +const EVP_CIPHER *EVP_aes_192_ecb(void); +const EVP_CIPHER *EVP_aes_192_cbc(void); +const EVP_CIPHER *EVP_aes_192_cfb(void); +const EVP_CIPHER *EVP_aes_192_ofb(void); +#if 0 +const EVP_CIPHER *EVP_aes_192_ctr(void); +#endif +const EVP_CIPHER *EVP_aes_256_ecb(void); +const EVP_CIPHER *EVP_aes_256_cbc(void); +const EVP_CIPHER *EVP_aes_256_cfb(void); +const EVP_CIPHER *EVP_aes_256_ofb(void); +#if 0 +const EVP_CIPHER *EVP_aes_256_ctr(void); +#endif +#endif + +void OPENSSL_add_all_algorithms_noconf(void); +void OPENSSL_add_all_algorithms_conf(void); + +#ifdef OPENSSL_LOAD_CONF +#define OpenSSL_add_all_algorithms() \ + OPENSSL_add_all_algorithms_conf() +#else +#define OpenSSL_add_all_algorithms() \ + OPENSSL_add_all_algorithms_noconf() +#endif + +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(const EVP_CIPHER *cipher); +int EVP_add_digest(const 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, @@ -592,6 +694,24 @@ 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 OPENSSL_NO_RSA +struct rsa_st; +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,struct rsa_st *key); +struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); +#endif +#ifndef OPENSSL_NO_DSA +struct dsa_st; +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey,struct dsa_st *key); +struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); +#endif +#ifndef OPENSSL_NO_DH +struct dh_st; +int EVP_PKEY_set1_DH(EVP_PKEY *pkey,struct dh_st *key); +struct dh_st *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, @@ -600,6 +720,8 @@ 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); @@ -607,6 +729,8 @@ 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); @@ -615,179 +739,106 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type); 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); -#else - -void EVP_DigestInit(); -void EVP_DigestUpdate(); -void EVP_DigestFinal(); - -int EVP_read_pw_string(); -void EVP_set_pw_prompt(); -char * EVP_get_pw_prompt(); - -int EVP_BytesToKey(); - -EVP_CIPHER *EVP_get_cipherbyname(); - -void EVP_EncryptInit(); -void EVP_EncryptUpdate(); -void EVP_EncryptFinal(); - -void EVP_DecryptInit(); -void EVP_DecryptUpdate(); -int EVP_DecryptFinal(); - -void EVP_CipherInit(); -void EVP_CipherUpdate(); -int EVP_CipherFinal(); - -int EVP_SignFinal(); - -int EVP_VerifyFinal(); - -int EVP_OpenInit(); -int EVP_OpenFinal(); - -int EVP_SealInit(); -void EVP_SealFinal(); - -void EVP_EncodeInit(); -void EVP_EncodeUpdate(); -void EVP_EncodeFinal(); -int EVP_EncodeBlock(); - -void EVP_DecodeInit(); -int EVP_DecodeUpdate(); -int EVP_DecodeFinal(); -int EVP_DecodeBlock(); - -void ERR_load_EVP_strings(); - -void EVP_CIPHER_CTX_init(); -void EVP_CIPHER_CTX_cleanup(); - -#ifdef HEADER_BIO_H -BIO_METHOD *BIO_f_md(); -BIO_METHOD *BIO_f_base64(); -BIO_METHOD *BIO_f_cipher(); -void BIO_set_cipher(); -#endif - -EVP_MD *EVP_md_null(); -EVP_MD *EVP_md2(); -EVP_MD *EVP_md5(); -EVP_MD *EVP_sha(); -EVP_MD *EVP_sha1(); -EVP_MD *EVP_dss(); -EVP_MD *EVP_dss1(); -EVP_MD *EVP_mdc2(); - -EVP_CIPHER *EVP_enc_null(); -EVP_CIPHER *EVP_des_ecb(); -EVP_CIPHER *EVP_des_ede(); -EVP_CIPHER *EVP_des_ede3(); -EVP_CIPHER *EVP_des_cfb(); -EVP_CIPHER *EVP_des_ede_cfb(); -EVP_CIPHER *EVP_des_ede3_cfb(); -EVP_CIPHER *EVP_des_ofb(); -EVP_CIPHER *EVP_des_ede_ofb(); -EVP_CIPHER *EVP_des_ede3_ofb(); -EVP_CIPHER *EVP_des_cbc(); -EVP_CIPHER *EVP_des_ede_cbc(); -EVP_CIPHER *EVP_des_ede3_cbc(); -EVP_CIPHER *EVP_desx_cbc(); -EVP_CIPHER *EVP_rc4(); -EVP_CIPHER *EVP_rc4_40(); -EVP_CIPHER *EVP_idea_ecb(); -EVP_CIPHER *EVP_idea_cfb(); -EVP_CIPHER *EVP_idea_ofb(); -EVP_CIPHER *EVP_idea_cbc(); -EVP_CIPHER *EVP_rc2_ecb(); -EVP_CIPHER *EVP_rc2_cbc(); -EVP_CIPHER *EVP_rc2_40_cbc(); -EVP_CIPHER *EVP_rc2_cfb(); -EVP_CIPHER *EVP_rc2_ofb(); -EVP_CIPHER *EVP_bf_ecb(); -EVP_CIPHER *EVP_bf_cbc(); -EVP_CIPHER *EVP_bf_cfb(); -EVP_CIPHER *EVP_bf_ofb(); -EVP_CIPHER *EVP_cast5_ecb(); -EVP_CIPHER *EVP_cast5_cbc(); -EVP_CIPHER *EVP_cast5_cfb(); -EVP_CIPHER *EVP_cast5_ofb(); -EVP_CIPHER *EVP_rc5_32_12_16_cbc(); -EVP_CIPHER *EVP_rc5_32_12_16_ecb(); -EVP_CIPHER *EVP_rc5_32_12_16_cfb(); -EVP_CIPHER *EVP_rc5_32_12_16_ofb(); - -void SSLeay_add_all_algorithms(); -void SSLeay_add_all_ciphers(); -void SSLeay_add_all_digests(); - -int EVP_add_cipher(); -int EVP_add_digest(); -int EVP_add_alias(); -int EVP_delete_alias(); - -EVP_CIPHER *EVP_get_cipherbyname(); -EVP_MD *EVP_get_digestbyname(); -void EVP_cleanup(); - -int EVP_PKEY_decrypt(); -int EVP_PKEY_encrypt(); -int EVP_PKEY_type(); -int EVP_PKEY_bits(); -int EVP_PKEY_size(); -int EVP_PKEY_assign(); -EVP_PKEY * EVP_PKEY_new(); -void EVP_PKEY_free(); -EVP_PKEY * d2i_PublicKey(); -int i2d_PublicKey(); - -EVP_PKEY * d2i_PrivateKey(); -int i2d_PrivateKey(); - -int EVP_PKEY_copy_parameters(); -int EVP_PKEY_missing_parameters(); -int EVP_PKEY_save_parameters(); -int EVP_PKEY_cmp_parameters(); - -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); - -int EVP_CIPHER_set_asn1_iv(); -int EVP_CIPHER_get_asn1_iv(); - -#endif +/* PKCS5 password based encryption */ +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const 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, const EVP_CIPHER *cipher, const 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, const EVP_CIPHER *cipher, const 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. + */ +void ERR_load_EVP_strings(void); + /* Error codes for the EVP functions. */ /* Function codes. */ #define EVP_F_D2I_PKEY 100 +#define EVP_F_EVP_CIPHERINIT 123 +#define EVP_F_EVP_CIPHER_CTX_CTRL 124 +#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122 #define EVP_F_EVP_DECRYPTFINAL 101 +#define EVP_F_EVP_DIGESTINIT 128 +#define EVP_F_EVP_ENCRYPTFINAL 127 +#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_RIJNDAEL 126 #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 +#define EVP_F_RC5_CTRL 125 /* Reason codes. */ +#define EVP_R_BAD_BLOCK_LENGTH 136 #define EVP_R_BAD_DECRYPT 100 +#define EVP_R_BAD_KEY_LENGTH 137 +#define EVP_R_BN_DECODE_ERROR 112 +#define EVP_R_BN_PUBKEY_ERROR 113 +#define EVP_R_CIPHER_PARAMETER_ERROR 122 +#define EVP_R_CTRL_NOT_IMPLEMENTED 132 +#define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 +#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138 +#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_INITIALIZATION_ERROR 134 +#define EVP_R_INPUT_NOT_INITIALIZED 111 +#define EVP_R_INVALID_KEY_LENGTH 130 #define EVP_R_IV_TOO_LARGE 102 -#define EVP_R_MISSING_PARMATERS 103 +#define EVP_R_KEYGEN_FAILURE 120 +#define EVP_R_MISSING_PARAMETERS 103 +#define EVP_R_NO_CIPHER_SET 131 +#define EVP_R_NO_DIGEST_SET 139 +#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_UNSUPORTED_NUMBER_OF_ROUNDS 135 #define EVP_R_UNSUPPORTED_CIPHER 107 -#define EVP_R_WRONG_FINAL_BLOCK_LENGTH 108 -#define EVP_R_WRONG_PUBLIC_KEY_TYPE 109 - +#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/src/lib/libcrypto/evp/evp_enc.c b/src/lib/libcrypto/evp/evp_enc.c index 93cc3a9464..32a1c7a2e9 100644 --- a/src/lib/libcrypto/evp/evp_enc.c +++ b/src/lib/libcrypto/evp/evp_enc.c @@ -58,218 +58,369 @@ #include #include "cryptlib.h" -#include "evp.h" +#include +#include +#include +#include "evp_locl.h" -char *EVP_version="EVP part of SSLeay 0.9.0b 29-Jun-1998"; +#include -void EVP_CIPHER_CTX_init(ctx) -EVP_CIPHER_CTX *ctx; +const char *EVP_version="EVP" OPENSSL_VERSION_PTEXT; + +void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) { memset(ctx,0,sizeof(EVP_CIPHER_CTX)); /* ctx->cipher=NULL; */ } -void EVP_CipherInit(ctx,data,key,iv,enc) -EVP_CIPHER_CTX *ctx; -EVP_CIPHER *data; -unsigned char *key; -unsigned char *iv; -int enc; + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv, int enc) { - if (enc) - EVP_EncryptInit(ctx,data,key,iv); - else - EVP_DecryptInit(ctx,data,key,iv); + if (cipher) + EVP_CIPHER_CTX_init(ctx); + return EVP_CipherInit_ex(ctx,cipher,NULL,key,iv,enc); } -void EVP_CipherUpdate(ctx,out,outl,in,inl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; -unsigned char *in; -int inl; +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, const unsigned char *iv, int enc) + { + if (enc == -1) + enc = ctx->encrypt; + else + { + if (enc) + enc = 1; + ctx->encrypt = enc; + } + /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts + * so this context may already have an ENGINE! Try to avoid releasing + * the previous handle, re-querying for an ENGINE, and having a + * reinitialisation, when it may all be unecessary. */ + if (ctx->engine && ctx->cipher && (!cipher || + (cipher && (cipher->nid == ctx->cipher->nid)))) + goto skip_to_init; + if (cipher) + { + /* Ensure a context left lying around from last time is cleared + * (the previous check attempted to avoid this if the same + * ENGINE and EVP_CIPHER could be used). */ + EVP_CIPHER_CTX_cleanup(ctx); + + /* Restore encrypt field: it is zeroed by cleanup */ + ctx->encrypt = enc; + if(impl) + { + if (!ENGINE_init(impl)) + { + EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } + else + /* Ask if an ENGINE is reserved for this job */ + impl = ENGINE_get_cipher_engine(cipher->nid); + if(impl) + { + /* There's an ENGINE for this job ... (apparently) */ + const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid); + if(!c) + { + /* One positive side-effect of US's export + * control history, is that we should at least + * be able to avoid using US mispellings of + * "initialisation"? */ + EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR); + return 0; + } + /* We'll use the ENGINE's private cipher definition */ + cipher = c; + /* Store the ENGINE functional reference so we know + * 'cipher' came from an ENGINE and we need to release + * it when done. */ + ctx->engine = impl; + } + else + ctx->engine = NULL; + + ctx->cipher=cipher; + ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size); + ctx->key_len = cipher->key_len; + ctx->flags = 0; + if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) + { + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) + { + EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } + } + else if(!ctx->cipher) + { + EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_NO_CIPHER_SET); + return 0; + } +skip_to_init: + /* we assume block size is a power of 2 in *cryptUpdate */ + assert(ctx->cipher->block_size == 1 + || ctx->cipher->block_size == 8 + || ctx->cipher->block_size == 16); + + if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { + switch(EVP_CIPHER_CTX_mode(ctx)) { + + case EVP_CIPH_STREAM_CIPHER: + case EVP_CIPH_ECB_MODE: + break; + + case EVP_CIPH_CFB_MODE: + case EVP_CIPH_OFB_MODE: + + ctx->num = 0; + + case EVP_CIPH_CBC_MODE: + + if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); + memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); + break; + + default: + return 0; + break; + } + } + + if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { + if(!ctx->cipher->init(ctx,key,iv,enc)) return 0; + } + ctx->buf_len=0; + ctx->final_used=0; + ctx->block_mask=ctx->cipher->block_size-1; + return 1; + } + +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) { if (ctx->encrypt) - EVP_EncryptUpdate(ctx,out,outl,in,inl); - else EVP_DecryptUpdate(ctx,out,outl,in,inl); + return EVP_EncryptUpdate(ctx,out,outl,in,inl); + else return EVP_DecryptUpdate(ctx,out,outl,in,inl); } -int EVP_CipherFinal(ctx,out,outl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; +int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { if (ctx->encrypt) - { - EVP_EncryptFinal(ctx,out,outl); - return(1); - } - else return(EVP_DecryptFinal(ctx,out,outl)); + return EVP_EncryptFinal_ex(ctx,out,outl); + else return EVP_DecryptFinal_ex(ctx,out,outl); } -void EVP_EncryptInit(ctx,cipher,key,iv) -EVP_CIPHER_CTX *ctx; -EVP_CIPHER *cipher; -unsigned char *key; -unsigned char *iv; +int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { - if (cipher != NULL) - ctx->cipher=cipher; - ctx->cipher->init(ctx,key,iv,1); - ctx->encrypt=1; - ctx->buf_len=0; + if (ctx->encrypt) + return EVP_EncryptFinal(ctx,out,outl); + else return EVP_DecryptFinal(ctx,out,outl); } -void EVP_DecryptInit(ctx,cipher,key,iv) -EVP_CIPHER_CTX *ctx; -EVP_CIPHER *cipher; -unsigned char *key; -unsigned char *iv; +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv) { - if (cipher != NULL) - ctx->cipher=cipher; - ctx->cipher->init(ctx,key,iv,0); - ctx->encrypt=0; - ctx->buf_len=0; + return EVP_CipherInit(ctx, cipher, key, iv, 1); + } + +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, const unsigned char *iv) + { + return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1); + } + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv) + { + return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0); } +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, + const unsigned char *key, const unsigned char *iv) + { + return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0); + } -void EVP_EncryptUpdate(ctx,out,outl,in,inl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; -unsigned char *in; -int inl; +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) { int i,j,bl; + if(ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0) + { + if(ctx->cipher->do_cipher(ctx,out,in,inl)) + { + *outl=inl; + return 1; + } + else + { + *outl=0; + return 0; + } + } i=ctx->buf_len; bl=ctx->cipher->block_size; - *outl=0; - if ((inl == 0) && (i != bl)) return; if (i != 0) { if (i+inl < bl) { memcpy(&(ctx->buf[i]),in,inl); ctx->buf_len+=inl; - return; + *outl=0; + return 1; } else { j=bl-i; - if (j != 0) memcpy(&(ctx->buf[i]),in,j); - ctx->cipher->do_cipher(ctx,out,ctx->buf,bl); + memcpy(&(ctx->buf[i]),in,j); + if(!ctx->cipher->do_cipher(ctx,out,ctx->buf,bl)) return 0; inl-=j; in+=j; out+=bl; - *outl+=bl; + *outl=bl; } } - i=inl%bl; /* how much is left */ + else + *outl = 0; + i=inl&(bl-1); inl-=i; if (inl > 0) { - ctx->cipher->do_cipher(ctx,out,in,inl); + if(!ctx->cipher->do_cipher(ctx,out,in,inl)) return 0; *outl+=inl; } if (i != 0) memcpy(ctx->buf,&(in[inl]),i); ctx->buf_len=i; + return 1; } -void EVP_EncryptFinal(ctx,out,outl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; +int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { - int i,n,b,bl; + int ret; + ret = EVP_EncryptFinal_ex(ctx, out, outl); + return ret; + } + +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) + { + int i,n,b,bl,ret; b=ctx->cipher->block_size; if (b == 1) { *outl=0; - return; + return 1; } bl=ctx->buf_len; + if (ctx->flags & EVP_CIPH_NO_PADDING) + { + if(bl) + { + EVPerr(EVP_F_EVP_ENCRYPTFINAL,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); + return 0; + } + *outl = 0; + return 1; + } + n=b-bl; for (i=bl; ibuf[i]=n; - ctx->cipher->do_cipher(ctx,out,ctx->buf,b); - *outl=b; + ret=ctx->cipher->do_cipher(ctx,out,ctx->buf,b); + + + if(ret) + *outl=b; + + return ret; } -void EVP_DecryptUpdate(ctx,out,outl,in,inl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; -unsigned char *in; -int inl; +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl) { - int b,bl,n; - int keep_last=0; + int b, fix_len; - *outl=0; - if (inl == 0) return; + if (inl == 0) + { + *outl=0; + return 1; + } + + if (ctx->flags & EVP_CIPH_NO_PADDING) + return EVP_EncryptUpdate(ctx, out, outl, in, inl); b=ctx->cipher->block_size; - if (b > 1) + + if(ctx->final_used) { - /* Is the input a multiple of the block size? */ - bl=ctx->buf_len; - n=inl+bl; - if (n%b == 0) - { - if (inl < b) /* must be 'just one' buff */ - { - memcpy(&(ctx->buf[bl]),in,inl); - ctx->buf_len=b; - *outl=0; - return; - } - keep_last=1; - inl-=b; /* don't do the last block */ - } + memcpy(out,ctx->final,b); + out+=b; + fix_len = 1; } - EVP_EncryptUpdate(ctx,out,outl,in,inl); + else + fix_len = 0; + + + if(!EVP_EncryptUpdate(ctx,out,outl,in,inl)) + return 0; /* if we have 'decrypted' a multiple of block size, make sure * we have a copy of this last block */ - if (keep_last) + if (b > 1 && !ctx->buf_len) { - memcpy(&(ctx->buf[0]),&(in[inl]),b); -#ifdef DEBUG - if (ctx->buf_len != 0) - { - abort(); - } -#endif - ctx->buf_len=b; + *outl-=b; + ctx->final_used=1; + memcpy(ctx->final,&out[*outl],b); } + else + ctx->final_used = 0; + + if (fix_len) + *outl += b; + + return 1; } -int EVP_DecryptFinal(ctx,out,outl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; +int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) + { + int ret; + ret = EVP_DecryptFinal_ex(ctx, out, outl); + return ret; + } + +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { int i,b; int n; *outl=0; b=ctx->cipher->block_size; + if (ctx->flags & EVP_CIPH_NO_PADDING) + { + if(ctx->buf_len) + { + EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); + return 0; + } + *outl = 0; + return 1; + } if (b > 1) { - if (ctx->buf_len != b) + if (ctx->buf_len || !ctx->final_used) { EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_WRONG_FINAL_BLOCK_LENGTH); return(0); } - EVP_EncryptUpdate(ctx,ctx->buf,&n,ctx->buf,0); - if (n != b) - return(0); - n=ctx->buf[b-1]; + n=ctx->final[b-1]; if (n > b) { EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_BAD_DECRYPT); @@ -277,7 +428,7 @@ int *outl; } for (i=0; ibuf[--b] != n) + if (ctx->final[--b] != n) { EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_BAD_DECRYPT); return(0); @@ -285,7 +436,7 @@ int *outl; } n=ctx->cipher->block_size-n; for (i=0; ibuf[i]; + out[i]=ctx->final[i]; *outl=n; } else @@ -293,11 +444,64 @@ int *outl; return(1); } -void EVP_CIPHER_CTX_cleanup(c) -EVP_CIPHER_CTX *c; +int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) { - if ((c->cipher != NULL) && (c->cipher->cleanup != NULL)) - c->cipher->cleanup(c); + if (c->cipher != NULL) + { + if(c->cipher->cleanup && !c->cipher->cleanup(c)) + return 0; + /* Zero cipher context data */ + if (c->cipher_data) + memset(c->cipher_data, 0, c->cipher->ctx_size); + } + if (c->cipher_data) + OPENSSL_free(c->cipher_data); + if (c->engine) + /* The EVP_CIPHER we used belongs to an ENGINE, release the + * functional reference we held for this reason. */ + ENGINE_finish(c->engine); memset(c,0,sizeof(EVP_CIPHER_CTX)); + return 1; + } + +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) + { + if(c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) + return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL); + if(c->key_len == keylen) return 1; + if((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) + { + c->key_len = keylen; + return 1; + } + EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,EVP_R_INVALID_KEY_LENGTH); + return 0; + } + +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) + { + if (pad) ctx->flags &= ~EVP_CIPH_NO_PADDING; + else ctx->flags |= EVP_CIPH_NO_PADDING; + return 1; + } + +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ + int ret; + if(!ctx->cipher) { + EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET); + return 0; } + if(!ctx->cipher->ctrl) { + EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED); + return 0; + } + + ret = ctx->cipher->ctrl(ctx, type, arg, ptr); + if(ret == -1) { + EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED); + return 0; + } + return ret; +} diff --git a/src/lib/libcrypto/evp/evp_err.c b/src/lib/libcrypto/evp/evp_err.c index 2b0a0ab93f..3a23d21c21 100644 --- a/src/lib/libcrypto/evp/evp_err.c +++ b/src/lib/libcrypto/evp/evp_err.c @@ -1,105 +1,157 @@ -/* lib/evp/evp_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/evp/evp_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "evp.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA EVP_str_functs[]= { {ERR_PACK(0,EVP_F_D2I_PKEY,0), "D2I_PKEY"}, +{ERR_PACK(0,EVP_F_EVP_CIPHERINIT,0), "EVP_CipherInit"}, +{ERR_PACK(0,EVP_F_EVP_CIPHER_CTX_CTRL,0), "EVP_CIPHER_CTX_ctrl"}, +{ERR_PACK(0,EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,0), "EVP_CIPHER_CTX_set_key_length"}, {ERR_PACK(0,EVP_F_EVP_DECRYPTFINAL,0), "EVP_DecryptFinal"}, +{ERR_PACK(0,EVP_F_EVP_DIGESTINIT,0), "EVP_DigestInit"}, +{ERR_PACK(0,EVP_F_EVP_ENCRYPTFINAL,0), "EVP_EncryptFinal"}, +{ERR_PACK(0,EVP_F_EVP_MD_CTX_COPY,0), "EVP_MD_CTX_copy"}, {ERR_PACK(0,EVP_F_EVP_OPENINIT,0), "EVP_OpenInit"}, +{ERR_PACK(0,EVP_F_EVP_PBE_ALG_ADD,0), "EVP_PBE_alg_add"}, +{ERR_PACK(0,EVP_F_EVP_PBE_CIPHERINIT,0), "EVP_PBE_CipherInit"}, +{ERR_PACK(0,EVP_F_EVP_PKCS82PKEY,0), "EVP_PKCS82PKEY"}, +{ERR_PACK(0,EVP_F_EVP_PKCS8_SET_BROKEN,0), "EVP_PKCS8_SET_BROKEN"}, +{ERR_PACK(0,EVP_F_EVP_PKEY2PKCS8,0), "EVP_PKEY2PKCS8"}, {ERR_PACK(0,EVP_F_EVP_PKEY_COPY_PARAMETERS,0), "EVP_PKEY_copy_parameters"}, {ERR_PACK(0,EVP_F_EVP_PKEY_DECRYPT,0), "EVP_PKEY_decrypt"}, {ERR_PACK(0,EVP_F_EVP_PKEY_ENCRYPT,0), "EVP_PKEY_encrypt"}, +{ERR_PACK(0,EVP_F_EVP_PKEY_GET1_DH,0), "EVP_PKEY_get1_DH"}, +{ERR_PACK(0,EVP_F_EVP_PKEY_GET1_DSA,0), "EVP_PKEY_get1_DSA"}, +{ERR_PACK(0,EVP_F_EVP_PKEY_GET1_RSA,0), "EVP_PKEY_get1_RSA"}, {ERR_PACK(0,EVP_F_EVP_PKEY_NEW,0), "EVP_PKEY_new"}, +{ERR_PACK(0,EVP_F_EVP_RIJNDAEL,0), "EVP_RIJNDAEL"}, {ERR_PACK(0,EVP_F_EVP_SIGNFINAL,0), "EVP_SignFinal"}, {ERR_PACK(0,EVP_F_EVP_VERIFYFINAL,0), "EVP_VerifyFinal"}, -{0,NULL}, +{ERR_PACK(0,EVP_F_PKCS5_PBE_KEYIVGEN,0), "PKCS5_PBE_keyivgen"}, +{ERR_PACK(0,EVP_F_PKCS5_V2_PBE_KEYIVGEN,0), "PKCS5_v2_PBE_keyivgen"}, +{ERR_PACK(0,EVP_F_RC2_MAGIC_TO_METH,0), "RC2_MAGIC_TO_METH"}, +{ERR_PACK(0,EVP_F_RC5_CTRL,0), "RC5_CTRL"}, +{0,NULL} }; static ERR_STRING_DATA EVP_str_reasons[]= { +{EVP_R_BAD_BLOCK_LENGTH ,"bad block length"}, {EVP_R_BAD_DECRYPT ,"bad decrypt"}, +{EVP_R_BAD_KEY_LENGTH ,"bad key length"}, +{EVP_R_BN_DECODE_ERROR ,"bn decode error"}, +{EVP_R_BN_PUBKEY_ERROR ,"bn pubkey error"}, +{EVP_R_CIPHER_PARAMETER_ERROR ,"cipher parameter error"}, +{EVP_R_CTRL_NOT_IMPLEMENTED ,"ctrl not implemented"}, +{EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED ,"ctrl operation not implemented"}, +{EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH ,"data not multiple of block length"}, +{EVP_R_DECODE_ERROR ,"decode error"}, {EVP_R_DIFFERENT_KEY_TYPES ,"different key types"}, +{EVP_R_ENCODE_ERROR ,"encode error"}, +{EVP_R_EVP_PBE_CIPHERINIT_ERROR ,"evp pbe cipherinit error"}, +{EVP_R_EXPECTING_AN_RSA_KEY ,"expecting an rsa key"}, +{EVP_R_EXPECTING_A_DH_KEY ,"expecting a dh key"}, +{EVP_R_EXPECTING_A_DSA_KEY ,"expecting a dsa key"}, +{EVP_R_INITIALIZATION_ERROR ,"initialization error"}, +{EVP_R_INPUT_NOT_INITIALIZED ,"input not initialized"}, +{EVP_R_INVALID_KEY_LENGTH ,"invalid key length"}, {EVP_R_IV_TOO_LARGE ,"iv too large"}, -{EVP_R_MISSING_PARMATERS ,"missing parmaters"}, +{EVP_R_KEYGEN_FAILURE ,"keygen failure"}, +{EVP_R_MISSING_PARAMETERS ,"missing parameters"}, +{EVP_R_NO_CIPHER_SET ,"no cipher set"}, +{EVP_R_NO_DIGEST_SET ,"no digest set"}, +{EVP_R_NO_DSA_PARAMETERS ,"no dsa parameters"}, {EVP_R_NO_SIGN_FUNCTION_CONFIGURED ,"no sign function configured"}, {EVP_R_NO_VERIFY_FUNCTION_CONFIGURED ,"no verify function configured"}, +{EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE ,"pkcs8 unknown broken type"}, {EVP_R_PUBLIC_KEY_NOT_RSA ,"public key not rsa"}, +{EVP_R_UNKNOWN_PBE_ALGORITHM ,"unknown pbe algorithm"}, +{EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS ,"unsuported number of rounds"}, {EVP_R_UNSUPPORTED_CIPHER ,"unsupported cipher"}, +{EVP_R_UNSUPPORTED_KEYLENGTH ,"unsupported keylength"}, +{EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION,"unsupported key derivation function"}, +{EVP_R_UNSUPPORTED_KEY_SIZE ,"unsupported key size"}, +{EVP_R_UNSUPPORTED_PRF ,"unsupported prf"}, +{EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM ,"unsupported private key algorithm"}, +{EVP_R_UNSUPPORTED_SALT_TYPE ,"unsupported salt type"}, {EVP_R_WRONG_FINAL_BLOCK_LENGTH ,"wrong final block length"}, {EVP_R_WRONG_PUBLIC_KEY_TYPE ,"wrong public key type"}, -{0,NULL}, +{0,NULL} }; #endif -void ERR_load_EVP_strings() +void ERR_load_EVP_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_EVP,EVP_str_functs); ERR_load_strings(ERR_LIB_EVP,EVP_str_reasons); #endif diff --git a/src/lib/libcrypto/evp/evp_key.c b/src/lib/libcrypto/evp/evp_key.c index dafa686f64..4271393069 100644 --- a/src/lib/libcrypto/evp/evp_key.c +++ b/src/lib/libcrypto/evp/evp_key.c @@ -58,23 +58,26 @@ #include #include "cryptlib.h" -#include "x509.h" -#include "objects.h" -#include "evp.h" +#include +#include +#include +#include /* should be init to zeros. */ static char prompt_string[80]; -void EVP_set_pw_prompt(prompt) -char *prompt; +void EVP_set_pw_prompt(char *prompt) { if (prompt == NULL) prompt_string[0]='\0'; else + { strncpy(prompt_string,prompt,79); + prompt_string[79]='\0'; + } } -char *EVP_get_pw_prompt() +char *EVP_get_pw_prompt(void) { if (prompt_string[0] == '\0') return(NULL); @@ -82,30 +85,31 @@ char *EVP_get_pw_prompt() return(prompt_string); } -#ifdef NO_DES -int des_read_pw_string(char *buf,int len,char *prompt,int verify); -#endif - -int EVP_read_pw_string(buf,len,prompt,verify) -char *buf; -int len; -char *prompt; -int verify; +/* For historical reasons, the standard function for reading passwords is + * in the DES library -- if someone ever wants to disable DES, + * this function will fail */ +int EVP_read_pw_string(char *buf, int len, const char *prompt, int verify) { + int ret; + char buff[BUFSIZ]; + UI *ui; + if ((prompt == NULL) && (prompt_string[0] != '\0')) prompt=prompt_string; - return(des_read_pw_string(buf,len,prompt,verify)); + ui = UI_new(); + UI_add_input_string(ui,prompt,0,buf,0,(len>=BUFSIZ)?BUFSIZ-1:len); + if (verify) + UI_add_verify_string(ui,prompt,0, + buff,0,(len>=BUFSIZ)?BUFSIZ-1:len,buf); + ret = UI_process(ui); + UI_free(ui); + memset(buff,0,BUFSIZ); + return ret; } -int EVP_BytesToKey(type,md,salt,data,datal,count,key,iv) -EVP_CIPHER *type; -EVP_MD *md; -unsigned char *salt; -unsigned char *data; -int datal; -int count; -unsigned char *key; -unsigned char *iv; +int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const unsigned char *salt, const unsigned char *data, int datal, + int count, unsigned char *key, unsigned char *iv) { EVP_MD_CTX c; unsigned char md_buf[EVP_MAX_MD_SIZE]; @@ -117,21 +121,22 @@ unsigned char *iv; if (data == NULL) return(nkey); + EVP_MD_CTX_init(&c); for (;;) { - EVP_DigestInit(&c,md); + EVP_DigestInit_ex(&c,md, NULL); if (addmd++) EVP_DigestUpdate(&c,&(md_buf[0]),mds); EVP_DigestUpdate(&c,data,datal); if (salt != NULL) - EVP_DigestUpdate(&c,salt,8); - EVP_DigestFinal(&c,&(md_buf[0]),&mds); + EVP_DigestUpdate(&c,salt,PKCS5_SALT_LEN); + EVP_DigestFinal_ex(&c,&(md_buf[0]),&mds); for (i=1; i<(unsigned int)count; i++) { - EVP_DigestInit(&c,md); + EVP_DigestInit_ex(&c,md, NULL); EVP_DigestUpdate(&c,&(md_buf[0]),mds); - EVP_DigestFinal(&c,&(md_buf[0]),&mds); + EVP_DigestFinal_ex(&c,&(md_buf[0]),&mds); } i=0; if (nkey) @@ -160,7 +165,7 @@ unsigned char *iv; } if ((nkey == 0) && (niv == 0)) break; } - memset(&c,0,sizeof(c)); + EVP_MD_CTX_cleanup(&c); memset(&(md_buf[0]),0,EVP_MAX_MD_SIZE); return(type->key_len); } diff --git a/src/lib/libcrypto/evp/evp_lib.c b/src/lib/libcrypto/evp/evp_lib.c index 69784eb555..a431945ef5 100644 --- a/src/lib/libcrypto/evp/evp_lib.c +++ b/src/lib/libcrypto/evp/evp_lib.c @@ -58,12 +58,10 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" +#include +#include -int EVP_CIPHER_param_to_asn1(c,type) -EVP_CIPHER_CTX *c; -ASN1_TYPE *type; +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int ret; @@ -74,9 +72,7 @@ ASN1_TYPE *type; return(ret); } -int EVP_CIPHER_asn1_to_param(c,type) -EVP_CIPHER_CTX *c; -ASN1_TYPE *type; +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int ret; @@ -87,9 +83,7 @@ ASN1_TYPE *type; return(ret); } -int EVP_CIPHER_get_asn1_iv(c,type) -EVP_CIPHER_CTX *c; -ASN1_TYPE *type; +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int i=0,l; @@ -97,14 +91,15 @@ ASN1_TYPE *type; { l=EVP_CIPHER_CTX_iv_length(c); i=ASN1_TYPE_get_octetstring(type,c->oiv,l); - memcpy(c->iv,c->oiv,l); + if (i != l) + return(-1); + else if (i > 0) + memcpy(c->iv,c->oiv,l); } return(i); } -int EVP_CIPHER_set_asn1_iv(c,type) -EVP_CIPHER_CTX *c; -ASN1_TYPE *type; +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int i=0,j; @@ -115,3 +110,33 @@ ASN1_TYPE *type; } return(i); } + +/* Convert the various cipher NIDs and dummies to a proper OID NID */ +int EVP_CIPHER_type(const EVP_CIPHER *ctx) +{ + int nid; + ASN1_OBJECT *otmp; + nid = EVP_CIPHER_nid(ctx); + + switch(nid) { + + case NID_rc2_cbc: + case NID_rc2_64_cbc: + case NID_rc2_40_cbc: + + return NID_rc2_cbc; + + case NID_rc4: + case NID_rc4_40: + + return NID_rc4; + + default: + /* Check it has an OID and it is valid */ + otmp = OBJ_nid2obj(nid); + if(!otmp || !otmp->data) nid = NID_undef; + ASN1_OBJECT_free(otmp); + return nid; + } +} + diff --git a/src/lib/libcrypto/evp/evp_locl.h b/src/lib/libcrypto/evp/evp_locl.h index ce49d5b7d8..7b088b4848 100644 --- a/src/lib/libcrypto/evp/evp_locl.h +++ b/src/lib/libcrypto/evp/evp_locl.h @@ -61,50 +61,107 @@ /* Wrapper functions for each cipher mode */ #define BLOCK_CIPHER_ecb_loop() \ - unsigned int i; \ - if(inl < 8) return 1;\ - inl -= 8; \ - for(i=0; i <= inl; i+=8) \ + unsigned int i, bl; \ + bl = ctx->cipher->block_size;\ + if(inl < bl) return 1;\ + inl -= bl; \ + for(i=0; i <= inl; i+=bl) \ -#define BLOCK_CIPHER_func_ecb(cname, cprefix, kname) \ +#define BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \ static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ {\ BLOCK_CIPHER_ecb_loop() \ - cprefix##_ecb_encrypt(in + i, out + i, &ctx->c.kname, ctx->encrypt);\ + cprefix##_ecb_encrypt(in + i, out + i, &((kstruct *)ctx->cipher_data)->ksched, ctx->encrypt);\ return 1;\ } -#define BLOCK_CIPHER_func_ofb(cname, cprefix, kname) \ +#define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \ static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ {\ - cprefix##_ofb64_encrypt(in, out, (long)inl, &ctx->c.kname, ctx->iv, &ctx->num);\ + cprefix##_ofb##cbits##_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num);\ return 1;\ } -#define BLOCK_CIPHER_func_cbc(cname, cprefix, kname) \ +#define BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \ static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ {\ - cprefix##_cbc_encrypt(in, out, (long)inl, &ctx->c.kname, ctx->iv, ctx->encrypt);\ + cprefix##_cbc_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, ctx->encrypt);\ return 1;\ } -#define BLOCK_CIPHER_func_cfb(cname, cprefix, kname) \ +#define BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \ static int cname##_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) \ {\ - cprefix##_cfb64_encrypt(in, out, (long)inl, &ctx->c.kname, ctx->iv, &ctx->num, ctx->encrypt);\ + cprefix##_cfb##cbits##_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num, ctx->encrypt);\ return 1;\ } -#define BLOCK_CIPHER_all_funcs(cname, cprefix, kname) \ - BLOCK_CIPHER_func_cbc(cname, cprefix, kname) \ - BLOCK_CIPHER_func_cfb(cname, cprefix, kname) \ - BLOCK_CIPHER_func_ecb(cname, cprefix, kname) \ - BLOCK_CIPHER_func_ofb(cname, cprefix, kname) +#define BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \ + BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \ + BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \ + BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \ + BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) +#define BLOCK_CIPHER_def1(cname, nmode, mode, MODE, kstruct, nid, block_size, \ + key_len, iv_len, flags, init_key, cleanup, \ + set_asn1, get_asn1, ctrl) \ +static const EVP_CIPHER cname##_##mode = { \ + nid##_##nmode, block_size, key_len, iv_len, \ + flags | EVP_CIPH_##MODE##_MODE, \ + init_key, \ + cname##_##mode##_cipher, \ + cleanup, \ + sizeof(kstruct), \ + set_asn1, get_asn1,\ + ctrl, \ + NULL \ +}; \ +const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; } + +#define BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, \ + iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, cbc, cbc, CBC, kstruct, nid, block_size, key_len, \ + iv_len, flags, init_key, cleanup, set_asn1, get_asn1, ctrl) + +#define BLOCK_CIPHER_def_cfb(cname, kstruct, nid, block_size, key_len, \ + iv_len, cbits, flags, init_key, cleanup, \ + set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, cfb##cbits, cfb, CFB, kstruct, nid, block_size, \ + key_len, iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) + +#define BLOCK_CIPHER_def_ofb(cname, kstruct, nid, block_size, key_len, \ + iv_len, cbits, flags, init_key, cleanup, \ + set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, ofb##cbits, ofb, OFB, kstruct, nid, block_size, \ + key_len, iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) + +#define BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, \ + iv_len, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) \ +BLOCK_CIPHER_def1(cname, ecb, ecb, ECB, kstruct, nid, block_size, key_len, \ + iv_len, flags, init_key, cleanup, set_asn1, get_asn1, ctrl) + +#define BLOCK_CIPHER_defs(cname, kstruct, \ + nid, block_size, key_len, iv_len, cbits, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, iv_len, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_cfb(cname, kstruct, nid, block_size, key_len, iv_len, cbits, \ + flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_ofb(cname, kstruct, nid, block_size, key_len, iv_len, cbits, \ + flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \ +BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, iv_len, flags, \ + init_key, cleanup, set_asn1, get_asn1, ctrl) + + +/* #define BLOCK_CIPHER_defs(cname, kstruct, \ nid, block_size, key_len, iv_len, flags,\ init_key, cleanup, set_asn1, get_asn1, ctrl)\ -static EVP_CIPHER cname##_cbc = {\ +static const EVP_CIPHER cname##_cbc = {\ nid##_cbc, block_size, key_len, iv_len, \ flags | EVP_CIPH_CBC_MODE,\ init_key,\ @@ -116,8 +173,8 @@ static EVP_CIPHER cname##_cbc = {\ ctrl, \ NULL \ };\ -EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\ -static EVP_CIPHER cname##_cfb = {\ +const EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\ +static const EVP_CIPHER cname##_cfb = {\ nid##_cfb64, 1, key_len, iv_len, \ flags | EVP_CIPH_CFB_MODE,\ init_key,\ @@ -129,8 +186,8 @@ static EVP_CIPHER cname##_cfb = {\ ctrl,\ NULL \ };\ -EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\ -static EVP_CIPHER cname##_ofb = {\ +const EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\ +static const EVP_CIPHER cname##_ofb = {\ nid##_ofb64, 1, key_len, iv_len, \ flags | EVP_CIPH_OFB_MODE,\ init_key,\ @@ -142,8 +199,8 @@ static EVP_CIPHER cname##_ofb = {\ ctrl,\ NULL \ };\ -EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\ -static EVP_CIPHER cname##_ecb = {\ +const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\ +static const EVP_CIPHER cname##_ecb = {\ nid##_ecb, block_size, key_len, iv_len, \ flags | EVP_CIPH_ECB_MODE,\ init_key,\ @@ -155,14 +212,16 @@ static EVP_CIPHER cname##_ecb = {\ ctrl,\ NULL \ };\ -EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; } - - +const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; } +*/ -#define IMPLEMENT_BLOCK_CIPHER(cname, kname, cprefix, kstruct, \ - nid, block_size, key_len, iv_len, flags, \ - init_key, cleanup, set_asn1, get_asn1, ctrl) \ - BLOCK_CIPHER_all_funcs(cname, cprefix, kname) \ - BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, flags,\ - init_key, cleanup, set_asn1, get_asn1, ctrl) +#define IMPLEMENT_BLOCK_CIPHER(cname, ksched, cprefix, kstruct, nid, \ + block_size, key_len, iv_len, cbits, \ + flags, init_key, \ + cleanup, set_asn1, get_asn1, ctrl) \ + BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \ + BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, \ + cbits, flags, init_key, cleanup, set_asn1, \ + get_asn1, ctrl) +#define EVP_C_DATA(kstruct, ctx) ((kstruct *)(ctx)->cipher_data) diff --git a/src/lib/libcrypto/evp/evp_pbe.c b/src/lib/libcrypto/evp/evp_pbe.c index 353c3ad667..06afb9d152 100644 --- a/src/lib/libcrypto/evp/evp_pbe.c +++ b/src/lib/libcrypto/evp/evp_pbe.c @@ -69,8 +69,8 @@ static STACK *pbe_algs; typedef struct { int pbe_nid; -EVP_CIPHER *cipher; -EVP_MD *md; +const EVP_CIPHER *cipher; +const EVP_MD *md; EVP_PBE_KEYGEN *keygen; } EVP_PBE_CTL; @@ -92,7 +92,8 @@ int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, ERR_add_error_data(2, "TYPE=", obj_tmp); return 0; } - if (passlen == -1) passlen = strlen(pass); + if(!pass) passlen = 0; + else if (passlen == -1) passlen = strlen(pass); pbetmp = (EVP_PBE_CTL *)sk_value (pbe_algs, i); i = (*pbetmp->keygen)(ctx, pass, passlen, param, pbetmp->cipher, pbetmp->md, en_de); @@ -103,19 +104,20 @@ int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, return 1; } -static int pbe_cmp (EVP_PBE_CTL **pbe1, EVP_PBE_CTL **pbe2) +static int pbe_cmp(const char * const *a, const char * const *b) { + EVP_PBE_CTL **pbe1 = (EVP_PBE_CTL **) a, **pbe2 = (EVP_PBE_CTL **)b; return ((*pbe1)->pbe_nid - (*pbe2)->pbe_nid); } /* Add a PBE algorithm */ -int EVP_PBE_alg_add (int nid, EVP_CIPHER *cipher, EVP_MD *md, +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, EVP_PBE_KEYGEN *keygen) { EVP_PBE_CTL *pbe_tmp; - if (!pbe_algs) pbe_algs = sk_new (pbe_cmp); - if (!(pbe_tmp = (EVP_PBE_CTL*) Malloc (sizeof(EVP_PBE_CTL)))) { + if (!pbe_algs) pbe_algs = sk_new(pbe_cmp); + if (!(pbe_tmp = (EVP_PBE_CTL*) OPENSSL_malloc (sizeof(EVP_PBE_CTL)))) { EVPerr(EVP_F_EVP_PBE_ALG_ADD,ERR_R_MALLOC_FAILURE); return 0; } @@ -129,6 +131,6 @@ int EVP_PBE_alg_add (int nid, EVP_CIPHER *cipher, EVP_MD *md, void EVP_PBE_cleanup(void) { - sk_pop_free(pbe_algs, FreeFunc); + sk_pop_free(pbe_algs, OPENSSL_freeFunc); pbe_algs = NULL; } diff --git a/src/lib/libcrypto/evp/evp_pkey.c b/src/lib/libcrypto/evp/evp_pkey.c index 421e452db1..34b5b1d21c 100644 --- a/src/lib/libcrypto/evp/evp_pkey.c +++ b/src/lib/libcrypto/evp/evp_pkey.c @@ -62,41 +62,40 @@ #include #include +#ifndef OPENSSL_NO_DSA +static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey); +#endif + /* Extract a private key from a PKCS8 structure */ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8) { - EVP_PKEY *pkey; -#ifndef NO_RSA - RSA *rsa; + EVP_PKEY *pkey = NULL; +#ifndef OPENSSL_NO_RSA + RSA *rsa = NULL; #endif -#ifndef NO_DSA - DSA *dsa; - ASN1_INTEGER *dsapriv; - STACK *ndsa; - BN_CTX *ctx; +#ifndef OPENSSL_NO_DSA + DSA *dsa = NULL; + ASN1_INTEGER *privkey; + ASN1_TYPE *t1, *t2, *param = NULL; + STACK_OF(ASN1_TYPE) *ndsa = NULL; + BN_CTX *ctx = NULL; int plen; #endif X509_ALGOR *a; unsigned char *p; + const unsigned char *cp; int pkeylen; char obj_tmp[80]; - switch (p8->broken) { - case PKCS8_OK: + if(p8->pkey->type == V_ASN1_OCTET_STRING) { + p8->broken = PKCS8_OK; p = p8->pkey->value.octet_string->data; pkeylen = p8->pkey->value.octet_string->length; - break; - - case PKCS8_NO_OCTET: + } else { + p8->broken = PKCS8_NO_OCTET; p = p8->pkey->value.sequence->data; pkeylen = p8->pkey->value.sequence->length; - break; - - default: - EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE); - return NULL; - break; } if (!(pkey = EVP_PKEY_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); @@ -105,81 +104,108 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8) a = p8->pkeyalg; switch (OBJ_obj2nid(a->algorithm)) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case NID_rsaEncryption: - if (!(rsa = d2i_RSAPrivateKey (NULL, &p, pkeylen))) { + cp = p; + if (!(rsa = d2i_RSAPrivateKey (NULL,&cp, pkeylen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); return NULL; } EVP_PKEY_assign_RSA (pkey, rsa); break; #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA case NID_dsa: /* PKCS#8 DSA is weird: you just get a private key integer * and parameters in the AlgorithmIdentifier the pubkey must * be recalculated. */ - /* Check for broken Netscape Database DSA PKCS#8, UGH! */ + /* Check for broken DSA PKCS#8, UGH! */ if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { - if(!(ndsa = ASN1_seq_unpack(p, pkeylen, - (char *(*)())d2i_ASN1_INTEGER, - ASN1_STRING_free))) { + if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pkeylen, + d2i_ASN1_TYPE, + ASN1_TYPE_free))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); - return NULL; + goto dsaerr; } - if(sk_num(ndsa) != 2 ) { + if(sk_ASN1_TYPE_num(ndsa) != 2 ) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); - sk_pop_free(ndsa, ASN1_STRING_free); - return NULL; + goto dsaerr; } - dsapriv = (ASN1_INTEGER *) sk_pop(ndsa); - sk_pop_free(ndsa, ASN1_STRING_free); - } else if (!(dsapriv=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { + /* Handle Two broken types: + * SEQUENCE {parameters, priv_key} + * SEQUENCE {pub_key, priv_key} + */ + + t1 = sk_ASN1_TYPE_value(ndsa, 0); + t2 = sk_ASN1_TYPE_value(ndsa, 1); + if(t1->type == V_ASN1_SEQUENCE) { + p8->broken = PKCS8_EMBEDDED_PARAM; + param = t1; + } else if(a->parameter->type == V_ASN1_SEQUENCE) { + p8->broken = PKCS8_NS_DB; + param = a->parameter; + } else { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); - return NULL; + goto dsaerr; + } + + if(t2->type != V_ASN1_INTEGER) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + goto dsaerr; + } + privkey = t2->value.integer; + } else { + if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + goto dsaerr; + } + param = p8->pkeyalg->parameter; } - /* Retrieve parameters */ - if (a->parameter->type != V_ASN1_SEQUENCE) { - EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_NO_DSA_PARAMETERS); - return NULL; + if (!param || (param->type != V_ASN1_SEQUENCE)) { + EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); + goto dsaerr; } - p = a->parameter->value.sequence->data; - plen = a->parameter->value.sequence->length; - if (!(dsa = d2i_DSAparams (NULL, &p, plen))) { + cp = p = param->value.sequence->data; + plen = param->value.sequence->length; + if (!(dsa = d2i_DSAparams (NULL, &cp, plen))) { EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR); - return NULL; + goto dsaerr; } /* We have parameters now set private key */ - if (!(dsa->priv_key = ASN1_INTEGER_to_BN(dsapriv, NULL))) { + if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR); - DSA_free (dsa); - return NULL; + goto dsaerr; } /* Calculate public key (ouch!) */ if (!(dsa->pub_key = BN_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); - DSA_free (dsa); - return NULL; + goto dsaerr; } if (!(ctx = BN_CTX_new())) { EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE); - DSA_free (dsa); - return NULL; + goto dsaerr; } if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) { EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR); - BN_CTX_free (ctx); - DSA_free (dsa); - return NULL; + goto dsaerr; } - EVP_PKEY_assign_DSA (pkey, dsa); + EVP_PKEY_assign_DSA(pkey, dsa); BN_CTX_free (ctx); + if(ndsa) sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); + else ASN1_INTEGER_free(privkey); + break; + dsaerr: + BN_CTX_free (ctx); + sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); + DSA_free(dsa); + EVP_PKEY_free(pkey); + return NULL; break; #endif default: @@ -193,30 +219,35 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8) return pkey; } +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) +{ + return EVP_PKEY2PKCS8_broken(pkey, PKCS8_OK); +} + /* Turn a private key into a PKCS8 structure */ -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 *p8; -#ifndef NO_DSA - ASN1_INTEGER *dpkey; - unsigned char *p, *q; - int len; -#endif + if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) { EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); return NULL; } + p8->broken = broken; ASN1_INTEGER_set (p8->version, 0); if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) { EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); PKCS8_PRIV_KEY_INFO_free (p8); return NULL; } + p8->pkey->type = V_ASN1_OCTET_STRING; switch (EVP_PKEY_type(pkey->type)) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: + if(p8->broken == PKCS8_NO_OCTET) p8->pkey->type = V_ASN1_SEQUENCE; + p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption); p8->pkeyalg->parameter->type = V_ASN1_NULL; if (!ASN1_pack_string ((char *)pkey, i2d_PrivateKey, @@ -227,38 +258,13 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) } break; #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: - p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa); - - /* get paramaters and place in AlgorithmIdentifier */ - len = i2d_DSAparams (pkey->pkey.dsa, NULL); - if (!(p = Malloc(len))) { - EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); - PKCS8_PRIV_KEY_INFO_free (p8); - return NULL; - } - q = p; - i2d_DSAparams (pkey->pkey.dsa, &q); - p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; - p8->pkeyalg->parameter->value.sequence = ASN1_STRING_new(); - ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, len); - Free(p); - /* Get private key into an integer and pack */ - if (!(dpkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) { - EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); + if(!dsa_pkey2pkcs8(p8, pkey)) { PKCS8_PRIV_KEY_INFO_free (p8); return NULL; } - - if (!ASN1_pack_string((char *)dpkey, i2d_ASN1_INTEGER, - &p8->pkey->value.octet_string)) { - EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); - ASN1_INTEGER_free (dpkey); - PKCS8_PRIV_KEY_INFO_free (p8); - return NULL; - } - ASN1_INTEGER_free (dpkey); + break; #endif default: @@ -266,9 +272,8 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) PKCS8_PRIV_KEY_INFO_free (p8); return NULL; } - p8->pkey->type = V_ASN1_OCTET_STRING; - RAND_seed (p8->pkey->value.octet_string->data, - p8->pkey->value.octet_string->length); + RAND_add(p8->pkey->value.octet_string->data, + p8->pkey->value.octet_string->length, 0); return p8; } @@ -295,4 +300,113 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken) } } +#ifndef OPENSSL_NO_DSA +static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey) +{ + ASN1_STRING *params; + ASN1_INTEGER *prkey; + ASN1_TYPE *ttmp; + STACK_OF(ASN1_TYPE) *ndsa; + unsigned char *p, *q; + int len; + + p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa); + len = i2d_DSAparams (pkey->pkey.dsa, NULL); + if (!(p = OPENSSL_malloc(len))) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + PKCS8_PRIV_KEY_INFO_free (p8); + return 0; + } + q = p; + i2d_DSAparams (pkey->pkey.dsa, &q); + params = ASN1_STRING_new(); + ASN1_STRING_set(params, p, len); + OPENSSL_free(p); + /* Get private key into integer */ + if (!(prkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); + return 0; + } + + switch(p8->broken) { + + case PKCS8_OK: + case PKCS8_NO_OCTET: + + if (!ASN1_pack_string((char *)prkey, i2d_ASN1_INTEGER, + &p8->pkey->value.octet_string)) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + M_ASN1_INTEGER_free (prkey); + return 0; + } + + M_ASN1_INTEGER_free (prkey); + p8->pkeyalg->parameter->value.sequence = params; + p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; + + break; + + case PKCS8_NS_DB: + + p8->pkeyalg->parameter->value.sequence = params; + p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE; + ndsa = sk_ASN1_TYPE_new_null(); + ttmp = ASN1_TYPE_new(); + if (!(ttmp->value.integer = BN_to_ASN1_INTEGER (pkey->pkey.dsa->pub_key, NULL))) { + EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR); + PKCS8_PRIV_KEY_INFO_free(p8); + return 0; + } + ttmp->type = V_ASN1_INTEGER; + sk_ASN1_TYPE_push(ndsa, ttmp); + + ttmp = ASN1_TYPE_new(); + ttmp->value.integer = prkey; + ttmp->type = V_ASN1_INTEGER; + sk_ASN1_TYPE_push(ndsa, ttmp); + + p8->pkey->value.octet_string = ASN1_OCTET_STRING_new(); + + if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE, + &p8->pkey->value.octet_string->data, + &p8->pkey->value.octet_string->length)) { + + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); + M_ASN1_INTEGER_free(prkey); + return 0; + } + sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); + break; + case PKCS8_EMBEDDED_PARAM: + + p8->pkeyalg->parameter->type = V_ASN1_NULL; + ndsa = sk_ASN1_TYPE_new_null(); + ttmp = ASN1_TYPE_new(); + ttmp->value.sequence = params; + ttmp->type = V_ASN1_SEQUENCE; + sk_ASN1_TYPE_push(ndsa, ttmp); + + ttmp = ASN1_TYPE_new(); + ttmp->value.integer = prkey; + ttmp->type = V_ASN1_INTEGER; + sk_ASN1_TYPE_push(ndsa, ttmp); + + p8->pkey->value.octet_string = ASN1_OCTET_STRING_new(); + + if (!ASN1_seq_pack_ASN1_TYPE(ndsa, i2d_ASN1_TYPE, + &p8->pkey->value.octet_string->data, + &p8->pkey->value.octet_string->length)) { + + EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE); + sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); + M_ASN1_INTEGER_free (prkey); + return 0; + } + sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free); + break; + } + return 1; +} +#endif diff --git a/src/lib/libcrypto/evp/m_dss.c b/src/lib/libcrypto/evp/m_dss.c index 3549b1699c..beb8d7fc5c 100644 --- a/src/lib/libcrypto/evp/m_dss.c +++ b/src/lib/libcrypto/evp/m_dss.c @@ -58,25 +58,38 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -static EVP_MD dsa_md= +#ifndef OPENSSL_NO_SHA +static int init(EVP_MD_CTX *ctx) + { return SHA1_Init(ctx->md_data); } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return SHA1_Update(ctx->md_data,data,count); } + +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return SHA1_Final(md,ctx->md_data); } + +static const EVP_MD dsa_md= { NID_dsaWithSHA, NID_dsaWithSHA, SHA_DIGEST_LENGTH, - SHA1_Init, - SHA1_Update, - SHA1_Final, + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_DSA_method, SHA_CBLOCK, sizeof(EVP_MD *)+sizeof(SHA_CTX), }; -EVP_MD *EVP_dss() +const EVP_MD *EVP_dss(void) { return(&dsa_md); } - +#endif diff --git a/src/lib/libcrypto/evp/m_dss1.c b/src/lib/libcrypto/evp/m_dss1.c index ff256b7b20..f5668ebda0 100644 --- a/src/lib/libcrypto/evp/m_dss1.c +++ b/src/lib/libcrypto/evp/m_dss1.c @@ -56,26 +56,40 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_SHA #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -static EVP_MD dss1_md= +static int init(EVP_MD_CTX *ctx) + { return SHA1_Init(ctx->md_data); } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return SHA1_Update(ctx->md_data,data,count); } + +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return SHA1_Final(md,ctx->md_data); } + +static const EVP_MD dss1_md= { NID_dsa, NID_dsaWithSHA1, SHA_DIGEST_LENGTH, - SHA1_Init, - SHA1_Update, - SHA1_Final, + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_DSA_method, SHA_CBLOCK, sizeof(EVP_MD *)+sizeof(SHA_CTX), }; -EVP_MD *EVP_dss1() +const EVP_MD *EVP_dss1(void) { return(&dss1_md); } +#endif diff --git a/src/lib/libcrypto/evp/m_md4.c b/src/lib/libcrypto/evp/m_md4.c index 6a24ceb86d..e19b663754 100644 --- a/src/lib/libcrypto/evp/m_md4.c +++ b/src/lib/libcrypto/evp/m_md4.c @@ -56,27 +56,40 @@ * [including the GNU Public Licence.] */ -#ifndef NO_MD4 +#ifndef OPENSSL_NO_MD4 #include #include "cryptlib.h" #include #include #include +#include -static EVP_MD md4_md= +static int init(EVP_MD_CTX *ctx) + { return MD4_Init(ctx->md_data); } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return MD4_Update(ctx->md_data,data,count); } + +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return MD4_Final(md,ctx->md_data); } + +static const EVP_MD md4_md= { NID_md4, - 0, + NID_md4WithRSAEncryption, MD4_DIGEST_LENGTH, - MD4_Init, - MD4_Update, - MD4_Final, + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_RSA_method, MD4_CBLOCK, sizeof(EVP_MD *)+sizeof(MD4_CTX), }; -EVP_MD *EVP_md4(void) +const EVP_MD *EVP_md4(void) { return(&md4_md); } diff --git a/src/lib/libcrypto/evp/m_md5.c b/src/lib/libcrypto/evp/m_md5.c index d65db9aa1d..b00a03e048 100644 --- a/src/lib/libcrypto/evp/m_md5.c +++ b/src/lib/libcrypto/evp/m_md5.c @@ -56,26 +56,41 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_MD5 #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include -static EVP_MD md5_md= +static int init(EVP_MD_CTX *ctx) + { return MD5_Init(ctx->md_data); } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return MD5_Update(ctx->md_data,data,count); } + +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return MD5_Final(md,ctx->md_data); } + +static const EVP_MD md5_md= { NID_md5, NID_md5WithRSAEncryption, MD5_DIGEST_LENGTH, - MD5_Init, - MD5_Update, - MD5_Final, + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_RSA_method, MD5_CBLOCK, sizeof(EVP_MD *)+sizeof(MD5_CTX), }; -EVP_MD *EVP_md5() +const EVP_MD *EVP_md5(void) { return(&md5_md); } +#endif diff --git a/src/lib/libcrypto/evp/m_null.c b/src/lib/libcrypto/evp/m_null.c index 6d80560df2..f6f0a1d2c0 100644 --- a/src/lib/libcrypto/evp/m_null.c +++ b/src/lib/libcrypto/evp/m_null.c @@ -58,29 +58,36 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -static void function() - { - } +static int init(EVP_MD_CTX *ctx) + { return 1; } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return 1; } -static EVP_MD null_md= +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return 1; } + +static const EVP_MD null_md= { NID_undef, NID_undef, 0, - function, - function, - function, - + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_NULL_method, 0, sizeof(EVP_MD *), }; -EVP_MD *EVP_md_null() +const EVP_MD *EVP_md_null(void) { return(&null_md); } diff --git a/src/lib/libcrypto/evp/m_ripemd.c b/src/lib/libcrypto/evp/m_ripemd.c index 04c5d8897b..64725528dc 100644 --- a/src/lib/libcrypto/evp/m_ripemd.c +++ b/src/lib/libcrypto/evp/m_ripemd.c @@ -56,26 +56,41 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_RIPEMD #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include -static EVP_MD ripemd160_md= +static int init(EVP_MD_CTX *ctx) + { return RIPEMD160_Init(ctx->md_data); } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return RIPEMD160_Update(ctx->md_data,data,count); } + +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return RIPEMD160_Final(md,ctx->md_data); } + +static const EVP_MD ripemd160_md= { NID_ripemd160, NID_ripemd160WithRSA, RIPEMD160_DIGEST_LENGTH, - RIPEMD160_Init, - RIPEMD160_Update, - RIPEMD160_Final, + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_RSA_method, RIPEMD160_CBLOCK, sizeof(EVP_MD *)+sizeof(RIPEMD160_CTX), }; -EVP_MD *EVP_ripemd160() +const EVP_MD *EVP_ripemd160(void) { return(&ripemd160_md); } +#endif diff --git a/src/lib/libcrypto/evp/m_sha1.c b/src/lib/libcrypto/evp/m_sha1.c index 87135a9cf2..d6be3502f0 100644 --- a/src/lib/libcrypto/evp/m_sha1.c +++ b/src/lib/libcrypto/evp/m_sha1.c @@ -56,26 +56,40 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_SHA #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -static EVP_MD sha1_md= +static int init(EVP_MD_CTX *ctx) + { return SHA1_Init(ctx->md_data); } + +static int update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { return SHA1_Update(ctx->md_data,data,count); } + +static int final(EVP_MD_CTX *ctx,unsigned char *md) + { return SHA1_Final(md,ctx->md_data); } + +static const EVP_MD sha1_md= { NID_sha1, NID_sha1WithRSAEncryption, SHA_DIGEST_LENGTH, - SHA1_Init, - SHA1_Update, - SHA1_Final, + 0, + init, + update, + final, + NULL, + NULL, EVP_PKEY_RSA_method, SHA_CBLOCK, sizeof(EVP_MD *)+sizeof(SHA_CTX), }; -EVP_MD *EVP_sha1() +const EVP_MD *EVP_sha1(void) { return(&sha1_md); } +#endif diff --git a/src/lib/libcrypto/evp/names.c b/src/lib/libcrypto/evp/names.c index e0774da20d..eb9f4329cd 100644 --- a/src/lib/libcrypto/evp/names.c +++ b/src/lib/libcrypto/evp/names.c @@ -58,228 +58,66 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" +#include +#include +#include -typedef struct aliases_st { - char *alias; - /* This must be the last field becaue I will allocate things - * so they go off the end of it */ - char name[4]; - } ALIASES; - -static STACK /* ALIASES */ *aliases=NULL; -static STACK /* EVP_CIPHERS */ *ciphers=NULL; -static STACK /* EVP_MD */ *digests=NULL; - -static int cipher_nid_cmp(a,b) -EVP_CIPHER **a,**b; - { return((*a)->nid - (*b)->nid); } - -static int digest_type_cmp(a,b) -EVP_MD **a,**b; - { return((*a)->pkey_type - (*b)->pkey_type); } - -int EVP_add_cipher(c) -EVP_CIPHER *c; - { - int i; - - if (ciphers == NULL) - { - ciphers=sk_new(cipher_nid_cmp); - if (ciphers == NULL) return(0); - } - if ((i=sk_find(ciphers,(char *)c)) >= 0) - { - if (sk_value(ciphers,i) == (char *)c) - return(1); - sk_delete(ciphers,i); - } - return(sk_push(ciphers,(char *)c)); - } - -int EVP_add_digest(md) -EVP_MD *md; +int EVP_add_cipher(const EVP_CIPHER *c) { - int i; - char *n; + int r; - if (digests == NULL) - { - digests=sk_new(digest_type_cmp); - if (digests == NULL) return(0); - } - if ((i=sk_find(digests,(char *)md)) >= 0) - { - if (sk_value(digests,i) == (char *)md) - return(1); - sk_delete(digests,i); - } - if (md->type != md->pkey_type) - { - n=OBJ_nid2sn(md->pkey_type); - EVP_add_alias(n,OBJ_nid2sn(md->type)); - EVP_add_alias(n,OBJ_nid2ln(md->type)); - } - sk_push(digests,(char *)md); - return(1); - } - -static int alias_cmp(a,b) -ALIASES **a,**b; - { - return(strcmp((*a)->alias,(*b)->alias)); + r=OBJ_NAME_add(OBJ_nid2sn(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c); + if (r == 0) return(0); + r=OBJ_NAME_add(OBJ_nid2ln(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c); + return(r); } -int EVP_add_alias(name,aname) -char *name; -char *aname; +int EVP_add_digest(const EVP_MD *md) { - int l1,l2,i; - ALIASES *a; - char *p; + int r; + const char *name; - if ((name == NULL) || (aname == NULL)) return(0); - l1=strlen(name)+1; - l2=strlen(aname)+1; - i=sizeof(ALIASES)+l1+l2; - if ((a=(ALIASES *)Malloc(i)) == NULL) - return(0); - strcpy(a->name,name); - p= &(a->name[l1]); - strcpy(p,aname); - a->alias=p; + name=OBJ_nid2sn(md->type); + r=OBJ_NAME_add(name,OBJ_NAME_TYPE_MD_METH,(char *)md); + if (r == 0) return(0); + r=OBJ_NAME_add(OBJ_nid2ln(md->type),OBJ_NAME_TYPE_MD_METH,(char *)md); + if (r == 0) return(0); - if (aliases == NULL) - { - aliases=sk_new(alias_cmp); - if (aliases == NULL) goto err; - } - - if ((i=sk_find(aliases,(char *)a)) >= 0) + if (md->type != md->pkey_type) { - Free(sk_delete(aliases,i)); + r=OBJ_NAME_add(OBJ_nid2sn(md->pkey_type), + OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,name); + if (r == 0) return(0); + r=OBJ_NAME_add(OBJ_nid2ln(md->pkey_type), + OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,name); } - if (!sk_push(aliases,(char *)a)) goto err; - return(1); -err: - return(0); + return(r); } -int EVP_delete_alias(name) -char *name; +const EVP_CIPHER *EVP_get_cipherbyname(const char *name) { - ALIASES a; - int i; + const EVP_CIPHER *cp; - if (aliases != NULL) - { - a.alias=name; - if ((i=sk_find(aliases,(char *)&a)) >= 0) - { - Free(sk_delete(aliases,i)); - return(1); - } - } - return(0); + cp=(const EVP_CIPHER *)OBJ_NAME_get(name,OBJ_NAME_TYPE_CIPHER_METH); + return(cp); } -EVP_CIPHER *EVP_get_cipherbyname(name) -char *name; +const EVP_MD *EVP_get_digestbyname(const char *name) { - int nid,num=6,i; - EVP_CIPHER c,*cp; - ALIASES a,*ap; - - if (ciphers == NULL) return(NULL); - for (;;) - { - if (num-- <= 0) return(NULL); - if (aliases != NULL) - { - a.alias=name; - i=sk_find(aliases,(char *)&a); - if (i >= 0) - { - ap=(ALIASES *)sk_value(aliases,i); - name=ap->name; - continue; - } - } + const EVP_MD *cp; - nid=OBJ_txt2nid(name); - if (nid == NID_undef) return(NULL); - c.nid=nid; - i=sk_find(ciphers,(char *)&c); - if (i >= 0) - { - cp=(EVP_CIPHER *)sk_value(ciphers,i); - return(cp); - } - else - return(NULL); - } + cp=(const EVP_MD *)OBJ_NAME_get(name,OBJ_NAME_TYPE_MD_METH); + return(cp); } -EVP_MD *EVP_get_digestbyname(name) -char *name; +void EVP_cleanup(void) { - int nid,num=6,i; - EVP_MD c,*cp; - ALIASES a,*ap; - - if (digests == NULL) return(NULL); - - for (;;) - { - if (num-- <= 0) return(NULL); - - if (aliases != NULL) - { - a.alias=name; - i=sk_find(aliases,(char *)&a); - if (i >= 0) - { - ap=(ALIASES *)sk_value(aliases,i); - name=ap->name; - continue; - } - } - - nid=OBJ_txt2nid(name); - if (nid == NID_undef) return(NULL); - c.pkey_type=nid; - i=sk_find(digests,(char *)&c); - if (i >= 0) - { - cp=(EVP_MD *)sk_value(digests,i); - return(cp); - } - else - return(NULL); - } - } - -void EVP_cleanup() - { - int i; - - if (aliases != NULL) - { - for (i=0; isalt->data; saltlen = pbe->salt->length; - EVP_DigestInit (&ctx, md); - EVP_DigestUpdate (&ctx, pass, passlen); - EVP_DigestUpdate (&ctx, salt, saltlen); + if(!pass) passlen = 0; + else if(passlen == -1) passlen = strlen(pass); + + EVP_MD_CTX_init(&ctx); + EVP_DigestInit_ex(&ctx, md, NULL); + EVP_DigestUpdate(&ctx, pass, passlen); + EVP_DigestUpdate(&ctx, salt, saltlen); PBEPARAM_free(pbe); - EVP_DigestFinal (&ctx, md_tmp, NULL); + EVP_DigestFinal_ex(&ctx, md_tmp, NULL); for (i = 1; i < iter; i++) { - EVP_DigestInit(&ctx, md); + EVP_DigestInit_ex(&ctx, md, NULL); EVP_DigestUpdate(&ctx, md_tmp, EVP_MD_size(md)); - EVP_DigestFinal (&ctx, md_tmp, NULL); + EVP_DigestFinal_ex (&ctx, md_tmp, NULL); } - memcpy (key, md_tmp, EVP_CIPHER_key_length(cipher)); - memcpy (iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), + EVP_MD_CTX_cleanup(&ctx); + memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher)); + memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), EVP_CIPHER_iv_length(cipher)); - EVP_CipherInit(cctx, cipher, key, iv, en_de); + EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de); memset(md_tmp, 0, EVP_MAX_MD_SIZE); memset(key, 0, EVP_MAX_KEY_LENGTH); memset(iv, 0, EVP_MAX_IV_LENGTH); diff --git a/src/lib/libcrypto/evp/p5_crpt2.c b/src/lib/libcrypto/evp/p5_crpt2.c index 27a2c518be..7881860b53 100644 --- a/src/lib/libcrypto/evp/p5_crpt2.c +++ b/src/lib/libcrypto/evp/p5_crpt2.c @@ -55,7 +55,7 @@ * Hudson (tjh@cryptsoft.com). * */ -#if !defined(NO_HMAC) && !defined(NO_SHA) +#if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA) #include #include #include @@ -84,9 +84,12 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, int cplen, j, k, tkeylen; unsigned long i = 1; HMAC_CTX hctx; + + HMAC_CTX_init(&hctx); p = out; tkeylen = keylen; - if(passlen == -1) passlen = strlen(pass); + if(!pass) passlen = 0; + else if(passlen == -1) passlen = strlen(pass); while(tkeylen) { if(tkeylen > SHA_DIGEST_LENGTH) cplen = SHA_DIGEST_LENGTH; else cplen = tkeylen; @@ -97,7 +100,7 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, itmp[1] = (unsigned char)((i >> 16) & 0xff); itmp[2] = (unsigned char)((i >> 8) & 0xff); itmp[3] = (unsigned char)(i & 0xff); - HMAC_Init(&hctx, pass, passlen, EVP_sha1()); + HMAC_Init_ex(&hctx, pass, passlen, EVP_sha1(), NULL); HMAC_Update(&hctx, salt, saltlen); HMAC_Update(&hctx, itmp, 4); HMAC_Final(&hctx, digtmp, NULL); @@ -111,7 +114,7 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, i++; p+= cplen; } - HMAC_cleanup(&hctx); + HMAC_CTX_cleanup(&hctx); #ifdef DEBUG_PKCS5V2 fprintf(stderr, "Password:\n"); h__dump (pass, passlen); @@ -142,7 +145,7 @@ main() */ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, - ASN1_TYPE *param, EVP_CIPHER *c, EVP_MD *md, + ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) { unsigned char *pbuf, *salt, key[EVP_MAX_KEY_LENGTH]; @@ -180,7 +183,7 @@ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, } /* Fixup cipher based on AlgorithmIdentifier */ - EVP_CipherInit(ctx, cipher, NULL, NULL, en_de); + EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de); if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR); @@ -226,7 +229,7 @@ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, saltlen = kdf->salt->value.octet_string->length; iter = ASN1_INTEGER_get(kdf->iter); PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, salt, saltlen, iter, keylen, key); - EVP_CipherInit(ctx, NULL, key, NULL, en_de); + EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); memset(key, 0, keylen); PBKDF2PARAM_free(kdf); return 1; diff --git a/src/lib/libcrypto/evp/p_dec.c b/src/lib/libcrypto/evp/p_dec.c index e845ce70c7..8af620400e 100644 --- a/src/lib/libcrypto/evp/p_dec.c +++ b/src/lib/libcrypto/evp/p_dec.c @@ -58,27 +58,30 @@ #include #include "cryptlib.h" -#include "rand.h" -#include "rsa.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#include +#include +#include -int EVP_PKEY_decrypt(key,ek,ekl,priv) -unsigned char *key; -unsigned char *ek; -int ekl; -EVP_PKEY *priv; +int EVP_PKEY_decrypt(unsigned char *key, unsigned char *ek, int ekl, + EVP_PKEY *priv) { int ret= -1; +#ifndef OPENSSL_NO_RSA if (priv->type != EVP_PKEY_RSA) { +#endif EVPerr(EVP_F_EVP_PKEY_DECRYPT,EVP_R_PUBLIC_KEY_NOT_RSA); +#ifndef OPENSSL_NO_RSA goto err; } ret=RSA_private_decrypt(ekl,ek,key,priv->pkey.rsa,RSA_PKCS1_PADDING); err: +#endif return(ret); } diff --git a/src/lib/libcrypto/evp/p_enc.c b/src/lib/libcrypto/evp/p_enc.c index a26bfad02a..656883b996 100644 --- a/src/lib/libcrypto/evp/p_enc.c +++ b/src/lib/libcrypto/evp/p_enc.c @@ -58,26 +58,29 @@ #include #include "cryptlib.h" -#include "rand.h" -#include "rsa.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#include +#include +#include -int EVP_PKEY_encrypt(ek,key,key_len,pubk) -unsigned char *ek; -unsigned char *key; -int key_len; -EVP_PKEY *pubk; +int EVP_PKEY_encrypt(unsigned char *ek, unsigned char *key, int key_len, + EVP_PKEY *pubk) { int ret=0; +#ifndef OPENSSL_NO_RSA if (pubk->type != EVP_PKEY_RSA) { +#endif EVPerr(EVP_F_EVP_PKEY_ENCRYPT,EVP_R_PUBLIC_KEY_NOT_RSA); +#ifndef OPENSSL_NO_RSA goto err; } ret=RSA_public_encrypt(key_len,key,ek,pubk->pkey.rsa,RSA_PKCS1_PADDING); err: +#endif return(ret); } diff --git a/src/lib/libcrypto/evp/p_lib.c b/src/lib/libcrypto/evp/p_lib.c index 395351b373..215b94292a 100644 --- a/src/lib/libcrypto/evp/p_lib.c +++ b/src/lib/libcrypto/evp/p_lib.c @@ -58,58 +58,49 @@ #include #include "cryptlib.h" -#include "objects.h" -#include "evp.h" -#include "asn1_mac.h" -#include "x509.h" +#include +#include +#include +#include -/* EVPerr(EVP_F_D2I_PKEY,EVP_R_UNSUPPORTED_CIPHER); */ -/* EVPerr(EVP_F_D2I_PKEY,EVP_R_IV_TOO_LARGE); */ - -#ifndef NOPROTO static void EVP_PKEY_free_it(EVP_PKEY *x); -#else -static void EVP_PKEY_free_it(); -#endif -int EVP_PKEY_bits(pkey) -EVP_PKEY *pkey; +int EVP_PKEY_bits(EVP_PKEY *pkey) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) return(BN_num_bits(pkey->pkey.rsa->n)); else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) return(BN_num_bits(pkey->pkey.dsa->p)); #endif return(0); } -int EVP_PKEY_size(pkey) -EVP_PKEY *pkey; +int EVP_PKEY_size(EVP_PKEY *pkey) { -#ifndef NO_RSA + if (pkey == NULL) + return(0); +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) return(RSA_size(pkey->pkey.rsa)); else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) return(DSA_size(pkey->pkey.dsa)); #endif return(0); } -int EVP_PKEY_save_parameters(pkey,mode) -EVP_PKEY *pkey; -int mode; +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) { -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { - int ret=pkey->save_parameters=mode; + int ret=pkey->save_parameters; if (mode >= 0) pkey->save_parameters=mode; @@ -119,8 +110,7 @@ int mode; return(0); } -int EVP_PKEY_copy_parameters(to,from) -EVP_PKEY *to,*from; +int EVP_PKEY_copy_parameters(EVP_PKEY *to, EVP_PKEY *from) { if (to->type != from->type) { @@ -130,10 +120,10 @@ EVP_PKEY *to,*from; if (EVP_PKEY_missing_parameters(from)) { - EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS,EVP_R_MISSING_PARMATERS); + EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS,EVP_R_MISSING_PARAMETERS); goto err; } -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (to->type == EVP_PKEY_DSA) { BIGNUM *a; @@ -156,10 +146,9 @@ err: return(0); } -int EVP_PKEY_missing_parameters(pkey) -EVP_PKEY *pkey; +int EVP_PKEY_missing_parameters(EVP_PKEY *pkey) { -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { DSA *dsa; @@ -172,10 +161,9 @@ EVP_PKEY *pkey; return(0); } -int EVP_PKEY_cmp_parameters(a,b) -EVP_PKEY *a,*b; +int EVP_PKEY_cmp_parameters(EVP_PKEY *a, EVP_PKEY *b) { -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if ((a->type == EVP_PKEY_DSA) && (b->type == EVP_PKEY_DSA)) { if ( BN_cmp(a->pkey.dsa->p,b->pkey.dsa->p) || @@ -189,11 +177,11 @@ EVP_PKEY *a,*b; return(-1); } -EVP_PKEY *EVP_PKEY_new() +EVP_PKEY *EVP_PKEY_new(void) { EVP_PKEY *ret; - ret=(EVP_PKEY *)Malloc(sizeof(EVP_PKEY)); + ret=(EVP_PKEY *)OPENSSL_malloc(sizeof(EVP_PKEY)); if (ret == NULL) { EVPerr(EVP_F_EVP_PKEY_NEW,ERR_R_MALLOC_FAILURE); @@ -207,10 +195,7 @@ EVP_PKEY *EVP_PKEY_new() return(ret); } -int EVP_PKEY_assign(pkey,type,key) -EVP_PKEY *pkey; -int type; -char *key; +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key) { if (pkey == NULL) return(0); if (pkey->pkey.ptr != NULL) @@ -218,11 +203,71 @@ char *key; pkey->type=EVP_PKEY_type(type); pkey->save_type=type; pkey->pkey.ptr=key; - return(1); + return(key != NULL); + } + +#ifndef OPENSSL_NO_RSA +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) +{ + int ret = EVP_PKEY_assign_RSA(pkey, key); + if(ret) + RSA_up_ref(key); + return ret; +} + +RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) + { + if(pkey->type != EVP_PKEY_RSA) { + EVPerr(EVP_F_EVP_PKEY_GET1_RSA, EVP_R_EXPECTING_AN_RSA_KEY); + return NULL; } + RSA_up_ref(pkey->pkey.rsa); + return pkey->pkey.rsa; +} +#endif + +#ifndef OPENSSL_NO_DSA +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) +{ + int ret = EVP_PKEY_assign_DSA(pkey, key); + if(ret) + DSA_up_ref(key); + return ret; +} + +DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) + { + if(pkey->type != EVP_PKEY_DSA) { + EVPerr(EVP_F_EVP_PKEY_GET1_DSA, EVP_R_EXPECTING_A_DSA_KEY); + return NULL; + } + DSA_up_ref(pkey->pkey.dsa); + return pkey->pkey.dsa; +} +#endif + +#ifndef OPENSSL_NO_DH + +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) +{ + int ret = EVP_PKEY_assign_DH(pkey, key); + if(ret) + DH_up_ref(key); + return ret; +} + +DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) + { + if(pkey->type != EVP_PKEY_DH) { + EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY); + return NULL; + } + DH_up_ref(pkey->pkey.dh); + return pkey->pkey.dh; +} +#endif -int EVP_PKEY_type(type) -int type; +int EVP_PKEY_type(int type) { switch (type) { @@ -242,8 +287,7 @@ int type; } } -void EVP_PKEY_free(x) -EVP_PKEY *x; +void EVP_PKEY_free(EVP_PKEY *x) { int i; @@ -262,21 +306,20 @@ EVP_PKEY *x; } #endif EVP_PKEY_free_it(x); - Free((char *)x); + OPENSSL_free(x); } -static void EVP_PKEY_free_it(x) -EVP_PKEY *x; +static void EVP_PKEY_free_it(EVP_PKEY *x) { switch (x->type) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: case EVP_PKEY_RSA2: RSA_free(x->pkey.rsa); break; #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: case EVP_PKEY_DSA2: case EVP_PKEY_DSA3: @@ -284,7 +327,7 @@ EVP_PKEY *x; DSA_free(x->pkey.dsa); break; #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH case EVP_PKEY_DH: DH_free(x->pkey.dh); break; diff --git a/src/lib/libcrypto/evp/p_open.c b/src/lib/libcrypto/evp/p_open.c index 28a8e02252..6976f2a867 100644 --- a/src/lib/libcrypto/evp/p_open.c +++ b/src/lib/libcrypto/evp/p_open.c @@ -56,64 +56,68 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_RSA #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -int EVP_OpenInit(ctx,type,ek,ekl,iv,priv) -EVP_CIPHER_CTX *ctx; -EVP_CIPHER *type; -unsigned char *ek; -int ekl; -unsigned char *iv; -EVP_PKEY *priv; +int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *ek, + int ekl, unsigned char *iv, EVP_PKEY *priv) { unsigned char *key=NULL; int i,size=0,ret=0; - + + if(type) { + EVP_CIPHER_CTX_init(ctx); + if(!EVP_DecryptInit_ex(ctx,type,NULL, NULL,NULL)) return 0; + } + + if(!priv) return 1; + if (priv->type != EVP_PKEY_RSA) { EVPerr(EVP_F_EVP_OPENINIT,EVP_R_PUBLIC_KEY_NOT_RSA); - ret= -1; goto err; } size=RSA_size(priv->pkey.rsa); - key=(unsigned char *)Malloc(size+2); + key=(unsigned char *)OPENSSL_malloc(size+2); if (key == NULL) { /* ERROR */ EVPerr(EVP_F_EVP_OPENINIT,ERR_R_MALLOC_FAILURE); - ret= -1; goto err; } i=EVP_PKEY_decrypt(key,ek,ekl,priv); - if (i != type->key_len) + if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) { /* ERROR */ goto err; } + if(!EVP_DecryptInit_ex(ctx,NULL,NULL,key,iv)) goto err; - EVP_CIPHER_CTX_init(ctx); - EVP_DecryptInit(ctx,type,key,iv); ret=1; err: if (key != NULL) memset(key,0,size); - Free(key); + OPENSSL_free(key); return(ret); } -int EVP_OpenFinal(ctx,out,outl) -EVP_CIPHER_CTX *ctx; -unsigned char *out; -int *outl; +int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { int i; - i=EVP_DecryptFinal(ctx,out,outl); - EVP_DecryptInit(ctx,NULL,NULL,NULL); + i=EVP_DecryptFinal_ex(ctx,out,outl); + EVP_DecryptInit_ex(ctx,NULL,NULL,NULL,NULL); return(i); } +#else /* !OPENSSL_NO_RSA */ + +# ifdef PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/src/lib/libcrypto/evp/p_seal.c b/src/lib/libcrypto/evp/p_seal.c index 09a408de35..37e547fe72 100644 --- a/src/lib/libcrypto/evp/p_seal.c +++ b/src/lib/libcrypto/evp/p_seal.c @@ -58,35 +58,36 @@ #include #include "cryptlib.h" -#include "rand.h" -#include "rsa.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#include +#include +#include -int EVP_SealInit(ctx,type,ek,ekl,iv,pubk,npubk) -EVP_CIPHER_CTX *ctx; -EVP_CIPHER *type; -unsigned char **ek; -int *ekl; -unsigned char *iv; -EVP_PKEY **pubk; -int npubk; +int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char **ek, + int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk) { unsigned char key[EVP_MAX_KEY_LENGTH]; int i; - if (npubk <= 0) return(0); - RAND_bytes(key,EVP_MAX_KEY_LENGTH); - if (type->iv_len > 0) - RAND_bytes(iv,type->iv_len); + if(type) { + EVP_CIPHER_CTX_init(ctx); + if(!EVP_EncryptInit_ex(ctx,type,NULL,NULL,NULL)) return 0; + } + if ((npubk <= 0) || !pubk) + return 1; + if (RAND_bytes(key,EVP_MAX_KEY_LENGTH) <= 0) + return 0; + if (EVP_CIPHER_CTX_iv_length(ctx)) + RAND_pseudo_bytes(iv,EVP_CIPHER_CTX_iv_length(ctx)); - EVP_CIPHER_CTX_init(ctx); - EVP_EncryptInit(ctx,type,key,iv); + if(!EVP_EncryptInit_ex(ctx,NULL,NULL,key,iv)) return 0; for (i=0; i #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include #ifdef undef -void EVP_SignInit(ctx,type) -EVP_MD_CTX *ctx; -EVP_MD *type; +void EVP_SignInit(EVP_MD_CTX *ctx, EVP_MD *type) { - EVP_DigestInit(ctx,type); + EVP_DigestInit_ex(ctx,type); } -void EVP_SignUpdate(ctx,data,count) -EVP_MD_CTX *ctx; -unsigned char *data; -unsigned int count; +void EVP_SignUpdate(EVP_MD_CTX *ctx, unsigned char *data, + unsigned int count) { EVP_DigestUpdate(ctx,data,count); } #endif -int EVP_SignFinal(ctx,sigret,siglen,pkey) -EVP_MD_CTX *ctx; -unsigned char *sigret; -unsigned int *siglen; -EVP_PKEY *pkey; +int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, + EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; @@ -91,8 +84,10 @@ EVP_PKEY *pkey; MS_STATIC EVP_MD_CTX tmp_ctx; *siglen=0; - memcpy(&tmp_ctx,ctx,sizeof(EVP_MD_CTX)); - EVP_DigestFinal(&tmp_ctx,&(m[0]),&m_len); + EVP_MD_CTX_init(&tmp_ctx); + EVP_MD_CTX_copy_ex(&tmp_ctx,ctx); + EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len); + EVP_MD_CTX_cleanup(&tmp_ctx); for (i=0; i<4; i++) { v=ctx->digest->required_pkey_type[i]; diff --git a/src/lib/libcrypto/evp/p_verify.c b/src/lib/libcrypto/evp/p_verify.c index 8d727d8f02..d854d743a5 100644 --- a/src/lib/libcrypto/evp/p_verify.c +++ b/src/lib/libcrypto/evp/p_verify.c @@ -58,15 +58,12 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -int EVP_VerifyFinal(ctx,sigbuf,siglen,pkey) -EVP_MD_CTX *ctx; -unsigned char *sigbuf; -unsigned int siglen; -EVP_PKEY *pkey; +int EVP_VerifyFinal(EVP_MD_CTX *ctx, unsigned char *sigbuf, + unsigned int siglen, EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; @@ -88,8 +85,10 @@ EVP_PKEY *pkey; EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_WRONG_PUBLIC_KEY_TYPE); return(-1); } - memcpy(&tmp_ctx,ctx,sizeof(EVP_MD_CTX)); - EVP_DigestFinal(&tmp_ctx,&(m[0]),&m_len); + EVP_MD_CTX_init(&tmp_ctx); + EVP_MD_CTX_copy_ex(&tmp_ctx,ctx); + EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len); + EVP_MD_CTX_cleanup(&tmp_ctx); if (ctx->digest->verify == NULL) { EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_NO_VERIFY_FUNCTION_CONFIGURED); diff --git a/src/lib/libcrypto/ex_data.c b/src/lib/libcrypto/ex_data.c index c858b518ff..5b2e345c27 100644 --- a/src/lib/libcrypto/ex_data.c +++ b/src/lib/libcrypto/ex_data.c @@ -1,4 +1,33 @@ /* crypto/ex_data.c */ + +/* + * Overhaul notes; + * + * This code is now *mostly* thread-safe. It is now easier to understand in what + * ways it is safe and in what ways it is not, which is an improvement. Firstly, + * all per-class stacks and index-counters for ex_data are stored in the same + * global LHASH table (keyed by class). This hash table uses locking for all + * access with the exception of CRYPTO_cleanup_all_ex_data(), which must only be + * called when no other threads can possibly race against it (even if it was + * locked, the race would mean it's possible the hash table might have been + * recreated after the cleanup). As classes can only be added to the hash table, + * and within each class, the stack of methods can only be incremented, the + * locking mechanics are simpler than they would otherwise be. For example, the + * new/dup/free ex_data functions will lock the hash table, copy the method + * pointers it needs from the relevant class, then unlock the hash table before + * actually applying those method pointers to the task of the new/dup/free + * operations. As they can't be removed from the method-stack, only + * supplemented, there's no race conditions associated with using them outside + * the lock. The get/set_ex_data functions are not locked because they do not + * involve this global state at all - they operate directly with a previously + * obtained per-class method index and a particular "ex_data" variable. These + * variables are usually instantiated per-context (eg. each RSA structure has + * one) so locking on read/write access to that variable can be locked locally + * if required (eg. using the "RSA" lock to synchronise access to a + * per-RSA-structure ex_data variable if required). + * [Geoff] + */ + /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -55,182 +84,553 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "buffer.h" -#include "bio.h" -#include "lhash.h" +#include +#include +#include #include "cryptlib.h" -int CRYPTO_get_ex_new_index(idx,skp,argl,argp,new_func,dup_func,free_func) -int idx; -STACK **skp; -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*free_func)(); +/* What an "implementation of ex_data functionality" looks like */ +struct st_CRYPTO_EX_DATA_IMPL + { + /*********************/ + /* GLOBAL OPERATIONS */ + /* Return a new class index */ + int (*cb_new_class)(void); + /* Cleanup all state used by the implementation */ + void (*cb_cleanup)(void); + /************************/ + /* PER-CLASS OPERATIONS */ + /* Get a new method index within a class */ + int (*cb_get_new_index)(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + /* Initialise a new CRYPTO_EX_DATA of a given class */ + int (*cb_new_ex_data)(int class_index, void *obj, + CRYPTO_EX_DATA *ad); + /* Duplicate a CRYPTO_EX_DATA of a given class onto a copy */ + int (*cb_dup_ex_data)(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from); + /* Cleanup a CRYPTO_EX_DATA of a given class */ + void (*cb_free_ex_data)(int class_index, void *obj, + CRYPTO_EX_DATA *ad); + }; + +/* The implementation we use at run-time */ +static const CRYPTO_EX_DATA_IMPL *impl = NULL; + +/* To call "impl" functions, use this macro rather than referring to 'impl' directly, eg. + * EX_IMPL(get_new_index)(...); */ +#define EX_IMPL(a) impl->cb_##a + +/* Predeclare the "default" ex_data implementation */ +static int int_new_class(void); +static void int_cleanup(void); +static int int_get_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +static int int_new_ex_data(int class_index, void *obj, + CRYPTO_EX_DATA *ad); +static int int_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from); +static void int_free_ex_data(int class_index, void *obj, + CRYPTO_EX_DATA *ad); +static CRYPTO_EX_DATA_IMPL impl_default = + { + int_new_class, + int_cleanup, + int_get_new_index, + int_new_ex_data, + int_dup_ex_data, + int_free_ex_data + }; + +/* Internal function that checks whether "impl" is set and if not, sets it to + * the default. */ +static void impl_check(void) + { + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); + if(!impl) + impl = &impl_default; + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + } +/* A macro wrapper for impl_check that first uses a non-locked test before + * invoking the function (which checks again inside a lock). */ +#define IMPL_CHECK if(!impl) impl_check(); + +/* API functions to get/set the "ex_data" implementation */ +const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void) + { + IMPL_CHECK + return impl; + } +int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i) + { + int toret = 0; + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); + if(!impl) + { + impl = i; + toret = 1; + } + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + return toret; + } + +/****************************************************************************/ +/* Interal (default) implementation of "ex_data" support. API functions are + * further down. */ + +/* The type that represents what each "class" used to implement locally. A STACK + * of CRYPTO_EX_DATA_FUNCS plus a index-counter. The 'class_index' is the global + * value representing the class that is used to distinguish these items. */ +typedef struct st_ex_class_item { + int class_index; + STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; + int meth_num; +} EX_CLASS_ITEM; + +/* When assigning new class indexes, this is our counter */ +static int ex_class = CRYPTO_EX_INDEX_USER; + +/* The global hash table of EX_CLASS_ITEM items */ +static LHASH *ex_data = NULL; + +/* The callbacks required in the "ex_data" hash table */ +static unsigned long ex_hash_cb(const void *a_void) + { + return ((const EX_CLASS_ITEM *)a_void)->class_index; + } +static int ex_cmp_cb(const void *a_void, const void *b_void) + { + return (((const EX_CLASS_ITEM *)a_void)->class_index - + ((const EX_CLASS_ITEM *)b_void)->class_index); + } + +/* Internal functions used by the "impl_default" implementation to access the + * state */ + +static int ex_data_check(void) + { + int toret = 1; + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); + if(!ex_data && ((ex_data = lh_new(ex_hash_cb, ex_cmp_cb)) == NULL)) + toret = 0; + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + return toret; + } +/* This macros helps reduce the locking from repeated checks because the + * ex_data_check() function checks ex_data again inside a lock. */ +#define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail} + +/* This "inner" callback is used by the callback function that follows it */ +static void def_cleanup_util_cb(CRYPTO_EX_DATA_FUNCS *funcs) + { + OPENSSL_free(funcs); + } + +/* This callback is used in lh_doall to destroy all EX_CLASS_ITEM values from + * "ex_data" prior to the ex_data hash table being itself destroyed. Doesn't do + * any locking. */ +static void def_cleanup_cb(const void *a_void) { - CRYPTO_EX_DATA_FUNCS *a; + EX_CLASS_ITEM *item = (EX_CLASS_ITEM *)a_void; + sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, def_cleanup_util_cb); + OPENSSL_free(item); + } - if (*skp == NULL) - *skp=sk_new_null(); - if (*skp == NULL) +/* Return the EX_CLASS_ITEM from the "ex_data" hash table that corresponds to a + * given class. Handles locking. */ +static EX_CLASS_ITEM *def_get_class(int class_index) + { + EX_CLASS_ITEM d, *p, *gen; + EX_DATA_CHECK(return NULL;) + d.class_index = class_index; + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); + p = lh_retrieve(ex_data, &d); + if(!p) { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE); - return(-1); + gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); + if(gen) + { + gen->class_index = class_index; + gen->meth_num = 0; + gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); + if(!gen->meth) + OPENSSL_free(gen); + else + { + /* Because we're inside the ex_data lock, the + * return value from the insert will be NULL */ + lh_insert(ex_data, gen); + p = gen; + } + } } - a=(CRYPTO_EX_DATA_FUNCS *)Malloc(sizeof(CRYPTO_EX_DATA_FUNCS)); - if (a == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + if(!p) + CRYPTOerr(CRYPTO_F_DEF_GET_CLASS,ERR_R_MALLOC_FAILURE); + return p; + } + +/* Add a new method to the given EX_CLASS_ITEM and return the corresponding + * index (or -1 for error). Handles locking. */ +static int def_add_index(EX_CLASS_ITEM *item, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) + { + int toret = -1; + CRYPTO_EX_DATA_FUNCS *a = (CRYPTO_EX_DATA_FUNCS *)OPENSSL_malloc( + sizeof(CRYPTO_EX_DATA_FUNCS)); + if(!a) { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE); - return(-1); + CRYPTOerr(CRYPTO_F_DEF_ADD_INDEX,ERR_R_MALLOC_FAILURE); + return -1; } a->argl=argl; a->argp=argp; a->new_func=new_func; a->dup_func=dup_func; a->free_func=free_func; - while (sk_num(*skp) <= idx) + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); + while (sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) <= item->meth_num) { - if (!sk_push(*skp,NULL)) + if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, NULL)) { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX,ERR_R_MALLOC_FAILURE); - Free(a); - return(-1); + CRYPTOerr(CRYPTO_F_DEF_ADD_INDEX,ERR_R_MALLOC_FAILURE); + OPENSSL_free(a); + goto err; } } - sk_value(*skp,idx)=(char *)a; - return(idx); + toret = item->meth_num++; + sk_CRYPTO_EX_DATA_FUNCS_set(item->meth, toret, a); +err: + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + return toret; } -int CRYPTO_set_ex_data(ad,idx,val) -CRYPTO_EX_DATA *ad; -int idx; -char *val; - { - int i; +/**************************************************************/ +/* The functions in the default CRYPTO_EX_DATA_IMPL structure */ - 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); +static int int_new_class(void) + { + int toret; + CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); + toret = ex_class++; + CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); + return toret; + } - while (i <= idx) - { - if (!sk_push(ad->sk,NULL)) - { - CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILURE); - return(0); - } - i++; - } - sk_value(ad->sk,idx)=val; - return(1); +static void int_cleanup(void) + { + EX_DATA_CHECK(return;) + lh_doall(ex_data, def_cleanup_cb); + lh_free(ex_data); + ex_data = NULL; + impl = NULL; } -char *CRYPTO_get_ex_data(ad,idx) -CRYPTO_EX_DATA *ad; -int idx; +static int int_get_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { - if (ad->sk == NULL) - return(0); - else if (idx >= sk_num(ad->sk)) - return(0); - else - return(sk_value(ad->sk,idx)); + EX_CLASS_ITEM *item = def_get_class(class_index); + if(!item) + return -1; + return def_add_index(item, argl, argp, new_func, dup_func, free_func); } -/* The callback is called with the 'object', which is the origional data object - * being duplicated, a pointer to the - * 'new' object to be inserted, the index, and the argi/argp - */ -int CRYPTO_dup_ex_data(meth,to,from) -STACK *meth; -CRYPTO_EX_DATA *to,*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_num(meth); - j=sk_num(from->sk); - for (i=0; isk = NULL; + CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); + mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); + if(mx > 0) + { + storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); + if(!storage) + goto skip; + for(i = 0; i < mx; i++) + storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i); + } +skip: + CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); + if((mx > 0) && !storage) + { + CRYPTOerr(CRYPTO_F_INT_NEW_EX_DATA,ERR_R_MALLOC_FAILURE); + return 0; + } + for(i = 0; i < mx; i++) + { + if(storage[i] && storage[i]->new_func) { - mm=(CRYPTO_EX_DATA_FUNCS *)sk_value(meth,i); - if (mm->dup_func != NULL) - r=mm->dup_func(to,from,(char **)&from_d,i, - mm->argl,mm->argp); + ptr = CRYPTO_get_ex_data(ad, i); + storage[i]->new_func(obj,ptr,ad,i, + storage[i]->argl,storage[i]->argp); } - CRYPTO_set_ex_data(to,i,from_d); } - return(1); + if(storage) + OPENSSL_free(storage); + return 1; } -/* Call each free callback */ -void CRYPTO_free_ex_data(meth,obj,ad) -STACK *meth; -char *obj; -CRYPTO_EX_DATA *ad; +/* Same thread-safety notes as for "int_new_ex_data" */ +static int int_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from) { - CRYPTO_EX_DATA_FUNCS *m; + int mx, j, i; char *ptr; - int i,max; + CRYPTO_EX_DATA_FUNCS **storage = NULL; + EX_CLASS_ITEM *item; + if(!from->sk) + /* 'to' should be "blank" which *is* just like 'from' */ + return 1; + if((item = def_get_class(class_index)) == NULL) + return 0; + CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); + mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); + j = sk_num(from->sk); + if(j < mx) + mx = j; + if(mx > 0) + { + storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); + if(!storage) + goto skip; + for(i = 0; i < mx; i++) + storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i); + } +skip: + CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); + if((mx > 0) && !storage) + { + CRYPTOerr(CRYPTO_F_INT_DUP_EX_DATA,ERR_R_MALLOC_FAILURE); + return 0; + } + for(i = 0; i < mx; i++) + { + ptr = CRYPTO_get_ex_data(from, i); + if(storage[i] && storage[i]->dup_func) + storage[i]->dup_func(to,from,&ptr,i, + storage[i]->argl,storage[i]->argp); + CRYPTO_set_ex_data(to,i,ptr); + } + if(storage) + OPENSSL_free(storage); + return 1; + } - if (meth != NULL) +/* Same thread-safety notes as for "int_new_ex_data" */ +static void int_free_ex_data(int class_index, void *obj, + CRYPTO_EX_DATA *ad) + { + int mx,i; + EX_CLASS_ITEM *item; + void *ptr; + CRYPTO_EX_DATA_FUNCS **storage = NULL; + if((item = def_get_class(class_index)) == NULL) + return; + CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); + mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); + if(mx > 0) + { + storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); + if(!storage) + goto skip; + for(i = 0; i < mx; i++) + storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i); + } +skip: + CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA); + if((mx > 0) && !storage) + { + CRYPTOerr(CRYPTO_F_INT_FREE_EX_DATA,ERR_R_MALLOC_FAILURE); + return; + } + for(i = 0; i < mx; i++) { - max=sk_num(meth); - for (i=0; ifree_func) { - m=(CRYPTO_EX_DATA_FUNCS *)sk_value(meth,i); - if ((m != NULL) && (m->free_func != NULL)) - { - ptr=CRYPTO_get_ex_data(ad,i); - m->free_func(obj,ptr,ad,i,m->argl,m->argp); - } + ptr = CRYPTO_get_ex_data(ad,i); + storage[i]->free_func(obj,ptr,ad,i, + storage[i]->argl,storage[i]->argp); } } - if (ad->sk != NULL) + if(storage) + OPENSSL_free(storage); + if(ad->sk) { sk_free(ad->sk); ad->sk=NULL; } } -void CRYPTO_new_ex_data(meth,obj,ad) -STACK *meth; -char *obj; -CRYPTO_EX_DATA *ad; +/********************************************************************/ +/* API functions that defer all "state" operations to the "ex_data" + * implementation we have set. */ + +/* Obtain an index for a new class (not the same as getting a new index within + * an existing class - this is actually getting a new *class*) */ +int CRYPTO_ex_data_new_class(void) { - CRYPTO_EX_DATA_FUNCS *m; - char *ptr; - int i,max; + IMPL_CHECK + return EX_IMPL(new_class)(); + } + +/* Release all "ex_data" state to prevent memory leaks. This can't be made + * thread-safe without overhauling a lot of stuff, and shouldn't really be + * called under potential race-conditions anyway (it's for program shutdown + * after all). */ +void CRYPTO_cleanup_all_ex_data(void) + { + IMPL_CHECK + EX_IMPL(cleanup)(); + } + +/* Inside an existing class, get/register a new index. */ +int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) + { + int ret = -1; - ad->sk=NULL; - if (meth != NULL) + IMPL_CHECK + ret = EX_IMPL(get_new_index)(class_index, + argl, argp, new_func, dup_func, free_func); + return ret; + } + +/* Initialise a new CRYPTO_EX_DATA for use in a particular class - including + * calling new() callbacks for each index in the class used by this variable */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) + { + IMPL_CHECK + return EX_IMPL(new_ex_data)(class_index, obj, ad); + } + +/* Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks for + * each index in the class used by this variable */ +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from) + { + IMPL_CHECK + return EX_IMPL(dup_ex_data)(class_index, to, from); + } + +/* Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for + * each index in the class used by this variable */ +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) + { + IMPL_CHECK + EX_IMPL(free_ex_data)(class_index, obj, ad); + } + +/* For a given CRYPTO_EX_DATA variable, set the value corresponding to a + * particular index in the class used by this variable */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) + { + int i; + + if (ad->sk == NULL) { - max=sk_num(meth); - for (i=0; isk=sk_new_null()) == NULL) { - m=(CRYPTO_EX_DATA_FUNCS *)sk_value(meth,i); - if ((m != NULL) && (m->new_func != NULL)) - { - ptr=CRYPTO_get_ex_data(ad,i); - m->new_func(obj,ptr,ad,i,m->argl,m->argp); - } + 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); } +/* For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a + * particular index in the class used by this variable */ +void *CRYPTO_get_ex_data(const 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)); + } +IMPLEMENT_STACK_OF(CRYPTO_EX_DATA_FUNCS) diff --git a/src/lib/libcrypto/hmac/hmac.c b/src/lib/libcrypto/hmac/hmac.c index fb09129963..da363b7950 100644 --- a/src/lib/libcrypto/hmac/hmac.c +++ b/src/lib/libcrypto/hmac/hmac.c @@ -58,13 +58,10 @@ #include #include #include -#include "hmac.h" +#include -void HMAC_Init(ctx,key,len,md) -HMAC_CTX *ctx; -unsigned char *key; -int len; -EVP_MD *md; +void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl) { int i,j,reset=0; unsigned char pad[HMAC_MAX_MD_CBLOCK]; @@ -83,47 +80,50 @@ EVP_MD *md; j=EVP_MD_block_size(md); if (j < len) { - EVP_DigestInit(&ctx->md_ctx,md); + EVP_DigestInit_ex(&ctx->md_ctx,md, impl); EVP_DigestUpdate(&ctx->md_ctx,key,len); - EVP_DigestFinal(&(ctx->md_ctx),ctx->key, + EVP_DigestFinal_ex(&(ctx->md_ctx),ctx->key, &ctx->key_length); } else { memcpy(ctx->key,key,len); - memset(&(ctx->key[len]),0,sizeof(ctx->key)-len); ctx->key_length=len; } + if(ctx->key_length != HMAC_MAX_MD_CBLOCK) + memset(&ctx->key[ctx->key_length], 0, + HMAC_MAX_MD_CBLOCK - ctx->key_length); } if (reset) { for (i=0; ikey[i]; - EVP_DigestInit(&ctx->i_ctx,md); + EVP_DigestInit_ex(&ctx->i_ctx,md, impl); EVP_DigestUpdate(&ctx->i_ctx,pad,EVP_MD_block_size(md)); for (i=0; ikey[i]; - EVP_DigestInit(&ctx->o_ctx,md); + EVP_DigestInit_ex(&ctx->o_ctx,md, impl); EVP_DigestUpdate(&ctx->o_ctx,pad,EVP_MD_block_size(md)); } + EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->i_ctx); + } - memcpy(&ctx->md_ctx,&ctx->i_ctx,sizeof(ctx->i_ctx)); +void HMAC_Init(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md) + { + if(key && md) + HMAC_CTX_init(ctx); + HMAC_Init_ex(ctx,key,len,md, NULL); } -void HMAC_Update(ctx,data,len) -HMAC_CTX *ctx; -unsigned char *data; -int len; +void HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len) { - EVP_DigestUpdate(&(ctx->md_ctx),data,len); + EVP_DigestUpdate(&ctx->md_ctx,data,len); } -void HMAC_Final(ctx,md,len) -HMAC_CTX *ctx; -unsigned char *md; -unsigned int *len; +void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { int j; unsigned int i; @@ -131,35 +131,40 @@ unsigned int *len; j=EVP_MD_block_size(ctx->md); - EVP_DigestFinal(&(ctx->md_ctx),buf,&i); - memcpy(&(ctx->md_ctx),&(ctx->o_ctx),sizeof(ctx->o_ctx)); - EVP_DigestUpdate(&(ctx->md_ctx),buf,i); - EVP_DigestFinal(&(ctx->md_ctx),md,len); + EVP_DigestFinal_ex(&ctx->md_ctx,buf,&i); + EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->o_ctx); + EVP_DigestUpdate(&ctx->md_ctx,buf,i); + EVP_DigestFinal_ex(&ctx->md_ctx,md,len); + } + +void HMAC_CTX_init(HMAC_CTX *ctx) + { + EVP_MD_CTX_init(&ctx->i_ctx); + EVP_MD_CTX_init(&ctx->o_ctx); + EVP_MD_CTX_init(&ctx->md_ctx); } -void HMAC_cleanup(ctx) -HMAC_CTX *ctx; +void HMAC_CTX_cleanup(HMAC_CTX *ctx) { - memset(ctx,0,sizeof(HMAC_CTX)); + EVP_MD_CTX_cleanup(&ctx->i_ctx); + EVP_MD_CTX_cleanup(&ctx->o_ctx); + EVP_MD_CTX_cleanup(&ctx->md_ctx); + memset(ctx,0,sizeof *ctx); } -unsigned char *HMAC(evp_md,key,key_len,d,n,md,md_len) -EVP_MD *evp_md; -unsigned char *key; -int key_len; -unsigned char *d; -int n; -unsigned char *md; -unsigned int *md_len; +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, int n, unsigned char *md, + unsigned int *md_len) { HMAC_CTX c; static unsigned char m[EVP_MAX_MD_SIZE]; if (md == NULL) md=m; + HMAC_CTX_init(&c); HMAC_Init(&c,key,key_len,evp_md); HMAC_Update(&c,d,n); HMAC_Final(&c,md,md_len); - HMAC_cleanup(&c); + HMAC_CTX_cleanup(&c); return(md); } diff --git a/src/lib/libcrypto/hmac/hmac.h b/src/lib/libcrypto/hmac/hmac.h index e6b43f52c4..0364a1fcbd 100644 --- a/src/lib/libcrypto/hmac/hmac.h +++ b/src/lib/libcrypto/hmac/hmac.h @@ -58,17 +58,21 @@ #ifndef HEADER_HMAC_H #define HEADER_HMAC_H -#ifdef __cplusplus -extern "C" { +#ifdef OPENSSL_NO_HMAC +#error HMAC is disabled. #endif -#include "evp.h" +#include #define HMAC_MAX_MD_CBLOCK 64 +#ifdef __cplusplus +extern "C" { +#endif + typedef struct hmac_ctx_st { - EVP_MD *md; + const EVP_MD *md; EVP_MD_CTX md_ctx; EVP_MD_CTX i_ctx; EVP_MD_CTX o_ctx; @@ -78,26 +82,22 @@ typedef struct hmac_ctx_st #define HMAC_size(e) (EVP_MD_size((e)->md)) -#ifndef NOPROTO - -void HMAC_Init(HMAC_CTX *ctx, unsigned char *key, int len, - EVP_MD *md); -void HMAC_Update(HMAC_CTX *ctx,unsigned char *key, int len); -void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); -void HMAC_cleanup(HMAC_CTX *ctx); -unsigned char *HMAC(EVP_MD *evp_md, unsigned char *key, int key_len, - unsigned char *d, int n, unsigned char *md, unsigned int *md_len); +void HMAC_CTX_init(HMAC_CTX *ctx); +void HMAC_CTX_cleanup(HMAC_CTX *ctx); -#else +#define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) /* deprecated */ -void HMAC_Init(); -void HMAC_Update(); -void HMAC_Final(); -void HMAC_cleanup(); -unsigned char *HMAC(); +void HMAC_Init(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md); /* deprecated */ +void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl); +void HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len); +void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, int n, unsigned char *md, + unsigned int *md_len); -#endif #ifdef __cplusplus } diff --git a/src/lib/libcrypto/idea/idea.h b/src/lib/libcrypto/idea/idea.h index ae32f5692e..67132414ee 100644 --- a/src/lib/libcrypto/idea/idea.h +++ b/src/lib/libcrypto/idea/idea.h @@ -59,11 +59,7 @@ #ifndef HEADER_IDEA_H #define HEADER_IDEA_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef NO_IDEA +#ifdef OPENSSL_NO_IDEA #error IDEA is disabled. #endif @@ -74,22 +70,26 @@ extern "C" { #define IDEA_BLOCK 8 #define IDEA_KEY_LENGTH 16 +#ifdef __cplusplus +extern "C" { +#endif + typedef struct idea_key_st { IDEA_INT data[9][6]; } IDEA_KEY_SCHEDULE; const char *idea_options(void); -void idea_ecb_encrypt(unsigned char *in, unsigned char *out, +void idea_ecb_encrypt(const unsigned char *in, unsigned char *out, IDEA_KEY_SCHEDULE *ks); -void idea_set_encrypt_key(unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks); void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk); -void idea_cbc_encrypt(unsigned char *in, unsigned char *out, +void idea_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc); -void idea_cfb64_encrypt(unsigned char *in, unsigned char *out, +void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num,int enc); -void idea_ofb64_encrypt(unsigned char *in, unsigned char *out, +void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num); void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); #ifdef __cplusplus diff --git a/src/lib/libcrypto/lhash/lh_stats.c b/src/lib/libcrypto/lhash/lh_stats.c index 23fe82f777..39ea2885f4 100644 --- a/src/lib/libcrypto/lhash/lh_stats.c +++ b/src/lib/libcrypto/lhash/lh_stats.c @@ -63,13 +63,14 @@ * and things should work as expected */ #include "cryptlib.h" -#include "lhash.h" +#ifndef OPENSSL_NO_BIO +#include +#endif +#include -#ifndef HEADER_BIO_H +#ifdef OPENSSL_NO_BIO -void lh_stats(lh, out) -LHASH *lh; -FILE *out; +void lh_stats(LHASH *lh, FILE *out) { fprintf(out,"num_items = %lu\n",lh->num_items); fprintf(out,"num_nodes = %u\n",lh->num_nodes); @@ -87,7 +88,7 @@ FILE *out; fprintf(out,"num_retrieve = %lu\n",lh->num_retrieve); fprintf(out,"num_retrieve_miss = %lu\n",lh->num_retrieve_miss); fprintf(out,"num_hash_comps = %lu\n",lh->num_hash_comps); -#ifdef DEBUG +#if 0 fprintf(out,"p = %u\n",lh->p); fprintf(out,"pmax = %u\n",lh->pmax); fprintf(out,"up_load = %lu\n",lh->up_load); @@ -95,9 +96,7 @@ FILE *out; #endif } -void lh_node_stats(lh, out) -LHASH *lh; -FILE *out; +void lh_node_stats(LHASH *lh, FILE *out) { LHASH_NODE *n; unsigned int i,num; @@ -110,9 +109,7 @@ FILE *out; } } -void lh_node_usage_stats(lh, out) -LHASH *lh; -FILE *out; +void lh_node_usage_stats(LHASH *lh, FILE *out) { LHASH_NODE *n; unsigned long num; @@ -141,10 +138,8 @@ FILE *out; #else -#ifndef NO_FP_API -void lh_stats(lh,fp) -LHASH *lh; -FILE *fp; +#ifndef OPENSSL_NO_FP_API +void lh_stats(const LHASH *lh, FILE *fp) { BIO *bp; @@ -156,9 +151,7 @@ FILE *fp; end:; } -void lh_node_stats(lh,fp) -LHASH *lh; -FILE *fp; +void lh_node_stats(const LHASH *lh, FILE *fp) { BIO *bp; @@ -170,9 +163,7 @@ FILE *fp; end:; } -void lh_node_usage_stats(lh,fp) -LHASH *lh; -FILE *fp; +void lh_node_usage_stats(const LHASH *lh, FILE *fp) { BIO *bp; @@ -186,9 +177,7 @@ end:; #endif -void lh_stats_bio(lh, out) -LHASH *lh; -BIO *out; +void lh_stats_bio(const LHASH *lh, BIO *out) { char buf[128]; @@ -224,7 +213,7 @@ BIO *out; BIO_puts(out,buf); sprintf(buf,"num_hash_comps = %lu\n",lh->num_hash_comps); BIO_puts(out,buf); -#ifdef DEBUG +#if 0 sprintf(buf,"p = %u\n",lh->p); BIO_puts(out,buf); sprintf(buf,"pmax = %u\n",lh->pmax); @@ -236,9 +225,7 @@ BIO *out; #endif } -void lh_node_stats_bio(lh, out) -LHASH *lh; -BIO *out; +void lh_node_stats_bio(const LHASH *lh, BIO *out) { LHASH_NODE *n; unsigned int i,num; @@ -253,9 +240,7 @@ BIO *out; } } -void lh_node_usage_stats_bio(lh, out) -LHASH *lh; -BIO *out; +void lh_node_usage_stats_bio(const LHASH *lh, BIO *out) { LHASH_NODE *n; unsigned long num; diff --git a/src/lib/libcrypto/lhash/lhash.c b/src/lib/libcrypto/lhash/lhash.c index 6dfb5c9ccc..0a16fcf27d 100644 --- a/src/lib/libcrypto/lhash/lhash.c +++ b/src/lib/libcrypto/lhash/lhash.c @@ -56,16 +56,19 @@ * [including the GNU Public Licence.] */ -char *lh_version="lhash part of SSLeay 0.9.0b 29-Jun-1998"; - /* Code for dynamic hash table routines * Author - Eric Young v 2.0 * - * 2.0 eay - Fixed a bug that occured when using lh_delete + * 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 - * skiping the lh_doall() processing. eay - 4/12/95 + * 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 @@ -94,46 +97,33 @@ char *lh_version="lhash part of SSLeay 0.9.0b 29-Jun-1998"; #include #include #include -#include "lhash.h" +#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) */ -#ifndef NOPROTO - -#define P_CP char * -#define P_CPP char *,char * static void expand(LHASH *lh); static void contract(LHASH *lh); -static LHASH_NODE **getrn(LHASH *lh, char *data, unsigned long *rhash); +static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash); -#else - -#define P_CP -#define P_CPP -static void expand(); -static void contract(); -static LHASH_NODE **getrn(); - -#endif - -LHASH *lh_new(h, c) -unsigned long (*h)(); -int (*c)(); +LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c) { LHASH *ret; int i; - if ((ret=(LHASH *)malloc(sizeof(LHASH))) == NULL) + if ((ret=(LHASH *)OPENSSL_malloc(sizeof(LHASH))) == NULL) goto err0; - if ((ret->b=(LHASH_NODE **)malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL) + if ((ret->b=(LHASH_NODE **)OPENSSL_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->comp=((c == NULL)?(LHASH_COMP_FN_TYPE)strcmp:c); + ret->hash=((h == NULL)?(LHASH_HASH_FN_TYPE)lh_strhash:h); ret->num_nodes=MIN_NODES/2; ret->num_alloc_nodes=MIN_NODES; ret->p=0; @@ -156,41 +146,43 @@ int (*c)(); ret->num_retrieve_miss=0; ret->num_hash_comps=0; + ret->error=0; return(ret); err1: - free((char *)ret); + OPENSSL_free(ret); err0: return(NULL); } -void lh_free(lh) -LHASH *lh; +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); + OPENSSL_free(n); n=nn; } } - free((char *)lh->b); - free((char *)lh); + OPENSSL_free(lh->b); + OPENSSL_free(lh); } -char *lh_insert(lh, data) -LHASH *lh; -char *data; +void *lh_insert(LHASH *lh, const void *data) { unsigned long hash; LHASH_NODE *nn,**rn; - char *ret; + const void *ret; + lh->error=0; if (lh->up_load <= (lh->num_items*LH_LOAD_MULT/lh->num_nodes)) expand(lh); @@ -198,11 +190,14 @@ char *data; if (*rn == NULL) { - if ((nn=(LHASH_NODE *)malloc(sizeof(LHASH_NODE))) == NULL) + if ((nn=(LHASH_NODE *)OPENSSL_malloc(sizeof(LHASH_NODE))) == NULL) + { + lh->error++; return(NULL); + } nn->data=data; nn->next=NULL; -#ifndef NO_HASH_COMP +#ifndef OPENSSL_NO_HASH_COMP nn->hash=hash; #endif *rn=nn; @@ -216,17 +211,16 @@ char *data; (*rn)->data=data; lh->num_replace++; } - return(ret); + return((void *)ret); } -char *lh_delete(lh, data) -LHASH *lh; -char *data; +void *lh_delete(LHASH *lh, const void *data) { unsigned long hash; LHASH_NODE *nn,**rn; - char *ret; + const void *ret; + lh->error=0; rn=getrn(lh,data,&hash); if (*rn == NULL) @@ -239,7 +233,7 @@ char *data; nn= *rn; *rn=nn->next; ret=nn->data; - free((char *)nn); + OPENSSL_free(nn); lh->num_delete++; } @@ -248,17 +242,16 @@ char *data; (lh->down_load >= (lh->num_items*LH_LOAD_MULT/lh->num_nodes))) contract(lh); - return(ret); + return((void *)ret); } -char *lh_retrieve(lh, data) -LHASH *lh; -char *data; +void *lh_retrieve(LHASH *lh, const void *data) { unsigned long hash; LHASH_NODE **rn; - char *ret; + const void *ret; + lh->error=0; rn=getrn(lh,data,&hash); if (*rn == NULL) @@ -271,20 +264,11 @@ char *data; ret= (*rn)->data; lh->num_retrieve++; } - return(ret); + return((void *)ret); } -void lh_doall(lh, func) -LHASH *lh; -void (*func)(); - { - lh_doall_arg(lh,func,NULL); - } - -void lh_doall_arg(lh, func, arg) -LHASH *lh; -void (*func)(); -char *arg; +static void doall_util_fn(LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func, + LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg) { int i; LHASH_NODE *a,*n; @@ -299,14 +283,26 @@ char *arg; /* 28/05/91 - eay - n added so items can be deleted * via lh_doall */ n=a->next; - func(a->data,arg); + if(use_arg) + func_arg(a->data,arg); + else + func(a->data); a=n; } } } -static void expand(lh) -LHASH *lh; +void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func) + { + doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL); + } + +void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg) + { + doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg); + } + +static void expand(LHASH *lh) { LHASH_NODE **n,**n1,**n2,*np; unsigned int p,i,j; @@ -322,10 +318,10 @@ LHASH *lh; for (np= *n1; np != NULL; ) { -#ifndef NO_HASH_COMP +#ifndef OPENSSL_NO_HASH_COMP hash=np->hash; #else - hash=(*(lh->hash))(np->data); + hash=lh->hash(np->data); lh->num_hash_calls++; #endif if ((hash%nni) != p) @@ -342,11 +338,12 @@ LHASH *lh; if ((lh->p) >= lh->pmax) { j=(int)lh->num_alloc_nodes*2; - n=(LHASH_NODE **)realloc((char *)lh->b, + n=(LHASH_NODE **)OPENSSL_realloc(lh->b, (unsigned int)sizeof(LHASH_NODE *)*j); if (n == NULL) { /* fputs("realloc error in lhash",stderr); */ + lh->error++; lh->p=0; return; } @@ -361,8 +358,7 @@ LHASH *lh; } } -static void contract(lh) -LHASH *lh; +static void contract(LHASH *lh) { LHASH_NODE **n,*n1,*np; @@ -370,11 +366,12 @@ LHASH *lh; lh->b[lh->p+lh->pmax-1]=NULL; /* 24/07-92 - eay - weird but :-( */ if (lh->p == 0) { - n=(LHASH_NODE **)realloc((char *)lh->b, + n=(LHASH_NODE **)OPENSSL_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++; @@ -400,10 +397,7 @@ LHASH *lh; } } -static LHASH_NODE **getrn(lh, data, rhash) -LHASH *lh; -char *data; -unsigned long *rhash; +static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash) { LHASH_NODE **ret,*n1; unsigned long hash,nn; @@ -421,7 +415,7 @@ unsigned long *rhash; ret= &(lh->b[(int)nn]); for (n1= *ret; n1 != NULL; n1=n1->next) { -#ifndef NO_HASH_COMP +#ifndef OPENSSL_NO_HASH_COMP lh->num_hash_comps++; if (n1->hash != hash) { @@ -430,35 +424,18 @@ unsigned long *rhash; } #endif lh->num_comp_calls++; - if ((*cf)(n1->data,data) == 0) + if(cf(n1->data,data) == 0) break; ret= &(n1->next); } return(ret); } -/* -static unsigned long lh_strhash(str) -char *str; - { - int i,l; - unsigned long ret=0; - unsigned short *s; - - if (str == NULL) return(0); - l=(strlen(str)+1)/2; - s=(unsigned short *)str; - for (i=0; i>16)^ret); } +unsigned long lh_num_items(const LHASH *lh) + { + return lh ? lh->num_items : 0; + } diff --git a/src/lib/libcrypto/lhash/lhash.h b/src/lib/libcrypto/lhash/lhash.h index 70cbc6dfe7..dee8207333 100644 --- a/src/lib/libcrypto/lhash/lhash.h +++ b/src/lib/libcrypto/lhash/lhash.h @@ -63,24 +63,82 @@ #ifndef HEADER_LHASH_H #define HEADER_LHASH_H +#ifndef OPENSSL_NO_FP_API +#include +#endif + +#ifndef OPENSSL_NO_BIO +#include +#endif + #ifdef __cplusplus extern "C" { #endif typedef struct lhash_node_st { - char *data; + const void *data; struct lhash_node_st *next; -#ifndef NO_HASH_COMP +#ifndef OPENSSL_NO_HASH_COMP unsigned long hash; #endif } LHASH_NODE; +typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *); +typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *); +typedef void (*LHASH_DOALL_FN_TYPE)(const void *); +typedef void (*LHASH_DOALL_ARG_FN_TYPE)(const void *, void *); + +/* Macros for declaring and implementing type-safe wrappers for LHASH callbacks. + * This way, callbacks can be provided to LHASH structures without function + * pointer casting and the macro-defined callbacks provide per-variable casting + * before deferring to the underlying type-specific callbacks. NB: It is + * possible to place a "static" in front of both the DECLARE and IMPLEMENT + * macros if the functions are strictly internal. */ + +/* First: "hash" functions */ +#define DECLARE_LHASH_HASH_FN(f_name,o_type) \ + unsigned long f_name##_LHASH_HASH(const void *); +#define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \ + unsigned long f_name##_LHASH_HASH(const void *arg) { \ + o_type a = (o_type)arg; \ + return f_name(a); } +#define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH + +/* Second: "compare" functions */ +#define DECLARE_LHASH_COMP_FN(f_name,o_type) \ + int f_name##_LHASH_COMP(const void *, const void *); +#define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \ + int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \ + o_type a = (o_type)arg1; \ + o_type b = (o_type)arg2; \ + return f_name(a,b); } +#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP + +/* Third: "doall" functions */ +#define DECLARE_LHASH_DOALL_FN(f_name,o_type) \ + void f_name##_LHASH_DOALL(const void *); +#define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \ + void f_name##_LHASH_DOALL(const void *arg) { \ + o_type a = (o_type)arg; \ + f_name(a); } +#define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL + +/* Fourth: "doall_arg" functions */ +#define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \ + void f_name##_LHASH_DOALL_ARG(const void *, void *); +#define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \ + void f_name##_LHASH_DOALL_ARG(const void *arg1, void *arg2) { \ + o_type a = (o_type)arg1; \ + a_type b = (a_type)arg2; \ + f_name(a,b); } +#define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG + typedef struct lhash_st { LHASH_NODE **b; - int (*comp)(); - unsigned long (*hash)(); + LHASH_COMP_FN_TYPE comp; + LHASH_HASH_FN_TYPE hash; unsigned int num_nodes; unsigned int num_alloc_nodes; unsigned int p; @@ -102,51 +160,37 @@ typedef struct lhash_st unsigned long num_retrieve; unsigned long num_retrieve_miss; unsigned long num_hash_comps; + + int error; } LHASH; #define LH_LOAD_MULT 256 -#ifndef NOPROTO -LHASH *lh_new(unsigned long (*h)(), int (*c)()); +/* Indicates a malloc() error in the last call, this is only bad + * in lh_insert(). */ +#define lh_error(lh) ((lh)->error) + +LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c); void lh_free(LHASH *lh); -char *lh_insert(LHASH *lh, char *data); -char *lh_delete(LHASH *lh, char *data); -char *lh_retrieve(LHASH *lh, char *data); -void lh_doall(LHASH *lh, void (*func)(/* char *b */)); -void lh_doall_arg(LHASH *lh, void (*func)(/*char *a,char *b*/),char *arg); -unsigned long lh_strhash(char *c); - -#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 +void *lh_insert(LHASH *lh, const void *data); +void *lh_delete(LHASH *lh, const void *data); +void *lh_retrieve(LHASH *lh, const void *data); +void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func); +void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg); +unsigned long lh_strhash(const char *c); +unsigned long lh_num_items(const LHASH *lh); -#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 -#else -LHASH *lh_new(); -void lh_free(); -char *lh_insert(); -char *lh_delete(); -char *lh_retrieve(); -void lh_doall(); -void lh_doall_arg(); -unsigned long lh_strhash(); - -#ifndef NO_FP_API -void lh_stats(); -void lh_node_stats(); -void lh_node_usage_stats(); -#endif -void lh_stats_bio(); -void lh_node_stats_bio(); -void lh_node_usage_stats_bio(); +#ifndef OPENSSL_NO_FP_API +void lh_stats(const LHASH *lh, FILE *out); +void lh_node_stats(const LHASH *lh, FILE *out); +void lh_node_usage_stats(const LHASH *lh, FILE *out); #endif +#ifndef OPENSSL_NO_BIO +void lh_stats_bio(const LHASH *lh, BIO *out); +void lh_node_stats_bio(const LHASH *lh, BIO *out); +void lh_node_usage_stats_bio(const LHASH *lh, BIO *out); +#endif #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/md32_common.h b/src/lib/libcrypto/md32_common.h index 2b91f9eef2..353d2b96ad 100644 --- a/src/lib/libcrypto/md32_common.h +++ b/src/lib/libcrypto/md32_common.h @@ -94,6 +94,8 @@ * in original (data) byte order, implemented externally (it * actually is optional if data and host are of the same * "endianess"). + * HASH_MAKE_STRING + * macro convering context variables to an ASCII hash string. * * Optional macros: * @@ -177,9 +179,18 @@ */ #undef ROTATE #ifndef PEDANTIC -# if defined(_MSC_VER) -# define ROTATE(a,n) _lrotl(a,n) -# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) +# if 0 /* defined(_MSC_VER) */ +# define ROTATE(a,n) _lrotl(a,n) +# elif defined(__MWERKS__) +# if defined(__POWERPC__) +# define ROTATE(a,n) __rlwinm(a,n,0,31) +# elif defined(__MC68K__) + /* Motorola specific tweak. */ +# define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) +# else +# define ROTATE(a,n) __rol(a,n) +# endif +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) /* * Some GNU C inline assembler templates. Note that these are * rotates by *constant* number of bits! But that's exactly @@ -187,18 +198,18 @@ * * */ -# if defined(__i386) +# if defined(__i386) || defined(__i386__) # define ROTATE(a,n) ({ register unsigned int ret; \ - asm volatile ( \ + asm ( \ "roll %1,%0" \ : "=r"(ret) \ : "I"(n), "0"(a) \ : "cc"); \ ret; \ }) -# elif defined(__powerpc) +# elif defined(__powerpc) || defined(__ppc) # define ROTATE(a,n) ({ register unsigned int ret; \ - asm volatile ( \ + asm ( \ "rlwinm %0,%1,%2,0,31" \ : "=r"(ret) \ : "r"(a), "I"(n)); \ @@ -211,27 +222,27 @@ * Engage compiler specific "fetch in reverse byte order" * intrinsic function if available. */ -# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) +# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) /* some GNU C inline assembler templates by */ -# if defined(__i386) && !defined(I386_ONLY) +# if (defined(__i386) || defined(__i386__)) && !defined(I386_ONLY) # define BE_FETCH32(a) ({ register unsigned int l=(a);\ - asm volatile ( \ + asm ( \ "bswapl %0" \ : "=r"(l) : "0"(l)); \ l; \ }) # elif defined(__powerpc) # define LE_FETCH32(a) ({ register unsigned int l; \ - asm volatile ( \ + asm ( \ "lwbrx %0,0,%1" \ : "=r"(l) \ : "r"(a)); \ l; \ }) -# elif defined(__sparc) && defined(ULTRASPARC) +# elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC) # define LE_FETCH32(a) ({ register unsigned int l; \ - asm volatile ( \ + asm ( \ "lda [%1]#ASI_PRIMARY_LITTLE,%0"\ : "=r"(l) \ : "r"(a)); \ @@ -399,13 +410,14 @@ * Time for some action:-) */ -void HASH_UPDATE (HASH_CTX *c, const unsigned char *data, unsigned long len) +int HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len) { + const unsigned char *data=data_; register HASH_LONG * p; register unsigned long l; int sw,sc,ew,ec; - if (len==0) return; + if (len==0) return 1; l=(c->Nl+(len<<3))&0xffffffffL; /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to @@ -454,7 +466,7 @@ void HASH_UPDATE (HASH_CTX *c, const unsigned char *data, unsigned long len) HOST_c2l_p(data,l,ec); p[sw]=l; } } - return; + return 1; } } @@ -508,6 +520,7 @@ void HASH_UPDATE (HASH_CTX *c, const unsigned char *data, unsigned long len) HOST_c2l_p(data,l,ec); *p=l; } + return 1; } @@ -531,7 +544,7 @@ void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) } -void HASH_FINAL (unsigned char *md, HASH_CTX *c) +int HASH_FINAL (unsigned char *md, HASH_CTX *c) { register HASH_LONG *p; register unsigned long l; @@ -581,14 +594,16 @@ void HASH_FINAL (unsigned char *md, HASH_CTX *c) #endif HASH_BLOCK_HOST_ORDER (c,p,1); - l=c->A; HOST_l2c(l,md); - l=c->B; HOST_l2c(l,md); - l=c->C; HOST_l2c(l,md); - l=c->D; HOST_l2c(l,md); +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c,md); +#endif c->num=0; /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack * but I'm not worried :-) memset((void *)c,0,sizeof(HASH_CTX)); */ + return 1; } diff --git a/src/lib/libcrypto/md4/md4.h b/src/lib/libcrypto/md4/md4.h index c794e186db..7a7b23682f 100644 --- a/src/lib/libcrypto/md4/md4.h +++ b/src/lib/libcrypto/md4/md4.h @@ -59,11 +59,13 @@ #ifndef HEADER_MD4_H #define HEADER_MD4_H +#include + #ifdef __cplusplus extern "C" { #endif -#ifdef NO_MD4 +#ifdef OPENSSL_NO_MD4 #error MD4 is disabled. #endif @@ -74,9 +76,9 @@ extern "C" { * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -#if defined(WIN16) || defined(__LP32__) +#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__) #define MD4_LONG unsigned long -#elif defined(_CRAY) || defined(__ILP64__) +#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) #define MD4_LONG unsigned long #define MD4_LONG_LOG2 3 /* @@ -102,9 +104,9 @@ typedef struct MD4state_st int num; } MD4_CTX; -void MD4_Init(MD4_CTX *c); -void MD4_Update(MD4_CTX *c, const void *data, unsigned long len); -void MD4_Final(unsigned char *md, MD4_CTX *c); +int MD4_Init(MD4_CTX *c); +int MD4_Update(MD4_CTX *c, const void *data, unsigned long len); +int MD4_Final(unsigned char *md, MD4_CTX *c); unsigned char *MD4(const unsigned char *d, unsigned long n, unsigned char *md); void MD4_Transform(MD4_CTX *c, const unsigned char *b); #ifdef __cplusplus diff --git a/src/lib/libcrypto/md4/md4_dgst.c b/src/lib/libcrypto/md4/md4_dgst.c index 81488ae2e2..6446f5f5e7 100644 --- a/src/lib/libcrypto/md4/md4_dgst.c +++ b/src/lib/libcrypto/md4/md4_dgst.c @@ -70,7 +70,7 @@ const char *MD4_version="MD4" OPENSSL_VERSION_PTEXT; #define INIT_DATA_C (unsigned long)0x98badcfeL #define INIT_DATA_D (unsigned long)0x10325476L -void MD4_Init(MD4_CTX *c) +int MD4_Init(MD4_CTX *c) { c->A=INIT_DATA_A; c->B=INIT_DATA_B; @@ -79,6 +79,7 @@ void MD4_Init(MD4_CTX *c) c->Nl=0; c->Nh=0; c->num=0; + return 1; } #ifndef md4_block_host_order diff --git a/src/lib/libcrypto/md4/md4_locl.h b/src/lib/libcrypto/md4/md4_locl.h index 0a2b39018d..a8d31d7a73 100644 --- a/src/lib/libcrypto/md4/md4_locl.h +++ b/src/lib/libcrypto/md4/md4_locl.h @@ -68,7 +68,7 @@ void md4_block_host_order (MD4_CTX *c, const void *p,int num); void md4_block_data_order (MD4_CTX *c, const void *p,int num); -#if defined(__i386) || defined(_M_IX86) || defined(__INTEL__) +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) /* * *_block_host_order is expected to handle aligned data while * *_block_data_order - unaligned. As algorithm and host (x86) diff --git a/src/lib/libcrypto/md5/asm/md5-586.pl b/src/lib/libcrypto/md5/asm/md5-586.pl index 2c7fb7dd98..5fc6a205ce 100644 --- a/src/lib/libcrypto/md5/asm/md5-586.pl +++ b/src/lib/libcrypto/md5/asm/md5-586.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # Normal is the # md5_block_x86(MD5_CTX *c, ULONG *X); @@ -29,7 +29,7 @@ $X="esi"; 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, # R3 ); -&md5_block("md5_block_x86"); +&md5_block("md5_block_asm_host_order"); &asm_finish(); sub Np @@ -44,7 +44,7 @@ sub R0 local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_; &mov($tmp1,$C) if $pos < 0; - &mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one + &mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one # body proper @@ -54,7 +54,6 @@ sub R0 &and($tmp1,$b); # F function - part 3 &lea($a,&DWP($t,$a,$tmp2,1)); - &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); &xor($tmp1,$d); # F function - part 4 &add($a,$tmp1); @@ -62,8 +61,10 @@ sub R0 &mov($tmp1,&Np($c)) if $pos == 1; # next tmp1 for R1 &rotl($a,$s); - &add($a,$b); + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + + &add($a,$b); } sub R1 @@ -100,16 +101,16 @@ if (($n & 1) == 0) # make sure to do 'D' first, not 'B', else we clash with # the last add from the previous round. - &xor($tmp1,$d); # H function - part 2 + &xor($tmp1,$d); # H function - part 2 &xor($tmp1,$b); # H function - part 3 - &lea($a,&DWP($t,$a,$tmp2,1)); + &lea($a,&DWP($t,$a,$tmp2,1)); &add($a,$tmp1); - &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)); &rotl($a,$s); + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)); &mov($tmp1,&Np($c)); } else @@ -118,17 +119,17 @@ else # make sure to do 'D' first, not 'B', else we clash with # the last add from the previous round. - &lea($a,&DWP($t,$a,$tmp2,1)); + &lea($a,&DWP($t,$a,$tmp2,1)); &add($b,$c); # MOVED FORWARD - &xor($tmp1,$d); # H function - part 2 + &xor($tmp1,$d); # H function - part 2 &xor($tmp1,$b); # H function - part 3 - &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if ($pos != 2); &add($a,$tmp1); - &mov($tmp1,&Np($c)) if $pos < 1; # H function - part 1 - &mov($tmp1,-1) if $pos == 1; # I function - part 1 + &mov($tmp1,&Np($c)) if $pos < 1; # H function - part 1 + &mov($tmp1,-1) if $pos == 1; # I function - part 1 &rotl($a,$s); @@ -146,21 +147,21 @@ sub R3 &xor($tmp1,$d) if $pos < 0; # I function - part 2 &or($tmp1,$b); # I function - part 3 - &lea($a,&DWP($t,$a,$tmp2,1)); + &lea($a,&DWP($t,$a,$tmp2,1)); &xor($tmp1,$c); # I function - part 4 - &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if $pos != 2; # load X/k value - &mov($tmp2,&wparam(0)) if $pos == 2; + &mov($tmp2,&DWP($xo[$ki+1]*4,$K,"",0)) if $pos != 2; # load X/k value + &mov($tmp2,&wparam(0)) if $pos == 2; &add($a,$tmp1); - &mov($tmp1,-1) if $pos < 1; # H function - part 1 - &add($K,64) if $pos >=1 && !$normal; + &mov($tmp1,-1) if $pos < 1; # H function - part 1 + &add($K,64) if $pos >=1 && !$normal; &rotl($a,$s); &xor($tmp1,&Np($d)) if $pos <= 0; # I function - part = first time &mov($tmp1,&DWP( 0,$tmp2,"",0)) if $pos > 0; - &add($a,$b); + &add($a,$b); } @@ -182,6 +183,7 @@ sub md5_block &mov($X, &wparam(1)); # esi &mov($C, &wparam(2)); &push("ebp"); + &shl($C, 6); &push("ebx"); &add($C, $X); # offset we end at &sub($C, 64); diff --git a/src/lib/libcrypto/md5/md5.h b/src/lib/libcrypto/md5/md5.h index 357c6c625d..52cb753e6a 100644 --- a/src/lib/libcrypto/md5/md5.h +++ b/src/lib/libcrypto/md5/md5.h @@ -63,35 +63,50 @@ extern "C" { #endif +#ifdef OPENSSL_NO_MD5 +#error MD5 is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! MD5_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__) +#define MD5_LONG unsigned long +#elif defined(OENSSL_SYS_CRAY) || defined(__ILP64__) +#define MD5_LONG unsigned long +#define MD5_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... + * + */ +#else +#define MD5_LONG unsigned int +#endif + #define MD5_CBLOCK 64 -#define MD5_LBLOCK 16 -#define MD5_BLOCK 16 -#define MD5_LAST_BLOCK 56 -#define MD5_LENGTH_BLOCK 8 +#define MD5_LBLOCK (MD5_CBLOCK/4) #define MD5_DIGEST_LENGTH 16 typedef struct MD5state_st { - unsigned long A,B,C,D; - unsigned long Nl,Nh; - unsigned long data[MD5_LBLOCK]; + MD5_LONG A,B,C,D; + MD5_LONG Nl,Nh; + MD5_LONG data[MD5_LBLOCK]; int num; } MD5_CTX; -#ifndef NOPROTO -void MD5_Init(MD5_CTX *c); -void MD5_Update(MD5_CTX *c, unsigned char *data, unsigned long len); -void MD5_Final(unsigned char *md, MD5_CTX *c); -unsigned char *MD5(unsigned char *d, unsigned long n, unsigned char *md); -void MD5_Transform(MD5_CTX *c, unsigned char *b); -#else -void MD5_Init(); -void MD5_Update(); -void MD5_Final(); -unsigned char *MD5(); -void MD5_Transform(); -#endif - +int MD5_Init(MD5_CTX *c); +int MD5_Update(MD5_CTX *c, const void *data, unsigned long len); +int MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md); +void MD5_Transform(MD5_CTX *c, const unsigned char *b); #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/md5/md5_dgst.c b/src/lib/libcrypto/md5/md5_dgst.c index 43b3498d92..c38a3f021e 100644 --- a/src/lib/libcrypto/md5/md5_dgst.c +++ b/src/lib/libcrypto/md5/md5_dgst.c @@ -58,8 +58,9 @@ #include #include "md5_locl.h" +#include -char *MD5_version="MD5 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *MD5_version="MD5" OPENSSL_VERSION_PTEXT; /* Implemented from RFC1321 The MD5 Message-Digest Algorithm */ @@ -69,24 +70,7 @@ char *MD5_version="MD5 part of SSLeay 0.9.0b 29-Jun-1998"; #define INIT_DATA_C (unsigned long)0x98badcfeL #define INIT_DATA_D (unsigned long)0x10325476L -#ifndef NOPROTO -# ifdef MD5_ASM - void md5_block_x86(MD5_CTX *c, unsigned long *p,int num); -# define md5_block md5_block_x86 -# else - static void md5_block(MD5_CTX *c, unsigned long *p,int num); -# endif -#else -# ifdef MD5_ASM - void md5_block_x86(); -# define md5_block md5_block_x86 -# else - static void md5_block(); -# endif -#endif - -void MD5_Init(c) -MD5_CTX *c; +int MD5_Init(MD5_CTX *c) { c->A=INIT_DATA_A; c->B=INIT_DATA_B; @@ -95,192 +79,35 @@ MD5_CTX *c; c->Nl=0; c->Nh=0; c->num=0; + return 1; } -void MD5_Update(c, data, len) -MD5_CTX *c; -register unsigned char *data; -unsigned long len; - { - register ULONG *p; - int sw,sc; - ULONG l; - - if (len == 0) return; - - l=(c->Nl+(len<<3))&0xffffffffL; - /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to - * Wei Dai for pointing it out. */ - if (l < c->Nl) /* overflow */ - c->Nh++; - c->Nh+=(len>>29); - c->Nl=l; - - if (c->num != 0) - { - p=c->data; - sw=c->num>>2; - sc=c->num&0x03; - - if ((c->num+len) >= MD5_CBLOCK) - { - l= p[sw]; - p_c2l(data,l,sc); - p[sw++]=l; - for (; swnum); - - md5_block(c,p,64); - c->num=0; - /* drop through and do the rest */ - } - else - { - int ew,ec; - - c->num+=(int)len; - if ((sc+len) < 4) /* ugly, add char's to a word */ - { - l= p[sw]; - p_c2l_p(data,l,sc,len); - p[sw]=l; - } - else - { - ew=(c->num>>2); - ec=(c->num&0x03); - l= p[sw]; - p_c2l(data,l,sc); - p[sw++]=l; - for (; sw < ew; sw++) - { c2l(data,l); p[sw]=l; } - if (ec) - { - c2l_p(data,l,ec); - p[sw]=l; - } - } - return; - } - } - /* we now can process the input data in blocks of MD5_CBLOCK - * chars and save the leftovers to c->data. */ -#ifdef L_ENDIAN - if ((((unsigned long)data)%sizeof(ULONG)) == 0) - { - sw=(int)len/MD5_CBLOCK; - if (sw > 0) - { - sw*=MD5_CBLOCK; - md5_block(c,(ULONG *)data,sw); - data+=sw; - len-=sw; - } - } -#endif - p=c->data; - while (len >= MD5_CBLOCK) - { -#if defined(L_ENDIAN) || defined(B_ENDIAN) - if (p != (unsigned long *)data) - memcpy(p,data,MD5_CBLOCK); - data+=MD5_CBLOCK; -#ifdef B_ENDIAN - for (sw=(MD5_LBLOCK/4); sw; sw--) - { - Endian_Reverse32(p[0]); - Endian_Reverse32(p[1]); - Endian_Reverse32(p[2]); - Endian_Reverse32(p[3]); - p+=4; - } -#endif -#else - for (sw=(MD5_LBLOCK/4); sw; sw--) - { - c2l(data,l); *(p++)=l; - c2l(data,l); *(p++)=l; - c2l(data,l); *(p++)=l; - c2l(data,l); *(p++)=l; - } -#endif - p=c->data; - md5_block(c,p,64); - len-=MD5_CBLOCK; - } - sc=(int)len; - c->num=sc; - if (sc) - { - sw=sc>>2; /* words to copy */ -#ifdef L_ENDIAN - p[sw]=0; - memcpy(p,data,sc); -#else - sc&=0x03; - for ( ; sw; sw--) - { c2l(data,l); *(p++)=l; } - c2l_p(data,l,sc); - *p=l; -#endif - } - } - -void MD5_Transform(c,b) -MD5_CTX *c; -unsigned char *b; - { - ULONG p[16]; -#if !defined(L_ENDIAN) - ULONG *q; - int i; -#endif - -#if defined(B_ENDIAN) || defined(L_ENDIAN) - memcpy(p,b,64); -#ifdef B_ENDIAN - q=p; - for (i=(MD5_LBLOCK/4); i; i--) - { - Endian_Reverse32(q[0]); - Endian_Reverse32(q[1]); - Endian_Reverse32(q[2]); - Endian_Reverse32(q[3]); - q+=4; - } -#endif -#else - q=p; - for (i=(MD5_LBLOCK/4); i; i--) - { - ULONG l; - c2l(b,l); *(q++)=l; - c2l(b,l); *(q++)=l; - c2l(b,l); *(q++)=l; - c2l(b,l); *(q++)=l; - } -#endif - md5_block(c,p,64); - } - -#ifndef MD5_ASM - -static void md5_block(c, X, num) -MD5_CTX *c; -register ULONG *X; -int num; +#ifndef md5_block_host_order +void md5_block_host_order (MD5_CTX *c, const void *data, int num) { - register ULONG A,B,C,D; + const MD5_LONG *X=data; + register unsigned long A,B,C,D; + /* + * In case you wonder why A-D are declared as long and not + * as MD5_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + * + * + */ A=c->A; B=c->B; C=c->C; D=c->D; - for (;;) + + for (;num--;X+=HASH_LBLOCK) { /* Round 0 */ R0(A,B,C,D,X[ 0], 7,0xd76aa478L); @@ -351,80 +178,133 @@ int num; R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL); R3(B,C,D,A,X[ 9],21,0xeb86d391L); - A+=c->A&0xffffffffL; - B+=c->B&0xffffffffL; - c->A=A; - c->B=B; - C+=c->C&0xffffffffL; - D+=c->D&0xffffffffL; - c->C=C; - c->D=D; - X+=16; - num-=64; - if (num <= 0) break; + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; } } #endif -void MD5_Final(md, c) -unsigned char *md; -MD5_CTX *c; +#ifndef md5_block_data_order +#ifdef X +#undef X +#endif +void md5_block_data_order (MD5_CTX *c, const void *data_, int num) { - register int i,j; - register ULONG l; - register ULONG *p; - static unsigned char end[4]={0x80,0x00,0x00,0x00}; - unsigned char *cp=end; + const unsigned char *data=data_; + register unsigned long A,B,C,D,l; + /* + * In case you wonder why A-D are declared as long and not + * as MD5_LONG. Doing so results in slight performance + * boost on LP64 architectures. The catch is we don't + * really care if 32 MSBs of a 64-bit register get polluted + * with eventual overflows as we *save* only 32 LSBs in + * *either* case. Now declaring 'em long excuses the compiler + * from keeping 32 MSBs zeroed resulting in 13% performance + * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. + * Well, to be honest it should say that this *prevents* + * performance degradation. + * + * + */ +#ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +# define X(i) XX##i +#else + MD5_LONG XX[MD5_LBLOCK]; +# define X(i) XX[i] +#endif - /* c->num should definitly have room for at least one more byte. */ - p=c->data; - j=c->num; - i=j>>2; + A=c->A; + B=c->B; + C=c->C; + D=c->D; - /* purify often complains about the following line as an - * Uninitialized Memory Read. While this can be true, the - * following p_c2l macro will reset l when that case is true. - * This is because j&0x03 contains the number of 'valid' bytes - * already in p[i]. If and only if j&0x03 == 0, the UMR will - * occur but this is also the only time p_c2l will do - * l= *(cp++) instead of l|= *(cp++) - * Many thanks to Alex Tang for pickup this - * 'potential bug' */ -#ifdef PURIFY - if ((j&0x03) == 0) p[i]=0; -#endif - l=p[i]; - p_c2l(cp,l,j&0x03); - p[i]=l; - i++; - /* i is the next 'undefined word' */ - if (c->num >= MD5_LAST_BLOCK) + for (;num--;) { - for (; iNl; - p[MD5_LBLOCK-1]=c->Nh; - md5_block(c,p,64); - cp=md; - l=c->A; l2c(l,cp); - l=c->B; l2c(l,cp); - l=c->C; l2c(l,cp); - l=c->D; l2c(l,cp); + HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + /* Round 0 */ + R0(A,B,C,D,X( 0), 7,0xd76aa478L); HOST_c2l(data,l); X( 2)=l; + R0(D,A,B,C,X( 1),12,0xe8c7b756L); HOST_c2l(data,l); X( 3)=l; + R0(C,D,A,B,X( 2),17,0x242070dbL); HOST_c2l(data,l); X( 4)=l; + R0(B,C,D,A,X( 3),22,0xc1bdceeeL); HOST_c2l(data,l); X( 5)=l; + R0(A,B,C,D,X( 4), 7,0xf57c0fafL); HOST_c2l(data,l); X( 6)=l; + R0(D,A,B,C,X( 5),12,0x4787c62aL); HOST_c2l(data,l); X( 7)=l; + R0(C,D,A,B,X( 6),17,0xa8304613L); HOST_c2l(data,l); X( 8)=l; + R0(B,C,D,A,X( 7),22,0xfd469501L); HOST_c2l(data,l); X( 9)=l; + R0(A,B,C,D,X( 8), 7,0x698098d8L); HOST_c2l(data,l); X(10)=l; + R0(D,A,B,C,X( 9),12,0x8b44f7afL); HOST_c2l(data,l); X(11)=l; + R0(C,D,A,B,X(10),17,0xffff5bb1L); HOST_c2l(data,l); X(12)=l; + R0(B,C,D,A,X(11),22,0x895cd7beL); HOST_c2l(data,l); X(13)=l; + R0(A,B,C,D,X(12), 7,0x6b901122L); HOST_c2l(data,l); X(14)=l; + R0(D,A,B,C,X(13),12,0xfd987193L); HOST_c2l(data,l); X(15)=l; + R0(C,D,A,B,X(14),17,0xa679438eL); + R0(B,C,D,A,X(15),22,0x49b40821L); + /* Round 1 */ + R1(A,B,C,D,X( 1), 5,0xf61e2562L); + R1(D,A,B,C,X( 6), 9,0xc040b340L); + R1(C,D,A,B,X(11),14,0x265e5a51L); + R1(B,C,D,A,X( 0),20,0xe9b6c7aaL); + R1(A,B,C,D,X( 5), 5,0xd62f105dL); + R1(D,A,B,C,X(10), 9,0x02441453L); + R1(C,D,A,B,X(15),14,0xd8a1e681L); + R1(B,C,D,A,X( 4),20,0xe7d3fbc8L); + R1(A,B,C,D,X( 9), 5,0x21e1cde6L); + R1(D,A,B,C,X(14), 9,0xc33707d6L); + R1(C,D,A,B,X( 3),14,0xf4d50d87L); + R1(B,C,D,A,X( 8),20,0x455a14edL); + R1(A,B,C,D,X(13), 5,0xa9e3e905L); + R1(D,A,B,C,X( 2), 9,0xfcefa3f8L); + R1(C,D,A,B,X( 7),14,0x676f02d9L); + R1(B,C,D,A,X(12),20,0x8d2a4c8aL); + /* Round 2 */ + R2(A,B,C,D,X( 5), 4,0xfffa3942L); + R2(D,A,B,C,X( 8),11,0x8771f681L); + R2(C,D,A,B,X(11),16,0x6d9d6122L); + R2(B,C,D,A,X(14),23,0xfde5380cL); + R2(A,B,C,D,X( 1), 4,0xa4beea44L); + R2(D,A,B,C,X( 4),11,0x4bdecfa9L); + R2(C,D,A,B,X( 7),16,0xf6bb4b60L); + R2(B,C,D,A,X(10),23,0xbebfbc70L); + R2(A,B,C,D,X(13), 4,0x289b7ec6L); + R2(D,A,B,C,X( 0),11,0xeaa127faL); + R2(C,D,A,B,X( 3),16,0xd4ef3085L); + R2(B,C,D,A,X( 6),23,0x04881d05L); + R2(A,B,C,D,X( 9), 4,0xd9d4d039L); + R2(D,A,B,C,X(12),11,0xe6db99e5L); + R2(C,D,A,B,X(15),16,0x1fa27cf8L); + R2(B,C,D,A,X( 2),23,0xc4ac5665L); + /* Round 3 */ + R3(A,B,C,D,X( 0), 6,0xf4292244L); + R3(D,A,B,C,X( 7),10,0x432aff97L); + R3(C,D,A,B,X(14),15,0xab9423a7L); + R3(B,C,D,A,X( 5),21,0xfc93a039L); + R3(A,B,C,D,X(12), 6,0x655b59c3L); + R3(D,A,B,C,X( 3),10,0x8f0ccc92L); + R3(C,D,A,B,X(10),15,0xffeff47dL); + R3(B,C,D,A,X( 1),21,0x85845dd1L); + R3(A,B,C,D,X( 8), 6,0x6fa87e4fL); + R3(D,A,B,C,X(15),10,0xfe2ce6e0L); + R3(C,D,A,B,X( 6),15,0xa3014314L); + R3(B,C,D,A,X(13),21,0x4e0811a1L); + R3(A,B,C,D,X( 4), 6,0xf7537e82L); + R3(D,A,B,C,X(11),10,0xbd3af235L); + R3(C,D,A,B,X( 2),15,0x2ad7d2bbL); + R3(B,C,D,A,X( 9),21,0xeb86d391L); - /* clear stuff, md5_block may be leaving some stuff on the stack - * but I'm not worried :-) */ - c->num=0; -/* memset((char *)&c,0,sizeof(c));*/ + A = c->A += A; + B = c->B += B; + C = c->C += C; + D = c->D += D; + } } +#endif #ifdef undef -int printit(l) -unsigned long *l; +int printit(unsigned long *l) { int i,ii; diff --git a/src/lib/libcrypto/md5/md5_locl.h b/src/lib/libcrypto/md5/md5_locl.h index dbbe1b71ca..34c5257306 100644 --- a/src/lib/libcrypto/md5/md5_locl.h +++ b/src/lib/libcrypto/md5/md5_locl.h @@ -56,109 +56,94 @@ * [including the GNU Public Licence.] */ -/* On sparc, this actually slows things down :-( */ -#if defined(sun) -#undef B_ENDIAN -#endif - #include #include -#include "md5.h" - -#define ULONG unsigned long -#define UCHAR unsigned char -#define UINT unsigned int +#include +#include -#if defined(NOCONST) -#define const +#ifndef MD5_LONG_LOG2 +#define MD5_LONG_LOG2 2 /* default to 32 bits */ #endif -#undef c2l -#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<<24)) - -#undef p_c2l -#define p_c2l(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++))); \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - case 3: l|=((unsigned long)(*((c)++)))<<24; \ - } \ - } +#ifdef MD5_ASM +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) +# define md5_block_host_order md5_block_asm_host_order +# elif defined(__sparc) && defined(OPENSSL_SYS_ULTRASPARC) + void md5_block_asm_data_order_aligned (MD5_CTX *c, const MD5_LONG *p,int num); +# define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned +# endif +#endif -/* NOTE the pointer is not incremented at the end of this */ -#undef c2l_p -#define c2l_p(c,l,n) { \ - l=0; \ - (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<<16; \ - case 2: l|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l|=((unsigned long)(*(--(c)))) ; \ - } \ - } +void md5_block_host_order (MD5_CTX *c, const void *p,int num); +void md5_block_data_order (MD5_CTX *c, const void *p,int num); -#undef p_c2l_p -#define p_c2l_p(c,l,sc,len) { \ - switch (sc) \ - { \ - case 0: l =((unsigned long)(*((c)++))); \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - } \ - } +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) +/* + * *_block_host_order is expected to handle aligned data while + * *_block_data_order - unaligned. As algorithm and host (x86) + * are in this case of the same "endianness" these two are + * otherwise indistinguishable. But normally you don't want to + * call the same function because unaligned access in places + * where alignment is expected is usually a "Bad Thing". Indeed, + * on RISCs you get punished with BUS ERROR signal or *severe* + * performance degradation. Intel CPUs are in turn perfectly + * capable of loading unaligned data without such drastic side + * effect. Yes, they say it's slower than aligned load, but no + * exception is generated and therefore performance degradation + * is *incomparable* with RISCs. What we should weight here is + * costs of unaligned access against costs of aligning data. + * According to my measurements allowing unaligned access results + * in ~9% performance improvement on Pentium II operating at + * 266MHz. I won't be surprised if the difference will be higher + * on faster systems:-) + * + * + */ +#define md5_block_data_order md5_block_host_order +#endif -#undef l2c -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG MD5_LONG +#define HASH_LONG_LOG2 MD5_LONG_LOG2 +#define HASH_CTX MD5_CTX +#define HASH_CBLOCK MD5_CBLOCK +#define HASH_LBLOCK MD5_LBLOCK +#define HASH_UPDATE MD5_Update +#define HASH_TRANSFORM MD5_Transform +#define HASH_FINAL MD5_Final +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; HOST_l2c(ll,(s)); \ + ll=(c)->B; HOST_l2c(ll,(s)); \ + ll=(c)->C; HOST_l2c(ll,(s)); \ + ll=(c)->D; HOST_l2c(ll,(s)); \ + } while (0) +#define HASH_BLOCK_HOST_ORDER md5_block_host_order +#if !defined(L_ENDIAN) || defined(md5_block_data_order) +#define HASH_BLOCK_DATA_ORDER md5_block_data_order +/* + * Little-endians (Intel and Alpha) feel better without this. + * It looks like memcpy does better job than generic + * md5_block_data_order on copying-n-aligning input data. + * But frankly speaking I didn't expect such result on Alpha. + * On the other hand I've got this with egcs-1.0.2 and if + * program is compiled with another (better?) compiler it + * might turn out other way around. + * + * + */ +#endif -/* 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)>>24)&0xff); \ - case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ - case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ - } \ - } +#include "md32_common.h" -/* A nice byte order reversal from Wei Dai */ -#if defined(WIN32) -/* 5 instructions with rotate instruction, else 9 */ -#define Endian_Reverse32(a) \ - { \ - unsigned long l=(a); \ - (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ - } -#else -/* 6 instructions with rotate instruction, else 8 */ -#define Endian_Reverse32(a) \ - { \ - unsigned long l=(a); \ - l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ - (a)=ROTATE(l,16L); \ - } -#endif /* #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) #define G(x,y,z) (((x) & (z)) | ((y) & (~(z)))) */ /* As pointed out by Wei Dai , the above can be - * simplified to the code below. Wei attributes these optimisations + * simplified to the code below. Wei attributes these optimizations * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. */ #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) @@ -166,14 +151,6 @@ #define H(b,c,d) ((b) ^ (c) ^ (d)) #define I(b,c,d) (((~(d)) | (b)) ^ (c)) -#undef ROTATE -#if defined(WIN32) -#define ROTATE(a,n) _lrotl(a,n) -#else -#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) -#endif - - #define R0(a,b,c,d,k,s,t) { \ a+=((k)+(t)+F((b),(c),(d))); \ a=ROTATE(a,s); \ diff --git a/src/lib/libcrypto/md5/md5_one.c b/src/lib/libcrypto/md5/md5_one.c index ab6bb435f9..b89dec850d 100644 --- a/src/lib/libcrypto/md5/md5_one.c +++ b/src/lib/libcrypto/md5/md5_one.c @@ -57,19 +57,37 @@ */ #include -#include "md5_locl.h" +#include +#include -unsigned char *MD5(d, n, md) -unsigned char *d; -unsigned long n; -unsigned char *md; +#ifdef CHARSET_EBCDIC +#include +#endif + +unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md) { MD5_CTX c; static unsigned char m[MD5_DIGEST_LENGTH]; if (md == NULL) md=m; MD5_Init(&c); +#ifndef CHARSET_EBCDIC MD5_Update(&c,d,n); +#else + { + char temp[1024]; + unsigned long chunk; + + while (n > 0) + { + chunk = (n > sizeof(temp)) ? sizeof(temp) : n; + ebcdic2ascii(temp, d, chunk); + MD5_Update(&c,temp,chunk); + n -= chunk; + d += chunk; + } + } +#endif MD5_Final(md,&c); memset(&c,0,sizeof(c)); /* security consideration */ return(md); diff --git a/src/lib/libcrypto/mem_dbg.c b/src/lib/libcrypto/mem_dbg.c index 14770c0733..1c4e04f51f 100644 --- a/src/lib/libcrypto/mem_dbg.c +++ b/src/lib/libcrypto/mem_dbg.c @@ -81,7 +81,8 @@ static int mh_mode=CRYPTO_MEM_CHECK_OFF; */ static unsigned long order = 0; /* number of memory requests */ -static LHASH *mh=NULL; /* hash-table of memory requests (address as key) */ +static LHASH *mh=NULL; /* hash-table of memory requests (address as key); + * access requires MALLOC2 lock */ typedef struct app_mem_info_st @@ -103,12 +104,13 @@ typedef struct app_mem_info_st static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's * that are at the top of their thread's stack - * (with `thread' as key) */ + * (with `thread' as key); + * access requires MALLOC2 lock */ typedef struct mem_st /* memory-block description */ { - char *addr; + void *addr; int num; const char *file; int line; @@ -128,7 +130,15 @@ static long options = /* extra information to be recorded */ 0; -static unsigned long disabling_thread = 0; +static unsigned int num_disable = 0; /* num_disable > 0 + * iff + * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) + */ +static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0. + * CRYPTO_LOCK_MALLOC2 is locked + * exactly in this case (by the + * thread named in disabling_thread). + */ int CRYPTO_mem_ctrl(int mode) { @@ -137,22 +147,23 @@ int CRYPTO_mem_ctrl(int mode) CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); switch (mode) { - /* for applications: */ + /* for applications (not to be called while multiple threads + * use the library): */ case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */ mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE; - disabling_thread = 0; + num_disable = 0; break; case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */ mh_mode = 0; - disabling_thread = 0; + num_disable = 0; /* should be true *before* MemCheck_stop is used, + or there'll be a lot of confusion */ break; /* switch off temporarily (for library-internal use): */ case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ if (mh_mode & CRYPTO_MEM_CHECK_ON) { - mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE; - if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */ + if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */ { /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if @@ -169,18 +180,23 @@ int CRYPTO_mem_ctrl(int mode) * OpenSSL threads. */ CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); + mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; disabling_thread=CRYPTO_thread_id(); } + num_disable++; } break; case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */ if (mh_mode & CRYPTO_MEM_CHECK_ON) { - mh_mode|=CRYPTO_MEM_CHECK_ENABLE; - if (disabling_thread != 0) + if (num_disable) /* always true, or something is going wrong */ { - disabling_thread=0; - CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + num_disable--; + if (num_disable == 0) + { + mh_mode|=CRYPTO_MEM_CHECK_ENABLE; + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + } } } break; @@ -198,12 +214,12 @@ int CRYPTO_is_mem_check_on(void) if (mh_mode & CRYPTO_MEM_CHECK_ON) { - CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); + CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) - && disabling_thread != CRYPTO_thread_id(); + || (disabling_thread != CRYPTO_thread_id()); - CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); + CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); } return(ret); } @@ -219,37 +235,43 @@ long CRYPTO_dbg_get_options(void) return options; } -static int mem_cmp(MEM *a, MEM *b) +/* static int mem_cmp(MEM *a, MEM *b) */ +static int mem_cmp(const void *a_void, const void *b_void) { - return(a->addr - b->addr); + return((const char *)((const MEM *)a_void)->addr + - (const char *)((const MEM *)b_void)->addr); } -static unsigned long mem_hash(MEM *a) +/* static unsigned long mem_hash(MEM *a) */ +static unsigned long mem_hash(const void *a_void) { unsigned long ret; - ret=(unsigned long)a->addr; + ret=(unsigned long)((const MEM *)a_void)->addr; ret=ret*17851+(ret>>14)*7+(ret>>4)*251; return(ret); } -static int app_info_cmp(APP_INFO *a, APP_INFO *b) +/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ +static int app_info_cmp(const void *a_void, const void *b_void) { - return(a->thread != b->thread); + return(((const APP_INFO *)a_void)->thread + != ((const APP_INFO *)b_void)->thread); } -static unsigned long app_info_hash(APP_INFO *a) +/* static unsigned long app_info_hash(APP_INFO *a) */ +static unsigned long app_info_hash(const void *a_void) { unsigned long ret; - ret=(unsigned long)a->thread; + ret=(unsigned long)((const APP_INFO *)a_void)->thread; ret=ret*17851+(ret>>14)*7+(ret>>4)*251; return(ret); } -static APP_INFO *pop_info() +static APP_INFO *pop_info(void) { APP_INFO tmp; APP_INFO *ret = NULL; @@ -266,7 +288,7 @@ static APP_INFO *pop_info() next->references++; lh_insert(amih,(char *)next); } -#ifdef LEVITTE_DEBUG +#ifdef LEVITTE_DEBUG_MEM if (ret->thread != tmp.thread) { fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n", @@ -279,7 +301,7 @@ static APP_INFO *pop_info() ret->next = NULL; if (next != NULL) next->references--; - Free(ret); + OPENSSL_free(ret); } } } @@ -293,18 +315,18 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) if (is_MemCheck_on()) { - MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + MemCheck_off(); /* obtain MALLOC2 lock */ - if ((ami = (APP_INFO *)Malloc(sizeof(APP_INFO))) == NULL) + if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) { ret=0; goto err; } if (amih == NULL) { - if ((amih=lh_new(app_info_hash,app_info_cmp)) == NULL) + if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL) { - Free(ami); + OPENSSL_free(ami); ret=0; goto err; } @@ -319,7 +341,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL) { -#ifdef LEVITTE_DEBUG +#ifdef LEVITTE_DEBUG_MEM if (ami->thread != amim->thread) { fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n", @@ -330,7 +352,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) ami->next=amim; } err: - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + MemCheck_on(); /* release MALLOC2 lock */ } return(ret); @@ -342,11 +364,11 @@ int CRYPTO_pop_info(void) if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */ { - MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + MemCheck_off(); /* obtain MALLOC2 lock */ ret=(pop_info() != NULL); - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + MemCheck_on(); /* release MALLOC2 lock */ } return(ret); } @@ -357,12 +379,12 @@ int CRYPTO_remove_all_info(void) if (is_MemCheck_on()) /* _must_ be true */ { - MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + MemCheck_off(); /* obtain MALLOC2 lock */ while(pop_info() != NULL) ret++; - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + MemCheck_on(); /* release MALLOC2 lock */ } return(ret); } @@ -385,19 +407,20 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, if (is_MemCheck_on()) { - MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ - if ((m=(MEM *)Malloc(sizeof(MEM))) == NULL) + MemCheck_off(); /* make sure we hold MALLOC2 lock */ + if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) { - Free(addr); - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + OPENSSL_free(addr); + MemCheck_on(); /* release MALLOC2 lock + * if num_disabled drops to 0 */ return; } if (mh == NULL) { - if ((mh=lh_new(mem_hash,mem_cmp)) == NULL) + if ((mh=lh_new(mem_hash, mem_cmp)) == NULL) { - Free(addr); - Free(m); + OPENSSL_free(addr); + OPENSSL_free(m); addr=NULL; goto err; } @@ -418,8 +441,8 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, m->order=order; } m->order=order++; -#ifdef LEVITTE_DEBUG - fprintf(stderr, "LEVITTE_DEBUG: [%5d] %c 0x%p (%d)\n", +#ifdef LEVITTE_DEBUG_MEM + fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n", m->order, (before_p & 128) ? '*' : '+', m->addr, m->num); @@ -445,10 +468,11 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, { mm->app_info->references--; } - Free(mm); + OPENSSL_free(mm); } err: - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + MemCheck_on(); /* release MALLOC2 lock + * if num_disabled drops to 0 */ } break; } @@ -467,24 +491,25 @@ void CRYPTO_dbg_free(void *addr, int before_p) if (is_MemCheck_on() && (mh != NULL)) { - MemCheck_off(); + MemCheck_off(); /* make sure we hold MALLOC2 lock */ m.addr=addr; mp=(MEM *)lh_delete(mh,(char *)&m); if (mp != NULL) { -#ifdef LEVITTE_DEBUG - fprintf(stderr, "LEVITTE_DEBUG: [%5d] - 0x%p (%d)\n", +#ifdef LEVITTE_DEBUG_MEM + fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n", mp->order, mp->addr, mp->num); #endif if (mp->app_info != NULL) { mp->app_info->references--; } - Free(mp); + OPENSSL_free(mp); } - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + MemCheck_on(); /* release MALLOC2 lock + * if num_disabled drops to 0 */ } break; case 1: @@ -497,8 +522,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, { MEM m,*mp; -#ifdef LEVITTE_DEBUG - fprintf(stderr, "LEVITTE_DEBUG: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", +#ifdef LEVITTE_DEBUG_MEM + fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n", addr1, addr2, num, file, line, before_p); #endif @@ -518,14 +543,14 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, if (is_MemCheck_on()) { - MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */ + MemCheck_off(); /* make sure we hold MALLOC2 lock */ m.addr=addr1; mp=(MEM *)lh_delete(mh,(char *)&m); if (mp != NULL) { -#ifdef LEVITTE_DEBUG - fprintf(stderr, "LEVITTE_DEBUG: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", +#ifdef LEVITTE_DEBUG_MEM + fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n", mp->order, mp->addr, mp->num, addr2, num); @@ -535,7 +560,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, lh_insert(mh,(char *)mp); } - MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */ + MemCheck_on(); /* release MALLOC2 lock + * if num_disabled drops to 0 */ } break; } @@ -550,7 +576,7 @@ typedef struct mem_leak_st long bytes; } MEM_LEAK; -static void print_leak(MEM *m, MEM_LEAK *l) +static void print_leak(const MEM *m, MEM_LEAK *l) { char buf[1024]; char *bufp = buf; @@ -626,7 +652,7 @@ static void print_leak(MEM *m, MEM_LEAK *l) } while(amip && amip->thread == ti); -#ifdef LEVITTE_DEBUG +#ifdef LEVITTE_DEBUG_MEM if (amip) { fprintf(stderr, "Thread switch detected in backtrace!!!!\n"); @@ -635,69 +661,114 @@ static void print_leak(MEM *m, MEM_LEAK *l) #endif } +static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *) + void CRYPTO_mem_leaks(BIO *b) { MEM_LEAK ml; char buf[80]; - if (mh == NULL) return; + if (mh == NULL && amih == NULL) + return; + + MemCheck_off(); /* obtain MALLOC2 lock */ + ml.bio=b; ml.bytes=0; ml.chunks=0; - CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); - lh_doall_arg(mh,(void (*)())print_leak,(char *)&ml); - CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + if (mh != NULL) + lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), + (char *)&ml); if (ml.chunks != 0) { sprintf(buf,"%ld bytes leaked in %d chunks\n", ml.bytes,ml.chunks); BIO_puts(b,buf); } + else + { + /* Make sure that, if we found no leaks, memory-leak debugging itself + * does not introduce memory leaks (which might irritate + * external debugging tools). + * (When someone enables leak checking, but does not call + * this function, we declare it to be their fault.) + * + * XXX This should be in CRYPTO_mem_leaks_cb, + * and CRYPTO_mem_leaks should be implemented by + * using CRYPTO_mem_leaks_cb. + * (Also their should be a variant of lh_doall_arg + * that takes a function pointer instead of a void *; + * this would obviate the ugly and illegal + * void_fn_to_char kludge in CRYPTO_mem_leaks_cb. + * Otherwise the code police will come and get us.) + */ + int old_mh_mode; -#if 0 - lh_stats_bio(mh,b); - lh_node_stats_bio(mh,b); - lh_node_usage_stats_bio(mh,b); -#endif - } - -union void_fn_to_char_u - { - char *char_p; - void (*fn_p)(); - }; - -static void cb_leak(MEM *m, char *cb) - { - union void_fn_to_char_u mem_callback; + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); - mem_callback.char_p=cb; - mem_callback.fn_p(m->order,m->file,m->line,m->num,m->addr); - } + /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(), + * which uses CRYPTO_is_mem_check_on */ + old_mh_mode = mh_mode; + mh_mode = CRYPTO_MEM_CHECK_OFF; -void CRYPTO_mem_leaks_cb(void (*cb)()) - { - union void_fn_to_char_u mem_cb; + if (mh != NULL) + { + lh_free(mh); + mh = NULL; + } + if (amih != NULL) + { + if (lh_num_items(amih) == 0) + { + lh_free(amih); + amih = NULL; + } + } - if (mh == NULL) return; - CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); - mem_cb.fn_p=cb; - lh_doall_arg(mh,(void (*)())cb_leak,mem_cb.char_p); - mem_cb.char_p=NULL; - CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + mh_mode = old_mh_mode; + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC); + } + MemCheck_on(); /* release MALLOC2 lock */ } -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API void CRYPTO_mem_leaks_fp(FILE *fp) { BIO *b; if (mh == NULL) return; - if ((b=BIO_new(BIO_s_file())) == NULL) - return; + /* Need to turn off memory checking when allocated BIOs ... especially + * as we're creating them at a time when we're trying to check we've not + * left anything un-free()'d!! */ + MemCheck_off(); + b = BIO_new(BIO_s_file()); + MemCheck_on(); + if(!b) return; BIO_set_fp(b,fp,BIO_NOCLOSE); CRYPTO_mem_leaks(b); BIO_free(b); } #endif + + +/* FIXME: We really don't allow much to the callback. For example, it has + no chance of reaching the info stack for the item it processes. Should + it really be this way? -- Richard Levitte */ +/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h + * If this code is restructured, remove the callback type if it is no longer + * needed. -- Geoff Thorpe */ +static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb) + { + (**cb)(m->order,m->file,m->line,m->num,m->addr); + } + +static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **) + +void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb) + { + if (mh == NULL) return; + CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); + lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb); + CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2); + } diff --git a/src/lib/libcrypto/objects/o_names.c b/src/lib/libcrypto/objects/o_names.c index 4da5e45b9c..b4453b4a98 100644 --- a/src/lib/libcrypto/objects/o_names.c +++ b/src/lib/libcrypto/objects/o_names.c @@ -4,78 +4,119 @@ #include #include +#include +#include + +/* Later versions of DEC C has started to add lnkage information to certain + * functions, which makes it tricky to use them as values to regular function + * pointers. One way is to define a macro that takes care of casting them + * correctly. + */ +#ifdef OPENSSL_SYS_VMS_DECC +# define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp +#else +# define OPENSSL_strcmp strcmp +#endif /* I use the ex_data stuff to manage the identifiers for the obj_name_types * that applications may define. I only really use the free function field. */ static LHASH *names_lh=NULL; static int names_type_num=OBJ_NAME_TYPE_NUM; -static STACK *names_cmp=NULL; -static STACK *names_hash=NULL; -static STACK *names_free=NULL; -static unsigned long obj_name_hash(OBJ_NAME *a); -static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); +typedef struct name_funcs_st + { + unsigned long (*hash_func)(const char *name); + int (*cmp_func)(const char *a,const char *b); + void (*free_func)(const char *, int, const char *); + } NAME_FUNCS; + +DECLARE_STACK_OF(NAME_FUNCS) +IMPLEMENT_STACK_OF(NAME_FUNCS) + +static STACK_OF(NAME_FUNCS) *name_funcs_stack; + +/* The LHASH callbacks now use the raw "void *" prototypes and do per-variable + * casting in the functions. This prevents function pointer casting without the + * need for macro-generated wrapper functions. */ + +/* static unsigned long obj_name_hash(OBJ_NAME *a); */ +static unsigned long obj_name_hash(const void *a_void); +/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */ +static int obj_name_cmp(const void *a_void,const void *b_void); int OBJ_NAME_init(void) { if (names_lh != NULL) return(1); MemCheck_off(); - names_lh=lh_new(obj_name_hash,obj_name_cmp); + names_lh=lh_new(obj_name_hash, obj_name_cmp); MemCheck_on(); return(names_lh != NULL); } -int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(), - void (*free_func)()) +int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *), + int (*cmp_func)(const char *, const char *), + void (*free_func)(const char *, int, const char *)) { int ret; int i; + NAME_FUNCS *name_funcs; - if (names_free == NULL) + if (name_funcs_stack == NULL) { MemCheck_off(); - names_hash=sk_new_null(); - names_cmp=sk_new_null(); - names_free=sk_new_null(); + name_funcs_stack=sk_NAME_FUNCS_new_null(); MemCheck_on(); } - if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL)) + if ((name_funcs_stack == NULL)) { /* ERROR */ return(0); } ret=names_type_num; names_type_num++; - for (i=sk_num(names_free); ihash_func = lh_strhash; + name_funcs->cmp_func = OPENSSL_strcmp; + name_funcs->free_func = 0; /* NULL is often declared to + * ((void *)0), which according + * to Compaq C is not really + * compatible with a function + * pointer. -- Richard Levitte*/ + MemCheck_off(); + sk_NAME_FUNCS_push(name_funcs_stack,name_funcs); MemCheck_on(); } + name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret); if (hash_func != NULL) - sk_set(names_hash,ret,(char *)hash_func); + name_funcs->hash_func = hash_func; if (cmp_func != NULL) - sk_set(names_cmp,ret,(char *)cmp_func); + name_funcs->cmp_func = cmp_func; if (free_func != NULL) - sk_set(names_free,ret,(char *)free_func); + name_funcs->free_func = free_func; return(ret); } -static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) +/* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */ +static int obj_name_cmp(const void *a_void, const void *b_void) { int ret; - int (*cmp)(); + OBJ_NAME *a = (OBJ_NAME *)a_void; + OBJ_NAME *b = (OBJ_NAME *)b_void; ret=a->type-b->type; if (ret == 0) { - if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type)) + if ((name_funcs_stack != NULL) + && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) { - cmp=(int (*)())sk_value(names_cmp,a->type); - ret=cmp(a->name,b->name); + ret=sk_NAME_FUNCS_value(name_funcs_stack, + a->type)->cmp_func(a->name,b->name); } else ret=strcmp(a->name,b->name); @@ -83,15 +124,16 @@ static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) return(ret); } -static unsigned long obj_name_hash(OBJ_NAME *a) +/* static unsigned long obj_name_hash(OBJ_NAME *a) */ +static unsigned long obj_name_hash(const void *a_void) { unsigned long ret; - unsigned long (*hash)(); + OBJ_NAME *a = (OBJ_NAME *)a_void; - if ((names_hash != NULL) && (sk_num(names_hash) > a->type)) + if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) { - hash=(unsigned long (*)())sk_value(names_hash,a->type); - ret=hash(a->name); + ret=sk_NAME_FUNCS_value(name_funcs_stack, + a->type)->hash_func(a->name); } else { @@ -116,8 +158,8 @@ const char *OBJ_NAME_get(const char *name, int type) on.type=type; for (;;) - { - ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on); + { + ret=(OBJ_NAME *)lh_retrieve(names_lh,&on); if (ret == NULL) return(NULL); if ((ret->alias) && !alias) { @@ -133,7 +175,6 @@ const char *OBJ_NAME_get(const char *name, int type) int OBJ_NAME_add(const char *name, int type, const char *data) { - void (*f)(); OBJ_NAME *onp,*ret; int alias; @@ -142,7 +183,7 @@ int OBJ_NAME_add(const char *name, int type, const char *data) alias=type&OBJ_NAME_ALIAS; type&= ~OBJ_NAME_ALIAS; - onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME)); + onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME)); if (onp == NULL) { /* ERROR */ @@ -154,16 +195,20 @@ int OBJ_NAME_add(const char *name, int type, const char *data) onp->type=type; onp->data=data; - ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp); + ret=(OBJ_NAME *)lh_insert(names_lh,onp); if (ret != NULL) { /* free things */ - if ((names_free != NULL) && (sk_num(names_free) > ret->type)) + if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) { - f=(void (*)())sk_value(names_free,ret->type); - f(ret->name,ret->type,ret->data); + /* XXX: I'm not sure I understand why the free + * function should get three arguments... + * -- Richard Levitte + */ + sk_NAME_FUNCS_value(name_funcs_stack, + ret->type)->free_func(ret->name,ret->type,ret->data); } - Free((char *)ret); + OPENSSL_free(ret); } else { @@ -179,35 +224,108 @@ int OBJ_NAME_add(const char *name, int type, const char *data) int OBJ_NAME_remove(const char *name, int type) { OBJ_NAME on,*ret; - void (*f)(); if (names_lh == NULL) return(0); type&= ~OBJ_NAME_ALIAS; on.name=name; on.type=type; - ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on); + ret=(OBJ_NAME *)lh_delete(names_lh,&on); if (ret != NULL) { /* free things */ - if ((names_free != NULL) && (sk_num(names_free) > type)) + if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) { - f=(void (*)())sk_value(names_free,type); - f(ret->name,ret->type,ret->data); + /* XXX: I'm not sure I understand why the free + * function should get three arguments... + * -- Richard Levitte + */ + sk_NAME_FUNCS_value(name_funcs_stack, + ret->type)->free_func(ret->name,ret->type,ret->data); } - Free((char *)ret); + OPENSSL_free(ret); return(1); } else return(0); } +struct doall + { + int type; + void (*fn)(const OBJ_NAME *,void *arg); + void *arg; + }; + +static void do_all_fn(const OBJ_NAME *name,struct doall *d) + { + if(name->type == d->type) + d->fn(name,d->arg); + } + +static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *) + +void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg) + { + struct doall d; + + d.type=type; + d.fn=fn; + d.arg=arg; + + lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d); + } + +struct doall_sorted + { + int type; + int n; + const OBJ_NAME **names; + }; + +static void do_all_sorted_fn(const OBJ_NAME *name,void *d_) + { + struct doall_sorted *d=d_; + + if(name->type != d->type) + return; + + d->names[d->n++]=name; + } + +static int do_all_sorted_cmp(const void *n1_,const void *n2_) + { + const OBJ_NAME * const *n1=n1_; + const OBJ_NAME * const *n2=n2_; + + return strcmp((*n1)->name,(*n2)->name); + } + +void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg), + void *arg) + { + struct doall_sorted d; + int n; + + d.type=type; + d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names); + d.n=0; + OBJ_NAME_do_all(type,do_all_sorted_fn,&d); + + qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp); + + for(n=0 ; n < d.n ; ++n) + fn(d.names[n],arg); + + OPENSSL_free((void *)d.names); + } + static int free_type; -static void names_lh_free(OBJ_NAME *onp, int type) +static void names_lh_free(OBJ_NAME *onp) { if(onp == NULL) - return; + return; if ((free_type < 0) || (free_type == onp->type)) { @@ -215,6 +333,13 @@ static void names_lh_free(OBJ_NAME *onp, int type) } } +static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *) + +static void name_funcs_free(NAME_FUNCS *ptr) + { + OPENSSL_free(ptr); + } + void OBJ_NAME_cleanup(int type) { unsigned long down_load; @@ -225,17 +350,13 @@ void OBJ_NAME_cleanup(int type) down_load=names_lh->down_load; names_lh->down_load=0; - lh_doall(names_lh,names_lh_free); + lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free)); if (type < 0) { lh_free(names_lh); - sk_free(names_hash); - sk_free(names_cmp); - sk_free(names_free); + sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free); names_lh=NULL; - names_hash=NULL; - names_cmp=NULL; - names_free=NULL; + name_funcs_stack = NULL; } else names_lh->down_load=down_load; diff --git a/src/lib/libcrypto/objects/obj_dat.c b/src/lib/libcrypto/objects/obj_dat.c index 34866ebbd2..3ff64bb8d1 100644 --- a/src/lib/libcrypto/objects/obj_dat.c +++ b/src/lib/libcrypto/objects/obj_dat.c @@ -59,23 +59,29 @@ #include #include #include "cryptlib.h" -#include "lhash.h" -#include "asn1.h" -#include "objects.h" +#include +#include +#include /* obj_dat.h is generated from objects.h by obj_dat.pl */ +#ifndef OPENSSL_NO_OBJECT #include "obj_dat.h" - -#ifndef NOPROTO -static int sn_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b); -static int ln_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b); -static int obj_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b); #else -static int sn_cmp(); -static int ln_cmp(); -static int obj_cmp(); +/* You will have to load all the objects needed manually in the application */ +#define NUM_NID 0 +#define NUM_SN 0 +#define NUM_LN 0 +#define NUM_OBJ 0 +static unsigned char lvalues[1]; +static ASN1_OBJECT nid_objs[1]; +static ASN1_OBJECT *sn_objs[1]; +static ASN1_OBJECT *ln_objs[1]; +static ASN1_OBJECT *obj_objs[1]; #endif +static int sn_cmp(const void *a, const void *b); +static int ln_cmp(const void *a, const void *b); +static int obj_cmp(const void *a, const void *b); #define ADDED_DATA 0 #define ADDED_SNAME 1 #define ADDED_LNAME 2 @@ -90,23 +96,26 @@ typedef struct added_obj_st static int new_nid=NUM_NID; static LHASH *added=NULL; -static int sn_cmp(ap,bp) -ASN1_OBJECT **ap; -ASN1_OBJECT **bp; - { return(strcmp((*ap)->sn,(*bp)->sn)); } +static int sn_cmp(const void *a, const void *b) + { + const ASN1_OBJECT * const *ap = a, * const *bp = b; + return(strcmp((*ap)->sn,(*bp)->sn)); + } -static int ln_cmp(ap,bp) -ASN1_OBJECT **ap; -ASN1_OBJECT **bp; - { return(strcmp((*ap)->ln,(*bp)->ln)); } +static int ln_cmp(const void *a, const void *b) + { + const ASN1_OBJECT * const *ap = a, * const *bp = b; + return(strcmp((*ap)->ln,(*bp)->ln)); + } -static unsigned long add_hash(ca) -ADDED_OBJ *ca; +/* static unsigned long add_hash(ADDED_OBJ *ca) */ +static unsigned long add_hash(const void *ca_void) { - ASN1_OBJECT *a; + const ASN1_OBJECT *a; int i; unsigned long ret=0; unsigned char *p; + ADDED_OBJ *ca = (ADDED_OBJ *)ca_void; a=ca->obj; switch (ca->type) @@ -127,18 +136,21 @@ ADDED_OBJ *ca; ret=a->nid; break; default: - abort(); + /* abort(); */ + return 0; } ret&=0x3fffffffL; ret|=ca->type<<30L; return(ret); } -static int add_cmp(ca,cb) -ADDED_OBJ *ca,*cb; +/* static int add_cmp(ADDED_OBJ *ca, ADDED_OBJ *cb) */ +static int add_cmp(const void *ca_void, const void *cb_void) { ASN1_OBJECT *a,*b; int i; + ADDED_OBJ *ca = (ADDED_OBJ *)ca_void; + ADDED_OBJ *cb = (ADDED_OBJ *)cb_void; i=ca->type-cb->type; if (i) return(i); @@ -161,50 +173,52 @@ ADDED_OBJ *ca,*cb; case ADDED_NID: return(a->nid-b->nid); default: - abort(); + /* abort(); */ + return 0; } } -static int init_added() +static int init_added(void) { if (added != NULL) return(1); added=lh_new(add_hash,add_cmp); return(added != NULL); } -static void cleanup1(a) -ADDED_OBJ *a; +static void cleanup1(ADDED_OBJ *a) { a->obj->nid=0; a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC| - ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; + ASN1_OBJECT_FLAG_DYNAMIC_STRINGS| + ASN1_OBJECT_FLAG_DYNAMIC_DATA; } -static void cleanup2(a) -ADDED_OBJ *a; +static void cleanup2(ADDED_OBJ *a) { a->obj->nid++; } -static void cleanup3(a) -ADDED_OBJ *a; +static void cleanup3(ADDED_OBJ *a) { if (--a->obj->nid == 0) ASN1_OBJECT_free(a->obj); - Free(a); + OPENSSL_free(a); } -void OBJ_cleanup() +static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ *) +static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ *) +static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ *) + +void OBJ_cleanup(void) { if (added == NULL) return; added->down_load=0; - lh_doall(added,cleanup1); /* zero counters */ - lh_doall(added,cleanup2); /* set counters */ - lh_doall(added,cleanup3); /* free objects */ + lh_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */ + lh_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */ + lh_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */ lh_free(added); added=NULL; } -int OBJ_new_nid(num) -int num; +int OBJ_new_nid(int num) { int i; @@ -213,27 +227,22 @@ int num; return(i); } -int OBJ_add_object(obj) -ASN1_OBJECT *obj; +int OBJ_add_object(const ASN1_OBJECT *obj) { ASN1_OBJECT *o; - ADDED_OBJ *ao[4],*aop; + ADDED_OBJ *ao[4]={NULL,NULL,NULL,NULL},*aop; int i; if (added == NULL) if (!init_added()) return(0); if ((o=OBJ_dup(obj)) == NULL) goto err; - ao[ADDED_DATA]=NULL; - ao[ADDED_SNAME]=NULL; - ao[ADDED_LNAME]=NULL; - ao[ADDED_NID]=NULL; - ao[ADDED_NID]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); + if (!(ao[ADDED_NID]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)))) goto err; if ((o->length != 0) && (obj->data != NULL)) - ao[ADDED_DATA]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); + ao[ADDED_DATA]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)); if (o->sn != NULL) - ao[ADDED_SNAME]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); + ao[ADDED_SNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)); if (o->ln != NULL) - ao[ADDED_LNAME]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); + ao[ADDED_LNAME]=(ADDED_OBJ *)OPENSSL_malloc(sizeof(ADDED_OBJ)); for (i=ADDED_DATA; i<=ADDED_NID; i++) { @@ -241,23 +250,24 @@ ASN1_OBJECT *obj; { ao[i]->type=i; ao[i]->obj=o; - aop=(ADDED_OBJ *)lh_insert(added,(char *)ao[i]); + aop=(ADDED_OBJ *)lh_insert(added,ao[i]); /* memory leak, buit should not normally matter */ if (aop != NULL) - Free(aop); + OPENSSL_free(aop); } } - o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS); + o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS| + ASN1_OBJECT_FLAG_DYNAMIC_DATA); + return(o->nid); err: for (i=ADDED_DATA; i<=ADDED_NID; i++) - if (ao[i] != NULL) Free(ao[i]); - if (o != NULL) Free(o); + if (ao[i] != NULL) OPENSSL_free(ao[i]); + if (o != NULL) OPENSSL_free(o); return(NID_undef); } -ASN1_OBJECT *OBJ_nid2obj(n) -int n; +ASN1_OBJECT *OBJ_nid2obj(int n) { ADDED_OBJ ad,*adp; ASN1_OBJECT ob; @@ -278,7 +288,7 @@ int n; ad.type=ADDED_NID; ad.obj= &ob; ob.nid=n; - adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); + adp=(ADDED_OBJ *)lh_retrieve(added,&ad); if (adp != NULL) return(adp->obj); else @@ -289,8 +299,7 @@ int n; } } -char *OBJ_nid2sn(n) -int n; +const char *OBJ_nid2sn(int n) { ADDED_OBJ ad,*adp; ASN1_OBJECT ob; @@ -311,7 +320,7 @@ int n; ad.type=ADDED_NID; ad.obj= &ob; ob.nid=n; - adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); + adp=(ADDED_OBJ *)lh_retrieve(added,&ad); if (adp != NULL) return(adp->obj->sn); else @@ -322,8 +331,7 @@ int n; } } -char *OBJ_nid2ln(n) -int n; +const char *OBJ_nid2ln(int n) { ADDED_OBJ ad,*adp; ASN1_OBJECT ob; @@ -344,7 +352,7 @@ int n; ad.type=ADDED_NID; ad.obj= &ob; ob.nid=n; - adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); + adp=(ADDED_OBJ *)lh_retrieve(added,&ad); if (adp != NULL) return(adp->obj->ln); else @@ -355,8 +363,7 @@ int n; } } -int OBJ_obj2nid(a) -ASN1_OBJECT *a; +int OBJ_obj2nid(const ASN1_OBJECT *a) { ASN1_OBJECT **op; ADDED_OBJ ad,*adp; @@ -369,56 +376,136 @@ ASN1_OBJECT *a; if (added != NULL) { ad.type=ADDED_DATA; - ad.obj=a; - adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); + ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */ + adp=(ADDED_OBJ *)lh_retrieve(added,&ad); if (adp != NULL) return (adp->obj->nid); } op=(ASN1_OBJECT **)OBJ_bsearch((char *)&a,(char *)obj_objs,NUM_OBJ, - sizeof(ASN1_OBJECT *),(int (*)())obj_cmp); + sizeof(ASN1_OBJECT *),obj_cmp); if (op == NULL) return(NID_undef); return((*op)->nid); } -int OBJ_txt2nid(s) -char *s; +/* Convert an object name into an ASN1_OBJECT + * if "noname" is not set then search for short and long names first. + * This will convert the "dotted" form into an object: unlike OBJ_txt2nid + * it can be used with any objects, not just registered ones. + */ + +ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) { - int ret; + int nid = NID_undef; + ASN1_OBJECT *op=NULL; + unsigned char *buf,*p; + int i, j; - ret=OBJ_sn2nid(s); - if (ret == NID_undef) - { - ret=OBJ_ln2nid(s); - if (ret == NID_undef) - { - ASN1_OBJECT *op=NULL; - unsigned char *buf,*p; - int i; + if(!no_name) { + if( ((nid = OBJ_sn2nid(s)) != NID_undef) || + ((nid = OBJ_ln2nid(s)) != NID_undef) ) + return OBJ_nid2obj(nid); + } - i=a2d_ASN1_OBJECT(NULL,0,s,-1); - if (i <= 0) - { - /* clear the error */ - ERR_get_error(); - return(0); - } + /* Work out size of content octets */ + i=a2d_ASN1_OBJECT(NULL,0,s,-1); + if (i <= 0) { + /* Clear the error */ + ERR_get_error(); + return NULL; + } + /* Work out total size */ + j = ASN1_object_size(0,i,V_ASN1_OBJECT); + + if((buf=(unsigned char *)OPENSSL_malloc(j)) == NULL) return NULL; + + p = buf; + /* Write out tag+length */ + ASN1_put_object(&p,0,i,V_ASN1_OBJECT,V_ASN1_UNIVERSAL); + /* Write out contents */ + a2d_ASN1_OBJECT(p,i,s,-1); + + p=buf; + op=d2i_ASN1_OBJECT(NULL,&p,i); + OPENSSL_free(buf); + return op; + } + +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) +{ + int i,idx=0,n=0,len,nid; + unsigned long l; + unsigned char *p; + const char *s; + char tbuf[32]; + + if (buf_len <= 0) return(0); - if ((buf=(unsigned char *)Malloc(i)) == NULL) - return(NID_undef); - a2d_ASN1_OBJECT(buf,i,s,-1); - p=buf; - op=d2i_ASN1_OBJECT(NULL,&p,i); - if (op == NULL) return(NID_undef); - ret=OBJ_obj2nid(op); - ASN1_OBJECT_free(op); - Free(buf); + if ((a == NULL) || (a->data == NULL)) { + buf[0]='\0'; + return(0); + } + + if (no_name || (nid=OBJ_obj2nid(a)) == NID_undef) { + len=a->length; + p=a->data; + + idx=0; + l=0; + while (idx < a->length) { + l|=(p[idx]&0x7f); + if (!(p[idx] & 0x80)) break; + l<<=7L; + idx++; + } + idx++; + i=(int)(l/40); + if (i > 2) i=2; + l-=(long)(i*40); + + sprintf(tbuf,"%d.%lu",i,l); + i=strlen(tbuf); + strncpy(buf,tbuf,buf_len); + buf_len-=i; + buf+=i; + n+=i; + + l=0; + for (; idx 0) + strncpy(buf,tbuf,buf_len); + buf_len-=i; + buf+=i; + n+=i; + l=0; } + l<<=7L; } - return(ret); + } else { + s=OBJ_nid2ln(nid); + if (s == NULL) + s=OBJ_nid2sn(nid); + strncpy(buf,s,buf_len); + n=strlen(s); } + buf[buf_len-1]='\0'; + return(n); +} -int OBJ_ln2nid(s) -char *s; +int OBJ_txt2nid(const char *s) +{ + ASN1_OBJECT *obj; + int nid; + obj = OBJ_txt2obj(s, 0); + nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + return nid; +} + +int OBJ_ln2nid(const char *s) { ASN1_OBJECT o,*oo= &o,**op; ADDED_OBJ ad,*adp; @@ -428,17 +515,16 @@ char *s; { ad.type=ADDED_LNAME; ad.obj= &o; - adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); + adp=(ADDED_OBJ *)lh_retrieve(added,&ad); if (adp != NULL) return (adp->obj->nid); } op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)ln_objs,NUM_LN, - sizeof(ASN1_OBJECT *),(int (*)())ln_cmp); + sizeof(ASN1_OBJECT *),ln_cmp); if (op == NULL) return(NID_undef); return((*op)->nid); } -int OBJ_sn2nid(s) -char *s; +int OBJ_sn2nid(const char *s) { ASN1_OBJECT o,*oo= &o,**op; ADDED_OBJ ad,*adp; @@ -448,37 +534,31 @@ char *s; { ad.type=ADDED_SNAME; ad.obj= &o; - adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); + adp=(ADDED_OBJ *)lh_retrieve(added,&ad); if (adp != NULL) return (adp->obj->nid); } op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN, - sizeof(ASN1_OBJECT *),(int (*)())sn_cmp); + sizeof(ASN1_OBJECT *),sn_cmp); if (op == NULL) return(NID_undef); return((*op)->nid); } -static int obj_cmp(ap, bp) -ASN1_OBJECT **ap; -ASN1_OBJECT **bp; +static int obj_cmp(const void *ap, const void *bp) { int j; - ASN1_OBJECT *a= *ap; - ASN1_OBJECT *b= *bp; + ASN1_OBJECT *a= *(ASN1_OBJECT **)ap; + ASN1_OBJECT *b= *(ASN1_OBJECT **)bp; j=(a->length - b->length); if (j) return(j); return(memcmp(a->data,b->data,a->length)); } -char *OBJ_bsearch(key,base,num,size,cmp) -char *key; -char *base; -int num; -int size; -int (*cmp)(); +const char *OBJ_bsearch(const char *key, const char *base, int num, int size, + int (*cmp)(const void *, const void *)) { int l,h,i,c; - char *p; + const char *p; if (num == 0) return(NULL); l=0; @@ -495,14 +575,24 @@ int (*cmp)(); else return(p); } +#ifdef CHARSET_EBCDIC +/* THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and + * I don't have perl (yet), we revert to a *LINEAR* search + * when the object wasn't found in the binary search. + */ + for (i=0; i) +open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]"; +open (OUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]"; + +while () { next unless /^\#define\s+(\S+)\s+(.*)$/; $v=$1; $d=$2; + $d =~ s/^\"//; + $d =~ s/\"$//; if ($v =~ /^SN_(.*)$/) - { $sn{$1}=$d; } + { + if(defined $snames{$d}) + { + print "WARNING: Duplicate short name \"$d\"\n"; + } + else + { $snames{$d} = "X"; } + $sn{$1}=$d; + } elsif ($v =~ /^LN_(.*)$/) - { $ln{$1}=$d; } + { + if(defined $lnames{$d}) + { + print "WARNING: Duplicate long name \"$d\"\n"; + } + else + { $lnames{$d} = "X"; } + $ln{$1}=$d; + } elsif ($v =~ /^NID_(.*)$/) { $nid{$d}=$1; } elsif ($v =~ /^OBJ_(.*)$/) @@ -55,6 +76,7 @@ while (<>) $objd{$v}=$d; } } +close IN; %ob=&expand_obj(*objd); @@ -74,11 +96,20 @@ for ($i=0; $i<$n; $i++) { $sn=defined($sn{$nid{$i}})?"$sn{$nid{$i}}":"NULL"; $ln=defined($ln{$nid{$i}})?"$ln{$nid{$i}}":"NULL"; - $sn=$ln if ($sn eq "NULL"); - $ln=$sn if ($ln eq "NULL"); + + if ($sn eq "NULL") { + $sn=$ln; + $sn{$nid{$i}} = $ln; + } + + if ($ln eq "NULL") { + $ln=$sn; + $ln{$nid{$i}} = $sn; + } + $out ="{"; - $out.=$sn; - $out.=",".$ln; + $out.="\"$sn\""; + $out.=","."\"$ln\""; $out.=",NID_$nid{$i},"; if (defined($obj{$nid{$i}})) { @@ -113,13 +144,13 @@ for ($i=0; $i<$n; $i++) @a=grep(defined($sn{$nid{$_}}),0 .. $n); foreach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a) { - push(@sn,sprintf("&(nid_objs[%2d]),/* $sn{$nid{$_}} */\n",$_)); + push(@sn,sprintf("&(nid_objs[%2d]),/* \"$sn{$nid{$_}}\" */\n",$_)); } @a=grep(defined($ln{$nid{$_}}),0 .. $n); foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a) { - push(@ln,sprintf("&(nid_objs[%2d]),/* $ln{$nid{$_}} */\n",$_)); + push(@ln,sprintf("&(nid_objs[%2d]),/* \"$ln{$nid{$_}}\" */\n",$_)); } @a=grep(defined($obj{$nid{$_}}),0 .. $n); @@ -132,8 +163,14 @@ foreach (sort obj_cmp @a) push(@ob,sprintf("&(nid_objs[%2d]),/* %-32s %s */\n",$_,$m,$v)); } -print <<'EOF'; -/* lib/obj/obj_dat.h */ +print OUT <<'EOF'; +/* crypto/objects/obj_dat.h */ + +/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the + * following command: + * perl obj_dat.pl obj_mac.h obj_dat.h + */ + /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -191,23 +228,18 @@ print <<'EOF'; * [including the GNU Public Licence.] */ -/* THIS FILE IS GENERATED FROM Objects.h by obj_dat.pl via the - * following command: - * perl obj_dat.pl < objects.h > obj_dat.h - */ - EOF -printf "#define NUM_NID %d\n",$n; -printf "#define NUM_SN %d\n",$#sn+1; -printf "#define NUM_LN %d\n",$#ln+1; -printf "#define NUM_OBJ %d\n\n",$#ob+1; +printf OUT "#define NUM_NID %d\n",$n; +printf OUT "#define NUM_SN %d\n",$#sn+1; +printf OUT "#define NUM_LN %d\n",$#ln+1; +printf OUT "#define NUM_OBJ %d\n\n",$#ob+1; -printf "static unsigned char lvalues[%d]={\n",$lvalues+1; -print @lvalues; -print "};\n\n"; +printf OUT "static unsigned char lvalues[%d]={\n",$lvalues+1; +print OUT @lvalues; +print OUT "};\n\n"; -printf "static ASN1_OBJECT nid_objs[NUM_NID]={\n"; +printf OUT "static ASN1_OBJECT nid_objs[NUM_NID]={\n"; foreach (@out) { if (length($_) > 75) @@ -218,30 +250,32 @@ foreach (@out) $t=$out.$_.","; if (length($t) > 70) { - print "$out\n"; + print OUT "$out\n"; $t="\t$_,"; } $out=$t; } chop $out; - print "$out"; + print OUT "$out"; } else - { print $_; } + { print OUT $_; } } -print "};\n\n"; +print OUT "};\n\n"; + +printf OUT "static ASN1_OBJECT *sn_objs[NUM_SN]={\n"; +print OUT @sn; +print OUT "};\n\n"; -printf "static ASN1_OBJECT *sn_objs[NUM_SN]={\n"; -print @sn; -print "};\n\n"; +printf OUT "static ASN1_OBJECT *ln_objs[NUM_LN]={\n"; +print OUT @ln; +print OUT "};\n\n"; -printf "static ASN1_OBJECT *ln_objs[NUM_LN]={\n"; -print @ln; -print "};\n\n"; +printf OUT "static ASN1_OBJECT *obj_objs[NUM_OBJ]={\n"; +print OUT @ob; +print OUT "};\n\n"; -printf "static ASN1_OBJECT *obj_objs[NUM_OBJ]={\n"; -print @ob; -print "};\n\n"; +close OUT; sub der_it { @@ -252,7 +286,7 @@ sub der_it $ret.=pack("C*",$a[0]*40+$a[1]); shift @a; shift @a; - while ($_=shift(@a)) + foreach (@a) { @r=(); $t=0; diff --git a/src/lib/libcrypto/objects/obj_err.c b/src/lib/libcrypto/objects/obj_err.c index 45206c616c..80ab6855af 100644 --- a/src/lib/libcrypto/objects/obj_err.c +++ b/src/lib/libcrypto/objects/obj_err.c @@ -1,66 +1,69 @@ -/* lib/obj/obj_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/objects/obj_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "objects.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA OBJ_str_functs[]= { {ERR_PACK(0,OBJ_F_OBJ_CREATE,0), "OBJ_create"}, @@ -68,26 +71,26 @@ static ERR_STRING_DATA OBJ_str_functs[]= {ERR_PACK(0,OBJ_F_OBJ_NID2LN,0), "OBJ_nid2ln"}, {ERR_PACK(0,OBJ_F_OBJ_NID2OBJ,0), "OBJ_nid2obj"}, {ERR_PACK(0,OBJ_F_OBJ_NID2SN,0), "OBJ_nid2sn"}, -{0,NULL}, +{0,NULL} }; static ERR_STRING_DATA OBJ_str_reasons[]= { {OBJ_R_MALLOC_FAILURE ,"malloc failure"}, {OBJ_R_UNKNOWN_NID ,"unknown nid"}, -{0,NULL}, +{0,NULL} }; #endif -void ERR_load_OBJ_strings() +void ERR_load_OBJ_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_OBJ,OBJ_str_functs); ERR_load_strings(ERR_LIB_OBJ,OBJ_str_reasons); #endif diff --git a/src/lib/libcrypto/objects/obj_lib.c b/src/lib/libcrypto/objects/obj_lib.c index 0a9c756197..b0b0f2ff24 100644 --- a/src/lib/libcrypto/objects/obj_lib.c +++ b/src/lib/libcrypto/objects/obj_lib.c @@ -58,27 +58,28 @@ #include #include "cryptlib.h" -#include "lhash.h" -#include "objects.h" -#include "buffer.h" +#include +#include +#include -ASN1_OBJECT *OBJ_dup(o) -ASN1_OBJECT *o; +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) { ASN1_OBJECT *r; int i; + char *ln=NULL; if (o == NULL) return(NULL); if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) - return(o); + return((ASN1_OBJECT *)o); /* XXX: ugh! Why? What kind of + duplication is this??? */ - r=(ASN1_OBJECT *)ASN1_OBJECT_new(); + r=ASN1_OBJECT_new(); if (r == NULL) { OBJerr(OBJ_F_OBJ_DUP,ERR_R_ASN1_LIB); return(NULL); } - r->data=(unsigned char *)Malloc(o->length); + r->data=OPENSSL_malloc(o->length); if (r->data == NULL) goto err; memcpy(r->data,o->data,o->length); @@ -88,35 +89,35 @@ ASN1_OBJECT *o; if (o->ln != NULL) { i=strlen(o->ln)+1; - r->ln=(char *)Malloc(i); + r->ln=ln=OPENSSL_malloc(i); if (r->ln == NULL) goto err; - memcpy(r->ln,o->ln,i); + memcpy(ln,o->ln,i); } if (o->sn != NULL) { + char *s; + i=strlen(o->sn)+1; - r->sn=(char *)Malloc(i); + r->sn=s=OPENSSL_malloc(i); if (r->sn == NULL) goto err; - memcpy(r->sn,o->sn,i); + memcpy(s,o->sn,i); } r->flags=o->flags|(ASN1_OBJECT_FLAG_DYNAMIC| - ASN1_OBJECT_FLAG_DYNAMIC_STRINGS); + ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|ASN1_OBJECT_FLAG_DYNAMIC_DATA); return(r); err: OBJerr(OBJ_F_OBJ_DUP,ERR_R_MALLOC_FAILURE); if (r != NULL) { - if (r->ln != NULL) Free(r->ln); - if (r->data != NULL) Free(r->data); - Free(r); + if (ln != NULL) OPENSSL_free(ln); + if (r->data != NULL) OPENSSL_free(r->data); + OPENSSL_free(r); } return(NULL); } -int OBJ_cmp(a,b) -ASN1_OBJECT *a; -ASN1_OBJECT *b; +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { int ret; diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num index d73a51370f..02b39062fe 100644 --- a/src/lib/libcrypto/objects/obj_mac.num +++ b/src/lib/libcrypto/objects/obj_mac.num @@ -30,8 +30,8 @@ dhKeyAgreement 28 des_ecb 29 des_cfb64 30 des_cbc 31 -des_ede 32 -des_ede3 33 +des_ede_ecb 32 +des_ede3_ecb 33 idea_cbc 34 idea_cfb64 35 idea_ecb 36 @@ -390,3 +390,120 @@ Enterprises 389 dcObject 390 domainComponent 391 Domain 392 +joint_iso_ccitt 393 +selected_attribute_types 394 +clearance 395 +md4WithRSAEncryption 396 +ac_proxying 397 +sinfo_access 398 +id_aca_encAttrs 399 +role 400 +policy_constraints 401 +target_information 402 +no_rev_avail 403 +ccitt 404 +ansi_X9_62 405 +X9_62_prime_field 406 +X9_62_characteristic_two_field 407 +X9_62_id_ecPublicKey 408 +X9_62_prime192v1 409 +X9_62_prime192v2 410 +X9_62_prime192v3 411 +X9_62_prime239v1 412 +X9_62_prime239v2 413 +X9_62_prime239v3 414 +X9_62_prime256v1 415 +ecdsa_with_SHA1 416 +ms_csp_name 417 +aes_128_ecb 418 +aes_128_cbc 419 +aes_128_ofb128 420 +aes_128_cfb128 421 +aes_192_ecb 422 +aes_192_cbc 423 +aes_192_ofb128 424 +aes_192_cfb128 425 +aes_256_ecb 426 +aes_256_cbc 427 +aes_256_ofb128 428 +aes_256_cfb128 429 +hold_instruction_code 430 +hold_instruction_none 431 +hold_instruction_call_issuer 432 +hold_instruction_reject 433 +data 434 +pss 435 +ucl 436 +pilot 437 +pilotAttributeType 438 +pilotAttributeSyntax 439 +pilotObjectClass 440 +pilotGroups 441 +iA5StringSyntax 442 +caseIgnoreIA5StringSyntax 443 +pilotObject 444 +pilotPerson 445 +account 446 +document 447 +room 448 +documentSeries 449 +rFC822localPart 450 +dNSDomain 451 +domainRelatedObject 452 +friendlyCountry 453 +simpleSecurityObject 454 +pilotOrganization 455 +pilotDSA 456 +qualityLabelledData 457 +userId 458 +textEncodedORAddress 459 +rfc822Mailbox 460 +info 461 +favouriteDrink 462 +roomNumber 463 +photo 464 +userClass 465 +host 466 +manager 467 +documentIdentifier 468 +documentTitle 469 +documentVersion 470 +documentAuthor 471 +documentLocation 472 +homeTelephoneNumber 473 +secretary 474 +otherMailbox 475 +lastModifiedTime 476 +lastModifiedBy 477 +aRecord 478 +pilotAttributeType27 479 +mXRecord 480 +nSRecord 481 +sOARecord 482 +cNAMERecord 483 +associatedDomain 484 +associatedName 485 +homePostalAddress 486 +personalTitle 487 +mobileTelephoneNumber 488 +pagerTelephoneNumber 489 +friendlyCountryName 490 +organizationalStatus 491 +janetMailbox 492 +mailPreferenceOption 493 +buildingName 494 +dSAQuality 495 +singleLevelQuality 496 +subtreeMinimumQuality 497 +subtreeMaximumQuality 498 +personalSignature 499 +dITRedirect 500 +audio 501 +documentPublisher 502 +x500UniqueIdentifier 503 +mime_mhs 504 +mime_mhs_headings 505 +mime_mhs_bodies 506 +id_hex_partial_message 507 +id_hex_multipart_message 508 +generationQualifier 509 diff --git a/src/lib/libcrypto/objects/objects.h b/src/lib/libcrypto/objects/objects.h index e1d555b47c..de10532813 100644 --- a/src/lib/libcrypto/objects/objects.h +++ b/src/lib/libcrypto/objects/objects.h @@ -59,13 +59,15 @@ #ifndef HEADER_OBJECTS_H #define HEADER_OBJECTS_H -#ifdef __cplusplus -extern "C" { -#endif +#define USE_OBJ_MAC +#ifdef USE_OBJ_MAC +#include +#else #define SN_undef "UNDEF" #define LN_undef "undefined" #define NID_undef 0 +#define OBJ_undef 0L #define SN_Algorithm "Algorithm" #define LN_algorithm "algorithm" @@ -109,10 +111,12 @@ extern "C" { #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 @@ -229,6 +233,7 @@ extern "C" { #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" @@ -379,17 +384,21 @@ extern "C" { #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 */ -#define LN_pbeWithSHA1AndRC4 "pbeWithSHA1AndRC4" -#define NID_pbeWithSHA1AndRC4 69 -#define OBJ_pbeWithSHA1AndRC4 OBJ_pkcs,5L,12L +/* 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" +#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 @@ -443,58 +452,59 @@ extern "C" { #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_id_ce "id-ce" +#define NID_id_ce 81 +#define OBJ_id_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 OBJ_subject_key_identifier OBJ_id_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 OBJ_key_usage OBJ_id_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 OBJ_private_key_usage_period OBJ_id_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 OBJ_subject_alt_name OBJ_id_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 OBJ_issuer_alt_name OBJ_id_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 OBJ_basic_constraints OBJ_id_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 OBJ_crl_number OBJ_id_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 OBJ_certificate_policies OBJ_id_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 OBJ_authority_key_identifier OBJ_id_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" @@ -550,7 +560,7 @@ extern "C" { #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 OBJ_crl_distribution_points OBJ_id_ce,31L #define SN_md5WithRSA "RSA-NP-MD5" #define LN_md5WithRSA "md5WithRSA" @@ -623,7 +633,7 @@ extern "C" { #define OBJ_ripemd160 1L,3L,36L,3L,2L,1L /* The name should actually be rsaSignatureWithripemd160, but I'm going - * to contiune using the convention I'm using with the other ciphers */ + * 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 @@ -654,56 +664,365 @@ extern "C" { #define LN_rc5_ofb64 "rc5-ofb" #define NID_rc5_ofb64 123 -#include "bio.h" -#include "asn1.h" +#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_id_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_id_ce,27L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason OBJ_id_ce,21L -#define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c) +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date OBJ_id_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 -#ifndef NOPROTO +#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 -ASN1_OBJECT * OBJ_dup(ASN1_OBJECT *o); -ASN1_OBJECT * OBJ_nid2obj(int n); -char * OBJ_nid2ln(int n); -char * OBJ_nid2sn(int n); -int OBJ_obj2nid(ASN1_OBJECT *o); -int OBJ_txt2nid(char *s); -int OBJ_ln2nid(char *s); -int OBJ_sn2nid(char *s); -int OBJ_cmp(ASN1_OBJECT *a,ASN1_OBJECT *b); -char * OBJ_bsearch(char *key,char *base,int num,int size,int (*cmp)()); +#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 -void ERR_load_OBJ_strings(void ); +#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 -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); +#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 -#else +#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 -ASN1_OBJECT * OBJ_dup(); -ASN1_OBJECT * OBJ_nid2obj(); -char * OBJ_nid2ln(); -char * OBJ_nid2sn(); -int OBJ_obj2nid(); -int OBJ_txt2nid(); -int OBJ_ln2nid(); -int OBJ_sn2nid(); -int OBJ_cmp(); -char * OBJ_bsearch(); - -void ERR_load_OBJ_strings(); - -int OBJ_new_nid(); -int OBJ_add_object(); -int OBJ_create(); -void OBJ_cleanup(); -int OBJ_create_objects(); +#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 +#endif /* USE_OBJ_MAC */ + +#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 + + +#ifdef __cplusplus +extern "C" { #endif +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)(const char *), + int (*cmp_func)(const char *, const char *), + void (*free_func)(const char *, int, const char *)); +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 */ +void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg), + void *arg); +void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg), + void *arg); + +ASN1_OBJECT * OBJ_dup(const ASN1_OBJECT *o); +ASN1_OBJECT * OBJ_nid2obj(int n); +const char * OBJ_nid2ln(int n); +const char * OBJ_nid2sn(int n); +int OBJ_obj2nid(const ASN1_OBJECT *o); +ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); +int OBJ_txt2nid(const char *s); +int OBJ_ln2nid(const char *s); +int OBJ_sn2nid(const char *s); +int OBJ_cmp(const ASN1_OBJECT *a,const ASN1_OBJECT *b); +const char * OBJ_bsearch(const char *key,const char *base,int num,int size, + int (*cmp)(const void *, const void *)); + +int OBJ_new_nid(int num); +int OBJ_add_object(const ASN1_OBJECT *obj); +int OBJ_create(const char *oid,const char *sn,const 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. + */ +void ERR_load_OBJ_strings(void); + /* Error codes for the OBJ functions. */ /* Function codes. */ @@ -716,9 +1035,8 @@ int OBJ_create_objects(); /* Reason codes. */ #define OBJ_R_MALLOC_FAILURE 100 #define OBJ_R_UNKNOWN_NID 101 - + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/objects/objects.pl b/src/lib/libcrypto/objects/objects.pl index c956bbb841..76c06cc8f9 100644 --- a/src/lib/libcrypto/objects/objects.pl +++ b/src/lib/libcrypto/objects/objects.pl @@ -9,7 +9,9 @@ while() $o++; s/#.*$//; next if /^\s*$/; + $_ = 'X'.$_; ($Cname,$mynum) = split; + $Cname =~ s/^X//; if (defined($nidn{$mynum})) { die "$ARGV[1]:$o:There's already an object with NID ",$mynum," on line ",$order{$mynum},"\n"; } $nid{$Cname} = $mynum; @@ -114,7 +116,13 @@ close NUMOUT; open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]"; print OUT <<'EOF'; -/* lib/obj/obj_mac.h */ +/* crypto/objects/obj_mac.h */ + +/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the + * following command: + * perl objects.pl objects.txt obj_mac.num obj_mac.h + */ + /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -172,11 +180,6 @@ print OUT <<'EOF'; * [including the GNU Public Licence.] */ -/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the - * following command: - * perl objects.pl objects.txt obj_mac.num obj_mac.h - */ - #define SN_undef "UNDEF" #define LN_undef "undefined" #define NID_undef 0 @@ -207,6 +210,8 @@ sub process_oid if (!($a[0] =~ /^[0-9]+$/)) { $a[0] =~ s/-/_/g; + if (!defined($obj{$a[0]})) + { die "$ARGV[0]:$o:Undefined identifier ",$a[0],"\n"; } $pref_oid = "OBJ_" . $a[0]; $pref_sep = ","; shift @a; diff --git a/src/lib/libcrypto/objects/objects.txt b/src/lib/libcrypto/objects/objects.txt index cb276e90e9..65d0b15629 100644 --- a/src/lib/libcrypto/objects/objects.txt +++ b/src/lib/libcrypto/objects/objects.txt @@ -1,40 +1,764 @@ -1 2 : ISO member bodies -1 2 840 : US (ANSI) -1 2 840 113549 : rsadsi : RSA Data Security, Inc. -1 2 840 113549 1 : pkcs : RSA Data Security, Inc. PKCS -1 2 840 113549 1 1 1 : rsaEncryption -1 2 840 113549 1 1 2 : md2withRSAEncryption -1 2 840 113549 1 1 4 : md5withRSAEncryption -1 2 840 113549 1 7 : pkcs-7 -1 2 840 113549 1 7 1 : pkcs-7-data -1 2 840 113549 1 7 2 : pkcs-7-signedData -1 2 840 113549 1 7 3 : pkcs-7-envelopedData -1 2 840 113549 1 7 4 : pkcs-7-signedAndEnvelopedData -1 2 840 113549 1 7 5 : pkcs-7-digestData -1 2 840 113549 1 7 6 : pkcs-7-encryptedData -1 2 840 113549 2 2 : md2 -1 2 840 113549 2 4 : md4 -1 2 840 113549 2 5 : md5 -1 2 840 113549 3 4 : rc4 -1 2 840 113549 5 1 : pbeWithMD2AndDES_CBC -1 2 840 113549 5 3 : pbeWithMD5AndDES_CBC -2 5 : X500 : directory services (X.500) -2 5 4 : X509 -2 5 4 3 : commonName -2 5 4 6 : countryName -2 5 4 7 : localityName -2 5 4 8 : stateOrProvinceName -2 5 4 10 : organizationName -2 5 4 11 : organizationalUnitName -2 5 8 : directory services - algorithms -2 5 8 1 1 : rsa - -algorithm 18 : sha -encryptionAlgorithm 1 : rsa +0 : CCITT : ccitt + +1 : ISO : iso + +2 : JOINT-ISO-CCITT : joint-iso-ccitt + +iso 2 : member-body : ISO Member Body + +joint-iso-ccitt 5 1 5 : selected-attribute-types : Selected Attribute Types + +selected-attribute-types 55 : clearance + +member-body 840 : ISO-US : ISO US Member Body +ISO-US 10040 : X9-57 : X9.57 +X9-57 4 : X9cm : X9.57 CM ? + +!Cname dsa +X9cm 1 : DSA : dsaEncryption +X9cm 3 : DSA-SHA1 : dsaWithSHA1 + + +ISO-US 10045 : ansi-X9-62 : ANSI X9.62 +!module X9-62 +!Alias id-fieldType ansi-X9-62 1 +X9-62_id-fieldType 1 : prime-field +X9-62_id-fieldType 2 : characteristic-two-field +# ... characteristic-two-field OID subtree +!Alias id-publicKeyType ansi-X9-62 2 +X9-62_id-publicKeyType 1 : id-ecPublicKey +!Alias ellipticCurve ansi-X9-62 3 +!Alias c-TwoCurve X9-62_ellipticCurve 0 +# ... characteristic 2 curve OIDs +!Alias primeCurve X9-62_ellipticCurve 1 +X9-62_primeCurve 1 : prime192v1 +X9-62_primeCurve 2 : prime192v2 +X9-62_primeCurve 3 : prime192v3 +X9-62_primeCurve 4 : prime239v1 +X9-62_primeCurve 5 : prime239v2 +X9-62_primeCurve 6 : prime239v3 +X9-62_primeCurve 7 : prime256v1 +!Alias id-ecSigType ansi-X9-62 4 +!global +X9-62_id-ecSigType 1 : ecdsa-with-SHA1 + + + +ISO-US 113533 7 66 10 : CAST5-CBC : cast5-cbc + : CAST5-ECB : cast5-ecb +!Cname cast5-cfb64 + : CAST5-CFB : cast5-cfb +!Cname cast5-ofb64 + : CAST5-OFB : cast5-ofb +!Cname pbeWithMD5AndCast5-CBC +ISO-US 113533 7 66 12 : : pbeWithMD5AndCast5CBC + +ISO-US 113549 : rsadsi : RSA Data Security, Inc. + +rsadsi 1 : pkcs : RSA Data Security, Inc. PKCS + +pkcs 1 : pkcs1 +pkcs1 1 : : rsaEncryption +pkcs1 2 : RSA-MD2 : md2WithRSAEncryption +pkcs1 3 : RSA-MD4 : md4WithRSAEncryption +pkcs1 4 : RSA-MD5 : md5WithRSAEncryption +pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption + +pkcs 3 : pkcs3 +pkcs3 1 : : dhKeyAgreement + +pkcs 5 : pkcs5 +pkcs5 1 : PBE-MD2-DES : pbeWithMD2AndDES-CBC +pkcs5 3 : PBE-MD5-DES : pbeWithMD5AndDES-CBC +pkcs5 4 : PBE-MD2-RC2-64 : pbeWithMD2AndRC2-CBC +pkcs5 6 : PBE-MD5-RC2-64 : pbeWithMD5AndRC2-CBC +pkcs5 10 : PBE-SHA1-DES : pbeWithSHA1AndDES-CBC +pkcs5 11 : PBE-SHA1-RC2-64 : pbeWithSHA1AndRC2-CBC +!Cname id_pbkdf2 +pkcs5 12 : : PBKDF2 +!Cname pbes2 +pkcs5 13 : : PBES2 +!Cname pbmac1 +pkcs5 14 : : PBMAC1 + +pkcs 7 : pkcs7 +pkcs7 1 : : pkcs7-data +!Cname pkcs7-signed +pkcs7 2 : : pkcs7-signedData +!Cname pkcs7-enveloped +pkcs7 3 : : pkcs7-envelopedData +!Cname pkcs7-signedAndEnveloped +pkcs7 4 : : pkcs7-signedAndEnvelopedData +!Cname pkcs7-digest +pkcs7 5 : : pkcs7-digestData +!Cname pkcs7-encrypted +pkcs7 6 : : pkcs7-encryptedData + +pkcs 9 : pkcs9 +!module pkcs9 +pkcs9 1 : : emailAddress +pkcs9 2 : : unstructuredName +pkcs9 3 : : contentType +pkcs9 4 : : messageDigest +pkcs9 5 : : signingTime +pkcs9 6 : : countersignature +pkcs9 7 : : challengePassword +pkcs9 8 : : unstructuredAddress +!Cname extCertAttributes +pkcs9 9 : : extendedCertificateAttributes +!global + +!Cname ext-req +pkcs9 14 : extReq : Extension Request + +!Cname SMIMECapabilities +pkcs9 15 : SMIME-CAPS : S/MIME Capabilities + +# S/MIME +!Cname SMIME +pkcs9 16 : SMIME : S/MIME +SMIME 0 : id-smime-mod +SMIME 1 : id-smime-ct +SMIME 2 : id-smime-aa +SMIME 3 : id-smime-alg +SMIME 4 : id-smime-cd +SMIME 5 : id-smime-spq +SMIME 6 : id-smime-cti + +# S/MIME Modules +id-smime-mod 1 : id-smime-mod-cms +id-smime-mod 2 : id-smime-mod-ess +id-smime-mod 3 : id-smime-mod-oid +id-smime-mod 4 : id-smime-mod-msg-v3 +id-smime-mod 5 : id-smime-mod-ets-eSignature-88 +id-smime-mod 6 : id-smime-mod-ets-eSignature-97 +id-smime-mod 7 : id-smime-mod-ets-eSigPolicy-88 +id-smime-mod 8 : id-smime-mod-ets-eSigPolicy-97 + +# S/MIME Content Types +id-smime-ct 1 : id-smime-ct-receipt +id-smime-ct 2 : id-smime-ct-authData +id-smime-ct 3 : id-smime-ct-publishCert +id-smime-ct 4 : id-smime-ct-TSTInfo +id-smime-ct 5 : id-smime-ct-TDTInfo +id-smime-ct 6 : id-smime-ct-contentInfo +id-smime-ct 7 : id-smime-ct-DVCSRequestData +id-smime-ct 8 : id-smime-ct-DVCSResponseData + +# S/MIME Attributes +id-smime-aa 1 : id-smime-aa-receiptRequest +id-smime-aa 2 : id-smime-aa-securityLabel +id-smime-aa 3 : id-smime-aa-mlExpandHistory +id-smime-aa 4 : id-smime-aa-contentHint +id-smime-aa 5 : id-smime-aa-msgSigDigest +# obsolete +id-smime-aa 6 : id-smime-aa-encapContentType +id-smime-aa 7 : id-smime-aa-contentIdentifier +# obsolete +id-smime-aa 8 : id-smime-aa-macValue +id-smime-aa 9 : id-smime-aa-equivalentLabels +id-smime-aa 10 : id-smime-aa-contentReference +id-smime-aa 11 : id-smime-aa-encrypKeyPref +id-smime-aa 12 : id-smime-aa-signingCertificate +id-smime-aa 13 : id-smime-aa-smimeEncryptCerts +id-smime-aa 14 : id-smime-aa-timeStampToken +id-smime-aa 15 : id-smime-aa-ets-sigPolicyId +id-smime-aa 16 : id-smime-aa-ets-commitmentType +id-smime-aa 17 : id-smime-aa-ets-signerLocation +id-smime-aa 18 : id-smime-aa-ets-signerAttr +id-smime-aa 19 : id-smime-aa-ets-otherSigCert +id-smime-aa 20 : id-smime-aa-ets-contentTimestamp +id-smime-aa 21 : id-smime-aa-ets-CertificateRefs +id-smime-aa 22 : id-smime-aa-ets-RevocationRefs +id-smime-aa 23 : id-smime-aa-ets-certValues +id-smime-aa 24 : id-smime-aa-ets-revocationValues +id-smime-aa 25 : id-smime-aa-ets-escTimeStamp +id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp +id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp +id-smime-aa 28 : id-smime-aa-signatureType +id-smime-aa 29 : id-smime-aa-dvcs-dvc + +# S/MIME Algorithm Identifiers +# obsolete +id-smime-alg 1 : id-smime-alg-ESDHwith3DES +# obsolete +id-smime-alg 2 : id-smime-alg-ESDHwithRC2 +# obsolete +id-smime-alg 3 : id-smime-alg-3DESwrap +# obsolete +id-smime-alg 4 : id-smime-alg-RC2wrap +id-smime-alg 5 : id-smime-alg-ESDH +id-smime-alg 6 : id-smime-alg-CMS3DESwrap +id-smime-alg 7 : id-smime-alg-CMSRC2wrap + +# S/MIME Certificate Distribution +id-smime-cd 1 : id-smime-cd-ldap + +# S/MIME Signature Policy Qualifier +id-smime-spq 1 : id-smime-spq-ets-sqt-uri +id-smime-spq 2 : id-smime-spq-ets-sqt-unotice + +# S/MIME Commitment Type Identifier +id-smime-cti 1 : id-smime-cti-ets-proofOfOrigin +id-smime-cti 2 : id-smime-cti-ets-proofOfReceipt +id-smime-cti 3 : id-smime-cti-ets-proofOfDelivery +id-smime-cti 4 : id-smime-cti-ets-proofOfSender +id-smime-cti 5 : id-smime-cti-ets-proofOfApproval +id-smime-cti 6 : id-smime-cti-ets-proofOfCreation + +pkcs9 20 : : friendlyName +pkcs9 21 : : localKeyID +!Cname ms-csp-name +1 3 6 1 4 1 311 17 1 : CSPName : Microsoft CSP Name +!Alias certTypes pkcs9 22 +certTypes 1 : : x509Certificate +certTypes 2 : : sdsiCertificate +!Alias crlTypes pkcs9 23 +crlTypes 1 : : x509Crl + +!Alias pkcs12 pkcs 12 +!Alias pkcs12-pbeids pkcs12 1 + +!Cname pbe-WithSHA1And128BitRC4 +pkcs12-pbeids 1 : PBE-SHA1-RC4-128 : pbeWithSHA1And128BitRC4 +!Cname pbe-WithSHA1And40BitRC4 +pkcs12-pbeids 2 : PBE-SHA1-RC4-40 : pbeWithSHA1And40BitRC4 +!Cname pbe-WithSHA1And3_Key_TripleDES-CBC +pkcs12-pbeids 3 : PBE-SHA1-3DES : pbeWithSHA1And3-KeyTripleDES-CBC +!Cname pbe-WithSHA1And2_Key_TripleDES-CBC +pkcs12-pbeids 4 : PBE-SHA1-2DES : pbeWithSHA1And2-KeyTripleDES-CBC +!Cname pbe-WithSHA1And128BitRC2-CBC +pkcs12-pbeids 5 : PBE-SHA1-RC2-128 : pbeWithSHA1And128BitRC2-CBC +!Cname pbe-WithSHA1And40BitRC2-CBC +pkcs12-pbeids 6 : PBE-SHA1-RC2-40 : pbeWithSHA1And40BitRC2-CBC + +!Alias pkcs12-Version1 pkcs12 10 +!Alias pkcs12-BagIds pkcs12-Version1 1 +pkcs12-BagIds 1 : : keyBag +pkcs12-BagIds 2 : : pkcs8ShroudedKeyBag +pkcs12-BagIds 3 : : certBag +pkcs12-BagIds 4 : : crlBag +pkcs12-BagIds 5 : : secretBag +pkcs12-BagIds 6 : : safeContentsBag + +rsadsi 2 2 : MD2 : md2 +rsadsi 2 4 : MD4 : md4 +rsadsi 2 5 : MD5 : md5 + : MD5-SHA1 : md5-sha1 +rsadsi 2 7 : : hmacWithSHA1 +rsadsi 3 2 : RC2-CBC : rc2-cbc + : RC2-ECB : rc2-ecb +!Cname rc2-cfb64 + : RC2-CFB : rc2-cfb +!Cname rc2-ofb64 + : RC2-OFB : rc2-ofb + : RC2-40-CBC : rc2-40-cbc + : RC2-64-CBC : rc2-64-cbc +rsadsi 3 4 : RC4 : rc4 + : RC4-40 : rc4-40 +rsadsi 3 7 : DES-EDE3-CBC : des-ede3-cbc +rsadsi 3 8 : RC5-CBC : rc5-cbc + : RC5-ECB : rc5-ecb +!Cname rc5-cfb64 + : RC5-CFB : rc5-cfb +!Cname rc5-ofb64 + : RC5-OFB : rc5-ofb + +!Cname ms-ext-req +1 3 6 1 4 1 311 2 1 14 : msExtReq : Microsoft Extension Request +!Cname ms-code-ind +1 3 6 1 4 1 311 2 1 21 : msCodeInd : Microsoft Individual Code Signing +!Cname ms-code-com +1 3 6 1 4 1 311 2 1 22 : msCodeCom : Microsoft Commercial Code Signing +!Cname ms-ctl-sign +1 3 6 1 4 1 311 10 3 1 : msCTLSign : Microsoft Trust List Signing +!Cname ms-sgc +1 3 6 1 4 1 311 10 3 3 : msSGC : Microsoft Server Gated Crypto +!Cname ms-efs +1 3 6 1 4 1 311 10 3 4 : msEFS : Microsoft Encrypted File System + +1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc + : IDEA-ECB : idea-ecb +!Cname idea-cfb64 + : IDEA-CFB : idea-cfb +!Cname idea-ofb64 + : IDEA-OFB : idea-ofb + +1 3 6 1 4 1 3029 1 2 : BF-CBC : bf-cbc + : BF-ECB : bf-ecb +!Cname bf-cfb64 + : BF-CFB : bf-cfb +!Cname bf-ofb64 + : BF-OFB : bf-ofb + +!Cname id-pkix +1 3 6 1 5 5 7 : PKIX + +# PKIX Arcs +id-pkix 0 : id-pkix-mod +id-pkix 1 : id-pe +id-pkix 2 : id-qt +id-pkix 3 : id-kp +id-pkix 4 : id-it +id-pkix 5 : id-pkip +id-pkix 6 : id-alg +id-pkix 7 : id-cmc +id-pkix 8 : id-on +id-pkix 9 : id-pda +id-pkix 10 : id-aca +id-pkix 11 : id-qcs +id-pkix 12 : id-cct +id-pkix 48 : id-ad + +# PKIX Modules +id-pkix-mod 1 : id-pkix1-explicit-88 +id-pkix-mod 2 : id-pkix1-implicit-88 +id-pkix-mod 3 : id-pkix1-explicit-93 +id-pkix-mod 4 : id-pkix1-implicit-93 +id-pkix-mod 5 : id-mod-crmf +id-pkix-mod 6 : id-mod-cmc +id-pkix-mod 7 : id-mod-kea-profile-88 +id-pkix-mod 8 : id-mod-kea-profile-93 +id-pkix-mod 9 : id-mod-cmp +id-pkix-mod 10 : id-mod-qualified-cert-88 +id-pkix-mod 11 : id-mod-qualified-cert-93 +id-pkix-mod 12 : id-mod-attribute-cert +id-pkix-mod 13 : id-mod-timestamp-protocol +id-pkix-mod 14 : id-mod-ocsp +id-pkix-mod 15 : id-mod-dvcs +id-pkix-mod 16 : id-mod-cmp2000 + +# PKIX Private Extensions +!Cname info-access +id-pe 1 : authorityInfoAccess : Authority Information Access +id-pe 2 : biometricInfo : Biometric Info +id-pe 3 : qcStatements +id-pe 4 : ac-auditEntity +id-pe 5 : ac-targeting +id-pe 6 : aaControls +id-pe 7 : sbqp-ipAddrBlock +id-pe 8 : sbqp-autonomousSysNum +id-pe 9 : sbqp-routerIdentifier +id-pe 10 : ac-proxying +!Cname sinfo-access +id-pe 11 : subjectInfoAccess : Subject Information Access + +# PKIX policyQualifiers for Internet policy qualifiers +id-qt 1 : id-qt-cps : Policy Qualifier CPS +id-qt 2 : id-qt-unotice : Policy Qualifier User Notice +id-qt 3 : textNotice + +# PKIX key purpose identifiers +!Cname server-auth +id-kp 1 : serverAuth : TLS Web Server Authentication +!Cname client-auth +id-kp 2 : clientAuth : TLS Web Client Authentication +!Cname code-sign +id-kp 3 : codeSigning : Code Signing +!Cname email-protect +id-kp 4 : emailProtection : E-mail Protection +id-kp 5 : ipsecEndSystem : IPSec End System +id-kp 6 : ipsecTunnel : IPSec Tunnel +id-kp 7 : ipsecUser : IPSec User +!Cname time-stamp +id-kp 8 : timeStamping : Time Stamping +# From OCSP spec RFC2560 +!Cname OCSP-sign +id-kp 9 : OCSPSigning : OCSP Signing +id-kp 10 : DVCS : dvcs + +# CMP information types +id-it 1 : id-it-caProtEncCert +id-it 2 : id-it-signKeyPairTypes +id-it 3 : id-it-encKeyPairTypes +id-it 4 : id-it-preferredSymmAlg +id-it 5 : id-it-caKeyUpdateInfo +id-it 6 : id-it-currentCRL +id-it 7 : id-it-unsupportedOIDs +# obsolete +id-it 8 : id-it-subscriptionRequest +# obsolete +id-it 9 : id-it-subscriptionResponse +id-it 10 : id-it-keyPairParamReq +id-it 11 : id-it-keyPairParamRep +id-it 12 : id-it-revPassphrase +id-it 13 : id-it-implicitConfirm +id-it 14 : id-it-confirmWaitTime +id-it 15 : id-it-origPKIMessage + +# CRMF registration +id-pkip 1 : id-regCtrl +id-pkip 2 : id-regInfo + +# CRMF registration controls +id-regCtrl 1 : id-regCtrl-regToken +id-regCtrl 2 : id-regCtrl-authenticator +id-regCtrl 3 : id-regCtrl-pkiPublicationInfo +id-regCtrl 4 : id-regCtrl-pkiArchiveOptions +id-regCtrl 5 : id-regCtrl-oldCertID +id-regCtrl 6 : id-regCtrl-protocolEncrKey + +# CRMF registration information +id-regInfo 1 : id-regInfo-utf8Pairs +id-regInfo 2 : id-regInfo-certReq + +# algorithms +id-alg 1 : id-alg-des40 +id-alg 2 : id-alg-noSignature +id-alg 3 : id-alg-dh-sig-hmac-sha1 +id-alg 4 : id-alg-dh-pop + +# CMC controls +id-cmc 1 : id-cmc-statusInfo +id-cmc 2 : id-cmc-identification +id-cmc 3 : id-cmc-identityProof +id-cmc 4 : id-cmc-dataReturn +id-cmc 5 : id-cmc-transactionId +id-cmc 6 : id-cmc-senderNonce +id-cmc 7 : id-cmc-recipientNonce +id-cmc 8 : id-cmc-addExtensions +id-cmc 9 : id-cmc-encryptedPOP +id-cmc 10 : id-cmc-decryptedPOP +id-cmc 11 : id-cmc-lraPOPWitness +id-cmc 15 : id-cmc-getCert +id-cmc 16 : id-cmc-getCRL +id-cmc 17 : id-cmc-revokeRequest +id-cmc 18 : id-cmc-regInfo +id-cmc 19 : id-cmc-responseInfo +id-cmc 21 : id-cmc-queryPending +id-cmc 22 : id-cmc-popLinkRandom +id-cmc 23 : id-cmc-popLinkWitness +id-cmc 24 : id-cmc-confirmCertAcceptance + +# other names +id-on 1 : id-on-personalData + +# personal data attributes +id-pda 1 : id-pda-dateOfBirth +id-pda 2 : id-pda-placeOfBirth +id-pda 3 : id-pda-gender +id-pda 4 : id-pda-countryOfCitizenship +id-pda 5 : id-pda-countryOfResidence + +# attribute certificate attributes +id-aca 1 : id-aca-authenticationInfo +id-aca 2 : id-aca-accessIdentity +id-aca 3 : id-aca-chargingIdentity +id-aca 4 : id-aca-group +# attention : the following seems to be obsolete, replace by 'role' +id-aca 5 : id-aca-role +id-aca 6 : id-aca-encAttrs + +# qualified certificate statements +id-qcs 1 : id-qcs-pkixQCSyntax-v1 + +# CMC content types +id-cct 1 : id-cct-crs +id-cct 2 : id-cct-PKIData +id-cct 3 : id-cct-PKIResponse + +# access descriptors for authority info access extension +!Cname ad-OCSP +id-ad 1 : OCSP : OCSP +!Cname ad-ca-issuers +id-ad 2 : caIssuers : CA Issuers +!Cname ad-timeStamping +id-ad 3 : ad_timestamping : AD Time Stamping +!Cname ad-dvcs +id-ad 4 : AD_DVCS : ad dvcs + + +!Alias id-pkix-OCSP ad-OCSP +!module id-pkix-OCSP +!Cname basic +id-pkix-OCSP 1 : basicOCSPResponse : Basic OCSP Response +id-pkix-OCSP 2 : Nonce : OCSP Nonce +id-pkix-OCSP 3 : CrlID : OCSP CRL ID +id-pkix-OCSP 4 : acceptableResponses : Acceptable OCSP Responses +id-pkix-OCSP 5 : noCheck : OCSP No Check +id-pkix-OCSP 6 : archiveCutoff : OCSP Archive Cutoff +id-pkix-OCSP 7 : serviceLocator : OCSP Service Locator +id-pkix-OCSP 8 : extendedStatus : Extended OCSP Status +id-pkix-OCSP 9 : valid +id-pkix-OCSP 10 : path +id-pkix-OCSP 11 : trustRoot : Trust Root +!global + +1 3 14 3 2 : algorithm : algorithm +algorithm 3 : RSA-NP-MD5 : md5WithRSA +algorithm 6 : DES-ECB : des-ecb +algorithm 7 : DES-CBC : des-cbc +!Cname des-ofb64 +algorithm 8 : DES-OFB : des-ofb +!Cname des-cfb64 +algorithm 9 : DES-CFB : des-cfb algorithm 11 : rsaSignature +!Cname dsa-2 +algorithm 12 : DSA-old : dsaEncryption-old +algorithm 13 : DSA-SHA : dsaWithSHA +algorithm 15 : RSA-SHA : shaWithRSAEncryption +!Cname des-ede-ecb +algorithm 17 : DES-EDE : des-ede +!Cname des-ede3-ecb + : DES-EDE3 : des-ede3 + : DES-EDE-CBC : des-ede-cbc +!Cname des-ede-cfb64 + : DES-EDE-CFB : des-ede-cfb +!Cname des-ede3-cfb64 + : DES-EDE3-CFB : des-ede3-cfb +!Cname des-ede-ofb64 + : DES-EDE-OFB : des-ede-ofb +!Cname des-ede3-ofb64 + : DES-EDE3-OFB : des-ede3-ofb + : DESX-CBC : desx-cbc +algorithm 18 : SHA : sha +algorithm 26 : SHA1 : sha1 +!Cname dsaWithSHA1-2 +algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old +algorithm 29 : RSA-SHA1-2 : sha1WithRSA + +1 3 36 3 2 1 : RIPEMD160 : ripemd160 +1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA + +!Cname sxnet +1 3 101 1 4 1 : SXNetID : Strong Extranet ID + +2 5 : X500 : directory services (X.500) + +X500 4 : X509 +X509 3 : CN : commonName +X509 4 : SN : surname +X509 5 : : serialNumber +X509 6 : C : countryName +X509 7 : L : localityName +X509 8 : ST : stateOrProvinceName +X509 10 : O : organizationName +X509 11 : OU : organizationalUnitName +X509 12 : : title +X509 13 : : description +X509 41 : name : name +X509 42 : gn : givenName +X509 43 : : initials +X509 44 : : generationQualifier +X509 45 : : x500UniqueIdentifier +X509 46 : dnQualifier : dnQualifier +X509 72 : role : role + +X500 8 : X500algorithms : directory services - algorithms +X500algorithms 1 1 : RSA : rsa +X500algorithms 3 100 : RSA-MDC2 : mdc2WithRSA +X500algorithms 3 101 : MDC2 : mdc2 + +X500 29 : id-ce +!Cname subject-key-identifier +id-ce 14 : subjectKeyIdentifier : X509v3 Subject Key Identifier +!Cname key-usage +id-ce 15 : keyUsage : X509v3 Key Usage +!Cname private-key-usage-period +id-ce 16 : privateKeyUsagePeriod : X509v3 Private Key Usage Period +!Cname subject-alt-name +id-ce 17 : subjectAltName : X509v3 Subject Alternative Name +!Cname issuer-alt-name +id-ce 18 : issuerAltName : X509v3 Issuer Alternative Name +!Cname basic-constraints +id-ce 19 : basicConstraints : X509v3 Basic Constraints +!Cname crl-number +id-ce 20 : crlNumber : X509v3 CRL Number +!Cname crl-reason +id-ce 21 : CRLReason : X509v3 CRL Reason Code +!Cname invalidity-date +id-ce 24 : invalidityDate : Invalidity Date +!Cname delta-crl +id-ce 27 : deltaCRL : X509v3 Delta CRL Indicator +!Cname crl-distribution-points +id-ce 31 : crlDistributionPoints : X509v3 CRL Distribution Points +!Cname certificate-policies +id-ce 32 : certificatePolicies : X509v3 Certificate Policies +!Cname authority-key-identifier +id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier +!Cname policy-constraints +id-ce 36 : policyConstraints : X509v3 Policy Constraints +!Cname ext-key-usage +id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage +!Cname target-information +id-ce 55 : targetInformation : X509v3 AC Targeting +!Cname no-rev-avail +id-ce 56 : noRevAvail : X509v3 No Revocation Available + +!Cname netscape +2 16 840 1 113730 : Netscape : Netscape Communications Corp. +!Cname netscape-cert-extension +netscape 1 : nsCertExt : Netscape Certificate Extension +!Cname netscape-data-type +netscape 2 : nsDataType : Netscape Data Type +!Cname netscape-cert-type +netscape-cert-extension 1 : nsCertType : Netscape Cert Type +!Cname netscape-base-url +netscape-cert-extension 2 : nsBaseUrl : Netscape Base Url +!Cname netscape-revocation-url +netscape-cert-extension 3 : nsRevocationUrl : Netscape Revocation Url +!Cname netscape-ca-revocation-url +netscape-cert-extension 4 : nsCaRevocationUrl : Netscape CA Revocation Url +!Cname netscape-renewal-url +netscape-cert-extension 7 : nsRenewalUrl : Netscape Renewal Url +!Cname netscape-ca-policy-url +netscape-cert-extension 8 : nsCaPolicyUrl : Netscape CA Policy Url +!Cname netscape-ssl-server-name +netscape-cert-extension 12 : nsSslServerName : Netscape SSL Server Name +!Cname netscape-comment +netscape-cert-extension 13 : nsComment : Netscape Comment +!Cname netscape-cert-sequence +netscape-data-type 5 : nsCertSequence : Netscape Certificate Sequence +!Cname ns-sgc +netscape 4 1 : nsSGC : Netscape Server Gated Crypto + +# iso(1) +iso 3 : ORG : org +org 6 : DOD : dod +dod 1 : IANA : iana +!Alias internet iana + +internet 1 : directory : Directory +internet 2 : mgmt : Management +internet 3 : experimental : Experimental +internet 4 : private : Private +internet 5 : security : Security +internet 6 : snmpv2 : SNMPv2 +# Documents refer to "internet 7" as "mail". This however leads to ambiguities +# with RFC2798, Section 9.1.3, where "mail" is defined as the short name for +# rfc822Mailbox. The short name is therefore here left out for a reason. +# Subclasses of "mail", e.g. "MIME MHS" don't consitute a problem, as +# references are realized via long name "Mail" (with capital M). +internet 7 : : Mail + +Private 1 : enterprises : Enterprises + +# RFC 2247 +Enterprises 1466 344 : dcobject : dcObject + +# RFC 1495 +Mail 1 : mime-mhs : MIME MHS +mime-mhs 1 : mime-mhs-headings : mime-mhs-headings +mime-mhs 2 : mime-mhs-bodies : mime-mhs-bodies +mime-mhs-headings 1 : id-hex-partial-message : id-hex-partial-message +mime-mhs-headings 2 : id-hex-multipart-message : id-hex-multipart-message + +# What the hell are these OIDs, really? +!Cname rle-compression +1 1 1 1 666 1 : RLE : run length compression +!Cname zlib-compression +1 1 1 1 666 2 : ZLIB : zlib compression + +# AES aka Rijndael + +!Alias csor 2 16 840 1 101 3 +!Alias nistAlgorithms csor 4 +!Alias aes nistAlgorithms 1 + +aes 1 : AES-128-ECB : aes-128-ecb +aes 2 : AES-128-CBC : aes-128-cbc +!Cname aes-128-ofb128 +aes 3 : AES-128-OFB : aes-128-ofb +!Cname aes-128-cfb128 +aes 4 : AES-128-CFB : aes-128-cfb + +aes 21 : AES-192-ECB : aes-192-ecb +aes 22 : AES-192-CBC : aes-192-cbc +!Cname aes-192-ofb128 +aes 23 : AES-192-OFB : aes-192-ofb +!Cname aes-192-cfb128 +aes 24 : AES-192-CFB : aes-192-cfb + +aes 41 : AES-256-ECB : aes-256-ecb +aes 42 : AES-256-CBC : aes-256-cbc +!Cname aes-256-ofb128 +aes 43 : AES-256-OFB : aes-256-ofb +!Cname aes-256-cfb128 +aes 44 : AES-256-CFB : aes-256-cfb + +# Hold instruction CRL entry extension +!Cname hold-instruction-code +id-ce 23 : holdInstructionCode : Hold Instruction Code +!Alias holdInstruction X9-57 2 +!Cname hold-instruction-none +holdInstruction 1 : holdInstructionNone : Hold Instruction None +!Cname hold-instruction-call-issuer +holdInstruction 2 : holdInstructionCallIssuer : Hold Instruction Call Issuer +!Cname hold-instruction-reject +holdInstruction 3 : holdInstructionReject : Hold Instruction Reject -algorithm 6 : desECB -algorithm 7 : desCBC -algorithm 8 : desOFB -algorithm 9 : desCFB -algorithm 17 : desEDE2 +# OID's from CCITT. Most of this is defined in RFC 1274. A couple of +# them are also mentioned in RFC 2247 +ccitt 9 : data +data 2342 : pss +pss 19200300 : ucl +ucl 100 : pilot +pilot 1 : : pilotAttributeType +pilot 3 : : pilotAttributeSyntax +pilot 4 : : pilotObjectClass +pilot 10 : : pilotGroups +pilotAttributeSyntax 4 : : iA5StringSyntax +pilotAttributeSyntax 5 : : caseIgnoreIA5StringSyntax +pilotObjectClass 3 : : pilotObject +pilotObjectClass 4 : : pilotPerson +pilotObjectClass 5 : account +pilotObjectClass 6 : document +pilotObjectClass 7 : room +pilotObjectClass 9 : : documentSeries +pilotObjectClass 13 : domain : Domain +pilotObjectClass 14 : : rFC822localPart +pilotObjectClass 15 : : dNSDomain +pilotObjectClass 17 : : domainRelatedObject +pilotObjectClass 18 : : friendlyCountry +pilotObjectClass 19 : : simpleSecurityObject +pilotObjectClass 20 : : pilotOrganization +pilotObjectClass 21 : : pilotDSA +pilotObjectClass 22 : : qualityLabelledData +pilotAttributeType 1 : UID : userId +pilotAttributeType 2 : : textEncodedORAddress +pilotAttributeType 3 : mail : rfc822Mailbox +pilotAttributeType 4 : info +pilotAttributeType 5 : : favouriteDrink +pilotAttributeType 6 : : roomNumber +pilotAttributeType 7 : photo +pilotAttributeType 8 : : userClass +pilotAttributeType 9 : host +pilotAttributeType 10 : manager +pilotAttributeType 11 : : documentIdentifier +pilotAttributeType 12 : : documentTitle +pilotAttributeType 13 : : documentVersion +pilotAttributeType 14 : : documentAuthor +pilotAttributeType 15 : : documentLocation +pilotAttributeType 20 : : homeTelephoneNumber +pilotAttributeType 21 : secretary +pilotAttributeType 22 : : otherMailbox +pilotAttributeType 23 : : lastModifiedTime +pilotAttributeType 24 : : lastModifiedBy +pilotAttributeType 25 : DC : domainComponent +pilotAttributeType 26 : : aRecord +pilotAttributeType 27 : : pilotAttributeType27 +pilotAttributeType 28 : : mXRecord +pilotAttributeType 29 : : nSRecord +pilotAttributeType 30 : : sOARecord +pilotAttributeType 31 : : cNAMERecord +pilotAttributeType 37 : : associatedDomain +pilotAttributeType 38 : : associatedName +pilotAttributeType 39 : : homePostalAddress +pilotAttributeType 40 : : personalTitle +pilotAttributeType 41 : : mobileTelephoneNumber +pilotAttributeType 42 : : pagerTelephoneNumber +pilotAttributeType 43 : : friendlyCountryName +# The following clashes with 2.5.4.45, so commented away +#pilotAttributeType 44 : uid : uniqueIdentifier +pilotAttributeType 45 : : organizationalStatus +pilotAttributeType 46 : : janetMailbox +pilotAttributeType 47 : : mailPreferenceOption +pilotAttributeType 48 : : buildingName +pilotAttributeType 49 : : dSAQuality +pilotAttributeType 50 : : singleLevelQuality +pilotAttributeType 51 : : subtreeMinimumQuality +pilotAttributeType 52 : : subtreeMaximumQuality +pilotAttributeType 53 : : personalSignature +pilotAttributeType 54 : : dITRedirect +pilotAttributeType 55 : audio +pilotAttributeType 56 : : documentPublisher diff --git a/src/lib/libcrypto/opensslv.h b/src/lib/libcrypto/opensslv.h index b841347f05..0d23a02fb2 100644 --- a/src/lib/libcrypto/opensslv.h +++ b/src/lib/libcrypto/opensslv.h @@ -2,20 +2,84 @@ #define HEADER_OPENSSLV_H /* Numeric release version identifier: - * MMNNFFRBB: major minor fix final beta/patch + * MNNFFPPS: 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.3beta1 0x00903001 - * 0.9.3beta2-dev 0x00903002 - * 0.9.3beta2 0x00903002 - * 0.9.3 0x00903100 - * 0.9.3a 0x00903101 - * 0.9.4 0x00904100 - * 1.2.3z 0x1020311a + * 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 0x00904100L -#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.4 09 Aug 1999" +#define OPENSSL_VERSION_NUMBER 0x00907001L +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.7-beta1 01 Jun 2002" #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT + +/* The macros below are to be used for shared library (.so, .dll, ...) + * versioning. That kind of versioning works a bit differently between + * operating systems. The most usual scheme is to set a major and a minor + * number, and have the runtime loader check that the major number is equal + * to what it was at application link time, while the minor number has to + * be greater or equal to what it was at application link time. With this + * scheme, the version number is usually part of the file name, like this: + * + * libcrypto.so.0.9 + * + * Some unixen also make a softlink with the major verson number only: + * + * libcrypto.so.0 + * + * On Tru64 and IRIX 6.x it works a little bit differently. There, the + * shared library version is stored in the file, and is actually a series + * of versions, separated by colons. The rightmost version present in the + * library when linking an application is stored in the application to be + * matched at run time. When the application is run, a check is done to + * see if the library version stored in the application matches any of the + * versions in the version string of the library itself. + * This version string can be constructed in any way, depending on what + * kind of matching is desired. However, to implement the same scheme as + * the one used in the other unixen, all compatible versions, from lowest + * to highest, should be part of the string. Consecutive builds would + * give the following versions strings: + * + * 3.0 + * 3.0:3.1 + * 3.0:3.1:3.2 + * 4.0 + * 4.0:4.1 + * + * Notice how version 4 is completely incompatible with version, and + * therefore give the breach you can see. + * + * There may be other schemes as well that I haven't yet discovered. + * + * So, here's the way it works here: first of all, the library version + * number doesn't need at all to match the overall OpenSSL version. + * However, it's nice and more understandable if it actually does. + * The current library version is stored in the macro SHLIB_VERSION_NUMBER, + * which is just a piece of text in the format "M.m.e" (Major, minor, edit). + * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways, + * we need to keep a history of version numbers, which is done in the + * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and + * should only keep the versions that are binary compatible with the current. + */ +#define SHLIB_VERSION_HISTORY "" +#define SHLIB_VERSION_NUMBER "0.9.7" + + #endif /* HEADER_OPENSSLV_H */ diff --git a/src/lib/libcrypto/pem/pem.h b/src/lib/libcrypto/pem/pem.h index 55fbaeffe2..3785fca77d 100644 --- a/src/lib/libcrypto/pem/pem.h +++ b/src/lib/libcrypto/pem/pem.h @@ -1,4 +1,4 @@ -/* crypto/pem/pem.org */ +/* crypto/pem/pem.h */ /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,23 +56,25 @@ * [including the GNU Public Licence.] */ -/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING - * - * Always modify pem.org since pem.h is automatically generated from - * it during SSLeay configuration. - * - * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING - */ - #ifndef HEADER_PEM_H #define HEADER_PEM_H +#ifndef OPENSSL_NO_BIO +#include +#endif +#ifndef OPENSSL_NO_STACK +#include +#endif +#include +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include "evp.h" -#include "x509.h" +#define PEM_BUFSIZE 1024 #define PEM_OBJ_UNDEF 0 #define PEM_OBJ_X509 1 @@ -108,49 +110,25 @@ extern "C" { #define PEM_STRING_X509_OLD "X509 CERTIFICATE" #define PEM_STRING_X509 "CERTIFICATE" +#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" #define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" #define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" #define PEM_STRING_X509_CRL "X509 CRL" -#define PEM_STRING_EVP_PKEY "PRIVATE KEY" +#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +#define PEM_STRING_PUBLIC "PUBLIC KEY" #define PEM_STRING_RSA "RSA PRIVATE KEY" #define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" #define PEM_STRING_DSA "DSA PRIVATE KEY" +#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" #define PEM_STRING_PKCS7 "PKCS7" +#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +#define PEM_STRING_PKCS8INF "PRIVATE KEY" #define PEM_STRING_DHPARAMS "DH PARAMETERS" #define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" #define PEM_STRING_DSAPARAMS "DSA PARAMETERS" -#ifndef HEADER_ENVELOPE_H - -#define EVP_ENCODE_CTX_SIZE 96 -#define EVP_MD_SIZE 60 -#define EVP_MD_CTX_SIZE 152 -#define EVP_CIPHER_SIZE 40 -#define EVP_CIPHER_CTX_SIZE 4212 -#define EVP_MAX_MD_SIZE 20 - -typedef struct evp_encode_ctx_st - { - char data[EVP_ENCODE_CTX_SIZE]; - } EVP_ENCODE_CTX; - -typedef struct env_md_ctx_st - { - char data[EVP_MD_CTX_SIZE]; - } EVP_MD_CTX; - -typedef struct evp_cipher_st - { - char data[EVP_CIPHER_SIZE]; - } EVP_CIPHER; - -typedef struct evp_cipher_ctx_st - { - char data[EVP_CIPHER_CTX_SIZE]; - } EVP_CIPHER_CTX; -#endif - - + /* Note that this structure is initialised by PEM_SealInit and cleaned up + by PEM_SealFinal (at least for now) */ typedef struct PEM_Encode_Seal_st { EVP_ENCODE_CTX encode; @@ -195,7 +173,7 @@ typedef struct pem_ctx_st int num_recipient; PEM_USER **recipient; -#ifdef HEADER_STACK_H +#ifndef OPENSSL_NO_STACK STACK *x509_chain; /* certificate chain */ #else char *x509_chain; /* certificate chain */ @@ -217,151 +195,324 @@ typedef struct pem_ctx_st unsigned char *data; } PEM_CTX; +/* These macros make the PEM_read/PEM_write functions easier to maintain and + * write. Now they are all implemented with either: + * IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...) + */ + +#ifdef OPENSSL_NO_FP_API + +#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/ +#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/ +#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/ + +#else + +#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ +type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return((type *)PEM_ASN1_read((char *(*)())d2i_##asn1, str,fp,(char **)x,\ + cb,u)); \ +} \ + +#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x) \ +{ \ +return(PEM_ASN1_write((int (*)())i2d_##asn1,str,fp, (char *)x, \ + NULL,NULL,0,NULL,NULL)); \ +} + +#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return(PEM_ASN1_write((int (*)())i2d_##asn1,str,fp, \ + (char *)x,enc,kstr,klen,cb,u)); \ + } + +#endif + +#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ +type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return((type *)PEM_ASN1_read_bio((char *(*)())d2i_##asn1, str,bp,\ + (char **)x,cb,u)); \ +} + +#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x) \ +{ \ +return(PEM_ASN1_write_bio((int (*)())i2d_##asn1,str,bp, (char *)x, \ + NULL,NULL,0,NULL,NULL)); \ +} + +#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return(PEM_ASN1_write_bio((int (*)())i2d_##asn1,str,bp, \ + (char *)x,enc,kstr,klen,cb,u)); \ + } + +#define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +/* These are the same except they are for the declarations */ + +#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_NO_FP_API) + +#define DECLARE_PEM_read_fp(name, type) /**/ +#define DECLARE_PEM_write_fp(name, type) /**/ +#define DECLARE_PEM_write_cb_fp(name, type) /**/ + +#else + +#define DECLARE_PEM_read_fp(name, type) \ + type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x); + +#define DECLARE_PEM_write_cb_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +#endif + +#ifndef OPENSSL_NO_BIO +#define DECLARE_PEM_read_bio(name, type) \ + type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x); + +#define DECLARE_PEM_write_cb_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +#else + +#define DECLARE_PEM_read_bio(name, type) /**/ +#define DECLARE_PEM_write_bio(name, type) /**/ +#define DECLARE_PEM_write_cb_bio(name, type) /**/ + +#endif + +#define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) + +#define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) + +#define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) + +#define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) + +#define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) + #ifdef SSLEAY_MACROS #define PEM_write_SSL_SESSION(fp,x) \ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \ - PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL) + PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_X509(fp,x) \ PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, \ - (char *)x, NULL,NULL,0,NULL) + (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_X509_REQ(fp,x) PEM_ASN1_write( \ (int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp,(char *)x, \ - NULL,NULL,0,NULL) + NULL,NULL,0,NULL,NULL) #define PEM_write_X509_CRL(fp,x) \ PEM_ASN1_write((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL, \ - fp,(char *)x, NULL,NULL,0,NULL) -#define PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb) \ + fp,(char *)x, NULL,NULL,0,NULL,NULL) +#define PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \ PEM_ASN1_write((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,fp,\ - (char *)x,enc,kstr,klen,cb) + (char *)x,enc,kstr,klen,cb,u) #define PEM_write_RSAPublicKey(fp,x) \ PEM_ASN1_write((int (*)())i2d_RSAPublicKey,\ - PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL) -#define PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb) \ + PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL,NULL) +#define PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \ PEM_ASN1_write((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,fp,\ - (char *)x,enc,kstr,klen,cb) -#define PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb) \ + (char *)x,enc,kstr,klen,cb,u) +#define PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb,u) \ PEM_ASN1_write((int (*)())i2d_PrivateKey,\ (((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\ - bp,(char *)x,enc,kstr,klen,cb) + bp,(char *)x,enc,kstr,klen,cb,u) #define PEM_write_PKCS7(fp,x) \ PEM_ASN1_write((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,fp, \ - (char *)x, NULL,NULL,0,NULL) + (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_DHparams(fp,x) \ PEM_ASN1_write((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,fp,\ - (char *)x,NULL,NULL,0,NULL) - -#define PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \ - (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb) -#define PEM_read_X509(fp,x,cb) (X509 *)PEM_ASN1_read( \ - (char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb) -#define PEM_read_X509_REQ(fp,x,cb) (X509_REQ *)PEM_ASN1_read( \ - (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb) -#define PEM_read_X509_CRL(fp,x,cb) (X509_CRL *)PEM_ASN1_read( \ - (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb) -#define PEM_read_RSAPrivateKey(fp,x,cb) (RSA *)PEM_ASN1_read( \ - (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb) -#define PEM_read_RSAPublicKey(fp,x,cb) (RSA *)PEM_ASN1_read( \ - (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb) -#define PEM_read_DSAPrivateKey(fp,x,cb) (DSA *)PEM_ASN1_read( \ - (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb) -#define PEM_read_PrivateKey(fp,x,cb) (EVP_PKEY *)PEM_ASN1_read( \ - (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb) -#define PEM_read_PKCS7(fp,x,cb) (PKCS7 *)PEM_ASN1_read( \ - (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb) -#define PEM_read_DHparams(fp,x,cb) (DH *)PEM_ASN1_read( \ - (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb) + (char *)x,NULL,NULL,0,NULL,NULL) + +#define PEM_write_NETSCAPE_CERT_SEQUENCE(fp,x) \ + PEM_ASN1_write((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \ + PEM_STRING_X509,fp, \ + (char *)x, NULL,NULL,0,NULL,NULL) + +#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u) +#define PEM_read_X509(fp,x,cb,u) (X509 *)PEM_ASN1_read( \ + (char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u) +#define PEM_read_X509_REQ(fp,x,cb,u) (X509_REQ *)PEM_ASN1_read( \ + (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb,u) +#define PEM_read_X509_CRL(fp,x,cb,u) (X509_CRL *)PEM_ASN1_read( \ + (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb,u) +#define PEM_read_RSAPrivateKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \ + (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb,u) +#define PEM_read_RSAPublicKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \ + (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb,u) +#define PEM_read_DSAPrivateKey(fp,x,cb,u) (DSA *)PEM_ASN1_read( \ + (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb,u) +#define PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read( \ + (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u) +#define PEM_read_PKCS7(fp,x,cb,u) (PKCS7 *)PEM_ASN1_read( \ + (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb,u) +#define PEM_read_DHparams(fp,x,cb,u) (DH *)PEM_ASN1_read( \ + (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb,u) + +#define PEM_read_NETSCAPE_CERT_SEQUENCE(fp,x,cb,u) \ + (NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read( \ + (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,fp,\ + (char **)x,cb,u) #define PEM_write_bio_SSL_SESSION(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \ - PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL) + PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_bio_X509(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_X509,PEM_STRING_X509,bp, \ - (char *)x, NULL,NULL,0,NULL) + (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_bio_X509_REQ(bp,x) PEM_ASN1_write_bio( \ (int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,bp,(char *)x, \ - NULL,NULL,0,NULL) + NULL,NULL,0,NULL,NULL) #define PEM_write_bio_X509_CRL(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL,\ - bp,(char *)x, NULL,NULL,0,NULL) -#define PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb) \ + bp,(char *)x, NULL,NULL,0,NULL,NULL) +#define PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \ PEM_ASN1_write_bio((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,\ - bp,(char *)x,enc,kstr,klen,cb) + bp,(char *)x,enc,kstr,klen,cb,u) #define PEM_write_bio_RSAPublicKey(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_RSAPublicKey, \ PEM_STRING_RSA_PUBLIC,\ - bp,(char *)x,NULL,NULL,0,NULL) -#define PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb) \ + bp,(char *)x,NULL,NULL,0,NULL,NULL) +#define PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \ PEM_ASN1_write_bio((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,\ - bp,(char *)x,enc,kstr,klen,cb) -#define PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb) \ + bp,(char *)x,enc,kstr,klen,cb,u) +#define PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb,u) \ PEM_ASN1_write_bio((int (*)())i2d_PrivateKey,\ (((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\ - bp,(char *)x,enc,kstr,klen,cb) + bp,(char *)x,enc,kstr,klen,cb,u) #define PEM_write_bio_PKCS7(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,bp, \ - (char *)x, NULL,NULL,0,NULL) + (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_bio_DHparams(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,\ - bp,(char *)x,NULL,NULL,0,NULL) + bp,(char *)x,NULL,NULL,0,NULL,NULL) #define PEM_write_bio_DSAparams(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_DSAparams, \ - PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL) - -#define PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb) -#define PEM_read_bio_X509(bp,x,cb) (X509 *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb) -#define PEM_read_bio_X509_REQ(bp,x,cb) (X509_REQ *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb) -#define PEM_read_bio_X509_CRL(bp,x,cb) (X509_CRL *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb) -#define PEM_read_bio_RSAPrivateKey(bp,x,cb) (RSA *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb) -#define PEM_read_bio_RSAPublicKey(bp,x,cb) (RSA *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb) -#define PEM_read_bio_DSAPrivateKey(bp,x,cb) (DSA *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb) -#define PEM_read_bio_PrivateKey(bp,x,cb) (EVP_PKEY *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb) - -#define PEM_read_bio_PKCS7(bp,x,cb) (PKCS7 *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb) -#define PEM_read_bio_DHparams(bp,x,cb) (DH *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb) -#define PEM_read_bio_DSAparams(bp,x,cb) (DSA *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb) + PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL,NULL) + +#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE(bp,x) \ + PEM_ASN1_write_bio((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \ + PEM_STRING_X509,bp, \ + (char *)x, NULL,NULL,0,NULL,NULL) + +#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb,u) +#define PEM_read_bio_X509(bp,x,cb,u) (X509 *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb,u) +#define PEM_read_bio_X509_REQ(bp,x,cb,u) (X509_REQ *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb,u) +#define PEM_read_bio_X509_CRL(bp,x,cb,u) (X509_CRL *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb,u) +#define PEM_read_bio_RSAPrivateKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb,u) +#define PEM_read_bio_RSAPublicKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb,u) +#define PEM_read_bio_DSAPrivateKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb,u) +#define PEM_read_bio_PrivateKey(bp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb,u) + +#define PEM_read_bio_PKCS7(bp,x,cb,u) (PKCS7 *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb,u) +#define PEM_read_bio_DHparams(bp,x,cb,u) (DH *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb,u) +#define PEM_read_bio_DSAparams(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb,u) + +#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE(bp,x,cb,u) \ + (NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,bp,\ + (char **)x,cb,u) #endif -#ifndef NOPROTO +#if 1 +/* "userdata": new with OpenSSL 0.9.4 */ +typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata); +#else +/* OpenSSL 0.9.3, 0.9.3a */ +typedef int pem_password_cb(char *buf, int size, int rwflag); +#endif + int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher); int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len, - int (*callback)()); + pem_password_cb *callback,void *u); -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,long *len); -int PEM_write_bio(BIO *bp,char *name,char *hdr,unsigned char *data, +int PEM_write_bio(BIO *bp,const char *name,char *hdr,unsigned char *data, long len); -char * PEM_ASN1_read_bio(char *(*d2i)(),char *name,BIO *bp,char **x, - int (*cb)()); -int PEM_ASN1_write_bio(int (*i2d)(),char *name,BIO *bp,char *x, - EVP_CIPHER *enc,unsigned char *kstr,int klen,int (*callback)()); -STACK * PEM_X509_INFO_read_bio(BIO *bp, STACK *sk, int (*cb)()); +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, + pem_password_cb *cb, void *u); +char * PEM_ASN1_read_bio(char *(*d2i)(),const char *name,BIO *bp,char **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write_bio(int (*i2d)(),const char *name,BIO *bp,char *x, + const EVP_CIPHER *enc,unsigned char *kstr,int klen, + pem_password_cb *cb, void *u); +STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); int PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc, - unsigned char *kstr, int klen, int (*cb)()); + unsigned char *kstr, int klen, pem_password_cb *cd, void *u); #endif -#ifndef WIN16 +#ifndef OPENSSL_SYS_WIN16 int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,long *len); int PEM_write(FILE *fp,char *name,char *hdr,unsigned char *data,long len); -char * PEM_ASN1_read(char *(*d2i)(),char *name,FILE *fp,char **x, - int (*cb)()); -int PEM_ASN1_write(int (*i2d)(),char *name,FILE *fp,char *x, - EVP_CIPHER *enc,unsigned char *kstr,int klen,int (*callback)()); -STACK * PEM_X509_INFO_read(FILE *fp, STACK *sk, int (*cb)()); +char * PEM_ASN1_read(char *(*d2i)(),const char *name,FILE *fp,char **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write(int (*i2d)(),const char *name,FILE *fp,char *x, + const EVP_CIPHER *enc,unsigned char *kstr,int klen, + pem_password_cb *callback, void *u); +STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); #endif int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, @@ -377,148 +528,102 @@ void PEM_SignUpdate(EVP_MD_CTX *ctx,unsigned char *d,unsigned int cnt); int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, EVP_PKEY *pkey); -void ERR_load_PEM_strings(void); - +int PEM_def_callback(char *buf, int num, int w, void *key); void PEM_proc_type(char *buf, int type); -void PEM_dek_info(char *buf, char *type, int len, char *str); +void PEM_dek_info(char *buf, const char *type, int len, char *str); #ifndef SSLEAY_MACROS -#ifndef WIN16 -X509 *PEM_read_X509(FILE *fp,X509 **x,int (*cb)()); -X509_REQ *PEM_read_X509_REQ(FILE *fp,X509_REQ **x,int (*cb)()); -X509_CRL *PEM_read_X509_CRL(FILE *fp,X509_CRL **x,int (*cb)()); -RSA *PEM_read_RSAPrivateKey(FILE *fp,RSA **x,int (*cb)()); -RSA *PEM_read_RSAPublicKey(FILE *fp,RSA **x,int (*cb)()); -DSA *PEM_read_DSAPrivateKey(FILE *fp,DSA **x,int (*cb)()); -EVP_PKEY *PEM_read_PrivateKey(FILE *fp,EVP_PKEY **x,int (*cb)()); -PKCS7 *PEM_read_PKCS7(FILE *fp,PKCS7 **x,int (*cb)()); -DH *PEM_read_DHparams(FILE *fp,DH **x,int (*cb)()); -DSA *PEM_read_DSAparams(FILE *fp,DSA **x,int (*cb)()); -int PEM_write_X509(FILE *fp,X509 *x); -int PEM_write_X509_REQ(FILE *fp,X509_REQ *x); -int PEM_write_X509_CRL(FILE *fp,X509_CRL *x); -int PEM_write_RSAPrivateKey(FILE *fp,RSA *x,EVP_CIPHER *enc,unsigned char *kstr, - int klen,int (*cb)()); -int PEM_write_RSAPublicKey(FILE *fp,RSA *x); -int PEM_write_DSAPrivateKey(FILE *fp,DSA *x,EVP_CIPHER *enc,unsigned char *kstr, - int klen,int (*cb)()); -int PEM_write_PrivateKey(FILE *fp,EVP_PKEY *x,EVP_CIPHER *enc, - unsigned char *kstr,int klen,int (*cb)()); -int PEM_write_PKCS7(FILE *fp,PKCS7 *x); -int PEM_write_DHparams(FILE *fp,DH *x); -int PEM_write_DSAparams(FILE *fp,DSA *x); -#endif +#include + +DECLARE_PEM_rw(X509, X509) + +DECLARE_PEM_rw(X509_AUX, X509) + +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) + +DECLARE_PEM_rw(X509_CRL, X509_CRL) + +DECLARE_PEM_rw(PKCS7, PKCS7) + +DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) + +DECLARE_PEM_rw(PKCS8, X509_SIG) + +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) + +#ifndef OPENSSL_NO_RSA + +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) + +DECLARE_PEM_rw(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) -#ifdef HEADER_BIO_H -X509 *PEM_read_bio_X509(BIO *bp,X509 **x,int (*cb)()); -X509_REQ *PEM_read_bio_X509_REQ(BIO *bp,X509_REQ **x,int (*cb)()); -X509_CRL *PEM_read_bio_X509_CRL(BIO *bp,X509_CRL **x,int (*cb)()); -RSA *PEM_read_bio_RSAPrivateKey(BIO *bp,RSA **x,int (*cb)()); -RSA *PEM_read_bio_RSAPublicKey(BIO *bp,RSA **x,int (*cb)()); -DSA *PEM_read_bio_DSAPrivateKey(BIO *bp,DSA **x,int (*cb)()); -EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp,EVP_PKEY **x,int (*cb)()); -PKCS7 *PEM_read_bio_PKCS7(BIO *bp,PKCS7 **x,int (*cb)()); -DH *PEM_read_bio_DHparams(BIO *bp,DH **x,int (*cb)()); -DSA *PEM_read_bio_DSAparams(BIO *bp,DSA **x,int (*cb)()); -int PEM_write_bio_X509(BIO *bp,X509 *x); -int PEM_write_bio_X509_REQ(BIO *bp,X509_REQ *x); -int PEM_write_bio_X509_CRL(BIO *bp,X509_CRL *x); -int PEM_write_bio_RSAPrivateKey(BIO *fp,RSA *x,EVP_CIPHER *enc, - unsigned char *kstr,int klen,int (*cb)()); -int PEM_write_bio_RSAPublicKey(BIO *fp,RSA *x); -int PEM_write_bio_DSAPrivateKey(BIO *fp,DSA *x,EVP_CIPHER *enc, - unsigned char *kstr,int klen,int (*cb)()); -int PEM_write_bio_PrivateKey(BIO *fp,EVP_PKEY *x,EVP_CIPHER *enc, - unsigned char *kstr,int klen,int (*cb)()); -int PEM_write_bio_PKCS7(BIO *bp,PKCS7 *x); -int PEM_write_bio_DHparams(BIO *bp,DH *x); -int PEM_write_bio_DSAparams(BIO *bp,DSA *x); #endif -#endif /* SSLEAY_MACROS */ +#ifndef OPENSSL_NO_DSA +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) -#else +DECLARE_PEM_rw(DSA_PUBKEY, DSA) + +DECLARE_PEM_rw(DSAparams, DSA) -int PEM_get_EVP_CIPHER_INFO(); -int PEM_do_header(); -int PEM_read_bio(); -int PEM_write_bio(); -#ifndef WIN16 -int PEM_read(); -int PEM_write(); -STACK * PEM_X509_INFO_read(); -char * PEM_ASN1_read(); -int PEM_ASN1_write(); #endif -STACK * PEM_X509_INFO_read_bio(); -int PEM_X509_INFO_write_bio(); -char * PEM_ASN1_read_bio(); -int PEM_ASN1_write_bio(); -int PEM_SealInit(); -void PEM_SealUpdate(); -int PEM_SealFinal(); -int PEM_SignFinal(); -void ERR_load_PEM_strings(); +#ifndef OPENSSL_NO_DH -void PEM_proc_type(); -void PEM_dek_info(); +DECLARE_PEM_rw(DHparams, DH) -#ifndef SSLEAY_MACROS -#ifndef WIN16 -X509 *PEM_read_X509(); -X509_REQ *PEM_read_X509_REQ(); -X509_CRL *PEM_read_X509_CRL(); -RSA *PEM_read_RSAPrivateKey(); -RSA *PEM_read_RSAPublicKey(); -DSA *PEM_read_DSAPrivateKey(); -EVP_PKEY *PEM_read_PrivateKey(); -PKCS7 *PEM_read_PKCS7(); -DH *PEM_read_DHparams(); -DSA *PEM_read_DSAparams(); -int PEM_write_X509(); -int PEM_write_X509_REQ(); -int PEM_write_X509_CRL(); -int PEM_write_RSAPrivateKey(); -int PEM_write_RSAPublicKey(); -int PEM_write_DSAPrivateKey(); -int PEM_write_PrivateKey(); -int PEM_write_PKCS7(); -int PEM_write_DHparams(); -int PEM_write_DSAparams(); #endif -X509 *PEM_read_bio_X509(); -X509_REQ *PEM_read_bio_X509_REQ(); -X509_CRL *PEM_read_bio_X509_CRL(); -RSA *PEM_read_bio_RSAPrivateKey(); -RSA *PEM_read_bio_RSAPublicKey(); -DSA *PEM_read_bio_DSAPrivateKey(); -EVP_PKEY *PEM_read_bio_PrivateKey(); -PKCS7 *PEM_read_bio_PKCS7(); -DH *PEM_read_bio_DHparams(); -DSA *PEM_read_bio_DSAparams(); -int PEM_write_bio_X509(); -int PEM_write_bio_X509_REQ(); -int PEM_write_bio_X509_CRL(); -int PEM_write_bio_RSAPrivateKey(); -int PEM_write_bio_RSAPublicKey(); -int PEM_write_bio_DSAPrivateKey(); -int PEM_write_bio_PrivateKey(); -int PEM_write_bio_PKCS7(); -int PEM_write_bio_DHparams(); -int PEM_write_bio_DSAparams(); +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) + +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, + char *, int, pem_password_cb *, void *); +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u); + +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u); + +int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc, + char *kstr,int klen, pem_password_cb *cd, void *u); #endif /* SSLEAY_MACROS */ -#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. + */ +void ERR_load_PEM_strings(void); + /* Error codes for the PEM functions. */ /* Function codes. */ +#define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120 +#define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121 #define PEM_F_DEF_CALLBACK 100 #define PEM_F_LOAD_IV 101 #define PEM_F_PEM_ASN1_READ 102 @@ -526,6 +631,8 @@ int PEM_write_bio_DSAparams(); #define PEM_F_PEM_ASN1_WRITE 104 #define PEM_F_PEM_ASN1_WRITE_BIO 105 #define PEM_F_PEM_DO_HEADER 106 +#define PEM_F_PEM_F_DO_PK8KEY_FP 122 +#define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY 118 #define PEM_F_PEM_GET_EVP_CIPHER_INFO 107 #define PEM_F_PEM_READ 108 #define PEM_F_PEM_READ_BIO 109 @@ -534,6 +641,7 @@ int PEM_write_bio_DSAparams(); #define PEM_F_PEM_SIGNFINAL 112 #define PEM_F_PEM_WRITE 113 #define PEM_F_PEM_WRITE_BIO 114 +#define PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY 119 #define PEM_F_PEM_X509_INFO_READ 115 #define PEM_F_PEM_X509_INFO_READ_BIO 116 #define PEM_F_PEM_X509_INFO_WRITE_BIO 117 @@ -544,6 +652,7 @@ int PEM_write_bio_DSAparams(); #define PEM_R_BAD_END_LINE 102 #define PEM_R_BAD_IV_CHARS 103 #define PEM_R_BAD_PASSWORD_READ 104 +#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115 #define PEM_R_NOT_DEK_INFO 105 #define PEM_R_NOT_ENCRYPTED 106 #define PEM_R_NOT_PROC_TYPE 107 @@ -554,9 +663,8 @@ int PEM_write_bio_DSAparams(); #define PEM_R_SHORT_HEADER 112 #define PEM_R_UNSUPPORTED_CIPHER 113 #define PEM_R_UNSUPPORTED_ENCRYPTION 114 - + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libcrypto/pem/pem2.h b/src/lib/libcrypto/pem/pem2.h index 4a016aacd2..4e484bcd82 100644 --- a/src/lib/libcrypto/pem/pem2.h +++ b/src/lib/libcrypto/pem/pem2.h @@ -57,4 +57,12 @@ * Ben 30 Jan 1999. */ +#ifdef __cplusplus +extern "C" { +#endif + void ERR_load_PEM_strings(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/lib/libcrypto/pem/pem_all.c b/src/lib/libcrypto/pem/pem_all.c index d1cda7aabe..e72b7134ce 100644 --- a/src/lib/libcrypto/pem/pem_all.c +++ b/src/lib/libcrypto/pem/pem_all.c @@ -59,430 +59,138 @@ #include #undef SSLEAY_MACROS #include "cryptlib.h" -#include "bio.h" -#include "evp.h" -#include "x509.h" -#include "pkcs7.h" -#include "pem.h" - -#ifndef NO_FP_API -/* The X509 functions */ -X509 *PEM_read_X509(fp,x,cb) -FILE *fp; -X509 **x; -int (*cb)(); - { - return((X509 *)PEM_ASN1_read((char *(*)())d2i_X509, - PEM_STRING_X509,fp,(char **)x,cb)); - } -#endif - -X509 *PEM_read_bio_X509(bp,x,cb) -BIO *bp; -X509 **x; -int (*cb)(); - { - return((X509 *)PEM_ASN1_read_bio((char *(*)())d2i_X509, - PEM_STRING_X509,bp,(char **)x,cb)); - } +#include +#include +#include +#include +#include -#ifndef NO_FP_API -int PEM_write_X509(fp,x) -FILE *fp; -X509 *x; - { - return(PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, - (char *)x, NULL,NULL,0,NULL)); - } +#ifndef OPENSSL_NO_RSA +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa); #endif - -int PEM_write_bio_X509(bp,x) -BIO *bp; -X509 *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_X509,PEM_STRING_X509,bp, - (char *)x, NULL,NULL,0,NULL)); - } - -#ifndef NO_FP_API -/* The X509_REQ functions */ -X509_REQ *PEM_read_X509_REQ(fp,x,cb) -FILE *fp; -X509_REQ **x; -int (*cb)(); - { - return((X509_REQ *)PEM_ASN1_read((char *(*)())d2i_X509_REQ, - PEM_STRING_X509_REQ,fp,(char **)x,cb)); - } +#ifndef OPENSSL_NO_DSA +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa); #endif -X509_REQ *PEM_read_bio_X509_REQ(bp,x,cb) -BIO *bp; -X509_REQ **x; -int (*cb)(); - { - return((X509_REQ *)PEM_ASN1_read_bio((char *(*)())d2i_X509_REQ, - PEM_STRING_X509_REQ,bp,(char **)x,cb)); - } +IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ) -#ifndef NO_FP_API -int PEM_write_X509_REQ(fp,x) -FILE *fp; -X509_REQ *x; - { - return(PEM_ASN1_write((int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp, - (char *)x, NULL,NULL,0,NULL)); - } -#endif +IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ) -int PEM_write_bio_X509_REQ(bp,x) -BIO *bp; -X509_REQ *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ, - bp,(char *)x, NULL,NULL,0,NULL)); - } +IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL) -#ifndef NO_FP_API -/* The X509_CRL functions */ -X509_CRL *PEM_read_X509_CRL(fp,x,cb) -FILE *fp; -X509_CRL **x; -int (*cb)(); - { - return((X509_CRL *)PEM_ASN1_read((char *(*)())d2i_X509_CRL, - PEM_STRING_X509_CRL,fp,(char **)x,cb)); - } -#endif +IMPLEMENT_PEM_rw(PKCS7, PKCS7, PEM_STRING_PKCS7, PKCS7) -X509_CRL *PEM_read_bio_X509_CRL(bp,x,cb) -BIO *bp; -X509_CRL **x; -int (*cb)(); - { - return((X509_CRL *)PEM_ASN1_read_bio((char *(*)())d2i_X509_CRL, - PEM_STRING_X509_CRL,bp,(char **)x,cb)); - } +IMPLEMENT_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE, + PEM_STRING_X509, NETSCAPE_CERT_SEQUENCE) -#ifndef NO_FP_API -int PEM_write_X509_CRL(fp,x) -FILE *fp; -X509_CRL *x; - { - return(PEM_ASN1_write((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL,fp, - (char *)x, NULL,NULL,0,NULL)); - } -#endif - -int PEM_write_bio_X509_CRL(bp,x) -BIO *bp; -X509_CRL *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL, - bp,(char *)x, NULL,NULL,0,NULL)); - } -#ifndef NO_RSA -#ifndef NO_FP_API -/* The RSAPrivateKey functions */ -RSA *PEM_read_RSAPrivateKey(fp,x,cb) -FILE *fp; -RSA **x; -int (*cb)(); - { - return((RSA *)PEM_ASN1_read((char *(*)())d2i_RSAPrivateKey, - PEM_STRING_RSA,fp,(char **)x,cb)); - } - -RSA *PEM_read_RSAPublicKey(fp,x,cb) -FILE *fp; -RSA **x; -int (*cb)(); - { - return((RSA *)PEM_ASN1_read((char *(*)())d2i_RSAPublicKey, - PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb)); - } -#endif +#ifndef OPENSSL_NO_RSA -RSA *PEM_read_bio_RSAPrivateKey(bp,x,cb) -BIO *bp; -RSA **x; -int (*cb)(); - { - return((RSA *)PEM_ASN1_read_bio((char *(*)())d2i_RSAPrivateKey, - PEM_STRING_RSA,bp,(char **)x,cb)); - } +/* We treat RSA or DSA private keys as a special case. + * + * For private keys we read in an EVP_PKEY structure with + * PEM_read_bio_PrivateKey() and extract the relevant private + * key: this means can handle "traditional" and PKCS#8 formats + * transparently. + */ -RSA *PEM_read_bio_RSAPublicKey(bp,x,cb) -BIO *bp; -RSA **x; -int (*cb)(); - { - return((RSA *)PEM_ASN1_read_bio((char *(*)())d2i_RSAPublicKey, - PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb)); +static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa) +{ + RSA *rtmp; + if(!key) return NULL; + rtmp = EVP_PKEY_get1_RSA(key); + EVP_PKEY_free(key); + if(!rtmp) return NULL; + if(rsa) { + RSA_free(*rsa); + *rsa = rtmp; } + return rtmp; +} -#ifndef NO_FP_API -int PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb) -FILE *fp; -RSA *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*cb)(); - { - return(PEM_ASN1_write((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,fp, - (char *)x,enc,kstr,klen,cb)); - } +RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} -int PEM_write_RSAPublicKey(fp,x) -FILE *fp; -RSA *x; - { - return(PEM_ASN1_write((int (*)())i2d_RSAPublicKey, - PEM_STRING_RSA_PUBLIC,fp, - (char *)x,NULL,NULL,0,NULL)); - } -#endif +#ifndef OPENSSL_NO_FP_API -int PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb) -BIO *bp; -RSA *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*cb)(); - { - return(PEM_ASN1_write_bio((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA, - bp,(char *)x,enc,kstr,klen,cb)); - } +RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_rsa(pktmp, rsa); +} -int PEM_write_bio_RSAPublicKey(bp,x) -BIO *bp; -RSA *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_RSAPublicKey, - PEM_STRING_RSA_PUBLIC, - bp,(char *)x,NULL,NULL,0,NULL)); - } -#endif /* !NO_RSA */ - -#ifndef NO_DSA -#ifndef NO_FP_API -/* The DSAPrivateKey functions */ -DSA *PEM_read_DSAPrivateKey(fp,x,cb) -FILE *fp; -DSA **x; -int (*cb)(); - { - return((DSA *)PEM_ASN1_read((char *(*)())d2i_DSAPrivateKey, - PEM_STRING_DSA,fp,(char **)x,cb)); - } #endif -DSA *PEM_read_bio_DSAPrivateKey(bp,x,cb) -BIO *bp; -DSA **x; -int (*cb)(); - { - return((DSA *)PEM_ASN1_read_bio((char *(*)())d2i_DSAPrivateKey, - PEM_STRING_DSA,bp,(char **)x,cb)); - } - -#ifndef NO_FP_API -int PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb) -FILE *fp; -DSA *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*cb)(); - { - return(PEM_ASN1_write((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,fp, - (char *)x,enc,kstr,klen,cb)); - } -#endif +IMPLEMENT_PEM_write_cb(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey) +IMPLEMENT_PEM_rw(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey) +IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY) -int PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb) -BIO *bp; -DSA *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*cb)(); - { - return(PEM_ASN1_write_bio((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA, - bp,(char *)x,enc,kstr,klen,cb)); - } #endif -#ifndef NO_FP_API -/* The PrivateKey functions */ -EVP_PKEY *PEM_read_PrivateKey(fp,x,cb) -FILE *fp; -EVP_PKEY **x; -int (*cb)(); - { - return((EVP_PKEY *)PEM_ASN1_read((char *(*)())d2i_PrivateKey, - PEM_STRING_EVP_PKEY,fp,(char **)x,cb)); - } -#endif +#ifndef OPENSSL_NO_DSA -EVP_PKEY *PEM_read_bio_PrivateKey(bp,x,cb) -BIO *bp; -EVP_PKEY **x; -int (*cb)(); - { - return((EVP_PKEY *)PEM_ASN1_read_bio((char *(*)())d2i_PrivateKey, - PEM_STRING_EVP_PKEY,bp,(char **)x,cb)); +static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa) +{ + DSA *dtmp; + if(!key) return NULL; + dtmp = EVP_PKEY_get1_DSA(key); + EVP_PKEY_free(key); + if(!dtmp) return NULL; + if(dsa) { + DSA_free(*dsa); + *dsa = dtmp; } + return dtmp; +} -#ifndef NO_FP_API -int PEM_write_PrivateKey(fp,x,enc,kstr,klen,cb) -FILE *fp; -EVP_PKEY *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*cb)(); - { - return(PEM_ASN1_write((int (*)())i2d_PrivateKey, - ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), - fp,(char *)x,enc,kstr,klen,cb)); - } -#endif +DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); +} -int PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb) -BIO *bp; -EVP_PKEY *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*cb)(); - { - return(PEM_ASN1_write_bio((int (*)())i2d_PrivateKey, - ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), - bp,(char *)x,enc,kstr,klen,cb)); - } +IMPLEMENT_PEM_write_cb(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey) +IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY) -#ifndef NO_FP_API -/* The PKCS7 functions */ -PKCS7 *PEM_read_PKCS7(fp,x,cb) -FILE *fp; -PKCS7 **x; -int (*cb)(); - { - return((PKCS7 *)PEM_ASN1_read((char *(*)())d2i_PKCS7, - PEM_STRING_PKCS7,fp,(char **)x,cb)); - } -#endif +#ifndef OPENSSL_NO_FP_API -PKCS7 *PEM_read_bio_PKCS7(bp,x,cb) -BIO *bp; -PKCS7 **x; -int (*cb)(); - { - return((PKCS7 *)PEM_ASN1_read_bio((char *(*)())d2i_PKCS7, - PEM_STRING_PKCS7,bp,(char **)x,cb)); - } +DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, + void *u) +{ + EVP_PKEY *pktmp; + pktmp = PEM_read_PrivateKey(fp, NULL, cb, u); + return pkey_get_dsa(pktmp, dsa); +} -#ifndef NO_FP_API -int PEM_write_PKCS7(fp,x) -FILE *fp; -PKCS7 *x; - { - return(PEM_ASN1_write((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,fp, - (char *)x, NULL,NULL,0,NULL)); - } #endif -int PEM_write_bio_PKCS7(bp,x) -BIO *bp; -PKCS7 *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,bp, - (char *)x, NULL,NULL,0,NULL)); - } +IMPLEMENT_PEM_rw(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams) -#ifndef NO_DH -#ifndef NO_FP_API -/* The DHparams functions */ -DH *PEM_read_DHparams(fp,x,cb) -FILE *fp; -DH **x; -int (*cb)(); - { - return((DH *)PEM_ASN1_read((char *(*)())d2i_DHparams, - PEM_STRING_DHPARAMS,fp,(char **)x,cb)); - } #endif -DH *PEM_read_bio_DHparams(bp,x,cb) -BIO *bp; -DH **x; -int (*cb)(); - { - return((DH *)PEM_ASN1_read_bio((char *(*)())d2i_DHparams, - PEM_STRING_DHPARAMS,bp,(char **)x,cb)); - } +#ifndef OPENSSL_NO_DH -#ifndef NO_FP_API -int PEM_write_DHparams(fp,x) -FILE *fp; -DH *x; - { - return(PEM_ASN1_write((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,fp, - (char *)x, NULL,NULL,0,NULL)); - } -#endif +IMPLEMENT_PEM_rw(DHparams, DH, PEM_STRING_DHPARAMS, DHparams) -int PEM_write_bio_DHparams(bp,x) -BIO *bp; -DH *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS, - bp,(char *)x, NULL,NULL,0,NULL)); - } #endif -#ifndef NO_DSA -#ifndef NO_FP_API -/* The DSAparams functions */ -DSA *PEM_read_DSAparams(fp,x,cb) -FILE *fp; -DSA **x; -int (*cb)(); - { - return((DSA *)PEM_ASN1_read((char *(*)())d2i_DSAparams, - PEM_STRING_DSAPARAMS,fp,(char **)x,cb)); - } -#endif -DSA *PEM_read_bio_DSAparams(bp,x,cb) -BIO *bp; -DSA **x; -int (*cb)(); - { - return((DSA *)PEM_ASN1_read_bio((char *(*)())d2i_DSAparams, - PEM_STRING_DSAPARAMS,bp,(char **)x,cb)); - } - -#ifndef NO_FP_API -int PEM_write_DSAparams(fp,x) -FILE *fp; -DSA *x; - { - return(PEM_ASN1_write((int (*)())i2d_DSAparams,PEM_STRING_DSAPARAMS,fp, - (char *)x, NULL,NULL,0,NULL)); - } -#endif +/* The PrivateKey case is not that straightforward. + * IMPLEMENT_PEM_rw_cb(PrivateKey, EVP_PKEY, PEM_STRING_EVP_PKEY, PrivateKey) + * does not work, RSA and DSA keys have specific strings. + * (When reading, parameter PEM_STRING_EVP_PKEY is a wildcard for anything + * appropriate.) + */ +IMPLEMENT_PEM_write_cb(PrivateKey, EVP_PKEY, ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), PrivateKey) -int PEM_write_bio_DSAparams(bp,x) -BIO *bp; -DSA *x; - { - return(PEM_ASN1_write_bio((int (*)())i2d_DSAparams,PEM_STRING_DSAPARAMS, - bp,(char *)x, NULL,NULL,0,NULL)); - } -#endif +IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) diff --git a/src/lib/libcrypto/pem/pem_err.c b/src/lib/libcrypto/pem/pem_err.c index e17fcdb540..3b39b84d66 100644 --- a/src/lib/libcrypto/pem/pem_err.c +++ b/src/lib/libcrypto/pem/pem_err.c @@ -1,68 +1,73 @@ -/* lib/pem/pem_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/pem/pem_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "pem.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA PEM_str_functs[]= { +{ERR_PACK(0,PEM_F_D2I_PKCS8PRIVATEKEY_BIO,0), "d2i_PKCS8PrivateKey_bio"}, +{ERR_PACK(0,PEM_F_D2I_PKCS8PRIVATEKEY_FP,0), "d2i_PKCS8PrivateKey_fp"}, {ERR_PACK(0,PEM_F_DEF_CALLBACK,0), "DEF_CALLBACK"}, {ERR_PACK(0,PEM_F_LOAD_IV,0), "LOAD_IV"}, {ERR_PACK(0,PEM_F_PEM_ASN1_READ,0), "PEM_ASN1_read"}, @@ -70,6 +75,8 @@ static ERR_STRING_DATA PEM_str_functs[]= {ERR_PACK(0,PEM_F_PEM_ASN1_WRITE,0), "PEM_ASN1_write"}, {ERR_PACK(0,PEM_F_PEM_ASN1_WRITE_BIO,0), "PEM_ASN1_write_bio"}, {ERR_PACK(0,PEM_F_PEM_DO_HEADER,0), "PEM_do_header"}, +{ERR_PACK(0,PEM_F_PEM_F_DO_PK8KEY_FP,0), "PEM_F_DO_PK8KEY_FP"}, +{ERR_PACK(0,PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY,0), "PEM_F_PEM_WRITE_PKCS8PRIVATEKEY"}, {ERR_PACK(0,PEM_F_PEM_GET_EVP_CIPHER_INFO,0), "PEM_get_EVP_CIPHER_INFO"}, {ERR_PACK(0,PEM_F_PEM_READ,0), "PEM_read"}, {ERR_PACK(0,PEM_F_PEM_READ_BIO,0), "PEM_read_bio"}, @@ -78,10 +85,11 @@ static ERR_STRING_DATA PEM_str_functs[]= {ERR_PACK(0,PEM_F_PEM_SIGNFINAL,0), "PEM_SignFinal"}, {ERR_PACK(0,PEM_F_PEM_WRITE,0), "PEM_write"}, {ERR_PACK(0,PEM_F_PEM_WRITE_BIO,0), "PEM_write_bio"}, +{ERR_PACK(0,PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY,0), "PEM_write_bio_PKCS8PrivateKey"}, {ERR_PACK(0,PEM_F_PEM_X509_INFO_READ,0), "PEM_X509_INFO_read"}, {ERR_PACK(0,PEM_F_PEM_X509_INFO_READ_BIO,0), "PEM_X509_INFO_read_bio"}, {ERR_PACK(0,PEM_F_PEM_X509_INFO_WRITE_BIO,0), "PEM_X509_INFO_write_bio"}, -{0,NULL}, +{0,NULL} }; static ERR_STRING_DATA PEM_str_reasons[]= @@ -91,6 +99,7 @@ static ERR_STRING_DATA PEM_str_reasons[]= {PEM_R_BAD_END_LINE ,"bad end line"}, {PEM_R_BAD_IV_CHARS ,"bad iv chars"}, {PEM_R_BAD_PASSWORD_READ ,"bad password read"}, +{PEM_R_ERROR_CONVERTING_PRIVATE_KEY ,"error converting private key"}, {PEM_R_NOT_DEK_INFO ,"not dek info"}, {PEM_R_NOT_ENCRYPTED ,"not encrypted"}, {PEM_R_NOT_PROC_TYPE ,"not proc type"}, @@ -101,19 +110,19 @@ static ERR_STRING_DATA PEM_str_reasons[]= {PEM_R_SHORT_HEADER ,"short header"}, {PEM_R_UNSUPPORTED_CIPHER ,"unsupported cipher"}, {PEM_R_UNSUPPORTED_ENCRYPTION ,"unsupported encryption"}, -{0,NULL}, +{0,NULL} }; #endif -void ERR_load_PEM_strings() +void ERR_load_PEM_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_PEM,PEM_str_functs); ERR_load_strings(ERR_LIB_PEM,PEM_str_reasons); #endif diff --git a/src/lib/libcrypto/pem/pem_info.c b/src/lib/libcrypto/pem/pem_info.c index 4b69833b62..9a6dffb45c 100644 --- a/src/lib/libcrypto/pem/pem_info.c +++ b/src/lib/libcrypto/pem/pem_info.c @@ -58,20 +58,17 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" -#include "pem.h" +#include +#include +#include +#include +#include -#ifndef NO_FP_API -STACK *PEM_X509_INFO_read(fp,sk,cb) -FILE *fp; -STACK *sk; -int (*cb)(); +#ifndef OPENSSL_NO_FP_API +STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u) { BIO *b; - STACK *ret; + STACK_OF(X509_INFO) *ret; if ((b=BIO_new(BIO_s_file())) == NULL) { @@ -79,29 +76,26 @@ int (*cb)(); return(0); } BIO_set_fp(b,fp,BIO_NOCLOSE); - ret=PEM_X509_INFO_read_bio(b,sk,cb); + ret=PEM_X509_INFO_read_bio(b,sk,cb,u); BIO_free(b); return(ret); } #endif -STACK *PEM_X509_INFO_read_bio(bp,sk,cb) -BIO *bp; -STACK *sk; -int (*cb)(); +STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u) { X509_INFO *xi=NULL; char *name=NULL,*header=NULL,**pp; unsigned char *data=NULL,*p; long len,error=0; int ok=0; - STACK *ret=NULL; + STACK_OF(X509_INFO) *ret=NULL; unsigned int i,raw; char *(*d2i)(); if (sk == NULL) { - if ((ret=sk_new_null()) == NULL) + if ((ret=sk_X509_INFO_new_null()) == NULL) { PEMerr(PEM_F_PEM_X509_INFO_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; @@ -117,7 +111,7 @@ int (*cb)(); i=PEM_read_bio(bp,&name,&header,&data,&len); if (i == 0) { - error=ERR_GET_REASON(ERR_peek_error()); + error=ERR_GET_REASON(ERR_peek_last_error()); if (error == PEM_R_NO_START_LINE) { ERR_clear_error(); @@ -132,7 +126,18 @@ start: d2i=(char *(*)())d2i_X509; if (xi->x509 != NULL) { - if (!sk_push(ret,(char *)xi)) goto err; + if (!sk_X509_INFO_push(ret,xi)) goto err; + if ((xi=X509_INFO_new()) == NULL) goto err; + goto start; + } + pp=(char **)&(xi->x509); + } + else if ((strcmp(name,PEM_STRING_X509_TRUSTED) == 0)) + { + d2i=(char *(*)())d2i_X509_AUX; + if (xi->x509 != NULL) + { + if (!sk_X509_INFO_push(ret,xi)) goto err; if ((xi=X509_INFO_new()) == NULL) goto err; goto start; } @@ -143,20 +148,20 @@ start: d2i=(char *(*)())d2i_X509_CRL; if (xi->crl != NULL) { - if (!sk_push(ret,(char *)xi)) goto err; + if (!sk_X509_INFO_push(ret,xi)) goto err; if ((xi=X509_INFO_new()) == NULL) goto err; goto start; } pp=(char **)&(xi->crl); } else -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (strcmp(name,PEM_STRING_RSA) == 0) { d2i=(char *(*)())d2i_RSAPrivateKey; if (xi->x_pkey != NULL) { - if (!sk_push(ret,(char *)xi)) goto err; + if (!sk_X509_INFO_push(ret,xi)) goto err; if ((xi=X509_INFO_new()) == NULL) goto err; goto start; } @@ -174,13 +179,13 @@ start: } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (strcmp(name,PEM_STRING_DSA) == 0) { d2i=(char *(*)())d2i_DSAPrivateKey; if (xi->x_pkey != NULL) { - if (!sk_push(ret,(char *)xi)) goto err; + if (!sk_X509_INFO_push(ret,xi)) goto err; if ((xi=X509_INFO_new()) == NULL) goto err; goto start; } @@ -211,7 +216,7 @@ start: if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err; - if (!PEM_do_header(&cipher,data,&len,cb)) + if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err; p=data; if (d2i(pp,&p,len) == NULL) @@ -232,9 +237,9 @@ start: else { /* unknown */ } - if (name != NULL) Free(name); - if (header != NULL) Free(header); - if (data != NULL) Free(data); + if (name != NULL) OPENSSL_free(name); + if (header != NULL) OPENSSL_free(header); + if (data != NULL) OPENSSL_free(data); name=NULL; header=NULL; data=NULL; @@ -246,7 +251,7 @@ start: if ((xi->x509 != NULL) || (xi->crl != NULL) || (xi->x_pkey != NULL) || (xi->enc_data != NULL)) { - if (!sk_push(ret,(char *)xi)) goto err; + if (!sk_X509_INFO_push(ret,xi)) goto err; xi=NULL; } ok=1; @@ -254,36 +259,30 @@ err: if (xi != NULL) X509_INFO_free(xi); if (!ok) { - for (i=0; ((int)i)enc_data!=NULL) && (xi->enc_len>0) ) { - /* copy from wierdo names into more normal things */ + /* copy from weirdo names into more normal things */ iv=xi->enc_cipher.iv; data=(unsigned char *)xi->enc_data; i=xi->enc_len; @@ -327,7 +326,7 @@ int (*cb)(); /* create the right magic header stuff */ buf[0]='\0'; PEM_proc_type(buf,PEM_TYPE_ENCRYPTED); - PEM_dek_info(buf,objstr,8,(char *)iv); + PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv); /* use the normal code to write things out */ i=PEM_write_bio(bp,PEM_STRING_RSA,buf,data,i); @@ -336,18 +335,18 @@ int (*cb)(); else { /* Add DSA/DH */ -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA /* normal optionally encrypted stuff */ if (PEM_write_bio_RSAPrivateKey(bp, xi->x_pkey->dec_pkey->pkey.rsa, - enc,kstr,klen,cb)<=0) + enc,kstr,klen,cb,u)<=0) goto err; #endif } } /* if we have a certificate then write it out now */ - if ((xi->x509 != NULL) || (PEM_write_bio_X509(bp,xi->x509) <= 0)) + if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp,xi->x509) <= 0)) goto err; /* we are ignoring anything else that is loaded into the X509_INFO diff --git a/src/lib/libcrypto/pem/pem_lib.c b/src/lib/libcrypto/pem/pem_lib.c index 7a2c0ad83b..18b751a91a 100644 --- a/src/lib/libcrypto/pem/pem_lib.c +++ b/src/lib/libcrypto/pem/pem_lib.c @@ -58,45 +58,40 @@ #include #include "cryptlib.h" -#include "buffer.h" -#include "objects.h" -#include "evp.h" -#include "rand.h" -#include "x509.h" -#include "pem.h" -#ifndef NO_DES -#include "des.h" +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_DES +#include #endif -char *PEM_version="PEM part of SSLeay 0.9.0b 29-Jun-1998"; +const char *PEM_version="PEM" OPENSSL_VERSION_PTEXT; #define MIN_LENGTH 4 -/* PEMerr(PEM_F_PEM_WRITE_BIO,ERR_R_MALLOC_FAILURE); - * PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); - */ - -#ifndef NOPROTO -static int def_callback(char *buf, int num, int w); static int load_iv(unsigned char **fromp,unsigned char *to, int num); -#else -static int def_callback(); -static int load_iv(); -#endif +static int check_pem(const char *nm, const char *name); -static int def_callback(buf, num, w) -char *buf; -int num; -int w; +int PEM_def_callback(char *buf, int num, int w, void *key) { -#ifdef NO_FP_API +#ifdef OPENSSL_NO_FP_API /* We should not ever call the default callback routine from * windows. */ PEMerr(PEM_F_DEF_CALLBACK,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return(-1); #else int i,j; - char *prompt; + const char *prompt; + if(key) { + i=strlen(key); + i=(i > num)?num:i; + memcpy(buf,key,i); + return(i); + } prompt=EVP_get_pw_prompt(); if (prompt == NULL) @@ -123,11 +118,9 @@ int w; #endif } -void PEM_proc_type(buf, type) -char *buf; -int type; +void PEM_proc_type(char *buf, int type) { - char *str; + const char *str; if (type == PEM_TYPE_ENCRYPTED) str="ENCRYPTED"; @@ -143,11 +136,7 @@ int type; strcat(buf,"\n"); } -void PEM_dek_info(buf, type, len, str) -char *buf; -char *type; -int len; -char *str; +void PEM_dek_info(char *buf, const char *type, int len, char *str) { static unsigned char map[17]="0123456789ABCDEF"; long i; @@ -166,13 +155,9 @@ char *str; buf[j+i*2+1]='\0'; } -#ifndef NO_FP_API -char *PEM_ASN1_read(d2i,name,fp, x, cb) -char *(*d2i)(); -char *name; -FILE *fp; -char **x; -int (*cb)(); +#ifndef OPENSSL_NO_FP_API +char *PEM_ASN1_read(char *(*d2i)(), const char *name, FILE *fp, char **x, + pem_password_cb *cb, void *u) { BIO *b; char *ret; @@ -183,74 +168,97 @@ int (*cb)(); return(0); } BIO_set_fp(b,fp,BIO_NOCLOSE); - ret=PEM_ASN1_read_bio(d2i,name,b,x,cb); + ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u); BIO_free(b); return(ret); } #endif -char *PEM_ASN1_read_bio(d2i,name,bp, x, cb) -char *(*d2i)(); -char *name; -BIO *bp; -char **x; -int (*cb)(); +static int check_pem(const char *nm, const char *name) +{ + /* Normal matching nm and name */ + if (!strcmp(nm,name)) return 1; + + /* Make PEM_STRING_EVP_PKEY match any private key */ + + if(!strcmp(nm,PEM_STRING_PKCS8) && + !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; + + if(!strcmp(nm,PEM_STRING_PKCS8INF) && + !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; + + if(!strcmp(nm,PEM_STRING_RSA) && + !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; + + if(!strcmp(nm,PEM_STRING_DSA) && + !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; + + /* Permit older strings */ + + if(!strcmp(nm,PEM_STRING_X509_OLD) && + !strcmp(name,PEM_STRING_X509)) return 1; + + if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) && + !strcmp(name,PEM_STRING_X509_REQ)) return 1; + + /* Allow normal certs to be read as trusted certs */ + if(!strcmp(nm,PEM_STRING_X509) && + !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; + + if(!strcmp(nm,PEM_STRING_X509_OLD) && + !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; + + /* Some CAs use PKCS#7 with CERTIFICATE headers */ + if(!strcmp(nm, PEM_STRING_X509) && + !strcmp(name, PEM_STRING_PKCS7)) return 1; + + return 0; +} + +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, + pem_password_cb *cb, void *u) { EVP_CIPHER_INFO cipher; char *nm=NULL,*header=NULL; - unsigned char *p=NULL,*data=NULL; + unsigned char *data=NULL; long len; - char *ret=NULL; + int ret = 0; for (;;) { - if (!PEM_read_bio(bp,&nm,&header,&data,&len)) return(NULL); - if ( (strcmp(nm,name) == 0) || - ((strcmp(nm,PEM_STRING_RSA) == 0) && - (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) || - ((strcmp(nm,PEM_STRING_DSA) == 0) && - (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) || - ((strcmp(nm,PEM_STRING_X509_OLD) == 0) && - (strcmp(name,PEM_STRING_X509) == 0)) || - ((strcmp(nm,PEM_STRING_X509_REQ_OLD) == 0) && - (strcmp(name,PEM_STRING_X509_REQ) == 0)) - ) - break; - Free(nm); - Free(header); - Free(data); + if (!PEM_read_bio(bp,&nm,&header,&data,&len)) { + if(ERR_GET_REASON(ERR_peek_error()) == + PEM_R_NO_START_LINE) + ERR_add_error_data(2, "Expecting: ", name); + return 0; } - if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err; - if (!PEM_do_header(&cipher,data,&len,cb)) goto err; - p=data; - if (strcmp(name,PEM_STRING_EVP_PKEY) == 0) - { - if (strcmp(nm,PEM_STRING_RSA) == 0) - ret=d2i(EVP_PKEY_RSA,x,&p,len); - else if (strcmp(nm,PEM_STRING_DSA) == 0) - ret=d2i(EVP_PKEY_DSA,x,&p,len); + if(check_pem(nm, name)) break; + OPENSSL_free(nm); + OPENSSL_free(header); + OPENSSL_free(data); } - else - ret=d2i(x,&p,len); - if (ret == NULL) - PEMerr(PEM_F_PEM_ASN1_READ_BIO,ERR_R_ASN1_LIB); + if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err; + if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err; + + *pdata = data; + *plen = len; + + if (pnm) + *pnm = nm; + + ret = 1; + err: - Free(nm); - Free(header); - Free(data); - return(ret); + if (!pnm) OPENSSL_free(nm); + OPENSSL_free(header); + if (!ret) OPENSSL_free(data); + return ret; } -#ifndef NO_FP_API -int PEM_ASN1_write(i2d,name,fp, x, enc, kstr, klen, callback) -int (*i2d)(); -char *name; -FILE *fp; -char *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*callback)(); +#ifndef OPENSSL_NO_FP_API +int PEM_ASN1_write(int (*i2d)(), const char *name, FILE *fp, char *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *callback, void *u) { BIO *b; int ret; @@ -261,27 +269,20 @@ int (*callback)(); return(0); } BIO_set_fp(b,fp,BIO_NOCLOSE); - ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback); + ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u); BIO_free(b); return(ret); } #endif -int PEM_ASN1_write_bio(i2d,name,bp, x, enc, kstr, klen, callback) -int (*i2d)(); -char *name; -BIO *bp; -char *x; -EVP_CIPHER *enc; -unsigned char *kstr; -int klen; -int (*callback)(); +int PEM_ASN1_write_bio(int (*i2d)(), const char *name, BIO *bp, char *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *callback, void *u) { EVP_CIPHER_CTX ctx; int dsize=0,i,j,ret=0; unsigned char *p,*data=NULL; - char *objstr=NULL; -#define PEM_BUFSIZE 1024 + const char *objstr=NULL; char buf[PEM_BUFSIZE]; unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; @@ -303,7 +304,7 @@ int (*callback)(); goto err; } /* dzise + 8 bytes are needed */ - data=(unsigned char *)Malloc((unsigned int)dsize+20); + data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20); if (data == NULL) { PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE); @@ -317,18 +318,23 @@ int (*callback)(); if (kstr == NULL) { if (callback == NULL) - klen=def_callback(buf,PEM_BUFSIZE,1); + klen=PEM_def_callback(buf,PEM_BUFSIZE,1,u); else - klen=(*callback)(buf,PEM_BUFSIZE,1); + klen=(*callback)(buf,PEM_BUFSIZE,1,u); if (klen <= 0) { PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY); goto err; } +#ifdef CHARSET_EBCDIC + /* Convert the pass phrase from EBCDIC */ + ebcdic2ascii(buf, buf, klen); +#endif kstr=(unsigned char *)buf; } - RAND_seed(data,i);/* put in the RSA key. */ - RAND_bytes(iv,8); /* Generate a salt */ + RAND_add(data,i,0);/* put in the RSA key. */ + if (RAND_pseudo_bytes(iv,enc->iv_len) < 0) /* Generate a salt */ + goto err; /* The 'iv' is used as the iv and as a salt. It is * NOT taken from the BytesToKey function */ EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL); @@ -337,12 +343,14 @@ int (*callback)(); buf[0]='\0'; PEM_proc_type(buf,PEM_TYPE_ENCRYPTED); - PEM_dek_info(buf,objstr,8,(char *)iv); + PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv); /* k=strlen(buf); */ - - EVP_EncryptInit(&ctx,enc,key,iv); + + EVP_CIPHER_CTX_init(&ctx); + EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv); EVP_EncryptUpdate(&ctx,data,&j,data,i); - EVP_EncryptFinal(&ctx,&(data[j]),&i); + EVP_EncryptFinal_ex(&ctx,&(data[j]),&i); + EVP_CIPHER_CTX_cleanup(&ctx); i+=j; ret=1; } @@ -359,15 +367,12 @@ err: memset((char *)&ctx,0,sizeof(ctx)); memset(buf,0,PEM_BUFSIZE); memset(data,0,(unsigned int)dsize); - Free(data); + OPENSSL_free(data); return(ret); } -int PEM_do_header(cipher, data, plen, callback) -EVP_CIPHER_INFO *cipher; -unsigned char *data; -long *plen; -int (*callback)(); +int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, + pem_password_cb *callback,void *u) { int i,j,o,klen; long len; @@ -379,21 +384,27 @@ int (*callback)(); if (cipher->cipher == NULL) return(1); if (callback == NULL) - klen=def_callback(buf,PEM_BUFSIZE,0); + klen=PEM_def_callback(buf,PEM_BUFSIZE,0,u); else - klen=callback(buf,PEM_BUFSIZE,0); + klen=callback(buf,PEM_BUFSIZE,0,u); if (klen <= 0) { PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ); return(0); } +#ifdef CHARSET_EBCDIC + /* Convert the pass phrase from EBCDIC */ + ebcdic2ascii(buf, buf, klen); +#endif + EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]), (unsigned char *)buf,klen,1,key,NULL); j=(int)len; - EVP_DecryptInit(&ctx,cipher->cipher,key,&(cipher->iv[0])); + EVP_CIPHER_CTX_init(&ctx); + EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0])); EVP_DecryptUpdate(&ctx,data,&i,data,j); - o=EVP_DecryptFinal(&ctx,&(data[i]),&j); + o=EVP_DecryptFinal_ex(&ctx,&(data[i]),&j); EVP_CIPHER_CTX_cleanup(&ctx); memset((char *)buf,0,sizeof(buf)); memset((char *)key,0,sizeof(key)); @@ -407,12 +418,10 @@ int (*callback)(); return(1); } -int PEM_get_EVP_CIPHER_INFO(header,cipher) -char *header; -EVP_CIPHER_INFO *cipher; +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) { int o; - EVP_CIPHER *enc=NULL; + const EVP_CIPHER *enc=NULL; char *p,c; cipher->cipher=NULL; @@ -438,9 +447,15 @@ EVP_CIPHER_INFO *cipher; for (;;) { c= *header; +#ifndef CHARSET_EBCDIC if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') || ((c >= '0') && (c <= '9')))) break; +#else + if (!( isupper(c) || (c == '-') || + isdigit(c))) + break; +#endif header++; } *header='\0'; @@ -454,14 +469,12 @@ EVP_CIPHER_INFO *cipher; PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION); return(0); } - if (!load_iv((unsigned char **)&header,&(cipher->iv[0]),8)) return(0); + if (!load_iv((unsigned char **)&header,&(cipher->iv[0]),enc->iv_len)) return(0); return(1); } -static int load_iv(fromp,to,num) -unsigned char **fromp,*to; -int num; +static int load_iv(unsigned char **fromp, unsigned char *to, int num) { int v,i; unsigned char *from; @@ -490,13 +503,9 @@ int num; return(1); } -#ifndef NO_FP_API -int PEM_write(fp, name, header, data,len) -FILE *fp; -char *name; -char *header; -unsigned char *data; -long len; +#ifndef OPENSSL_NO_FP_API +int PEM_write(FILE *fp, char *name, char *header, unsigned char *data, + long len) { BIO *b; int ret; @@ -513,12 +522,8 @@ long len; } #endif -int PEM_write_bio(bp, name, header, data,len) -BIO *bp; -char *name; -char *header; -unsigned char *data; -long len; +int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data, + long len) { int nlen,n,i,j,outl; unsigned char *buf; @@ -541,7 +546,7 @@ long len; goto err; } - buf=(unsigned char *)Malloc(PEM_BUFSIZE*8); + buf=(unsigned char *)OPENSSL_malloc(PEM_BUFSIZE*8); if (buf == NULL) { reason=ERR_R_MALLOC_FAILURE; @@ -561,7 +566,7 @@ long len; } EVP_EncodeFinal(&ctx,buf,&outl); if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err; - Free(buf); + OPENSSL_free(buf); if ( (BIO_write(bp,"-----END ",9) != 9) || (BIO_write(bp,name,nlen) != nlen) || (BIO_write(bp,"-----\n",6) != 6)) @@ -572,13 +577,9 @@ err: return(0); } -#ifndef NO_FP_API -int PEM_read(fp, name, header, data,len) -FILE *fp; -char **name; -char **header; -unsigned char **data; -long *len; +#ifndef OPENSSL_NO_FP_API +int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, + long *len) { BIO *b; int ret; @@ -595,12 +596,8 @@ long *len; } #endif -int PEM_read_bio(bp, name, header, data, len) -BIO *bp; -char **name; -char **header; -unsigned char **data; -long *len; +int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, + long *len) { EVP_ENCODE_CTX ctx; int end=0,i,k,bl=0,hl=0,nohead=0; @@ -643,7 +640,7 @@ long *len; PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } - strncpy(nameB->data,&(buf[11]),(unsigned int)i-6); + memcpy(nameB->data,&(buf[11]),i-6); nameB->data[i-6]='\0'; break; } @@ -668,7 +665,7 @@ long *len; nohead=1; break; } - strncpy(&(headerB->data[hl]),buf,(unsigned int)i); + memcpy(&(headerB->data[hl]),buf,i); headerB->data[hl+i]='\0'; hl+=i; } @@ -696,7 +693,7 @@ long *len; PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } - strncpy(&(dataB->data[bl]),buf,(unsigned int)i); + memcpy(&(dataB->data[bl]),buf,i); dataB->data[bl+i]='\0'; bl+=i; if (end) @@ -721,7 +718,7 @@ long *len; } i=strlen(nameB->data); if ( (strncmp(buf,"-----END ",9) != 0) || - (strncmp(nameB->data,&(buf[9]),(unsigned int)i) != 0) || + (strncmp(nameB->data,&(buf[9]),i) != 0) || (strncmp(&(buf[9+i]),"-----\n",6) != 0)) { PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE); @@ -750,9 +747,9 @@ long *len; *header=headerB->data; *data=(unsigned char *)dataB->data; *len=bl; - Free(nameB); - Free(headerB); - Free(dataB); + OPENSSL_free(nameB); + OPENSSL_free(headerB); + OPENSSL_free(dataB); return(1); err: BUF_MEM_free(nameB); diff --git a/src/lib/libcrypto/pem/pem_seal.c b/src/lib/libcrypto/pem/pem_seal.c index b4b36df453..ae463a301d 100644 --- a/src/lib/libcrypto/pem/pem_seal.c +++ b/src/lib/libcrypto/pem/pem_seal.c @@ -56,23 +56,18 @@ * [including the GNU Public Licence.] */ +#ifndef OPENSSL_NO_RSA #include #include "cryptlib.h" -#include "evp.h" -#include "rand.h" -#include "objects.h" -#include "x509.h" -#include "pem.h" - -int PEM_SealInit(ctx,type,md_type,ek,ekl,iv,pubk,npubk) -PEM_ENCODE_SEAL_CTX *ctx; -EVP_CIPHER *type; -EVP_MD *md_type; -unsigned char **ek; -int *ekl; -unsigned char *iv; -EVP_PKEY **pubk; -int npubk; +#include +#include +#include +#include +#include + +int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, + unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, + int npubk) { unsigned char key[EVP_MAX_KEY_LENGTH]; int ret= -1; @@ -89,17 +84,20 @@ int npubk; j=RSA_size(pubk[i]->pkey.rsa); if (j > max) max=j; } - s=(char *)Malloc(max*2); + s=(char *)OPENSSL_malloc(max*2); if (s == NULL) { PEMerr(PEM_F_PEM_SEALINIT,ERR_R_MALLOC_FAILURE); goto err; } - EVP_EncodeInit(&(ctx->encode)); - EVP_SignInit(&(ctx->md),md_type); + EVP_EncodeInit(&ctx->encode); + + EVP_MD_CTX_init(&ctx->md); + EVP_SignInit(&ctx->md,md_type); - ret=EVP_SealInit(&(ctx->cipher),type,ek,ekl,iv,pubk,npubk); + EVP_CIPHER_CTX_init(&ctx->cipher); + ret=EVP_SealInit(&ctx->cipher,type,ek,ekl,iv,pubk,npubk); if (!ret) goto err; /* base64 encode the keys */ @@ -113,23 +111,19 @@ int npubk; ret=npubk; err: - if (s != NULL) Free(s); + if (s != NULL) OPENSSL_free(s); memset(key,0,EVP_MAX_KEY_LENGTH); return(ret); } -void PEM_SealUpdate(ctx,out,outl,in,inl) -PEM_ENCODE_SEAL_CTX *ctx; -unsigned char *out; -int *outl; -unsigned char *in; -int inl; +void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl, + unsigned char *in, int inl) { unsigned char buffer[1600]; int i,j; *outl=0; - EVP_SignUpdate(&(ctx->md),in,inl); + EVP_SignUpdate(&ctx->md,in,inl); for (;;) { if (inl <= 0) break; @@ -137,8 +131,8 @@ int inl; i=1200; else i=inl; - EVP_EncryptUpdate(&(ctx->cipher),buffer,&j,in,i); - EVP_EncodeUpdate(&(ctx->encode),out,&j,buffer,j); + EVP_EncryptUpdate(&ctx->cipher,buffer,&j,in,i); + EVP_EncodeUpdate(&ctx->encode,out,&j,buffer,j); *outl+=j; out+=j; in+=i; @@ -146,13 +140,8 @@ int inl; } } -int PEM_SealFinal(ctx,sig,sigl,out,outl,priv) -PEM_ENCODE_SEAL_CTX *ctx; -unsigned char *sig; -int *sigl; -unsigned char *out; -int *outl; -EVP_PKEY *priv; +int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig, int *sigl, + unsigned char *out, int *outl, EVP_PKEY *priv) { unsigned char *s=NULL; int ret=0,j; @@ -165,27 +154,34 @@ EVP_PKEY *priv; } i=RSA_size(priv->pkey.rsa); if (i < 100) i=100; - s=(unsigned char *)Malloc(i*2); + s=(unsigned char *)OPENSSL_malloc(i*2); if (s == NULL) { PEMerr(PEM_F_PEM_SEALFINAL,ERR_R_MALLOC_FAILURE); goto err; } - EVP_EncryptFinal(&(ctx->cipher),s,(int *)&i); - EVP_EncodeUpdate(&(ctx->encode),out,&j,s,i); + EVP_EncryptFinal_ex(&ctx->cipher,s,(int *)&i); + EVP_EncodeUpdate(&ctx->encode,out,&j,s,i); *outl=j; out+=j; - EVP_EncodeFinal(&(ctx->encode),out,&j); + EVP_EncodeFinal(&ctx->encode,out,&j); *outl+=j; - if (!EVP_SignFinal(&(ctx->md),s,&i,priv)) goto err; + if (!EVP_SignFinal(&ctx->md,s,&i,priv)) goto err; *sigl=EVP_EncodeBlock(sig,s,i); ret=1; err: - memset((char *)&(ctx->md),0,sizeof(ctx->md)); - memset((char *)&(ctx->cipher),0,sizeof(ctx->cipher)); - if (s != NULL) Free(s); + EVP_MD_CTX_cleanup(&ctx->md); + EVP_CIPHER_CTX_cleanup(&ctx->cipher); + if (s != NULL) OPENSSL_free(s); return(ret); } +#else /* !OPENSSL_NO_RSA */ + +# if PEDANTIC +static void *dummy=&dummy; +# endif + +#endif diff --git a/src/lib/libcrypto/pem/pem_sign.c b/src/lib/libcrypto/pem/pem_sign.c index d56f9f9e14..c3b9808cb2 100644 --- a/src/lib/libcrypto/pem/pem_sign.c +++ b/src/lib/libcrypto/pem/pem_sign.c @@ -58,38 +58,31 @@ #include #include "cryptlib.h" -#include "rand.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" -#include "pem.h" +#include +#include +#include +#include +#include -void PEM_SignInit(ctx,type) -EVP_MD_CTX *ctx; -EVP_MD *type; +void PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type) { - EVP_DigestInit(ctx,type); + EVP_DigestInit_ex(ctx, type, NULL); } -void PEM_SignUpdate(ctx,data,count) -EVP_MD_CTX *ctx; -unsigned char *data; -unsigned int count; +void PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *data, + unsigned int count) { EVP_DigestUpdate(ctx,data,count); } -int PEM_SignFinal(ctx,sigret,siglen,pkey) -EVP_MD_CTX *ctx; -unsigned char *sigret; -unsigned int *siglen; -EVP_PKEY *pkey; +int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, + EVP_PKEY *pkey) { unsigned char *m; int i,ret=0; unsigned int m_len; - m=(unsigned char *)Malloc(EVP_PKEY_size(pkey)+2); + m=(unsigned char *)OPENSSL_malloc(EVP_PKEY_size(pkey)+2); if (m == NULL) { PEMerr(PEM_F_PEM_SIGNFINAL,ERR_R_MALLOC_FAILURE); @@ -103,7 +96,7 @@ EVP_PKEY *pkey; ret=1; err: /* ctx has been zeroed by EVP_SignFinal() */ - if (m != NULL) Free(m); + if (m != NULL) OPENSSL_free(m); return(ret); } diff --git a/src/lib/libcrypto/perlasm/cbc.pl b/src/lib/libcrypto/perlasm/cbc.pl index 2789305790..0145c4f0cc 100644 --- a/src/lib/libcrypto/perlasm/cbc.pl +++ b/src/lib/libcrypto/perlasm/cbc.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) # des_cblock (*input); diff --git a/src/lib/libcrypto/perlasm/x86asm.pl b/src/lib/libcrypto/perlasm/x86asm.pl index 6a9156ae9a..81c6e64e87 100644 --- a/src/lib/libcrypto/perlasm/x86asm.pl +++ b/src/lib/libcrypto/perlasm/x86asm.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # require 'x86asm.pl'; # &asm_init("cpp","des-586.pl"); @@ -15,20 +15,24 @@ sub main'asm_finish sub main'asm_init { - ($type,$fn)=@_; + ($type,$fn,$i386)=@_; $filename=$fn; - $cpp=$sol=$aout=$win32=0; + $cpp=$sol=$aout=$win32=$gaswin=0; if ( ($type eq "elf")) { require "x86unix.pl"; } elsif ( ($type eq "a.out")) { $aout=1; require "x86unix.pl"; } + elsif ( ($type eq "gaswin")) + { $gaswin=1; $aout=1; require "x86unix.pl"; } elsif ( ($type eq "sol")) { $sol=1; require "x86unix.pl"; } elsif ( ($type eq "cpp")) { $cpp=1; require "x86unix.pl"; } elsif ( ($type eq "win32")) { $win32=1; require "x86ms.pl"; } + elsif ( ($type eq "win32n")) + { $win32=1; require "x86nasm.pl"; } else { print STDERR <<"EOF"; @@ -38,6 +42,7 @@ Pick one target type from sol - x86 solaris cpp - format so x86unix.cpp can be used win32 - Windows 95/Windows NT + win32n - Windows 95/Windows NT NASM format EOF exit(1); } @@ -47,7 +52,7 @@ EOF &comment("Don't even think of reading this code"); &comment("It was automatically generated by $filename"); &comment("Which is a perl program used to generate the x86 assember for"); -&comment("any of elf, a.out, BSDI,Win32, or Solaris"); +&comment("any of elf, a.out, BSDI, Win32, gaswin (for GNU as on Win32) or Solaris"); &comment("eric "); &comment(""); @@ -75,7 +80,7 @@ sub asm_finish_cpp #define TYPE(a,b) .type a,b #define SIZE(a,b) .size a,b -#if defined(OUT) || defined(BSDI) +#if defined(OUT) || (defined(BSDI) && !defined(ELF)) $tmp #endif @@ -84,7 +89,7 @@ $tmp #define ALIGN 4 #endif -#ifdef BSDI +#if defined(BSDI) && !defined(ELF) #define OK 1 #define ALIGN 4 #undef SIZE diff --git a/src/lib/libcrypto/pkcs12/p12_add.c b/src/lib/libcrypto/pkcs12/p12_add.c index ae3d9de3b4..1909f28506 100644 --- a/src/lib/libcrypto/pkcs12/p12_add.c +++ b/src/lib/libcrypto/pkcs12/p12_add.c @@ -62,21 +62,21 @@ /* Pack an object into an OCTET STRING and turn into a safebag */ -PKCS12_SAFEBAG *PKCS12_pack_safebag (char *obj, int (*i2d)(), int nid1, +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, int nid1, int nid2) { PKCS12_BAGS *bag; PKCS12_SAFEBAG *safebag; - if (!(bag = PKCS12_BAGS_new ())) { + if (!(bag = PKCS12_BAGS_new())) { PKCS12err(PKCS12_F_PKCS12_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); return NULL; } bag->type = OBJ_nid2obj(nid1); - if (!ASN1_pack_string(obj, i2d, &bag->value.octet)) { + if (!ASN1_item_pack(obj, it, &bag->value.octet)) { PKCS12err(PKCS12_F_PKCS12_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); return NULL; } - if (!(safebag = PKCS12_SAFEBAG_new ())) { + if (!(safebag = PKCS12_SAFEBAG_new())) { PKCS12err(PKCS12_F_PKCS12_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE); return NULL; } @@ -87,7 +87,7 @@ PKCS12_SAFEBAG *PKCS12_pack_safebag (char *obj, int (*i2d)(), int nid1, /* Turn PKCS8 object into a keybag */ -PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG (PKCS8_PRIV_KEY_INFO *p8) +PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8) { PKCS12_SAFEBAG *bag; if (!(bag = PKCS12_SAFEBAG_new())) { @@ -101,14 +101,14 @@ PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG (PKCS8_PRIV_KEY_INFO *p8) /* Turn PKCS8 object into a shrouded keybag */ -PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG (int pbe_nid, const char *pass, +PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8) { PKCS12_SAFEBAG *bag; /* Set up the safe bag */ - if (!(bag = PKCS12_SAFEBAG_new ())) { + if (!(bag = PKCS12_SAFEBAG_new())) { PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE); return NULL; } @@ -125,7 +125,7 @@ PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG (int pbe_nid, const char *pass, } /* Turn a stack of SAFEBAGS into a PKCS#7 data Contentinfo */ -PKCS7 *PKCS12_pack_p7data (STACK *sk) +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk) { PKCS7 *p7; if (!(p7 = PKCS7_new())) { @@ -133,23 +133,30 @@ PKCS7 *PKCS12_pack_p7data (STACK *sk) return NULL; } p7->type = OBJ_nid2obj(NID_pkcs7_data); - if (!(p7->d.data = ASN1_OCTET_STRING_new())) { + if (!(p7->d.data = M_ASN1_OCTET_STRING_new())) { PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE); return NULL; } - if (!ASN1_seq_pack(sk, i2d_PKCS12_SAFEBAG, &p7->d.data->data, - &p7->d.data->length)) { + if (!ASN1_item_pack(sk, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), &p7->d.data)) { PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, PKCS12_R_CANT_PACK_STRUCTURE); return NULL; } return p7; } +/* Unpack SAFEBAGS from PKCS#7 data ContentInfo */ +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7) +{ + if(!PKCS7_type_is_data(p7)) return NULL; + return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS)); +} + /* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */ -PKCS7 *PKCS12_pack_p7encdata (int pbe_nid, const char *pass, int passlen, - unsigned char *salt, int saltlen, int iter, STACK *bags) +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + STACK_OF(PKCS12_SAFEBAG) *bags) { PKCS7 *p7; X509_ALGOR *pbe; @@ -157,23 +164,21 @@ PKCS7 *PKCS12_pack_p7encdata (int pbe_nid, const char *pass, int passlen, PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); return NULL; } - p7->type = OBJ_nid2obj(NID_pkcs7_encrypted); - if (!(p7->d.encrypted = PKCS7_ENCRYPT_new ())) { - PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); + if(!PKCS7_set_type(p7, NID_pkcs7_encrypted)) { + PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, + PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE); return NULL; } - ASN1_INTEGER_set (p7->d.encrypted->version, 0); - p7->d.encrypted->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_data); - if (!(pbe = PKCS5_pbe_set (pbe_nid, iter, salt, saltlen))) { + if (!(pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen))) { PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE); return NULL; } X509_ALGOR_free(p7->d.encrypted->enc_data->algorithm); p7->d.encrypted->enc_data->algorithm = pbe; - ASN1_OCTET_STRING_free(p7->d.encrypted->enc_data->enc_data); + M_ASN1_OCTET_STRING_free(p7->d.encrypted->enc_data->enc_data); if (!(p7->d.encrypted->enc_data->enc_data = - PKCS12_i2d_encrypt (pbe, i2d_PKCS12_SAFEBAG, pass, passlen, - (char *)bags, 1))) { + PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass, passlen, + bags, 1))) { PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, PKCS12_R_ENCRYPT_ERROR); return NULL; } @@ -181,34 +186,30 @@ PKCS7 *PKCS12_pack_p7encdata (int pbe_nid, const char *pass, int passlen, return p7; } -X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, - const char *pass, int passlen, - unsigned char *salt, int saltlen, int iter, - PKCS8_PRIV_KEY_INFO *p8inf) +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, int passlen) { - X509_SIG *p8; - X509_ALGOR *pbe; + if(!PKCS7_type_is_encrypted(p7)) return NULL; + return PKCS12_item_decrypt_d2i(p7->d.encrypted->enc_data->algorithm, + ASN1_ITEM_rptr(PKCS12_SAFEBAGS), + pass, passlen, + p7->d.encrypted->enc_data->enc_data, 1); +} - if (!(p8 = X509_SIG_new())) { - PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_MALLOC_FAILURE); - return NULL; - } +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag, const char *pass, + int passlen) +{ + return PKCS8_decrypt(bag->value.shkeybag, pass, passlen); +} - if(pbe_nid == -1) pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen); - else pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen); - if(!pbe) { - PKCS12err(PKCS12_F_PKCS8_ENCRYPT, ERR_R_MALLOC_FAILURE); - return NULL; - } - X509_ALGOR_free(p8->algor); - p8->algor = pbe; - ASN1_OCTET_STRING_free(p8->digest); - if (!(p8->digest = - PKCS12_i2d_encrypt (pbe, i2d_PKCS8_PRIV_KEY_INFO, pass, passlen, - (char *)p8inf, 0))) { - PKCS12err(PKCS12_F_PKCS8_ENCRYPT, PKCS12_R_ENCRYPT_ERROR); - return NULL; - } +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes) +{ + if(ASN1_item_pack(safes, ASN1_ITEM_rptr(PKCS12_AUTHSAFES), + &p12->authsafes->d.data)) + return 1; + return 0; +} - return p8; +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(PKCS12 *p12) +{ + return ASN1_item_unpack(p12->authsafes->d.data, ASN1_ITEM_rptr(PKCS12_AUTHSAFES)); } diff --git a/src/lib/libcrypto/pkcs12/p12_attr.c b/src/lib/libcrypto/pkcs12/p12_attr.c index 31c9782b77..026cf3826a 100644 --- a/src/lib/libcrypto/pkcs12/p12_attr.c +++ b/src/lib/libcrypto/pkcs12/p12_attr.c @@ -62,156 +62,63 @@ /* Add a local keyid to a safebag */ -int PKCS12_add_localkeyid (PKCS12_SAFEBAG *bag, unsigned char *name, +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen) { - X509_ATTRIBUTE *attrib; - ASN1_BMPSTRING *oct; - ASN1_TYPE *keyid; - if (!(keyid = ASN1_TYPE_new ())) { - PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); - return 0; - } - keyid->type = V_ASN1_OCTET_STRING; - if (!(oct = ASN1_OCTET_STRING_new())) { - PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); - return 0; - } - if (!ASN1_OCTET_STRING_set(oct, name, namelen)) { - PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); - return 0; - } - keyid->value.octet_string = oct; - if (!(attrib = X509_ATTRIBUTE_new ())) { - PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); - return 0; - } - attrib->object = OBJ_nid2obj(NID_localKeyID); - if (!(attrib->value.set = sk_ASN1_TYPE_new(NULL))) { - PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); - return 0; - } - sk_ASN1_TYPE_push (attrib->value.set,keyid); - attrib->set = 1; - if (!bag->attrib && !(bag->attrib = sk_X509_ATTRIBUTE_new (NULL))) { - PKCS12err(PKCS12_F_PKCS12_ADD_LOCALKEYID, ERR_R_MALLOC_FAILURE); + if (X509at_add1_attr_by_NID(&bag->attrib, NID_localKeyID, + V_ASN1_OCTET_STRING, name, namelen)) + return 1; + else return 0; - } - sk_X509_ATTRIBUTE_push (bag->attrib, attrib); - return 1; } /* Add key usage to PKCS#8 structure */ -int PKCS8_add_keyusage (PKCS8_PRIV_KEY_INFO *p8, int usage) +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage) { - X509_ATTRIBUTE *attrib; - ASN1_BIT_STRING *bstr; - ASN1_TYPE *keyid; unsigned char us_val; us_val = (unsigned char) usage; - if (!(keyid = ASN1_TYPE_new ())) { - PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); - return 0; - } - keyid->type = V_ASN1_BIT_STRING; - if (!(bstr = ASN1_BIT_STRING_new())) { - PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); - return 0; - } - if (!ASN1_BIT_STRING_set(bstr, &us_val, 1)) { - PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); - return 0; - } - keyid->value.bit_string = bstr; - if (!(attrib = X509_ATTRIBUTE_new ())) { - PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); - return 0; - } - attrib->object = OBJ_nid2obj(NID_key_usage); - if (!(attrib->value.set = sk_ASN1_TYPE_new(NULL))) { - PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); + if (X509at_add1_attr_by_NID(&p8->attributes, NID_key_usage, + V_ASN1_BIT_STRING, &us_val, 1)) + return 1; + else return 0; - } - sk_ASN1_TYPE_push (attrib->value.set,keyid); - attrib->set = 1; - if (!p8->attributes - && !(p8->attributes = sk_X509_ATTRIBUTE_new (NULL))) { - PKCS12err(PKCS12_F_PKCS8_ADD_KEYUSAGE, ERR_R_MALLOC_FAILURE); - return 0; - } - sk_X509_ATTRIBUTE_push (p8->attributes, attrib); - return 1; } /* Add a friendlyname to a safebag */ -int PKCS12_add_friendlyname_asc (PKCS12_SAFEBAG *bag, const char *name, +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, int namelen) { - unsigned char *uniname; - int ret, unilen; - if (!asc2uni(name, &uniname, &unilen)) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC, - ERR_R_MALLOC_FAILURE); + if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, + MBSTRING_ASC, (unsigned char *)name, namelen)) + return 1; + else return 0; - } - ret = PKCS12_add_friendlyname_uni (bag, uniname, unilen); - Free(uniname); - return ret; } - -int PKCS12_add_friendlyname_uni (PKCS12_SAFEBAG *bag, + +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name, int namelen) { - X509_ATTRIBUTE *attrib; - ASN1_BMPSTRING *bmp; - ASN1_TYPE *fname; - /* Zap ending double null if included */ - if(!name[namelen - 1] && !name[namelen - 2]) namelen -= 2; - if (!(fname = ASN1_TYPE_new ())) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, - ERR_R_MALLOC_FAILURE); - return 0; - } - fname->type = V_ASN1_BMPSTRING; - if (!(bmp = ASN1_BMPSTRING_new())) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, - ERR_R_MALLOC_FAILURE); - return 0; - } - if (!(bmp->data = Malloc (namelen))) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, - ERR_R_MALLOC_FAILURE); + if (X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, + MBSTRING_BMP, name, namelen)) + return 1; + else return 0; - } - memcpy (bmp->data, name, namelen); - bmp->length = namelen; - fname->value.bmpstring = bmp; - if (!(attrib = X509_ATTRIBUTE_new ())) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, - ERR_R_MALLOC_FAILURE); - return 0; - } - attrib->object = OBJ_nid2obj(NID_friendlyName); - if (!(attrib->value.set = sk_ASN1_TYPE_new(NULL))) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME, - ERR_R_MALLOC_FAILURE); - return 0; - } - sk_ASN1_TYPE_push (attrib->value.set,fname); - attrib->set = 1; - if (!bag->attrib && !(bag->attrib = sk_X509_ATTRIBUTE_new (NULL))) { - PKCS12err(PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI, - ERR_R_MALLOC_FAILURE); +} + +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen) +{ + if (X509at_add1_attr_by_NID(&bag->attrib, NID_ms_csp_name, + MBSTRING_ASC, (unsigned char *)name, namelen)) + return 1; + else return 0; - } - sk_X509_ATTRIBUTE_push (bag->attrib, attrib); - return PKCS12_OK; } -ASN1_TYPE *PKCS12_get_attr_gen (STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid) +ASN1_TYPE *PKCS12_get_attr_gen(STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid) { X509_ATTRIBUTE *attrib; int i; diff --git a/src/lib/libcrypto/pkcs12/p12_crpt.c b/src/lib/libcrypto/pkcs12/p12_crpt.c index 6de6f8128f..97be6a5fb5 100644 --- a/src/lib/libcrypto/pkcs12/p12_crpt.c +++ b/src/lib/libcrypto/pkcs12/p12_crpt.c @@ -64,17 +64,19 @@ void PKCS12_PBE_add(void) { -#ifndef NO_RC4 +#ifndef OPENSSL_NO_RC4 EVP_PBE_alg_add(NID_pbe_WithSHA1And128BitRC4, EVP_rc4(), EVP_sha1(), PKCS12_PBE_keyivgen); EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC4, EVP_rc4_40(), EVP_sha1(), PKCS12_PBE_keyivgen); #endif +#ifndef OPENSSL_NO_DES EVP_PBE_alg_add(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); EVP_PBE_alg_add(NID_pbe_WithSHA1And2_Key_TripleDES_CBC, EVP_des_ede_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); -#ifndef NO_RC2 +#endif +#ifndef OPENSSL_NO_RC2 EVP_PBE_alg_add(NID_pbe_WithSHA1And128BitRC2_CBC, EVP_rc2_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc(), @@ -83,7 +85,7 @@ EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc(), } int PKCS12_PBE_keyivgen (EVP_CIPHER_CTX *ctx, const char *pass, int passlen, - ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md, int en_de) + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de) { PBEPARAM *pbe; int saltlen, iter; @@ -115,7 +117,7 @@ int PKCS12_PBE_keyivgen (EVP_CIPHER_CTX *ctx, const char *pass, int passlen, return 0; } PBEPARAM_free(pbe); - EVP_CipherInit(ctx, cipher, key, iv, en_de); + EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de); memset(key, 0, EVP_MAX_KEY_LENGTH); memset(iv, 0, EVP_MAX_IV_LENGTH); return 1; diff --git a/src/lib/libcrypto/pkcs12/p12_crt.c b/src/lib/libcrypto/pkcs12/p12_crt.c index 56d88b0759..4c36c643ce 100644 --- a/src/lib/libcrypto/pkcs12/p12_crt.c +++ b/src/lib/libcrypto/pkcs12/p12_crt.c @@ -61,11 +61,12 @@ #include PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, - STACK *ca, int nid_key, int nid_cert, int iter, int mac_iter, + STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype) { PKCS12 *p12; - STACK *bags, *safes; + STACK_OF(PKCS12_SAFEBAG) *bags; + STACK_OF(PKCS7) *safes; PKCS12_SAFEBAG *bag; PKCS8_PRIV_KEY_INFO *p8; PKCS7 *authsafe; @@ -85,28 +86,30 @@ PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, return NULL; } - if(!(bags = sk_new (NULL))) { + if(!X509_check_private_key(cert, pkey)) return NULL; + + if(!(bags = sk_PKCS12_SAFEBAG_new_null ())) { PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); return NULL; } /* Add user certificate */ - if(!(bag = M_PKCS12_x5092certbag(cert))) return NULL; + if(!(bag = PKCS12_x5092certbag(cert))) return NULL; if(name && !PKCS12_add_friendlyname(bag, name, -1)) return NULL; X509_digest(cert, EVP_sha1(), keyid, &keyidlen); if(!PKCS12_add_localkeyid(bag, keyid, keyidlen)) return NULL; - if(!sk_push(bags, (char *)bag)) { + if(!sk_PKCS12_SAFEBAG_push(bags, bag)) { PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); return NULL; } /* Add all other certificates */ if(ca) { - for(i = 0; i < sk_num(ca); i++) { - tcert = (X509 *)sk_value(ca, i); - if(!(bag = M_PKCS12_x5092certbag(tcert))) return NULL; - if(!sk_push(bags, (char *)bag)) { + for(i = 0; i < sk_X509_num(ca); i++) { + tcert = sk_X509_value(ca, i); + if(!(bag = PKCS12_x5092certbag(tcert))) return NULL; + if(!sk_PKCS12_SAFEBAG_push(bags, bag)) { PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); return NULL; } @@ -116,11 +119,12 @@ PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, /* Turn certbags into encrypted authsafe */ authsafe = PKCS12_pack_p7encdata (nid_cert, pass, -1, NULL, 0, iter, bags); - sk_pop_free(bags, PKCS12_SAFEBAG_free); + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if (!authsafe) return NULL; - if(!(safes = sk_new (NULL)) || !sk_push(safes, (char *)authsafe)) { + if(!(safes = sk_PKCS7_new_null ()) + || !sk_PKCS7_push(safes, authsafe)) { PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); return NULL; } @@ -133,23 +137,24 @@ PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, PKCS8_PRIV_KEY_INFO_free(p8); if (name && !PKCS12_add_friendlyname (bag, name, -1)) return NULL; if(!PKCS12_add_localkeyid (bag, keyid, keyidlen)) return NULL; - if(!(bags = sk_new(NULL)) || !sk_push (bags, (char *)bag)) { + if(!(bags = sk_PKCS12_SAFEBAG_new_null()) + || !sk_PKCS12_SAFEBAG_push (bags, bag)) { PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); return NULL; } /* Turn it into unencrypted safe bag */ if(!(authsafe = PKCS12_pack_p7data (bags))) return NULL; - sk_pop_free(bags, PKCS12_SAFEBAG_free); - if(!sk_push(safes, (char *)authsafe)) { + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + if(!sk_PKCS7_push(safes, authsafe)) { PKCS12err(PKCS12_F_PKCS12_CREATE,ERR_R_MALLOC_FAILURE); return NULL; } if(!(p12 = PKCS12_init (NID_pkcs7_data))) return NULL; - if(!M_PKCS12_pack_authsafes (p12, safes)) return NULL; + if(!PKCS12_pack_authsafes (p12, safes)) return NULL; - sk_pop_free(safes, PKCS7_free); + sk_PKCS7_pop_free(safes, PKCS7_free); if(!PKCS12_set_mac (p12, pass, -1, NULL, 0, mac_iter, NULL)) return NULL; diff --git a/src/lib/libcrypto/pkcs12/p12_decr.c b/src/lib/libcrypto/pkcs12/p12_decr.c index d3d288e187..394af368f4 100644 --- a/src/lib/libcrypto/pkcs12/p12_decr.c +++ b/src/lib/libcrypto/pkcs12/p12_decr.c @@ -65,10 +65,10 @@ /* Encrypt/Decrypt a buffer based on password and algor, result in a - * Malloc'ed buffer + * OPENSSL_malloc'ed buffer */ -unsigned char * PKCS12_pbe_crypt (X509_ALGOR *algor, const char *pass, +unsigned char * PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass, int passlen, unsigned char *in, int inlen, unsigned char **data, int *datalen, int en_de) { @@ -76,47 +76,48 @@ unsigned char * PKCS12_pbe_crypt (X509_ALGOR *algor, const char *pass, int outlen, i; EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); /* Decrypt data */ - if (!EVP_PBE_CipherInit (algor->algorithm, pass, passlen, + if (!EVP_PBE_CipherInit(algor->algorithm, pass, passlen, algor->parameter, &ctx, en_de)) { PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR); return NULL; } - if(!(out = Malloc (inlen + EVP_CIPHER_CTX_block_size(&ctx)))) { + if(!(out = OPENSSL_malloc(inlen + EVP_CIPHER_CTX_block_size(&ctx)))) { PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,ERR_R_MALLOC_FAILURE); - return NULL; + goto err; } - EVP_CipherUpdate (&ctx, out, &i, in, inlen); + EVP_CipherUpdate(&ctx, out, &i, in, inlen); outlen = i; - if(!EVP_CipherFinal (&ctx, out + i, &i)) { - Free (out); + if(!EVP_CipherFinal_ex(&ctx, out + i, &i)) { + OPENSSL_free(out); + out = NULL; PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,PKCS12_R_PKCS12_CIPHERFINAL_ERROR); - return NULL; + goto err; } outlen += i; if (datalen) *datalen = outlen; if (data) *data = out; + err: + EVP_CIPHER_CTX_cleanup(&ctx); return out; } /* Decrypt an OCTET STRING and decode ASN1 structure - * if seq & 1 'obj' is a stack of structures to be encoded - * if seq & 2 zero buffer after use - * as a sequence. + * if zbuf set zero buffer after use. */ -char * PKCS12_decrypt_d2i (X509_ALGOR *algor, char * (*d2i)(), - void (*free_func)(), const char *pass, int passlen, - ASN1_OCTET_STRING *oct, int seq) +void * PKCS12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, ASN1_OCTET_STRING *oct, int zbuf) { unsigned char *out, *p; - char *ret; + void *ret; int outlen; - if (!PKCS12_pbe_crypt (algor, pass, passlen, oct->data, oct->length, + if (!PKCS12_pbe_crypt(algor, pass, passlen, oct->data, oct->length, &out, &outlen, 0)) { PKCS12err(PKCS12_F_PKCS12_DECRYPT_D2I,PKCS12_R_PKCS12_PBE_CRYPT_ERROR); return NULL; @@ -134,52 +135,42 @@ char * PKCS12_decrypt_d2i (X509_ALGOR *algor, char * (*d2i)(), fclose(op); } #endif - if (seq & 1) ret = (char *) d2i_ASN1_SET(NULL, &p, outlen, d2i, - free_func, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); - else ret = d2i(NULL, &p, outlen); - if (seq & 2) memset(out, 0, outlen); + ret = ASN1_item_d2i(NULL, &p, outlen, it); + if (zbuf) memset(out, 0, outlen); if(!ret) PKCS12err(PKCS12_F_PKCS12_DECRYPT_D2I,PKCS12_R_DECODE_ERROR); - Free (out); + OPENSSL_free(out); return ret; } /* Encode ASN1 structure and encrypt, return OCTET STRING - * if 'seq' is non-zero 'obj' is a stack of structures to be encoded - * as a sequence + * if zbuf set zero encoding. */ -ASN1_OCTET_STRING *PKCS12_i2d_encrypt (X509_ALGOR *algor, int (*i2d)(), +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, const ASN1_ITEM *it, const char *pass, int passlen, - char *obj, int seq) + void *obj, int zbuf) { ASN1_OCTET_STRING *oct; - unsigned char *in, *p; + unsigned char *in = NULL; int inlen; - if (!(oct = ASN1_OCTET_STRING_new ())) { + if (!(oct = M_ASN1_OCTET_STRING_new ())) { PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,ERR_R_MALLOC_FAILURE); return NULL; } - if (seq) inlen = i2d_ASN1_SET((STACK *)obj, NULL, i2d, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE); - else inlen = i2d (obj, NULL); - if (!inlen) { + inlen = ASN1_item_i2d(obj, &in, it); + if (!in) { PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,PKCS12_R_ENCODE_ERROR); return NULL; } - if (!(in = Malloc (inlen))) { - PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,ERR_R_MALLOC_FAILURE); - return NULL; - } - p = in; - if (seq) i2d_ASN1_SET((STACK *)obj, &p, i2d, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE); - else i2d (obj, &p); - if (!PKCS12_pbe_crypt (algor, pass, passlen, in, inlen, &oct->data, + if (!PKCS12_pbe_crypt(algor, pass, passlen, in, inlen, &oct->data, &oct->length, 1)) { PKCS12err(PKCS12_F_PKCS12_I2D_ENCRYPT,PKCS12_R_ENCRYPT_ERROR); - Free(in); + OPENSSL_free(in); return NULL; } - Free (in); + if (zbuf) memset(in, 0, inlen); + OPENSSL_free(in); return oct; } + +IMPLEMENT_PKCS12_STACK_OF(PKCS7) diff --git a/src/lib/libcrypto/pkcs12/p12_init.c b/src/lib/libcrypto/pkcs12/p12_init.c index dc6ab41db8..eb837a78cf 100644 --- a/src/lib/libcrypto/pkcs12/p12_init.c +++ b/src/lib/libcrypto/pkcs12/p12_init.c @@ -69,20 +69,12 @@ PKCS12 *PKCS12_init (int mode) PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); return NULL; } - if (!(pkcs12->version = ASN1_INTEGER_new ())) { - PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); - return NULL; - } - ASN1_INTEGER_set (pkcs12->version, 3); - if (!(pkcs12->authsafes = PKCS7_new())) { - PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); - return NULL; - } + ASN1_INTEGER_set(pkcs12->version, 3); pkcs12->authsafes->type = OBJ_nid2obj(mode); switch (mode) { case NID_pkcs7_data: if (!(pkcs12->authsafes->d.data = - ASN1_OCTET_STRING_new())) { + M_ASN1_OCTET_STRING_new())) { PKCS12err(PKCS12_F_PKCS12_INIT,ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/src/lib/libcrypto/pkcs12/p12_key.c b/src/lib/libcrypto/pkcs12/p12_key.c index 25d8cdae57..0d39ebde8c 100644 --- a/src/lib/libcrypto/pkcs12/p12_key.c +++ b/src/lib/libcrypto/pkcs12/p12_key.c @@ -64,7 +64,7 @@ /* Uncomment out this line to get debugging info about key generation */ /*#define DEBUG_KEYGEN*/ #ifdef DEBUG_KEYGEN -#include +#include extern BIO *bio_err; void h__dump (unsigned char *p, int len); #endif @@ -74,53 +74,69 @@ void h__dump (unsigned char *p, int len); #define min(a,b) ((a) < (b) ? (a) : (b)) #endif -int PKCS12_key_gen_asc (const char *pass, int passlen, unsigned char *salt, +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type) { int ret; unsigned char *unipass; int uniplen; - if (!asc2uni (pass, &unipass, &uniplen)) { + if(!pass) { + unipass = NULL; + uniplen = 0; + } else if (!asc2uni(pass, passlen, &unipass, &uniplen)) { PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC,ERR_R_MALLOC_FAILURE); return 0; } - ret = PKCS12_key_gen_uni (unipass, uniplen, salt, saltlen, + ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen, id, iter, n, out, md_type); - memset(unipass, 0, uniplen); /* Clear password from memory */ - Free(unipass); + if(unipass) { + memset(unipass, 0, uniplen); /* Clear password from memory */ + OPENSSL_free(unipass); + } return ret; } -int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt, +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type) { unsigned char *B, *D, *I, *p, *Ai; - int Slen, Plen, Ilen; + int Slen, Plen, Ilen, Ijlen; int i, j, u, v; BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */ EVP_MD_CTX ctx; #ifdef DEBUG_KEYGEN unsigned char *tmpout = out; int tmpn = n; - BIO_printf (bio_err, "KEYGEN DEBUG\n"); - BIO_printf (bio_err, "ID %d, ITER %d\n", id, iter); - BIO_printf (bio_err, "Password (length %d):\n", passlen); - h__dump (pass, passlen); - BIO_printf (bio_err, "Salt (length %d):\n", saltlen); - h__dump (salt, saltlen); - BIO_printf (bio_err, "ID %d, ITER %d\n\n", id, iter); +#endif + +#if 0 + if (!pass) { + PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } +#endif + + EVP_MD_CTX_init(&ctx); +#ifdef DEBUG_KEYGEN + fprintf(stderr, "KEYGEN DEBUG\n"); + fprintf(stderr, "ID %d, ITER %d\n", id, iter); + fprintf(stderr, "Password (length %d):\n", passlen); + h__dump(pass, passlen); + fprintf(stderr, "Salt (length %d):\n", saltlen); + h__dump(salt, saltlen); #endif v = EVP_MD_block_size (md_type); u = EVP_MD_size (md_type); - D = Malloc (v); - Ai = Malloc (u); - B = Malloc (v + 1); + D = OPENSSL_malloc (v); + Ai = OPENSSL_malloc (u); + B = OPENSSL_malloc (v + 1); Slen = v * ((saltlen+v-1)/v); - Plen = v * ((passlen+v-1)/v); + if(passlen) Plen = v * ((passlen+v-1)/v); + else Plen = 0; Ilen = Slen + Plen; - I = Malloc (Ilen); + I = OPENSSL_malloc (Ilen); Ij = BN_new(); Bpl1 = BN_new(); if (!D || !Ai || !B || !I || !Ij || !Bpl1) { @@ -132,26 +148,27 @@ int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt, for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen]; for (i = 0; i < Plen; i++) *p++ = pass[i % passlen]; for (;;) { - EVP_DigestInit (&ctx, md_type); - EVP_DigestUpdate (&ctx, D, v); - EVP_DigestUpdate (&ctx, I, Ilen); - EVP_DigestFinal (&ctx, Ai, NULL); + EVP_DigestInit_ex(&ctx, md_type, NULL); + EVP_DigestUpdate(&ctx, D, v); + EVP_DigestUpdate(&ctx, I, Ilen); + EVP_DigestFinal_ex(&ctx, Ai, NULL); for (j = 1; j < iter; j++) { - EVP_DigestInit (&ctx, md_type); - EVP_DigestUpdate (&ctx, Ai, u); - EVP_DigestFinal (&ctx, Ai, NULL); + EVP_DigestInit_ex(&ctx, md_type, NULL); + EVP_DigestUpdate(&ctx, Ai, u); + EVP_DigestFinal_ex(&ctx, Ai, NULL); } memcpy (out, Ai, min (n, u)); if (u >= n) { - Free (Ai); - Free (B); - Free (D); - Free (I); + OPENSSL_free (Ai); + OPENSSL_free (B); + OPENSSL_free (D); + OPENSSL_free (I); BN_free (Ij); BN_free (Bpl1); + EVP_MD_CTX_cleanup(&ctx); #ifdef DEBUG_KEYGEN - BIO_printf (bio_err, "Output KEY (length %d)\n", tmpn); - h__dump (tmpout, tmpn); + fprintf(stderr, "Output KEY (length %d)\n", tmpn); + h__dump(tmpout, tmpn); #endif return 1; } @@ -165,10 +182,17 @@ int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt, BN_bin2bn (I + j, v, Ij); BN_add (Ij, Ij, Bpl1); BN_bn2bin (Ij, B); + Ijlen = BN_num_bytes (Ij); /* If more than 2^(v*8) - 1 cut off MSB */ - if (BN_num_bytes (Ij) > v) { + if (Ijlen > v) { BN_bn2bin (Ij, B); memcpy (I + j, B + 1, v); +#ifndef PKCS12_BROKEN_KEYGEN + /* If less than v bytes pad with zeroes */ + } else if (Ijlen < v) { + memset(I + j, 0, v - Ijlen); + BN_bn2bin(Ij, I + j + v - Ijlen); +#endif } else BN_bn2bin (Ij, I + j); } } @@ -176,7 +200,7 @@ int PKCS12_key_gen_uni (unsigned char *pass, int passlen, unsigned char *salt, #ifdef DEBUG_KEYGEN void h__dump (unsigned char *p, int len) { - for (; len --; p++) BIO_printf (bio_err, "%02X", *p); - BIO_printf (bio_err, "\n"); + for (; len --; p++) fprintf(stderr, "%02X", *p); + fprintf(stderr, "\n"); } #endif diff --git a/src/lib/libcrypto/pkcs12/p12_kiss.c b/src/lib/libcrypto/pkcs12/p12_kiss.c index 767e1303da..885087ad00 100644 --- a/src/lib/libcrypto/pkcs12/p12_kiss.c +++ b/src/lib/libcrypto/pkcs12/p12_kiss.c @@ -62,9 +62,18 @@ /* Simplified PKCS#12 routines */ -static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca); -static int parse_bags( STACK *bags, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca, ASN1_OCTET_STRING **keyid, char *keymatch); -static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PKEY **pkey, X509 **cert, STACK **ca, ASN1_OCTET_STRING **keyid, char *keymatch); +static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, + EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca); + +static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, + int passlen, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid, + char *keymatch); + +static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, + EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca, + ASN1_OCTET_STRING **keyid, char *keymatch); + /* Parse and decrypt a PKCS#12 structure returning user key, user cert * and other (CA) certs. Note either ca should be NULL, *ca should be NULL, * or it should point to a valid STACK structure. pkey and cert can be @@ -72,94 +81,111 @@ static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PK */ int PKCS12_parse (PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, - STACK **ca) + STACK_OF(X509) **ca) { -/* Check for NULL PKCS12 structure */ + /* Check for NULL PKCS12 structure */ -if(!p12) { - PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER); - return 0; -} - -/* Allocate stack for ca certificates if needed */ -if ((ca != NULL) && (*ca == NULL)) { - if (!(*ca = sk_new(NULL))) { - PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE); + if(!p12) { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER); return 0; } -} -if(pkey) *pkey = NULL; -if(cert) *cert = NULL; + /* Allocate stack for ca certificates if needed */ + if ((ca != NULL) && (*ca == NULL)) { + if (!(*ca = sk_X509_new_null())) { + PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE); + return 0; + } + } -/* Check the mac */ + if(pkey) *pkey = NULL; + if(cert) *cert = NULL; -if (!PKCS12_verify_mac (p12, pass, -1)) { - PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE); - goto err; -} + /* Check the mac */ -if (!parse_pk12 (p12, pass, -1, pkey, cert, ca)) { - PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR); - goto err; -} + /* If password is zero length or NULL then try verifying both cases + * to determine which password is correct. The reason for this is that + * under PKCS#12 password based encryption no password and a zero length + * password are two different things... + */ + + if(!pass || !*pass) { + if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL; + else if(PKCS12_verify_mac(p12, "", 0)) pass = ""; + else { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE); + goto err; + } + } else if (!PKCS12_verify_mac(p12, pass, -1)) { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE); + goto err; + } -return 1; + if (!parse_pk12 (p12, pass, -1, pkey, cert, ca)) + { + PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR); + goto err; + } -err: + return 1; -if (pkey && *pkey) EVP_PKEY_free (*pkey); -if (cert && *cert) X509_free (*cert); -if (ca) sk_pop_free (*ca, X509_free); -return 0; + err: + + if (pkey && *pkey) EVP_PKEY_free(*pkey); + if (cert && *cert) X509_free(*cert); + if (ca) sk_X509_pop_free(*ca, X509_free); + return 0; } /* Parse the outer PKCS#12 structure */ static int parse_pk12 (PKCS12 *p12, const char *pass, int passlen, - EVP_PKEY **pkey, X509 **cert, STACK **ca) + EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) { - STACK *asafes, *bags; + STACK_OF(PKCS7) *asafes; + STACK_OF(PKCS12_SAFEBAG) *bags; int i, bagnid; PKCS7 *p7; ASN1_OCTET_STRING *keyid = NULL; + char keymatch = 0; - if (!( asafes = M_PKCS12_unpack_authsafes (p12))) return 0; - for (i = 0; i < sk_num (asafes); i++) { - p7 = (PKCS7 *) sk_value (asafes, i); + if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0; + for (i = 0; i < sk_PKCS7_num (asafes); i++) { + p7 = sk_PKCS7_value (asafes, i); bagnid = OBJ_obj2nid (p7->type); if (bagnid == NID_pkcs7_data) { - bags = M_PKCS12_unpack_p7data (p7); + bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { - bags = M_PKCS12_unpack_p7encdata (p7, pass, passlen); + bags = PKCS12_unpack_p7encdata(p7, pass, passlen); } else continue; if (!bags) { - sk_pop_free (asafes, PKCS7_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } - if (!parse_bags (bags, pass, passlen, pkey, cert, ca, + if (!parse_bags(bags, pass, passlen, pkey, cert, ca, &keyid, &keymatch)) { - sk_pop_free (bags, PKCS12_SAFEBAG_free); - sk_pop_free (asafes, PKCS7_free); + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } - sk_pop_free (bags, PKCS12_SAFEBAG_free); + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); } - sk_pop_free (asafes, PKCS7_free); - if (keyid) ASN1_OCTET_STRING_free (keyid); + sk_PKCS7_pop_free(asafes, PKCS7_free); + if (keyid) M_ASN1_OCTET_STRING_free(keyid); return 1; } -static int parse_bags (STACK *bags, const char *pass, int passlen, - EVP_PKEY **pkey, X509 **cert, STACK **ca, - ASN1_OCTET_STRING **keyid, char *keymatch) +static int parse_bags (STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, + int passlen, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid, + char *keymatch) { int i; - for (i = 0; i < sk_num (bags); i++) { - if (!parse_bag ((PKCS12_SAFEBAG *)sk_value (bags, i), + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i), pass, passlen, pkey, cert, ca, keyid, keymatch)) return 0; } @@ -170,26 +196,31 @@ static int parse_bags (STACK *bags, const char *pass, int passlen, #define MATCH_CERT 0x2 #define MATCH_ALL 0x3 -static int parse_bag (PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, X509 **cert, STACK **ca, +static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, + EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid, char *keymatch) { PKCS8_PRIV_KEY_INFO *p8; X509 *x509; - ASN1_OCTET_STRING *lkey = NULL; + ASN1_OCTET_STRING *lkey = NULL, *ckid = NULL; ASN1_TYPE *attrib; + ASN1_BMPSTRING *fname = NULL; + if ((attrib = PKCS12_get_attr (bag, NID_friendlyName))) + fname = attrib->value.bmpstring; - if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) - lkey = attrib->value.octet_string; + if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) { + lkey = attrib->value.octet_string; + ckid = lkey; + } /* Check for any local key id matching (if needed) */ if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) { if (*keyid) { - if (ASN1_OCTET_STRING_cmp (*keyid, lkey)) lkey = NULL; + if (M_ASN1_OCTET_STRING_cmp(*keyid, lkey)) lkey = NULL; } else { - if (!(*keyid = ASN1_OCTET_STRING_dup (lkey))) { + if (!(*keyid = M_ASN1_OCTET_STRING_dup(lkey))) { PKCS12err(PKCS12_F_PARSE_BAGS,ERR_R_MALLOC_FAILURE); return 0; } @@ -200,16 +231,16 @@ static int parse_bag (PKCS12_SAFEBAG *bag, const char *pass, int passlen, { case NID_keyBag: if (!lkey || !pkey) return 1; - if (!(*pkey = EVP_PKCS82PKEY (bag->value.keybag))) return 0; + if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag))) return 0; *keymatch |= MATCH_KEY; break; case NID_pkcs8ShroudedKeyBag: if (!lkey || !pkey) return 1; - if (!(p8 = M_PKCS12_decrypt_skey (bag, pass, passlen))) + if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) return 0; - *pkey = EVP_PKCS82PKEY (p8); - PKCS8_PRIV_KEY_INFO_free (p8); + *pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); if (!(*pkey)) return 0; *keymatch |= MATCH_KEY; break; @@ -217,11 +248,27 @@ static int parse_bag (PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_certBag: if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) return 1; - if (!(x509 = M_PKCS12_certbag2x509(bag))) return 0; + if (!(x509 = PKCS12_certbag2x509(bag))) return 0; + if(ckid) X509_keyid_set1(x509, ckid->data, ckid->length); + if(fname) { + int len; + unsigned char *data; + len = ASN1_STRING_to_UTF8(&data, fname); + if(len > 0) { + X509_alias_set1(x509, data, len); + OPENSSL_free(data); + } + } + + if (lkey) { *keymatch |= MATCH_CERT; if (cert) *cert = x509; - } else if (ca) sk_push (*ca, (char *)x509); + else X509_free(x509); + } else { + if(ca) sk_X509_push (*ca, x509); + else X509_free(x509); + } break; case NID_safeContentsBag: diff --git a/src/lib/libcrypto/pkcs12/p12_mutl.c b/src/lib/libcrypto/pkcs12/p12_mutl.c index bac558d6b9..0fb67f74b8 100644 --- a/src/lib/libcrypto/pkcs12/p12_mutl.c +++ b/src/lib/libcrypto/pkcs12/p12_mutl.c @@ -56,7 +56,7 @@ * */ -#ifndef NO_HMAC +#ifndef OPENSSL_NO_HMAC #include #include "cryptlib.h" #include @@ -71,6 +71,7 @@ int PKCS12_gen_mac (PKCS12 *p12, const char *pass, int passlen, HMAC_CTX hmac; unsigned char key[PKCS12_MAC_KEY_LENGTH], *salt; int saltlen, iter; + salt = p12->mac->salt->data; saltlen = p12->mac->salt->length; if (!p12->mac->iter) iter = 1; @@ -85,10 +86,12 @@ int PKCS12_gen_mac (PKCS12 *p12, const char *pass, int passlen, PKCS12err(PKCS12_F_PKCS12_GEN_MAC,PKCS12_R_KEY_GEN_ERROR); return 0; } - HMAC_Init (&hmac, key, PKCS12_MAC_KEY_LENGTH, md_type); - HMAC_Update (&hmac, p12->authsafes->d.data->data, + HMAC_CTX_init(&hmac); + HMAC_Init_ex(&hmac, key, PKCS12_MAC_KEY_LENGTH, md_type, NULL); + HMAC_Update(&hmac, p12->authsafes->d.data->data, p12->authsafes->d.data->length); - HMAC_Final (&hmac, mac, maclen); + HMAC_Final(&hmac, mac, maclen); + HMAC_CTX_cleanup(&hmac); return 1; } @@ -106,17 +109,14 @@ int PKCS12_verify_mac (PKCS12 *p12, const char *pass, int passlen) return 0; } if ((maclen != (unsigned int)p12->mac->dinfo->digest->length) - || memcmp (mac, p12->mac->dinfo->digest->data, maclen)) { - PKCS12err(PKCS12_F_VERIFY_MAC,PKCS12_R_MAC_VERIFY_ERROR); - return 0; - } + || memcmp (mac, p12->mac->dinfo->digest->data, maclen)) return 0; return 1; } /* Set a mac */ int PKCS12_set_mac (PKCS12 *p12, const char *pass, int passlen, - unsigned char *salt, int saltlen, int iter, EVP_MD *md_type) + unsigned char *salt, int saltlen, int iter, const EVP_MD *md_type) { unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; @@ -131,7 +131,7 @@ int PKCS12_set_mac (PKCS12 *p12, const char *pass, int passlen, PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_GENERATION_ERROR); return 0; } - if (!(ASN1_OCTET_STRING_set (p12->mac->dinfo->digest, mac, maclen))) { + if (!(M_ASN1_OCTET_STRING_set (p12->mac->dinfo->digest, mac, maclen))) { PKCS12err(PKCS12_F_PKCS12_SET_MAC,PKCS12_R_MAC_STRING_SET_ERROR); return 0; } @@ -140,23 +140,26 @@ int PKCS12_set_mac (PKCS12 *p12, const char *pass, int passlen, /* Set up a mac structure */ int PKCS12_setup_mac (PKCS12 *p12, int iter, unsigned char *salt, int saltlen, - EVP_MD *md_type) + const EVP_MD *md_type) { - if (!(p12->mac = PKCS12_MAC_DATA_new ())) return PKCS12_ERROR; + if (!(p12->mac = PKCS12_MAC_DATA_new())) return PKCS12_ERROR; if (iter > 1) { - if(!(p12->mac->iter = ASN1_INTEGER_new())) { + if(!(p12->mac->iter = M_ASN1_INTEGER_new())) { PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); return 0; } - ASN1_INTEGER_set (p12->mac->iter, iter); + ASN1_INTEGER_set(p12->mac->iter, iter); } if (!saltlen) saltlen = PKCS12_SALT_LEN; p12->mac->salt->length = saltlen; - if (!(p12->mac->salt->data = Malloc (saltlen))) { + if (!(p12->mac->salt->data = OPENSSL_malloc (saltlen))) { PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE); return 0; } - if (!salt) RAND_bytes (p12->mac->salt->data, saltlen); + if (!salt) { + if (RAND_pseudo_bytes (p12->mac->salt->data, saltlen) < 0) + return 0; + } else memcpy (p12->mac->salt->data, salt, saltlen); p12->mac->dinfo->algor->algorithm = OBJ_nid2obj(EVP_MD_type(md_type)); if (!(p12->mac->dinfo->algor->parameter = ASN1_TYPE_new())) { diff --git a/src/lib/libcrypto/pkcs12/p12_npas.c b/src/lib/libcrypto/pkcs12/p12_npas.c index ee71707e2c..a549433eeb 100644 --- a/src/lib/libcrypto/pkcs12/p12_npas.c +++ b/src/lib/libcrypto/pkcs12/p12_npas.c @@ -66,7 +66,8 @@ /* PKCS#12 password change routine */ static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass); -static int newpass_bags(STACK *bags, char *oldpass, char *newpass); +static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *oldpass, + char *newpass); static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass); static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen); @@ -104,51 +105,53 @@ return 1; static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass) { - STACK *asafes, *newsafes, *bags; + STACK_OF(PKCS7) *asafes, *newsafes; + STACK_OF(PKCS12_SAFEBAG) *bags; int i, bagnid, pbe_nid, pbe_iter, pbe_saltlen; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; - if (!(asafes = M_PKCS12_unpack_authsafes(p12))) return 0; - if(!(newsafes = sk_new(NULL))) return 0; - for (i = 0; i < sk_num (asafes); i++) { - p7 = (PKCS7 *) sk_value(asafes, i); + + if (!(asafes = PKCS12_unpack_authsafes(p12))) return 0; + if(!(newsafes = sk_PKCS7_new_null())) return 0; + for (i = 0; i < sk_PKCS7_num (asafes); i++) { + p7 = sk_PKCS7_value(asafes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { - bags = M_PKCS12_unpack_p7data(p7); + bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { - bags = M_PKCS12_unpack_p7encdata(p7, oldpass, -1); + bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); alg_get(p7->d.encrypted->enc_data->algorithm, &pbe_nid, &pbe_iter, &pbe_saltlen); } else continue; if (!bags) { - sk_pop_free(asafes, PKCS7_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } if (!newpass_bags(bags, oldpass, newpass)) { - sk_pop_free(bags, PKCS12_SAFEBAG_free); - sk_pop_free(asafes, PKCS7_free); + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, pbe_saltlen, pbe_iter, bags); - sk_pop_free(bags, PKCS12_SAFEBAG_free); + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if(!p7new) { - sk_pop_free(asafes, PKCS7_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } - sk_push(newsafes, (char *)p7new); + sk_PKCS7_push(newsafes, p7new); } - sk_pop_free(asafes, PKCS7_free); + sk_PKCS7_pop_free(asafes, PKCS7_free); /* Repack safe: save old safe in case of error */ p12_data_tmp = p12->authsafes->d.data; if(!(p12->authsafes->d.data = ASN1_OCTET_STRING_new())) goto saferr; - if(!M_PKCS12_pack_authsafes(p12, newsafes)) goto saferr; + if(!PKCS12_pack_authsafes(p12, newsafes)) goto saferr; if(!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto saferr; if(!(macnew = ASN1_OCTET_STRING_new())) goto saferr; @@ -169,12 +172,14 @@ static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass) } -static int newpass_bags(STACK *bags, char *oldpass, char *newpass) +static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *oldpass, + char *newpass) { int i; - for (i = 0; i < sk_num(bags); i++) { - if (!newpass_bag((PKCS12_SAFEBAG *)sk_value(bags, i), - oldpass, newpass)) return 0; + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), + oldpass, newpass)) + return 0; } return 1; } @@ -189,7 +194,7 @@ static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass) if(M_PKCS12_bag_type(bag) != NID_pkcs8ShroudedKeyBag) return 1; - if (!(p8 = M_PKCS12_decrypt_skey(bag, oldpass, -1))) return 0; + if (!(p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1))) return 0; alg_get(bag->value.shkeybag->algor, &p8_nid, &p8_iter, &p8_saltlen); if(!(p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, p8_iter, p8))) return 0; diff --git a/src/lib/libcrypto/pkcs12/p12_utl.c b/src/lib/libcrypto/pkcs12/p12_utl.c index 2adcbc95e1..243ec76be9 100644 --- a/src/lib/libcrypto/pkcs12/p12_utl.c +++ b/src/lib/libcrypto/pkcs12/p12_utl.c @@ -62,30 +62,34 @@ /* Cheap and nasty Unicode stuff */ -unsigned char *asc2uni (const char *asc, unsigned char **uni, int *unilen) +unsigned char *asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen) { int ulen, i; unsigned char *unitmp; - ulen = strlen(asc)*2 + 2; - if (!(unitmp = Malloc (ulen))) return NULL; - for (i = 0; i < ulen; i+=2) { + if (asclen == -1) asclen = strlen(asc); + ulen = asclen*2 + 2; + if (!(unitmp = OPENSSL_malloc(ulen))) return NULL; + for (i = 0; i < ulen - 2; i+=2) { unitmp[i] = 0; unitmp[i + 1] = asc[i>>1]; } + /* Make result double null terminated */ + unitmp[ulen - 2] = 0; + unitmp[ulen - 1] = 0; if (unilen) *unilen = ulen; if (uni) *uni = unitmp; return unitmp; } -char *uni2asc (unsigned char *uni, int unilen) +char *uni2asc(unsigned char *uni, int unilen) { int asclen, i; char *asctmp; asclen = unilen / 2; /* If no terminating zero allow for one */ - if (uni[unilen - 1]) asclen++; + if (!unilen || uni[unilen - 1]) asclen++; uni++; - if (!(asctmp = Malloc (asclen))) return NULL; + if (!(asctmp = OPENSSL_malloc(asclen))) return NULL; for (i = 0; i < unilen; i+=2) asctmp[i>>1] = uni[i]; asctmp[asclen - 1] = 0; return asctmp; @@ -93,26 +97,50 @@ char *uni2asc (unsigned char *uni, int unilen) int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12) { - return ASN1_i2d_bio((int(*)())i2d_PKCS12, bp, (unsigned char *)p12); + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); } -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12) { - return ASN1_i2d_fp((int(*)())i2d_PKCS12, fp, (unsigned char *)p12); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); } #endif PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) { - return (PKCS12 *)ASN1_d2i_bio((char *(*)())PKCS12_new, - (char *(*)())d2i_PKCS12, bp, (unsigned char **)p12); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); } -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { - return (PKCS12 *)ASN1_d2i_fp((char *(*)())PKCS12_new, - (char *(*)())d2i_PKCS12, fp, (unsigned char **)(p12)); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); } #endif +PKCS12_SAFEBAG *PKCS12_x5092certbag(X509 *x509) +{ + return PKCS12_item_pack_safebag(x509, ASN1_ITEM_rptr(X509), + NID_x509Certificate, NID_certBag); +} + +PKCS12_SAFEBAG *PKCS12_x509crl2certbag(X509_CRL *crl) +{ + return PKCS12_item_pack_safebag(crl, ASN1_ITEM_rptr(X509_CRL), + NID_x509Crl, NID_crlBag); +} + +X509 *PKCS12_certbag2x509(PKCS12_SAFEBAG *bag) +{ + if(M_PKCS12_bag_type(bag) != NID_certBag) return NULL; + if(M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) return NULL; + return ASN1_item_unpack(bag->value.bag->value.octet, ASN1_ITEM_rptr(X509)); +} + +X509_CRL *PKCS12_certbag2x509crl(PKCS12_SAFEBAG *bag) +{ + if(M_PKCS12_bag_type(bag) != NID_crlBag) return NULL; + if(M_PKCS12_cert_bag_type(bag) != NID_x509Crl) return NULL; + return ASN1_item_unpack(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509_CRL)); +} diff --git a/src/lib/libcrypto/pkcs12/pk12err.c b/src/lib/libcrypto/pkcs12/pk12err.c index 38d7be7675..10ab80502c 100644 --- a/src/lib/libcrypto/pkcs12/pk12err.c +++ b/src/lib/libcrypto/pkcs12/pk12err.c @@ -54,7 +54,8 @@ */ /* 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. + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. */ #include @@ -62,7 +63,7 @@ #include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA PKCS12_str_functs[]= { {ERR_PACK(0,PKCS12_F_PARSE_BAGS,0), "PARSE_BAGS"}, @@ -79,6 +80,7 @@ static ERR_STRING_DATA PKCS12_str_functs[]= {ERR_PACK(0,PKCS12_F_PKCS12_KEY_GEN_UNI,0), "PKCS12_key_gen_uni"}, {ERR_PACK(0,PKCS12_F_PKCS12_MAKE_KEYBAG,0), "PKCS12_MAKE_KEYBAG"}, {ERR_PACK(0,PKCS12_F_PKCS12_MAKE_SHKEYBAG,0), "PKCS12_MAKE_SHKEYBAG"}, +{ERR_PACK(0,PKCS12_F_PKCS12_NEWPASS,0), "PKCS12_newpass"}, {ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7DATA,0), "PKCS12_pack_p7data"}, {ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7ENCDATA,0), "PKCS12_pack_p7encdata"}, {ERR_PACK(0,PKCS12_F_PKCS12_PACK_SAFEBAG,0), "PKCS12_pack_safebag"}, @@ -99,6 +101,7 @@ static ERR_STRING_DATA PKCS12_str_reasons[]= {PKCS12_R_DECODE_ERROR ,"decode error"}, {PKCS12_R_ENCODE_ERROR ,"encode error"}, {PKCS12_R_ENCRYPT_ERROR ,"encrypt error"}, +{PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE,"error setting encrypted data type"}, {PKCS12_R_INVALID_NULL_ARGUMENT ,"invalid null argument"}, {PKCS12_R_INVALID_NULL_PKCS12_POINTER ,"invalid null pkcs12 pointer"}, {PKCS12_R_IV_GEN_ERROR ,"iv gen error"}, @@ -127,7 +130,7 @@ void ERR_load_PKCS12_strings(void) if (init) { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_PKCS12,PKCS12_str_functs); ERR_load_strings(ERR_LIB_PKCS12,PKCS12_str_reasons); #endif diff --git a/src/lib/libcrypto/pkcs12/pkcs12.h b/src/lib/libcrypto/pkcs12/pkcs12.h index 4cfba5e6c6..1786b6d4f3 100644 --- a/src/lib/libcrypto/pkcs12/pkcs12.h +++ b/src/lib/libcrypto/pkcs12/pkcs12.h @@ -59,13 +59,13 @@ #ifndef HEADER_PKCS12_H #define HEADER_PKCS12_H +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include - #define PKCS12_KEY_ID 1 #define PKCS12_IV_ID 2 #define PKCS12_MAC_ID 3 @@ -108,19 +108,24 @@ PKCS12_MAC_DATA *mac; PKCS7 *authsafes; } PKCS12; +PREDECLARE_STACK_OF(PKCS12_SAFEBAG) + typedef struct { ASN1_OBJECT *type; union { struct pkcs12_bag_st *bag; /* secret, crl and certbag */ struct pkcs8_priv_key_info_st *keybag; /* keybag */ X509_SIG *shkeybag; /* shrouded key bag */ - STACK /* PKCS12_SAFEBAG */ *safes; + STACK_OF(PKCS12_SAFEBAG) *safes; ASN1_TYPE *other; }value; STACK_OF(X509_ATTRIBUTE) *attrib; -ASN1_TYPE *rest; } PKCS12_SAFEBAG; +DECLARE_STACK_OF(PKCS12_SAFEBAG) +DECLARE_ASN1_SET_OF(PKCS12_SAFEBAG) +DECLARE_PKCS12_STACK_OF(PKCS12_SAFEBAG) + typedef struct pkcs12_bag_st { ASN1_OBJECT *type; union { @@ -135,56 +140,25 @@ union { #define PKCS12_ERROR 0 #define PKCS12_OK 1 -#define M_PKCS12_bag_type(bag) OBJ_obj2nid(bag->type) -#define M_PKCS12_cert_bag_type(bag) OBJ_obj2nid(bag->value.bag->type) -#define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type - -#define M_PKCS12_x5092certbag(x509) \ -PKCS12_pack_safebag ((char *)(x509), i2d_X509, NID_x509Certificate, NID_certBag) - -#define M_PKCS12_x509crl2certbag(crl) \ -PKCS12_pack_safebag ((char *)(crl), i2d_X509CRL, NID_x509Crl, NID_crlBag) - -#define M_PKCS12_certbag2x509(bg) \ -(X509 *) ASN1_unpack_string ((bg)->value.bag->value.octet, \ -(char *(*)())d2i_X509) - -#define M_PKCS12_certbag2x509crl(bg) \ -(X509CRL *) ASN1_unpack_string ((bg)->value.bag->value.octet, \ -(char *(*)())d2i_X509CRL) +/* Compatibility macros */ -/*#define M_PKCS12_pkcs82rsa(p8) \ -(RSA *) ASN1_unpack_string ((p8)->pkey, (char *(*)())d2i_RSAPrivateKey)*/ +#define M_PKCS12_x5092certbag PKCS12_x5092certbag +#define M_PKCS12_x509crl2certbag PKCS12_x509crl2certbag -#define M_PKCS12_unpack_p7data(p7) \ -ASN1_seq_unpack ((p7)->d.data->data, p7->d.data->length, \ - (char *(*)())d2i_PKCS12_SAFEBAG, PKCS12_SAFEBAG_free) +#define M_PKCS12_certbag2x509 PKCS12_certbag2x509 +#define M_PKCS12_certbag2x509crl PKCS12_certbag2x509crl -#define M_PKCS12_pack_authsafes(p12, safes) \ -ASN1_seq_pack((safes), (int (*)())i2d_PKCS7,\ - &(p12)->authsafes->d.data->data, &(p12)->authsafes->d.data->length) +#define M_PKCS12_unpack_p7data PKCS12_unpack_p7data +#define M_PKCS12_pack_authsafes PKCS12_pack_authsafes +#define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes +#define M_PKCS12_unpack_p7encdata PKCS12_unpack_p7encdata -#define M_PKCS12_unpack_authsafes(p12) \ -ASN1_seq_unpack((p12)->authsafes->d.data->data, \ - (p12)->authsafes->d.data->length, (char *(*)())d2i_PKCS7, \ - PKCS7_free) +#define M_PKCS12_decrypt_skey PKCS12_decrypt_skey +#define M_PKCS8_decrypt PKCS8_decrypt -#define M_PKCS12_unpack_p7encdata(p7, pass, passlen) \ -(STACK *) PKCS12_decrypt_d2i ((p7)->d.encrypted->enc_data->algorithm,\ - (char *(*)())d2i_PKCS12_SAFEBAG, PKCS12_SAFEBAG_free, \ - (pass), (passlen), \ - (p7)->d.encrypted->enc_data->enc_data, 3) - -#define M_PKCS12_decrypt_skey(bag, pass, passlen) \ -(PKCS8_PRIV_KEY_INFO *) PKCS12_decrypt_d2i ((bag)->value.shkeybag->algor, \ -(char *(*)())d2i_PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free, \ - (pass), (passlen), \ - (bag)->value.shkeybag->digest, 2) - -#define M_PKCS8_decrypt(p8, pass, passlen) \ -(PKCS8_PRIV_KEY_INFO *) PKCS12_decrypt_d2i ((p8)->algor, \ -(char *(*)())d2i_PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free,\ - (pass), (passlen), (p8)->digest, 2) +#define M_PKCS12_bag_type(bag) OBJ_obj2nid(bag->type) +#define M_PKCS12_cert_bag_type(bag) OBJ_obj2nid(bag->value.bag->type) +#define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type #define PKCS12_get_attr(bag, attr_nid) \ PKCS12_get_attr_gen(bag->attrib, attr_nid) @@ -195,8 +169,17 @@ ASN1_seq_unpack((p12)->authsafes->d.data->data, \ #define PKCS12_mac_present(p12) ((p12)->mac ? 1 : 0) -PKCS12_SAFEBAG *PKCS12_pack_safebag(char *obj, int (*i2d)(), int nid1, int nid2); +PKCS12_SAFEBAG *PKCS12_x5092certbag(X509 *x509); +PKCS12_SAFEBAG *PKCS12_x509crl2certbag(X509_CRL *crl); +X509 *PKCS12_certbag2x509(PKCS12_SAFEBAG *bag); +X509_CRL *PKCS12_certbag2x509crl(PKCS12_SAFEBAG *bag); + +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, int nid1, + int nid2); PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, int passlen); +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag, const char *pass, + int passlen); X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, @@ -205,13 +188,21 @@ PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8); -PKCS7 *PKCS12_pack_p7data(STACK *sk); +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7); PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, - STACK *bags); + STACK_OF(PKCS12_SAFEBAG) *bags); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, int passlen); + +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes); +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(PKCS12 *p12); + int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen); int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, int namelen); +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name, int namelen); int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage); @@ -220,64 +211,55 @@ char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass, int passlen, unsigned char *in, int inlen, unsigned char **data, int *datalen, int en_de); -char *PKCS12_decrypt_d2i(X509_ALGOR *algor, char *(*d2i)(), - void (*free_func)(), const char *pass, int passlen, - ASN1_STRING *oct, int seq); -ASN1_STRING *PKCS12_i2d_encrypt(X509_ALGOR *algor, int (*i2d)(), - const char *pass, int passlen, char *obj, - int seq); +void * PKCS12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, ASN1_OCTET_STRING *oct, int zbuf); +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, + void *obj, int zbuf); PKCS12 *PKCS12_init(int mode); int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type); int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type); int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, - ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md_type, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md_type, int en_de); int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *mac, unsigned int *maclen); int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, - EVP_MD *md_type); + const EVP_MD *md_type); int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, - int saltlen, EVP_MD *md_type); -unsigned char *asc2uni(const char *asc, unsigned char **uni, int *unilen); + int saltlen, const EVP_MD *md_type); +unsigned char *asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen); char *uni2asc(unsigned char *uni, int unilen); -int i2d_PKCS12_BAGS(PKCS12_BAGS *a, unsigned char **pp); -PKCS12_BAGS *PKCS12_BAGS_new(void); -PKCS12_BAGS *d2i_PKCS12_BAGS(PKCS12_BAGS **a, unsigned char **pp, long length); -void PKCS12_BAGS_free(PKCS12_BAGS *a); -int i2d_PKCS12(PKCS12 *a, unsigned char **pp); -PKCS12 *d2i_PKCS12(PKCS12 **a, unsigned char **pp, long length); -PKCS12 *PKCS12_new(void); -void PKCS12_free(PKCS12 *a); -int i2d_PKCS12_MAC_DATA(PKCS12_MAC_DATA *a, unsigned char **pp); -PKCS12_MAC_DATA *PKCS12_MAC_DATA_new(void); -PKCS12_MAC_DATA *d2i_PKCS12_MAC_DATA(PKCS12_MAC_DATA **a, unsigned char **pp, - long length); -void PKCS12_MAC_DATA_free(PKCS12_MAC_DATA *a); -int i2d_PKCS12_SAFEBAG(PKCS12_SAFEBAG *a, unsigned char **pp); -PKCS12_SAFEBAG *PKCS12_SAFEBAG_new(void); -PKCS12_SAFEBAG *d2i_PKCS12_SAFEBAG(PKCS12_SAFEBAG **a, unsigned char **pp, - long length); -void PKCS12_SAFEBAG_free(PKCS12_SAFEBAG *a); -void ERR_load_PKCS12_strings(void); + +DECLARE_ASN1_FUNCTIONS(PKCS12) +DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA) +DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG) +DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS) + +DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS) +DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES) + void PKCS12_PBE_add(void); int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, - STACK **ca); + STACK_OF(X509) **ca); PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, - STACK *ca, int nid_key, int nid_cert, int iter, + STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype); int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); +int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass); /* 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. */ +void ERR_load_PKCS12_strings(void); /* Error codes for the PKCS12 functions. */ @@ -296,6 +278,7 @@ PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); #define PKCS12_F_PKCS12_KEY_GEN_UNI 111 #define PKCS12_F_PKCS12_MAKE_KEYBAG 112 #define PKCS12_F_PKCS12_MAKE_SHKEYBAG 113 +#define PKCS12_F_PKCS12_NEWPASS 128 #define PKCS12_F_PKCS12_PACK_P7DATA 114 #define PKCS12_F_PKCS12_PACK_P7ENCDATA 115 #define PKCS12_F_PKCS12_PACK_SAFEBAG 117 @@ -313,6 +296,7 @@ PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); #define PKCS12_R_DECODE_ERROR 101 #define PKCS12_R_ENCODE_ERROR 102 #define PKCS12_R_ENCRYPT_ERROR 103 +#define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120 #define PKCS12_R_INVALID_NULL_ARGUMENT 104 #define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105 #define PKCS12_R_IV_GEN_ERROR 106 @@ -334,4 +318,3 @@ PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); } #endif #endif - diff --git a/src/lib/libcrypto/pkcs7/pk7_attr.c b/src/lib/libcrypto/pkcs7/pk7_attr.c index 3b9c0fe3f2..5ff5a88b5c 100644 --- a/src/lib/libcrypto/pkcs7/pk7_attr.c +++ b/src/lib/libcrypto/pkcs7/pk7_attr.c @@ -1,9 +1,59 @@ /* pk7_attr.c */ -/* S/MIME code. - * Copyright (C) 1997-8 Dr S N Henson (shenson@bigfoot.com) - * All Rights Reserved. - * Redistribution of this code without the authors permission is expressly - * prohibited. +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 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 @@ -12,22 +62,24 @@ #include #include #include +#include #include -int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK *cap) +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK_OF(X509_ALGOR) *cap) { ASN1_STRING *seq; unsigned char *p, *pp; int len; - len=i2d_ASN1_SET(cap,NULL,i2d_X509_ALGOR, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE); - if(!(pp=(unsigned char *)Malloc(len))) { + len=i2d_ASN1_SET_OF_X509_ALGOR(cap,NULL,i2d_X509_ALGOR, + V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, + IS_SEQUENCE); + if(!(pp=(unsigned char *)OPENSSL_malloc(len))) { PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,ERR_R_MALLOC_FAILURE); return 0; } p=pp; - i2d_ASN1_SET(cap,&p,i2d_X509_ALGOR, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE); + i2d_ASN1_SET_OF_X509_ALGOR(cap,&p,i2d_X509_ALGOR, V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL, IS_SEQUENCE); if(!(seq = ASN1_STRING_new())) { PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,ERR_R_MALLOC_FAILURE); return 0; @@ -36,27 +88,29 @@ int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK *cap) PKCS7err(PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,ERR_R_MALLOC_FAILURE); return 0; } - Free (pp); + OPENSSL_free (pp); return PKCS7_add_signed_attribute(si, NID_SMIMECapabilities, V_ASN1_SEQUENCE, seq); } -STACK *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si) +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si) { ASN1_TYPE *cap; unsigned char *p; cap = PKCS7_get_signed_attribute(si, NID_SMIMECapabilities); if (!cap) return NULL; p = cap->value.sequence->data; - return d2i_ASN1_SET (NULL, &p, cap->value.sequence->length, - (char *(*)())d2i_X509_ALGOR, X509_ALGOR_free, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL); + return d2i_ASN1_SET_OF_X509_ALGOR(NULL, &p, + cap->value.sequence->length, + d2i_X509_ALGOR, X509_ALGOR_free, + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); } /* Basic smime-capabilities OID and optional integer arg */ -int PKCS7_simple_smimecap(STACK *sk, int nid, int arg) +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) { X509_ALGOR *alg; + if(!(alg = X509_ALGOR_new())) { PKCS7err(PKCS7_F_PKCS7_SIMPLE_SMIMECAP,ERR_R_MALLOC_FAILURE); return 0; @@ -80,6 +134,6 @@ int PKCS7_simple_smimecap(STACK *sk, int nid, int arg) alg->parameter->value.integer = nbit; alg->parameter->type = V_ASN1_INTEGER; } - sk_push (sk, (char *)alg); + sk_X509_ALGOR_push (sk, alg); return 1; } diff --git a/src/lib/libcrypto/pkcs7/pk7_doit.c b/src/lib/libcrypto/pkcs7/pk7_doit.c index b5689b3fe4..4a4ff340ce 100644 --- a/src/lib/libcrypto/pkcs7/pk7_doit.c +++ b/src/lib/libcrypto/pkcs7/pk7_doit.c @@ -58,20 +58,56 @@ #include #include "cryptlib.h" -#include "rand.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include -BIO *PKCS7_dataInit(p7,bio) -PKCS7 *p7; -BIO *bio; +static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, + void *value); +static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); + +static int PKCS7_type_is_other(PKCS7* p7) + { + int isOther=1; + + int nid=OBJ_obj2nid(p7->type); + + switch( nid ) + { + case NID_pkcs7_data: + case NID_pkcs7_signed: + case NID_pkcs7_enveloped: + case NID_pkcs7_signedAndEnveloped: + case NID_pkcs7_digest: + case NID_pkcs7_encrypted: + isOther=0; + break; + default: + isOther=1; + } + + return isOther; + + } + +static int PKCS7_type_is_octet_string(PKCS7* p7) + { + if ( 0==PKCS7_type_is_other(p7) ) + return 0; + + return (V_ASN1_OCTET_STRING==p7->d.other->type) ? 1 : 0; + } + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i,j; - BIO *out=NULL,*btmp; + BIO *out=NULL,*btmp=NULL; X509_ALGOR *xa; - EVP_MD *evp_md; - EVP_CIPHER *evp_cipher=NULL; - STACK *md_sk=NULL,*rsk=NULL; + const EVP_MD *evp_md; + const EVP_CIPHER *evp_cipher=NULL; + STACK_OF(X509_ALGOR) *md_sk=NULL; + STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; EVP_PKEY *pkey; @@ -87,13 +123,25 @@ BIO *bio; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; - evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(p7->d.signed_and_enveloped->enc_data->algorithm->algorithm))); + xalg=p7->d.signed_and_enveloped->enc_data->algorithm; + evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; if (evp_cipher == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATAINIT, + PKCS7_R_CIPHER_NOT_INITIALIZED); + goto err; + } + break; + case NID_pkcs7_enveloped: + rsk=p7->d.enveloped->recipientinfo; + xalg=p7->d.enveloped->enc_data->algorithm; + evp_cipher=p7->d.enveloped->enc_data->cipher; + if (evp_cipher == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATAINIT, + PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } - xalg=p7->d.signed_and_enveloped->enc_data->algorithm; break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); @@ -102,10 +150,14 @@ BIO *bio; if (md_sk != NULL) { - for (i=0; ialgorithm); evp_md=EVP_get_digestbyname(OBJ_nid2sn(j)); @@ -120,6 +172,7 @@ BIO *bio; out=btmp; else BIO_push(out,btmp); + btmp=NULL; } } @@ -130,79 +183,323 @@ BIO *bio; int keylen,ivlen; int jj,max; unsigned char *tmp; + EVP_CIPHER_CTX *ctx; - if ((btmp=BIO_new(BIO_f_cipher())) == NULL) goto err; + if ((btmp=BIO_new(BIO_f_cipher())) == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); + goto err; + } + BIO_get_cipher_ctx(btmp, &ctx); keylen=EVP_CIPHER_key_length(evp_cipher); ivlen=EVP_CIPHER_iv_length(evp_cipher); - - if (ivlen > 0) - { - ASN1_OCTET_STRING *os; - - RAND_bytes(iv,ivlen); - os=ASN1_OCTET_STRING_new(); - ASN1_OCTET_STRING_set(os,iv,ivlen); - /* ASN1_TYPE_set(xalg->parameter,V_ASN1_OCTET_STRING, - (char *)os); - */ } - RAND_bytes(key,keylen); + if (RAND_bytes(key,keylen) <= 0) + goto err; + xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); + if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen); + EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1); + + if (ivlen > 0) { + if (xalg->parameter == NULL) + xalg->parameter=ASN1_TYPE_new(); + if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) + goto err; + } /* Lets do the pub key stuff :-) */ max=0; - for (i=0; icert == NULL) abort(); + ri=sk_PKCS7_RECIP_INFO_value(rsk,i); + if (ri->cert == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO); + goto err; + } pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_size(pkey); + EVP_PKEY_free(pkey); if (max < jj) max=jj; } - if ((tmp=(unsigned char *)Malloc(max)) == NULL) abort(); - for (i=0; icert); jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey); - if (jj <= 0) abort(); - ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj); + EVP_PKEY_free(pkey); + if (jj <= 0) + { + PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB); + OPENSSL_free(tmp); + goto err; + } + M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj); } - - BIO_set_cipher(btmp,evp_cipher,key,iv,1); + OPENSSL_free(tmp); + memset(key, 0, keylen); if (out == NULL) out=btmp; else BIO_push(out,btmp); + btmp=NULL; } - if (bio == NULL) /* ??????????? */ - { - if (p7->detached) + if (bio == NULL) { + if (PKCS7_is_detached(p7)) bio=BIO_new(BIO_s_null()); - else + else { + if (PKCS7_type_is_signed(p7) ) { + if ( PKCS7_type_is_data(p7->d.sign->contents)) { + ASN1_OCTET_STRING *os; + os=p7->d.sign->contents->d.data; + if (os->length > 0) + bio = BIO_new_mem_buf(os->data, os->length); + } + else if ( PKCS7_type_is_octet_string(p7->d.sign->contents) ) { + ASN1_OCTET_STRING *os; + os=p7->d.sign->contents->d.other->value.octet_string; + if (os->length > 0) + bio = BIO_new_mem_buf(os->data, os->length); + } + } + if(bio == NULL) { + bio=BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(bio,0); + } + } + } + BIO_push(out,bio); + bio=NULL; + if (0) + { +err: + if (out != NULL) + BIO_free_all(out); + if (btmp != NULL) + BIO_free_all(btmp); + out=NULL; + } + return(out); + } + +/* int */ +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) + { + int i,j; + BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; + unsigned char *tmp=NULL; + X509_ALGOR *xa; + ASN1_OCTET_STRING *data_body=NULL; + const EVP_MD *evp_md; + const EVP_CIPHER *evp_cipher=NULL; + EVP_CIPHER_CTX *evp_ctx=NULL; + X509_ALGOR *enc_alg=NULL; + STACK_OF(X509_ALGOR) *md_sk=NULL; + STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; + X509_ALGOR *xalg=NULL; + PKCS7_RECIP_INFO *ri=NULL; + + i=OBJ_obj2nid(p7->type); + p7->state=PKCS7_S_HEADER; + + switch (i) + { + case NID_pkcs7_signed: + data_body=p7->d.sign->contents->d.data; + md_sk=p7->d.sign->md_algs; + break; + case NID_pkcs7_signedAndEnveloped: + rsk=p7->d.signed_and_enveloped->recipientinfo; + md_sk=p7->d.signed_and_enveloped->md_algs; + data_body=p7->d.signed_and_enveloped->enc_data->enc_data; + enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm; + evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm))); + if (evp_cipher == NULL) { - bio=BIO_new(BIO_s_mem()); - if (PKCS7_type_is_signed(p7) && - PKCS7_type_is_data(p7->d.sign->contents)) + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + goto err; + } + xalg=p7->d.signed_and_enveloped->enc_data->algorithm; + break; + case NID_pkcs7_enveloped: + rsk=p7->d.enveloped->recipientinfo; + enc_alg=p7->d.enveloped->enc_data->algorithm; + data_body=p7->d.enveloped->enc_data->enc_data; + evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm))); + if (evp_cipher == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + goto err; + } + xalg=p7->d.enveloped->enc_data->algorithm; + break; + default: + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; + } + + /* We will be checking the signature */ + if (md_sk != NULL) + { + for (i=0; id.sign->contents->d.data; - if (os->length > 0) - BIO_write(bio,(char *)os->data, - os->length); + j=OBJ_obj2nid(xa->algorithm); + evp_md=EVP_get_digestbyname(OBJ_nid2sn(j)); + if (evp_md == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); + goto err; } + + BIO_set_md(btmp,evp_md); + if (out == NULL) + out=btmp; + else + BIO_push(out,btmp); + btmp=NULL; } } + + if (evp_cipher != NULL) + { +#if 0 + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char *p; + int keylen,ivlen; + int max; + X509_OBJECT ret; +#endif + int jj; + + if ((etmp=BIO_new(BIO_f_cipher())) == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); + goto err; + } + + /* It was encrypted, we need to decrypt the secret key + * with the private key */ + + /* Find the recipientInfo which matches the passed certificate + * (if any) + */ + + for (i=0; iissuer_and_serial->issuer, + pcert->cert_info->issuer) && + !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, + ri->issuer_and_serial->serial)) break; + ri=NULL; + } + if (ri == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); + goto err; + } + + jj=EVP_PKEY_size(pkey); + tmp=(unsigned char *)OPENSSL_malloc(jj+10); + if (tmp == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); + goto err; + } + + jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), + M_ASN1_STRING_length(ri->enc_key), pkey); + if (jj <= 0) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB); + goto err; + } + + evp_ctx=NULL; + BIO_get_cipher_ctx(etmp,&evp_ctx); + EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0); + if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) + goto err; + + if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { + /* Some S/MIME clients don't use the same key + * and effective key length. The key length is + * determined by the size of the decrypted RSA key. + */ + if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); + goto err; + } + } + EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0); + + memset(tmp,0,jj); + + if (out == NULL) + out=etmp; + else + BIO_push(out,etmp); + etmp=NULL; + } + +#if 1 + if (PKCS7_is_detached(p7) || (in_bio != NULL)) + { + bio=in_bio; + } + else + { +#if 0 + bio=BIO_new(BIO_s_mem()); + /* We need to set this so that when we have read all + * the data, the encrypt BIO, if present, will read + * EOF and encode the last few bytes */ + BIO_set_mem_eof_return(bio,0); + + if (data_body->length > 0) + BIO_write(bio,(char *)data_body->data,data_body->length); +#else + if (data_body->length > 0) + bio = BIO_new_mem_buf(data_body->data,data_body->length); + else { + bio=BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(bio,0); + } +#endif + } BIO_push(out,bio); - return(out); + bio=NULL; +#endif + if (0) + { err: - return(NULL); + if (out != NULL) BIO_free_all(out); + if (btmp != NULL) BIO_free_all(btmp); + if (etmp != NULL) BIO_free_all(etmp); + if (bio != NULL) BIO_free_all(bio); + out=NULL; + } + if (tmp != NULL) + OPENSSL_free(tmp); + return(out); } -int PKCS7_dataSign(p7,bio) -PKCS7 *p7; -BIO *bio; +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { int ret=0; int i,j; @@ -211,11 +508,11 @@ BIO *bio; BUF_MEM *buf=NULL; PKCS7_SIGNER_INFO *si; EVP_MD_CTX *mdc,ctx_tmp; - STACK *sk,*si_sk=NULL; - unsigned char *p,*pp=NULL; - int x; + STACK_OF(X509_ATTRIBUTE) *sk; + STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; ASN1_OCTET_STRING *os=NULL; + EVP_MD_CTX_init(&ctx_tmp); i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; @@ -224,25 +521,38 @@ BIO *bio; case NID_pkcs7_signedAndEnveloped: /* XXXXXXXXXXXXXXXX */ si_sk=p7->d.signed_and_enveloped->signer_info; - os=ASN1_OCTET_STRING_new(); + os=M_ASN1_OCTET_STRING_new(); p7->d.signed_and_enveloped->enc_data->enc_data=os; break; + case NID_pkcs7_enveloped: + /* XXXXXXXXXXXXXXXX */ + os=M_ASN1_OCTET_STRING_new(); + p7->d.enveloped->enc_data->enc_data=os; + break; case NID_pkcs7_signed: si_sk=p7->d.sign->signer_info; os=p7->d.sign->contents->d.data; + /* If detached data then the content is excluded */ + if(p7->detached) { + M_ASN1_OCTET_STRING_free(os); + p7->d.sign->contents->d.data = NULL; + } break; } if (si_sk != NULL) { - if ((buf=BUF_MEM_new()) == NULL) goto err; - for (i=0; ipkey == NULL) - continue; - j=OBJ_obj2nid(si->digest_enc_alg->algorithm); + PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); + goto err; + } + for (i=0; ipkey == NULL) continue; + + j=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) @@ -256,88 +566,137 @@ BIO *bio; BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR); + PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR); goto err; } - if (EVP_MD_pkey_type(EVP_MD_CTX_type(mdc)) == j) + if (EVP_MD_CTX_type(mdc) == j) break; else - btmp=btmp->next_bio; + btmp=BIO_next(btmp); } /* We now have the EVP_MD_CTX, lets do the * signing. */ - memcpy(&ctx_tmp,mdc,sizeof(ctx_tmp)); + EVP_MD_CTX_copy_ex(&ctx_tmp,mdc); if (!BUF_MEM_grow(buf,EVP_PKEY_size(si->pkey))) + { + PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); goto err; + } sk=si->auth_attr; - if ((sk != NULL) && (sk_num(sk) != 0)) + + /* If there are attributes, we add the digest + * attribute and only sign the attributes */ + if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { - x=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE, - V_ASN1_SET,V_ASN1_UNIVERSAL); - pp=(unsigned char *)Malloc(i); - p=pp; - i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE, - V_ASN1_SET,V_ASN1_UNIVERSAL); - EVP_SignUpdate(&ctx_tmp,pp,x); - Free(pp); + unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; + unsigned int md_len, alen; + ASN1_OCTET_STRING *digest; + ASN1_UTCTIME *sign_time; + const EVP_MD *md_tmp; + + /* Add signing time if not already present */ + if (!PKCS7_get_signed_attribute(si, + NID_pkcs9_signingTime)) + { + sign_time=X509_gmtime_adj(NULL,0); + PKCS7_add_signed_attribute(si, + NID_pkcs9_signingTime, + V_ASN1_UTCTIME,sign_time); + } + + /* Add digest */ + md_tmp=EVP_MD_CTX_md(&ctx_tmp); + EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len); + digest=M_ASN1_OCTET_STRING_new(); + M_ASN1_OCTET_STRING_set(digest,md_data,md_len); + PKCS7_add_signed_attribute(si, + NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING,digest); + + /* Now sign the attributes */ + EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL); + alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, + ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); + if(!abuf) goto err; + EVP_SignUpdate(&ctx_tmp,abuf,alen); + OPENSSL_free(abuf); } +#ifndef OPENSSL_NO_DSA + if (si->pkey->type == EVP_PKEY_DSA) + ctx_tmp.digest=EVP_dss1(); +#endif + if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data, (unsigned int *)&buf->length,si->pkey)) + { + PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB); goto err; + } if (!ASN1_STRING_set(si->enc_digest, (unsigned char *)buf->data,buf->length)) - goto err; - } - if (p7->detached) - ASN1_OCTET_STRING_set(os,(unsigned char *)"",0); - else - { - btmp=BIO_find_type(bio,BIO_TYPE_MEM); - if (btmp == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); + PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB); goto err; } - BIO_get_mem_ptr(btmp,&buf_mem); - ASN1_OCTET_STRING_set(os, - (unsigned char *)buf_mem->data,buf_mem->length); } - if (pp != NULL) Free(pp); - pp=NULL; } + if (!PKCS7_is_detached(p7)) + { + btmp=BIO_find_type(bio,BIO_TYPE_MEM); + if (btmp == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); + goto err; + } + BIO_get_mem_ptr(btmp,&buf_mem); + /* Mark the BIO read only then we can use its copy of the data + * instead of making an extra copy. + */ + BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); + BIO_set_mem_eof_return(btmp, 0); + os->data = (unsigned char *)buf_mem->data; + os->length = buf_mem->length; +#if 0 + M_ASN1_OCTET_STRING_set(os, + (unsigned char *)buf_mem->data,buf_mem->length); +#endif + } ret=1; err: + EVP_MD_CTX_cleanup(&ctx_tmp); if (buf != NULL) BUF_MEM_free(buf); return(ret); } -int PKCS7_dataVerify(cert_store,ctx,bio,p7,si) -X509_STORE *cert_store; -X509_STORE_CTX *ctx; -BIO *bio; -PKCS7 *p7; -PKCS7_SIGNER_INFO *si; +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, + PKCS7 *p7, PKCS7_SIGNER_INFO *si) { - PKCS7_SIGNED *s; - ASN1_OCTET_STRING *os; - EVP_MD_CTX mdc_tmp,*mdc; - unsigned char *pp,*p; PKCS7_ISSUER_AND_SERIAL *ias; - int ret=0,md_type,i; - STACK *sk; - BIO *btmp; + int ret=0,i; + STACK_OF(X509) *cert; X509 *x509; - if (!PKCS7_type_is_signed(p7)) abort(); + if (PKCS7_type_is_signed(p7)) + { + cert=p7->d.sign->cert; + } + else if (PKCS7_type_is_signedAndEnveloped(p7)) + { + cert=p7->d.signed_and_enveloped->cert; + } + else + { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE); + goto err; + } /* XXXXXXXXXXXXXXXXXXXXXXX */ ias=si->issuer_and_serial; - s=p7->d.sign; - x509=X509_find_by_issuer_and_serial(s->cert,ias->issuer,ias->serial); + x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial); /* were we able to find the cert in passed to us */ if (x509 == NULL) @@ -347,12 +706,46 @@ PKCS7_SIGNER_INFO *si; } /* Lets verify */ - X509_STORE_CTX_init(ctx,cert_store,x509,s->cert); + if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert)) + { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); + goto err; + } + X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); i=X509_verify_cert(ctx); - if (i <= 0) goto err; + if (i <= 0) + { + PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); + X509_STORE_CTX_cleanup(ctx); + goto err; + } X509_STORE_CTX_cleanup(ctx); - /* So we like 'x509', lets check the signature. */ + return PKCS7_signatureVerify(bio, p7, si, x509); + err: + return ret; + } + +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509) + { + ASN1_OCTET_STRING *os; + EVP_MD_CTX mdc_tmp,*mdc; + int ret=0,i; + int md_type; + STACK_OF(X509_ATTRIBUTE) *sk; + BIO *btmp; + EVP_PKEY *pkey; + + EVP_MD_CTX_init(&mdc_tmp); + + if (!PKCS7_type_is_signed(p7) && + !PKCS7_type_is_signedAndEnveloped(p7)) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + PKCS7_R_WRONG_PKCS7_TYPE); + goto err; + } + md_type=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; @@ -361,48 +754,226 @@ PKCS7_SIGNER_INFO *si; if ((btmp == NULL) || ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) { - PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_INTERNAL_ERROR); + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + ERR_R_INTERNAL_ERROR); goto err; } - if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == md_type) + if (EVP_MD_CTX_type(mdc) == md_type) break; - btmp=btmp->next_bio; + btmp=BIO_next(btmp); } - /* mdc is the digest ctx that we want */ - memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp)); + /* mdc is the digest ctx that we want, unless there are attributes, + * in which case the digest is the signed attributes */ + EVP_MD_CTX_copy_ex(&mdc_tmp,mdc); sk=si->auth_attr; - if ((sk != NULL) && (sk_num(sk) != 0)) + if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { - i=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE, - V_ASN1_SET,V_ASN1_UNIVERSAL); - pp=(unsigned char *)malloc(i); - p=pp; - i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE, - V_ASN1_SET,V_ASN1_UNIVERSAL); - EVP_VerifyUpdate(&mdc_tmp,pp,i); - free(pp); + unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; + unsigned int md_len, alen; + ASN1_OCTET_STRING *message_digest; + + EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len); + message_digest=PKCS7_digest_from_attributes(sk); + if (!message_digest) + { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + goto err; + } + if ((message_digest->length != (int)md_len) || + (memcmp(message_digest->data,md_dat,md_len))) + { +#if 0 +{ +int ii; +for (ii=0; iilength; ii++) + printf("%02X",message_digest->data[ii]); printf(" sent\n"); +for (ii=0; iienc_digest; - i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, - X509_get_pubkey(x509)); + pkey = X509_get_pubkey(x509); + if (!pkey) + { + ret = -1; + goto err; + } +#ifndef OPENSSL_NO_DSA + if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); +#endif + + i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); + EVP_PKEY_free(pkey); if (i <= 0) { - PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_SIGNATURE_FAILURE); + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, + PKCS7_R_SIGNATURE_FAILURE); ret= -1; goto err; } else ret=1; err: + EVP_MD_CTX_cleanup(&mdc_tmp); return(ret); } +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) + { + STACK_OF(PKCS7_RECIP_INFO) *rsk; + PKCS7_RECIP_INFO *ri; + int i; + + i=OBJ_obj2nid(p7->type); + if (i != NID_pkcs7_signedAndEnveloped) return(NULL); + rsk=p7->d.signed_and_enveloped->recipientinfo; + ri=sk_PKCS7_RECIP_INFO_value(rsk,0); + if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL); + ri=sk_PKCS7_RECIP_INFO_value(rsk,idx); + return(ri->issuer_and_serial); + } + +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) + { + return(get_attribute(si->auth_attr,nid)); + } + +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) + { + return(get_attribute(si->unauth_attr,nid)); + } + +static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) + { + int i; + X509_ATTRIBUTE *xa; + ASN1_OBJECT *o; + + o=OBJ_nid2obj(nid); + if (!o || !sk) return(NULL); + for (i=0; iobject,o) == 0) + { + if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) + return(sk_ASN1_TYPE_value(xa->value.set,0)); + else + return(NULL); + } + } + return(NULL); + } + +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) +{ + ASN1_TYPE *astype; + if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL; + return astype->value.octet_string; +} + +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk) + { + int i; + + if (p7si->auth_attr != NULL) + sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free); + p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk); + for (i=0; iauth_attr,i, + X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) + == NULL) + return(0); + } + return(1); + } + +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) + { + int i; + + if (p7si->unauth_attr != NULL) + sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, + X509_ATTRIBUTE_free); + p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk); + for (i=0; iunauth_attr,i, + X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) + == NULL) + return(0); + } + return(1); + } + +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value) + { + return(add_attribute(&(p7si->auth_attr),nid,atrtype,value)); + } + +int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value) + { + return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value)); + } + +static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, + void *value) + { + X509_ATTRIBUTE *attr=NULL; + + if (*sk == NULL) + { + *sk = sk_X509_ATTRIBUTE_new_null(); +new_attrib: + attr=X509_ATTRIBUTE_create(nid,atrtype,value); + sk_X509_ATTRIBUTE_push(*sk,attr); + } + else + { + int i; + + for (i=0; iobject) == nid) + { + X509_ATTRIBUTE_free(attr); + attr=X509_ATTRIBUTE_create(nid,atrtype,value); + sk_X509_ATTRIBUTE_set(*sk,i,attr); + goto end; + } + } + goto new_attrib; + } +end: + return(1); + } + diff --git a/src/lib/libcrypto/pkcs7/pk7_lib.c b/src/lib/libcrypto/pkcs7/pk7_lib.c index 7d14ad1173..c00ed6833a 100644 --- a/src/lib/libcrypto/pkcs7/pk7_lib.c +++ b/src/lib/libcrypto/pkcs7/pk7_lib.c @@ -58,14 +58,10 @@ #include #include "cryptlib.h" -#include "objects.h" -#include "x509.h" - -long PKCS7_ctrl(p7,cmd,larg,parg) -PKCS7 *p7; -int cmd; -long larg; -char *parg; +#include +#include + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) { int nid; long ret; @@ -88,7 +84,11 @@ char *parg; case PKCS7_OP_GET_DETACHED_SIGNATURE: if (nid == NID_pkcs7_signed) { - ret=p7->detached; + if(!p7->d.sign || !p7->d.sign->contents->d.ptr) + ret = 1; + else ret = 0; + + p7->detached = ret; } else { @@ -98,14 +98,13 @@ char *parg; break; default: - abort(); + PKCS7err(PKCS7_F_PKCS7_CTRL,PKCS7_R_UNKNOWN_OPERATION); + ret=0; } return(ret); } -int PKCS7_content_new(p7,type) -PKCS7 *p7; -int type; +int PKCS7_content_new(PKCS7 *p7, int type) { PKCS7 *ret=NULL; @@ -119,9 +118,7 @@ err: return(0); } -int PKCS7_set_content(p7,p7_data) -PKCS7 *p7; -PKCS7 *p7_data; +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) { int i; @@ -130,7 +127,7 @@ PKCS7 *p7_data; { case NID_pkcs7_signed: if (p7->d.sign->contents != NULL) - PKCS7_content_free(p7->d.sign->contents); + PKCS7_free(p7->d.sign->contents); p7->d.sign->contents=p7_data; break; case NID_pkcs7_digest: @@ -147,13 +144,11 @@ err: return(0); } -int PKCS7_set_type(p7,type) -PKCS7 *p7; -int type; +int PKCS7_set_type(PKCS7 *p7, int type) { ASN1_OBJECT *obj; - PKCS7_content_free(p7); + /*PKCS7_content_free(p7);*/ obj=OBJ_nid2obj(type); /* will not fail */ switch (type) @@ -166,19 +161,35 @@ int type; break; case NID_pkcs7_data: p7->type=obj; - if ((p7->d.data=ASN1_OCTET_STRING_new()) == NULL) + if ((p7->d.data=M_ASN1_OCTET_STRING_new()) == NULL) goto err; break; case NID_pkcs7_signedAndEnveloped: p7->type=obj; if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new()) - == NULL) - goto err; - ASN1_INTEGER_set(p7->d.sign->version,1); + == NULL) goto err; + ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1); + p7->d.signed_and_enveloped->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); break; - case NID_pkcs7_digest: case NID_pkcs7_enveloped: + p7->type=obj; + if ((p7->d.enveloped=PKCS7_ENVELOPE_new()) + == NULL) goto err; + ASN1_INTEGER_set(p7->d.enveloped->version,0); + p7->d.enveloped->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); + break; case NID_pkcs7_encrypted: + p7->type=obj; + if ((p7->d.encrypted=PKCS7_ENCRYPT_new()) + == NULL) goto err; + ASN1_INTEGER_set(p7->d.encrypted->version,0); + p7->d.encrypted->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); + break; + + case NID_pkcs7_digest: default: PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; @@ -188,14 +199,12 @@ err: return(0); } -int PKCS7_add_signer(p7,psi) -PKCS7 *p7; -PKCS7_SIGNER_INFO *psi; +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) { int i,j,nid; X509_ALGOR *alg; - STACK *signer_sk; - STACK *md_sk; + STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; + STACK_OF(X509_ALGOR) *md_sk; i=OBJ_obj2nid(p7->type); switch (i) @@ -217,9 +226,9 @@ PKCS7_SIGNER_INFO *psi; /* If the digest is not currently listed, add it */ j=0; - for (i=0; ialgorithm) == nid) { j=1; @@ -228,21 +237,24 @@ PKCS7_SIGNER_INFO *psi; } if (!j) /* we need to add another algorithm */ { - alg=X509_ALGOR_new(); + if(!(alg=X509_ALGOR_new()) + || !(alg->parameter = ASN1_TYPE_new())) { + PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,ERR_R_MALLOC_FAILURE); + return(0); + } alg->algorithm=OBJ_nid2obj(nid); - sk_push(md_sk,(char *)alg); + alg->parameter->type = V_ASN1_NULL; + sk_X509_ALGOR_push(md_sk,alg); } - sk_push(signer_sk,(char *)psi); + sk_PKCS7_SIGNER_INFO_push(signer_sk,psi); return(1); } -int PKCS7_add_certificate(p7,x509) -PKCS7 *p7; -X509 *x509; +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) { int i; - STACK **sk; + STACK_OF(X509) **sk; i=OBJ_obj2nid(p7->type); switch (i) @@ -259,18 +271,16 @@ X509 *x509; } if (*sk == NULL) - *sk=sk_new_null(); + *sk=sk_X509_new_null(); CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); - sk_push(*sk,(char *)x509); + sk_X509_push(*sk,x509); return(1); } -int PKCS7_add_crl(p7,crl) -PKCS7 *p7; -X509_CRL *crl; +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) { int i; - STACK **sk; + STACK_OF(X509_CRL) **sk; i=OBJ_obj2nid(p7->type); switch (i) @@ -287,19 +297,19 @@ X509_CRL *crl; } if (*sk == NULL) - *sk=sk_new_null(); + *sk=sk_X509_CRL_new_null(); CRYPTO_add(&crl->references,1,CRYPTO_LOCK_X509_CRL); - sk_push(*sk,(char *)crl); + sk_X509_CRL_push(*sk,crl); return(1); } -int PKCS7_SIGNER_INFO_set(p7i,x509,pkey,dgst) -PKCS7_SIGNER_INFO *p7i; -X509 *x509; -EVP_PKEY *pkey; -EVP_MD *dgst; +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst) { + char is_dsa; + if (pkey->type == EVP_PKEY_DSA) is_dsa = 1; + else is_dsa = 0; /* We now need to add another PKCS7_SIGNER_INFO entry */ ASN1_INTEGER_set(p7i->version,1); X509_NAME_set(&p7i->issuer_and_serial->issuer, @@ -307,36 +317,43 @@ EVP_MD *dgst; /* because ASN1_INTEGER_set is used to set a 'long' we will do * things the ugly way. */ - ASN1_INTEGER_free(p7i->issuer_and_serial->serial); + M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial); p7i->issuer_and_serial->serial= - ASN1_INTEGER_dup(X509_get_serialNumber(x509)); + M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)); /* lets keep the pkey around for a while */ CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); p7i->pkey=pkey; /* Set the algorithms */ - p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst)); - p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_MD_pkey_type(dgst)); + if (is_dsa) p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1); + else + p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst)); + + if (p7i->digest_alg->parameter != NULL) + ASN1_TYPE_free(p7i->digest_alg->parameter); + if ((p7i->digest_alg->parameter=ASN1_TYPE_new()) == NULL) + goto err; + p7i->digest_alg->parameter->type=V_ASN1_NULL; + + p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_PKEY_type(pkey->type)); -#if 1 if (p7i->digest_enc_alg->parameter != NULL) ASN1_TYPE_free(p7i->digest_enc_alg->parameter); - if ((p7i->digest_enc_alg->parameter=ASN1_TYPE_new()) == NULL) - goto err; - p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; -#endif + if(is_dsa) p7i->digest_enc_alg->parameter = NULL; + else { + if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new())) + goto err; + p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; + } return(1); err: return(0); } -PKCS7_SIGNER_INFO *PKCS7_add_signature(p7,x509,pkey,dgst) -PKCS7 *p7; -X509 *x509; -EVP_PKEY *pkey; -EVP_MD *dgst; +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst) { PKCS7_SIGNER_INFO *si; @@ -348,20 +365,21 @@ err: return(NULL); } -STACK *PKCS7_get_signer_info(p7) -PKCS7 *p7; +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) { if (PKCS7_type_is_signed(p7)) { return(p7->d.sign->signer_info); } + else if (PKCS7_type_is_signedAndEnveloped(p7)) + { + return(p7->d.signed_and_enveloped->signer_info); + } else return(NULL); } -PKCS7_RECIP_INFO *PKCS7_add_recipient(p7,x509) -PKCS7 *p7; -X509 *x509; +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) { PKCS7_RECIP_INFO *ri; @@ -373,12 +391,10 @@ err: return(NULL); } -int PKCS7_add_recipient_info(p7,ri) -PKCS7 *p7; -PKCS7_RECIP_INFO *ri; +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) { int i; - STACK *sk; + STACK_OF(PKCS7_RECIP_INFO) *sk; i=OBJ_obj2nid(p7->type); switch (i) @@ -386,26 +402,30 @@ PKCS7_RECIP_INFO *ri; case NID_pkcs7_signedAndEnveloped: sk= p7->d.signed_and_enveloped->recipientinfo; break; + case NID_pkcs7_enveloped: + sk= p7->d.enveloped->recipientinfo; + break; default: PKCS7err(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,PKCS7_R_WRONG_CONTENT_TYPE); return(0); } - sk_push(sk,(char *)ri); + sk_PKCS7_RECIP_INFO_push(sk,ri); return(1); } -int PKCS7_RECIP_INFO_set(p7i,x509) -PKCS7_RECIP_INFO *p7i; -X509 *x509; +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) { ASN1_INTEGER_set(p7i->version,0); X509_NAME_set(&p7i->issuer_and_serial->issuer, X509_get_issuer_name(x509)); - ASN1_INTEGER_free(p7i->issuer_and_serial->serial); + M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial); p7i->issuer_and_serial->serial= - ASN1_INTEGER_dup(X509_get_serialNumber(x509)); + M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)); + + X509_ALGOR_free(p7i->key_enc_algor); + p7i->key_enc_algor= X509_ALGOR_dup(x509->cert_info->key->algor); CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); p7i->cert=x509; @@ -413,9 +433,7 @@ X509 *x509; return(1); } -X509 *PKCS7_cert_from_signer_info(p7,si) -PKCS7 *p7; -PKCS7_SIGNER_INFO *si; +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) { if (PKCS7_type_is_signed(p7)) return(X509_find_by_issuer_and_serial(p7->d.sign->cert, @@ -425,11 +443,10 @@ PKCS7_SIGNER_INFO *si; return(NULL); } -int PKCS7_set_cipher(p7,cipher) -PKCS7 *p7; -EVP_CIPHER *cipher; +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) { int i; + ASN1_OBJECT *objtmp; PKCS7_ENC_CONTENT *ec; i=OBJ_obj2nid(p7->type); @@ -438,12 +455,23 @@ EVP_CIPHER *cipher; case NID_pkcs7_signedAndEnveloped: ec=p7->d.signed_and_enveloped->enc_data; break; + case NID_pkcs7_enveloped: + ec=p7->d.enveloped->enc_data; + break; default: PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_WRONG_CONTENT_TYPE); return(0); } - ec->algorithm->algorithm=OBJ_nid2obj(EVP_CIPHER_nid(cipher)); - return(ec->algorithm->algorithm != NULL); + /* Check cipher OID exists and has data in it*/ + i = EVP_CIPHER_type(cipher); + if(i == NID_undef) { + PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + return(0); + } + objtmp = OBJ_nid2obj(i); + + ec->cipher = cipher; + return 1; } diff --git a/src/lib/libcrypto/pkcs7/pk7_mime.c b/src/lib/libcrypto/pkcs7/pk7_mime.c index 734643be28..086d394270 100644 --- a/src/lib/libcrypto/pkcs7/pk7_mime.c +++ b/src/lib/libcrypto/pkcs7/pk7_mime.c @@ -69,17 +69,22 @@ * parameter values. Quotes are stripped off */ -typedef struct { -char *name; /* Name of line e.g. "content-type" */ -char *value; /* Value of line e.g. "text/plain" */ -STACK /* MIME_PARAM */ *params; /* Zero or more parameters */ -} MIME_HEADER; - typedef struct { char *param_name; /* Param name e.g. "micalg" */ char *param_value; /* Param value e.g. "sha1" */ } MIME_PARAM; +DECLARE_STACK_OF(MIME_PARAM) +IMPLEMENT_STACK_OF(MIME_PARAM) + +typedef struct { +char *name; /* Name of line e.g. "content-type" */ +char *value; /* Value of line e.g. "text/plain" */ +STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ +} MIME_HEADER; + +DECLARE_STACK_OF(MIME_HEADER) +IMPLEMENT_STACK_OF(MIME_HEADER) static int B64_write_PKCS7(BIO *bio, PKCS7 *p7); static PKCS7 *B64_read_PKCS7(BIO *bio); @@ -88,14 +93,16 @@ static char * strip_start(char *name); static char * strip_end(char *name); static MIME_HEADER *mime_hdr_new(char *name, char *value); static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); -static STACK *mime_parse_hdr(BIO *bio); -static int mime_hdr_cmp(MIME_HEADER **a, MIME_HEADER **b); -static int mime_param_cmp(MIME_PARAM **a, MIME_PARAM **b); +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); +static int mime_hdr_cmp(const MIME_HEADER * const *a, + const MIME_HEADER * const *b); +static int mime_param_cmp(const MIME_PARAM * const *a, + const MIME_PARAM * const *b); static void mime_param_free(MIME_PARAM *param); static int mime_bound_check(char *line, int linelen, char *bound, int blen); -static int multi_split(BIO *bio, char *bound, STACK **ret); +static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret); static int iscrlf(char c); -static MIME_HEADER *mime_hdr_find(STACK *hdrs, char *name); +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name); static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name); static void mime_hdr_free(MIME_HEADER *hdr); @@ -158,12 +165,12 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) } bound[32] = 0; BIO_printf(bio, "MIME-Version: 1.0\n"); - BIO_printf(bio, "Content-Type: multipart/signed ; "); - BIO_printf(bio, "protocol=\"application/x-pkcs7-signature\" ; "); - BIO_printf(bio, "micalg=sha1 ; boundary=\"----%s\"\n\n", bound); + BIO_printf(bio, "Content-Type: multipart/signed;"); + BIO_printf(bio, " protocol=\"application/x-pkcs7-signature\";"); + BIO_printf(bio, " micalg=sha1; boundary=\"----%s\"\n\n", bound); BIO_printf(bio, "This is an S/MIME signed message\n\n"); /* Now write out the first part */ - BIO_printf(bio, "------%s\r\n", bound); + BIO_printf(bio, "------%s\n", bound); if(flags & PKCS7_TEXT) BIO_printf(bio, "Content-Type: text/plain\n\n"); while((i = BIO_read(data, linebuf, MAX_SMLEN)) > 0) BIO_write(bio, linebuf, i); @@ -196,8 +203,8 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) { BIO *p7in; - STACK *headers = NULL; - STACK *parts = NULL; + STACK_OF(MIME_HEADER) *headers = NULL; + STACK_OF(BIO) *parts = NULL; MIME_HEADER *hdr; MIME_PARAM *prm; PKCS7 *p7; @@ -211,7 +218,7 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) } if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_CONTENT_TYPE); return NULL; } @@ -222,24 +229,24 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) /* Split into two parts */ prm = mime_param_find(hdr, "boundary"); if(!prm || !prm->param_value) { - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BOUNDARY); return NULL; } ret = multi_split(bio, prm->param_value, &parts); - sk_pop_free(headers, mime_hdr_free); - if(!ret || (sk_num(parts) != 2) ) { + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + if(!ret || (sk_BIO_num(parts) != 2) ) { PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BODY_FAILURE); - sk_pop_free(parts, (stkfree)BIO_free); + sk_BIO_pop_free(parts, BIO_vfree); return NULL; } /* Parse the signature piece */ - p7in = (BIO *)sk_value(parts, 1); + p7in = sk_BIO_value(parts, 1); if (!(headers = mime_parse_hdr(p7in))) { PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_SIG_PARSE_ERROR); - sk_pop_free(parts, (stkfree)BIO_free); + sk_BIO_pop_free(parts, BIO_vfree); return NULL; } @@ -247,32 +254,32 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_SIG_CONTENT_TYPE); return NULL; } if(strcmp(hdr->value, "application/x-pkcs7-signature") && strcmp(hdr->value, "application/pkcs7-signature")) { - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_SIG_INVALID_MIME_TYPE); ERR_add_error_data(2, "type: ", hdr->value); - sk_pop_free(parts, (stkfree)BIO_free); + sk_BIO_pop_free(parts, BIO_vfree); return NULL; } - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); /* Read in PKCS#7 */ if(!(p7 = B64_read_PKCS7(p7in))) { PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_PKCS7_SIG_PARSE_ERROR); - sk_pop_free(parts, (stkfree)BIO_free); + sk_BIO_pop_free(parts, BIO_vfree); return NULL; } if(bcont) { - *bcont = (BIO *)sk_value(parts, 0); + *bcont = sk_BIO_value(parts, 0); BIO_free(p7in); - sk_free(parts); - } else sk_pop_free(parts, (stkfree)BIO_free); + sk_BIO_free(parts); + } else sk_BIO_pop_free(parts, BIO_vfree); return p7; } @@ -282,11 +289,11 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) strcmp (hdr->value, "application/pkcs7-mime")) { PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_INVALID_MIME_TYPE); ERR_add_error_data(2, "type: ", hdr->value); - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return NULL; } - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); if(!(p7 = B64_read_PKCS7(bio))) { PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_PKCS7_PARSE_ERROR); @@ -325,24 +332,25 @@ int SMIME_text(BIO *in, BIO *out) { char iobuf[4096]; int len; - STACK *headers; + STACK_OF(MIME_HEADER) *headers; MIME_HEADER *hdr; + if (!(headers = mime_parse_hdr(in))) { PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR); return 0; } if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE); - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return 0; } if (strcmp (hdr->value, "text/plain")) { PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE); ERR_add_error_data(2, "type: ", hdr->value); - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return 0; } - sk_pop_free(headers, mime_hdr_free); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) BIO_write(out, iobuf, len); return 1; @@ -352,18 +360,19 @@ int SMIME_text(BIO *in, BIO *out) * canonical parts in a STACK of bios */ -static int multi_split(BIO *bio, char *bound, STACK **ret) +static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) { char linebuf[MAX_SMLEN]; int len, blen; BIO *bpart = NULL; - STACK *parts; + STACK_OF(BIO) *parts; char state, part, first; + blen = strlen(bound); part = 0; state = 0; first = 1; - parts = sk_new(NULL); + parts = sk_BIO_new_null(); *ret = parts; while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { state = mime_bound_check(linebuf, len, bound, blen); @@ -371,12 +380,12 @@ static int multi_split(BIO *bio, char *bound, STACK **ret) first = 1; part++; } else if(state == 2) { - sk_push(parts, (char *)bpart); + sk_BIO_push(parts, bpart); return 1; } else if(part) { if(first) { first = 0; - if(bpart) sk_push(parts, (char *)bpart); + if(bpart) sk_BIO_push(parts, bpart); bpart = BIO_new(BIO_s_mem()); } else BIO_write(bpart, "\r\n", 2); @@ -405,15 +414,16 @@ static int iscrlf(char c) #define MIME_COMMENT 6 -static STACK *mime_parse_hdr(BIO *bio) +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) { char *p, *q, c; char *ntmp; char linebuf[MAX_SMLEN]; MIME_HEADER *mhdr = NULL; - STACK *headers; + STACK_OF(MIME_HEADER) *headers; int len, state, save_state = 0; - headers = sk_new(mime_hdr_cmp); + + headers = sk_MIME_HEADER_new(mime_hdr_cmp); while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { /* If whitespace at line start then continuation line */ if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME; @@ -441,7 +451,7 @@ static STACK *mime_parse_hdr(BIO *bio) mime_debug("Found End Value\n"); *p = 0; mhdr = mime_hdr_new(ntmp, strip_ends(q)); - sk_push(headers, (char *)mhdr); + sk_MIME_HEADER_push(headers, mhdr); ntmp = NULL; q = p + 1; state = MIME_NAME; @@ -493,7 +503,7 @@ static STACK *mime_parse_hdr(BIO *bio) if(state == MIME_TYPE) { mhdr = mime_hdr_new(ntmp, strip_ends(q)); - sk_push(headers, (char *)mhdr); + sk_MIME_HEADER_push(headers, mhdr); } else if(state == MIME_VALUE) mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); if(p == linebuf) break; /* Blank line means end of headers */ @@ -569,11 +579,11 @@ static MIME_HEADER *mime_hdr_new(char *name, char *value) } } } else tmpval = NULL; - mhdr = (MIME_HEADER *) Malloc(sizeof(MIME_HEADER)); + mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER)); if(!mhdr) return NULL; mhdr->name = tmpname; mhdr->value = tmpval; - if(!(mhdr->params = sk_new(mime_param_cmp))) return NULL; + if(!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) return NULL; return mhdr; } @@ -598,34 +608,36 @@ static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) if(!tmpval) return 0; } else tmpval = NULL; /* Parameter values are case sensitive so leave as is */ - mparam = (MIME_PARAM *) Malloc(sizeof(MIME_PARAM)); + mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM)); if(!mparam) return 0; mparam->param_name = tmpname; mparam->param_value = tmpval; - sk_push(mhdr->params, (char *)mparam); + sk_MIME_PARAM_push(mhdr->params, mparam); return 1; } -static int mime_hdr_cmp(MIME_HEADER **a, MIME_HEADER **b) +static int mime_hdr_cmp(const MIME_HEADER * const *a, + const MIME_HEADER * const *b) { return(strcmp((*a)->name, (*b)->name)); } -static int mime_param_cmp(MIME_PARAM **a, MIME_PARAM **b) +static int mime_param_cmp(const MIME_PARAM * const *a, + const MIME_PARAM * const *b) { return(strcmp((*a)->param_name, (*b)->param_name)); } /* Find a header with a given name (if possible) */ -static MIME_HEADER *mime_hdr_find(STACK *hdrs, char *name) +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name) { MIME_HEADER htmp; int idx; htmp.name = name; - idx = sk_find(hdrs, (char *)&htmp); + idx = sk_MIME_HEADER_find(hdrs, &htmp); if(idx < 0) return NULL; - return (MIME_HEADER *)sk_value(hdrs, idx); + return sk_MIME_HEADER_value(hdrs, idx); } static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) @@ -633,24 +645,24 @@ static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) MIME_PARAM param; int idx; param.param_name = name; - idx = sk_find(hdr->params, (char *)¶m); + idx = sk_MIME_PARAM_find(hdr->params, ¶m); if(idx < 0) return NULL; - return (MIME_PARAM *)sk_value(hdr->params, idx); + return sk_MIME_PARAM_value(hdr->params, idx); } static void mime_hdr_free(MIME_HEADER *hdr) { - if(hdr->name) Free(hdr->name); - if(hdr->value) Free(hdr->value); - if(hdr->params) sk_pop_free(hdr->params, mime_param_free); - Free(hdr); + if(hdr->name) OPENSSL_free(hdr->name); + if(hdr->value) OPENSSL_free(hdr->value); + if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); + OPENSSL_free(hdr); } static void mime_param_free(MIME_PARAM *param) { - if(param->param_name) Free(param->param_name); - if(param->param_value) Free(param->param_value); - Free(param); + if(param->param_name) OPENSSL_free(param->param_name); + if(param->param_value) OPENSSL_free(param->param_value); + OPENSSL_free(param); } /* Check for a multipart boundary. Returns: diff --git a/src/lib/libcrypto/pkcs7/pk7_smime.c b/src/lib/libcrypto/pkcs7/pk7_smime.c index b41f42ed04..f0d071e282 100644 --- a/src/lib/libcrypto/pkcs7/pk7_smime.c +++ b/src/lib/libcrypto/pkcs7/pk7_smime.c @@ -64,12 +64,12 @@ #include PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, - BIO *data, int flags) + BIO *data, int flags) { PKCS7 *p7; PKCS7_SIGNER_INFO *si; BIO *p7bio; - STACK *smcap; + STACK_OF(X509_ALGOR) *smcap; int i; if(!X509_check_private_key(signcert, pkey)) { @@ -109,25 +109,28 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); /* Add SMIMECapabilities */ - if(!(smcap = sk_new(NULL))) { + if(!(flags & PKCS7_NOSMIMECAP)) + { + if(!(smcap = sk_X509_ALGOR_new_null())) { PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); return NULL; } -#ifndef NO_DES +#ifndef OPENSSL_NO_DES PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1); #endif -#ifndef NO_RC2 +#ifndef OPENSSL_NO_RC2 PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128); PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64); #endif -#ifndef NO_DES +#ifndef OPENSSL_NO_DES PKCS7_simple_smimecap (smcap, NID_des_cbc, -1); #endif -#ifndef NO_RC2 +#ifndef OPENSSL_NO_RC2 PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40); #endif PKCS7_add_attrib_smimecap (si, smcap); - sk_pop_free(smcap, X509_ALGOR_free); + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + } } if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1); @@ -150,7 +153,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, PKCS7_SIGNER_INFO *si; X509_STORE_CTX cert_ctx; char buf[4096]; - int i, j=0; + int i, j=0, k, ret = 0; BIO *p7bio; BIO *tmpout; @@ -169,12 +172,17 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT); return 0; } +#if 0 + /* NB: this test commented out because some versions of Netscape + * illegally include zero length content when signing data. + */ /* Check for data and content: two sets of data */ if(!PKCS7_get_detached(p7) && indata) { PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CONTENT_AND_DATA_PRESENT); return 0; } +#endif sinfos = PKCS7_get_signer_info(p7); @@ -190,14 +198,23 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, /* Now verify the certificates */ - if (!(flags & PKCS7_NOVERIFY)) for (i = 0; i < sk_X509_num(signers); i++) { - signer = sk_X509_value (signers, i); + if (!(flags & PKCS7_NOVERIFY)) for (k = 0; k < sk_X509_num(signers); k++) { + signer = sk_X509_value (signers, k); if (!(flags & PKCS7_NOCHAIN)) { - X509_STORE_CTX_init(&cert_ctx, store, signer, - p7->d.sign->cert); + if(!X509_STORE_CTX_init(&cert_ctx, store, signer, + p7->d.sign->cert)) + { + PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB); + sk_X509_free(signers); + return 0; + } X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_SMIME_SIGN); - } else X509_STORE_CTX_init (&cert_ctx, store, signer, NULL); + } else if(!X509_STORE_CTX_init (&cert_ctx, store, signer, NULL)) { + PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB); + sk_X509_free(signers); + return 0; + } i = X509_verify_cert(&cert_ctx); if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx); X509_STORE_CTX_cleanup(&cert_ctx); @@ -250,18 +267,15 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, } } - sk_X509_free(signers); - if(indata) BIO_pop(p7bio); - BIO_free_all(p7bio); - - return 1; + ret = 1; err: + if(indata) BIO_pop(p7bio); + BIO_free_all(p7bio); sk_X509_free(signers); - BIO_free(p7bio); - return 0; + return ret; } STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) @@ -282,7 +296,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE); return NULL; } - if(!(signers = sk_X509_new(NULL))) { + if(!(signers = sk_X509_new_null())) { PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,ERR_R_MALLOC_FAILURE); return NULL; } @@ -322,7 +336,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) /* Build a complete PKCS#7 enveloped data */ -PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, int flags) { PKCS7 *p7; diff --git a/src/lib/libcrypto/pkcs7/pkcs7.h b/src/lib/libcrypto/pkcs7/pkcs7.h index ee12f670a8..5819700a85 100644 --- a/src/lib/libcrypto/pkcs7/pkcs7.h +++ b/src/lib/libcrypto/pkcs7/pkcs7.h @@ -59,12 +59,22 @@ #ifndef HEADER_PKCS7_H #define HEADER_PKCS7_H +#include +#include +#include + +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include "bio.h" -#include "x509.h" +#ifdef OPENSSL_SYS_WIN32 +/* Under Win32 thes are defined in wincrypt.h */ +#undef PKCS7_ISSUER_AND_SERIAL +#undef PKCS7_SIGNER_INFO +#endif /* Encryption_ID DES-CBC @@ -84,15 +94,18 @@ typedef struct pkcs7_signer_info_st ASN1_INTEGER *version; /* version 1 */ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; X509_ALGOR *digest_alg; - STACK /* X509_ATTRIBUTE */ *auth_attr; /* [ 0 ] */ + STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */ X509_ALGOR *digest_enc_alg; ASN1_OCTET_STRING *enc_digest; - STACK /* X509_ATTRIBUTE */ *unauth_attr; /* [ 1 ] */ + 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 */ @@ -102,13 +115,16 @@ typedef struct pkcs7_recip_info_st 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 /* X509_ALGOR's */ *md_algs; /* md used */ - STACK /* X509 */ *cert; /* [ 0 ] */ - STACK /* X509_CRL */ *crl; /* [ 1 ] */ - STACK /* PKCS7_SIGNER_INFO */ *signer_info; + 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; @@ -120,25 +136,26 @@ 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 /* PKCS7_RECIP_INFO */ *recipientinfo; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; PKCS7_ENC_CONTENT *enc_data; } PKCS7_ENVELOPE; - + typedef struct pkcs7_signedandenveloped_st { ASN1_INTEGER *version; /* version 1 */ - STACK /* X509_ALGOR's */ *md_algs; /* md used */ - STACK /* X509 */ *cert; /* [ 0 ] */ - STACK /* X509_CRL */ *crl; /* [ 1 ] */ - STACK /* PKCS7_SIGNER_INFO */ *signer_info; + 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 /* PKCS7_RECIP_INFO */ *recipientinfo; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; } PKCS7_SIGN_ENVELOPE; typedef struct pkcs7_digest_st @@ -193,13 +210,27 @@ typedef struct pkcs7_st /* NID_pkcs7_encrypted */ PKCS7_ENCRYPT *encrypted; + + /* Anything else */ + ASN1_TYPE *other; } d; } PKCS7; +DECLARE_STACK_OF(PKCS7) +DECLARE_ASN1_SET_OF(PKCS7) +DECLARE_PKCS12_STACK_OF(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_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) +#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) \ @@ -207,101 +238,67 @@ typedef struct pkcs7_st #define PKCS7_get_detached(p) \ PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL) -#ifdef SSLEAY_MACROS +#define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) +#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 - -#ifndef NOPROTO -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); +/* 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 +#define PKCS7_NOSMIMECAP 0x200 + +/* 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 + +DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) #ifndef SSLEAY_MACROS -int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,EVP_MD *type, +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); +#ifndef OPENSSL_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); +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); +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT) +DECLARE_ASN1_FUNCTIONS(PKCS7) -void ERR_load_PKCS7_strings(void); +DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) +DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); @@ -309,141 +306,144 @@ 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); + const 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_dataSign(PKCS7 *p7, BIO *bio); 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); */ +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); + EVP_PKEY *pkey, const EVP_MD *dgst); X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); -STACK *PKCS7_get_signer_info(PKCS7 *p7); +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, EVP_CIPHER *cipher); - - - -#else - -PKCS7_ISSUER_AND_SERIAL *PKCS7_ISSUER_AND_SERIAL_new(); -void PKCS7_ISSUER_AND_SERIAL_free(); -int i2d_PKCS7_ISSUER_AND_SERIAL(); -PKCS7_ISSUER_AND_SERIAL *d2i_PKCS7_ISSUER_AND_SERIAL(); - -#ifndef SSLEAY_MACROS -int PKCS7_ISSUER_AND_SERIAL_digest(); -#ifndef NO_FP_API -PKCS7 *d2i_PKCS7_fp(); -int i2d_PKCS7_fp(); -#endif -PKCS7 *PKCS7_dup(); -PKCS7 *d2i_PKCS7_bio(); -int i2d_PKCS7_bio(); - -#endif - -PKCS7_SIGNER_INFO *PKCS7_SIGNER_INFO_new(); -void PKCS7_SIGNER_INFO_free(); -int i2d_PKCS7_SIGNER_INFO(); -PKCS7_SIGNER_INFO *d2i_PKCS7_SIGNER_INFO(); -PKCS7_RECIP_INFO *PKCS7_RECIP_INFO_new(); -void PKCS7_RECIP_INFO_free(); -int i2d_PKCS7_RECIP_INFO(); -PKCS7_RECIP_INFO *d2i_PKCS7_RECIP_INFO(); -PKCS7_SIGNED *PKCS7_SIGNED_new(); -void PKCS7_SIGNED_free(); -int i2d_PKCS7_SIGNED(); -PKCS7_SIGNED *d2i_PKCS7_SIGNED(); -PKCS7_ENC_CONTENT *PKCS7_ENC_CONTENT_new(); -void PKCS7_ENC_CONTENT_free(); -int i2d_PKCS7_ENC_CONTENT(); -PKCS7_ENC_CONTENT *d2i_PKCS7_ENC_CONTENT(); -PKCS7_ENVELOPE *PKCS7_ENVELOPE_new(); -void PKCS7_ENVELOPE_free(); -int i2d_PKCS7_ENVELOPE(); -PKCS7_ENVELOPE *d2i_PKCS7_ENVELOPE(); -PKCS7_SIGN_ENVELOPE *PKCS7_SIGN_ENVELOPE_new(); -void PKCS7_SIGN_ENVELOPE_free(); -int i2d_PKCS7_SIGN_ENVELOPE(); -PKCS7_SIGN_ENVELOPE *d2i_PKCS7_SIGN_ENVELOPE(); -PKCS7_DIGEST *PKCS7_DIGEST_new(); -void PKCS7_DIGEST_free(); -int i2d_PKCS7_DIGEST(); -PKCS7_DIGEST *d2i_PKCS7_DIGEST(); -PKCS7_ENCRYPT *PKCS7_ENCRYPT_new(); -void PKCS7_ENCRYPT_free(); -int i2d_PKCS7_ENCRYPT(); -PKCS7_ENCRYPT *d2i_PKCS7_ENCRYPT(); -PKCS7 *PKCS7_new(); -void PKCS7_free(); -void PKCS7_content_free(); -int i2d_PKCS7(); -PKCS7 *d2i_PKCS7(); - -void ERR_load_PKCS7_strings(); - -long PKCS7_ctrl(); -int PKCS7_set_type(); -int PKCS7_set_content(); -int PKCS7_SIGNER_INFO_set(); -int PKCS7_add_signer(); -int PKCS7_add_certificate(); -int PKCS7_add_crl(); -int PKCS7_content_new(); -int PKCS7_dataSign(); -int PKCS7_dataVerify(); -BIO *PKCS7_dataInit(); -PKCS7_SIGNER_INFO *PKCS7_add_signature(); -X509 *PKCS7_cert_from_signer_info(); -STACK *PKCS7_get_signer_info(); - -PKCS7_RECIP_INFO *PKCS7_add_recipient(); -int PKCS7_add_recipient_info(); -int PKCS7_RECIP_INFO_set(); -int PKCS7_set_cipher(); - -#endif +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, const 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_OF(X509_ALGOR) *cap); +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si); +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *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. + */ +void ERR_load_PKCS7_strings(void); + /* 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_INTERNAL_ERROR 100 -#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 101 -#define PKCS7_R_SIGNATURE_FAILURE 102 -#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 103 -#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 104 -#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 105 -#define PKCS7_R_UNKNOWN_DIGEST_TYPE 106 -#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 107 -#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 108 -#define PKCS7_R_WRONG_CONTENT_TYPE 109 - +#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_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/src/lib/libcrypto/pkcs7/pkcs7err.c b/src/lib/libcrypto/pkcs7/pkcs7err.c index f851057422..5e51527a40 100644 --- a/src/lib/libcrypto/pkcs7/pkcs7err.c +++ b/src/lib/libcrypto/pkcs7/pkcs7err.c @@ -1,107 +1,157 @@ -/* lib/pkcs7/pkcs7_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/pkcs7/pkcs7err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "pkcs7.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA PKCS7_str_functs[]= { +{ERR_PACK(0,PKCS7_F_B64_READ_PKCS7,0), "B64_READ_PKCS7"}, +{ERR_PACK(0,PKCS7_F_B64_WRITE_PKCS7,0), "B64_WRITE_PKCS7"}, +{ERR_PACK(0,PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP,0), "PKCS7_add_attrib_smimecap"}, {ERR_PACK(0,PKCS7_F_PKCS7_ADD_CERTIFICATE,0), "PKCS7_add_certificate"}, {ERR_PACK(0,PKCS7_F_PKCS7_ADD_CRL,0), "PKCS7_add_crl"}, {ERR_PACK(0,PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,0), "PKCS7_add_recipient_info"}, {ERR_PACK(0,PKCS7_F_PKCS7_ADD_SIGNER,0), "PKCS7_add_signer"}, {ERR_PACK(0,PKCS7_F_PKCS7_CTRL,0), "PKCS7_ctrl"}, +{ERR_PACK(0,PKCS7_F_PKCS7_DATADECODE,0), "PKCS7_dataDecode"}, {ERR_PACK(0,PKCS7_F_PKCS7_DATAINIT,0), "PKCS7_dataInit"}, -{ERR_PACK(0,PKCS7_F_PKCS7_DATASIGN,0), "PKCS7_dataSign"}, +{ERR_PACK(0,PKCS7_F_PKCS7_DATASIGN,0), "PKCS7_DATASIGN"}, {ERR_PACK(0,PKCS7_F_PKCS7_DATAVERIFY,0), "PKCS7_dataVerify"}, +{ERR_PACK(0,PKCS7_F_PKCS7_DECRYPT,0), "PKCS7_decrypt"}, +{ERR_PACK(0,PKCS7_F_PKCS7_ENCRYPT,0), "PKCS7_encrypt"}, +{ERR_PACK(0,PKCS7_F_PKCS7_GET0_SIGNERS,0), "PKCS7_get0_signers"}, {ERR_PACK(0,PKCS7_F_PKCS7_SET_CIPHER,0), "PKCS7_set_cipher"}, {ERR_PACK(0,PKCS7_F_PKCS7_SET_CONTENT,0), "PKCS7_set_content"}, {ERR_PACK(0,PKCS7_F_PKCS7_SET_TYPE,0), "PKCS7_set_type"}, -{0,NULL}, +{ERR_PACK(0,PKCS7_F_PKCS7_SIGN,0), "PKCS7_sign"}, +{ERR_PACK(0,PKCS7_F_PKCS7_SIGNATUREVERIFY,0), "PKCS7_signatureVerify"}, +{ERR_PACK(0,PKCS7_F_PKCS7_SIMPLE_SMIMECAP,0), "PKCS7_simple_smimecap"}, +{ERR_PACK(0,PKCS7_F_PKCS7_VERIFY,0), "PKCS7_verify"}, +{ERR_PACK(0,PKCS7_F_SMIME_READ_PKCS7,0), "SMIME_read_PKCS7"}, +{ERR_PACK(0,PKCS7_F_SMIME_TEXT,0), "SMIME_text"}, +{0,NULL} }; static ERR_STRING_DATA PKCS7_str_reasons[]= { -{PKCS7_R_INTERNAL_ERROR ,"internal error"}, +{PKCS7_R_CERTIFICATE_VERIFY_ERROR ,"certificate verify error"}, +{PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER ,"cipher has no object identifier"}, +{PKCS7_R_CIPHER_NOT_INITIALIZED ,"cipher not initialized"}, +{PKCS7_R_CONTENT_AND_DATA_PRESENT ,"content and data present"}, +{PKCS7_R_DECODE_ERROR ,"decode error"}, +{PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH ,"decrypted key is wrong length"}, +{PKCS7_R_DECRYPT_ERROR ,"decrypt error"}, +{PKCS7_R_DIGEST_FAILURE ,"digest failure"}, +{PKCS7_R_ERROR_ADDING_RECIPIENT ,"error adding recipient"}, +{PKCS7_R_ERROR_SETTING_CIPHER ,"error setting cipher"}, +{PKCS7_R_INVALID_MIME_TYPE ,"invalid mime type"}, +{PKCS7_R_INVALID_NULL_POINTER ,"invalid null pointer"}, +{PKCS7_R_MIME_NO_CONTENT_TYPE ,"mime no content type"}, +{PKCS7_R_MIME_PARSE_ERROR ,"mime parse error"}, +{PKCS7_R_MIME_SIG_PARSE_ERROR ,"mime sig parse error"}, +{PKCS7_R_MISSING_CERIPEND_INFO ,"missing ceripend info"}, +{PKCS7_R_NO_CONTENT ,"no content"}, +{PKCS7_R_NO_CONTENT_TYPE ,"no content type"}, +{PKCS7_R_NO_MULTIPART_BODY_FAILURE ,"no multipart body failure"}, +{PKCS7_R_NO_MULTIPART_BOUNDARY ,"no multipart boundary"}, +{PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE,"no recipient matches certificate"}, +{PKCS7_R_NO_SIGNATURES_ON_DATA ,"no signatures on data"}, +{PKCS7_R_NO_SIGNERS ,"no signers"}, +{PKCS7_R_NO_SIG_CONTENT_TYPE ,"no sig content type"}, {PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE,"operation not supported on this type"}, +{PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR ,"pkcs7 add signature error"}, +{PKCS7_R_PKCS7_DATAFINAL_ERROR ,"pkcs7 datafinal error"}, +{PKCS7_R_PKCS7_DATASIGN ,"pkcs7 datasign"}, +{PKCS7_R_PKCS7_PARSE_ERROR ,"pkcs7 parse error"}, +{PKCS7_R_PKCS7_SIG_PARSE_ERROR ,"pkcs7 sig parse error"}, +{PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE,"private key does not match certificate"}, {PKCS7_R_SIGNATURE_FAILURE ,"signature failure"}, +{PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND ,"signer certificate not found"}, +{PKCS7_R_SIG_INVALID_MIME_TYPE ,"sig invalid mime type"}, +{PKCS7_R_SMIME_TEXT_ERROR ,"smime text error"}, {PKCS7_R_UNABLE_TO_FIND_CERTIFICATE ,"unable to find certificate"}, {PKCS7_R_UNABLE_TO_FIND_MEM_BIO ,"unable to find mem bio"}, {PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST ,"unable to find message digest"}, {PKCS7_R_UNKNOWN_DIGEST_TYPE ,"unknown digest type"}, +{PKCS7_R_UNKNOWN_OPERATION ,"unknown operation"}, {PKCS7_R_UNSUPPORTED_CIPHER_TYPE ,"unsupported cipher type"}, {PKCS7_R_UNSUPPORTED_CONTENT_TYPE ,"unsupported content type"}, {PKCS7_R_WRONG_CONTENT_TYPE ,"wrong content type"}, -{0,NULL}, +{PKCS7_R_WRONG_PKCS7_TYPE ,"wrong pkcs7 type"}, +{0,NULL} }; #endif -void ERR_load_PKCS7_strings() +void ERR_load_PKCS7_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_PKCS7,PKCS7_str_functs); ERR_load_strings(ERR_LIB_PKCS7,PKCS7_str_reasons); #endif diff --git a/src/lib/libcrypto/rand/rand.h b/src/lib/libcrypto/rand/rand.h index 477d7a150a..e17aa7a9f7 100644 --- a/src/lib/libcrypto/rand/rand.h +++ b/src/lib/libcrypto/rand/rand.h @@ -59,34 +59,68 @@ #ifndef HEADER_RAND_H #define HEADER_RAND_H +#include +#include + #ifdef __cplusplus extern "C" { #endif -#ifndef NOPROTO +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 + +int RAND_set_rand_method(const RAND_METHOD *meth); +const RAND_METHOD *RAND_get_rand_method(void); +int RAND_set_rand_engine(ENGINE *engine); +RAND_METHOD *RAND_SSLeay(void); void RAND_cleanup(void ); -void RAND_bytes( unsigned char *buf,int num); -void RAND_seed( unsigned char *buf,int num); -int RAND_load_file(char *file,long max_bytes); -int RAND_write_file(char *file); -char *RAND_file_name(char *file,int num); -#ifdef WINDOWS +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,size_t num); +int RAND_status(void); +int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes); +int RAND_egd(const char *path); +int RAND_egd_bytes(const char *path,int bytes); +int RAND_poll(void); + +#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) + void RAND_screen(void); +int RAND_event(UINT, WPARAM, LPARAM); + #endif -#else -void RAND_cleanup(); -void RAND_bytes(); -void RAND_seed(); -int RAND_load_file(); -int RAND_write_file(); -char *RAND_file_name(); -#ifdef WINDOWS -void RAND_screen(); -#endif -#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. + */ +void ERR_load_RAND_strings(void); + +/* Error codes for the RAND functions. */ + +/* Function codes. */ +#define RAND_F_RAND_GET_RAND_METHOD 101 +#define RAND_F_SSLEAY_RAND_BYTES 100 + +/* Reason codes. */ +#define RAND_R_PRNG_NOT_SEEDED 100 #ifdef __cplusplus } #endif - #endif diff --git a/src/lib/libcrypto/rand/rand_err.c b/src/lib/libcrypto/rand/rand_err.c index d1263edf80..b77267e213 100644 --- a/src/lib/libcrypto/rand/rand_err.c +++ b/src/lib/libcrypto/rand/rand_err.c @@ -54,7 +54,8 @@ */ /* 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. + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. */ #include @@ -62,16 +63,17 @@ #include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA RAND_str_functs[]= { +{ERR_PACK(0,RAND_F_RAND_GET_RAND_METHOD,0), "RAND_get_rand_method"}, {ERR_PACK(0,RAND_F_SSLEAY_RAND_BYTES,0), "SSLEAY_RAND_BYTES"}, {0,NULL} }; static ERR_STRING_DATA RAND_str_reasons[]= { -{RAND_R_PRNG_NOT_SEEDED ,"prng not seeded"}, +{RAND_R_PRNG_NOT_SEEDED ,"PRNG not seeded"}, {0,NULL} }; @@ -84,7 +86,7 @@ void ERR_load_RAND_strings(void) if (init) { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_RAND,RAND_str_functs); ERR_load_strings(ERR_LIB_RAND,RAND_str_reasons); #endif diff --git a/src/lib/libcrypto/rand/rand_lib.c b/src/lib/libcrypto/rand/rand_lib.c index 34c6d5b968..5cf5dc1188 100644 --- a/src/lib/libcrypto/rand/rand_lib.c +++ b/src/lib/libcrypto/rand/rand_lib.c @@ -57,42 +57,110 @@ */ #include -#include #include +#include "cryptlib.h" #include +#include -#ifdef NO_RAND -static RAND_METHOD *rand_meth=NULL; -#else -extern RAND_METHOD rand_ssleay_meth; -static RAND_METHOD *rand_meth= &rand_ssleay_meth; -#endif +/* non-NULL if default_RAND_meth is ENGINE-provided */ +static ENGINE *funct_ref =NULL; +static const RAND_METHOD *default_RAND_meth = NULL; -void RAND_set_rand_method(RAND_METHOD *meth) +int RAND_set_rand_method(const RAND_METHOD *meth) { - rand_meth=meth; + if(funct_ref) + { + ENGINE_finish(funct_ref); + funct_ref = NULL; + } + default_RAND_meth = meth; + return 1; } -RAND_METHOD *RAND_get_rand_method(void) +const RAND_METHOD *RAND_get_rand_method(void) { - return(rand_meth); + if (!default_RAND_meth) + { + ENGINE *e = ENGINE_get_default_RAND(); + if(e) + { + default_RAND_meth = ENGINE_get_RAND(e); + if(!default_RAND_meth) + { + ENGINE_finish(e); + e = NULL; + } + } + if(e) + funct_ref = e; + else + default_RAND_meth = RAND_SSLeay(); + } + return default_RAND_meth; + } + +int RAND_set_rand_engine(ENGINE *engine) + { + const RAND_METHOD *tmp_meth = NULL; + if(engine) + { + if(!ENGINE_init(engine)) + return 0; + tmp_meth = ENGINE_get_RAND(engine); + if(!tmp_meth) + { + ENGINE_finish(engine); + return 0; + } + } + /* This function releases any prior ENGINE so call it first */ + RAND_set_rand_method(tmp_meth); + funct_ref = engine; + return 1; } void RAND_cleanup(void) { - if (rand_meth != NULL) - rand_meth->cleanup(); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->cleanup) + meth->cleanup(); + RAND_set_rand_method(NULL); } void RAND_seed(const void *buf, int num) { - if (rand_meth != NULL) - rand_meth->seed(buf,num); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->seed) + meth->seed(buf,num); + } + +void RAND_add(const void *buf, int num, double entropy) + { + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->add) + meth->add(buf,num,entropy); } -void RAND_bytes(unsigned char *buf, int num) +int RAND_bytes(unsigned char *buf, int num) { - if (rand_meth != NULL) - rand_meth->bytes(buf,num); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->bytes) + return meth->bytes(buf,num); + return(-1); } +int RAND_pseudo_bytes(unsigned char *buf, int num) + { + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->pseudorand) + return meth->pseudorand(buf,num); + return(-1); + } + +int RAND_status(void) + { + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->status) + return meth->status(); + return 0; + } diff --git a/src/lib/libcrypto/rand/randfile.c b/src/lib/libcrypto/rand/randfile.c index f2b3746363..982074c465 100644 --- a/src/lib/libcrypto/rand/randfile.c +++ b/src/lib/libcrypto/rand/randfile.c @@ -56,22 +56,41 @@ * [including the GNU Public Licence.] */ +#include #include -#include "cryptlib.h" -#include -#include -#include "rand.h" +#include +#include + +#include "e_os.h" +#include +#include + +#ifdef OPENSSL_SYS_VMS +#include +#endif +#ifndef NO_SYS_TYPES_H +# include +#endif +#ifdef MAC_OS_pre_X +# include +#else +# include +#endif #undef BUFSIZE #define BUFSIZE 1024 #define RAND_DATA 1024 -/* #define RFILE ".rand" - defined in ../../e_os.h */ +/* #define RFILE ".rnd" - defined in ../../e_os.h */ + +/* Note that these functions are intended for seed files only. + * Entropy devices and EGD sockets are handled in rand_unix.c */ -int RAND_load_file(file,bytes) -char *file; -long bytes; +int RAND_load_file(const char *file, long bytes) { + /* If bytes >= 0, read up to 'bytes' bytes. + * if bytes == -1, read complete file. */ + MS_STATIC unsigned char buf[BUFSIZE]; struct stat sb; int i,ret=0,n; @@ -81,23 +100,28 @@ long bytes; i=stat(file,&sb); /* If the state fails, put some crap in anyway */ - RAND_seed((unsigned char *)&sb,sizeof(sb)); - ret+=sizeof(sb); + RAND_add(&sb,sizeof(sb),0); if (i < 0) return(0); - if (bytes <= 0) return(ret); + if (bytes == 0) return(ret); - in=fopen(file,"r"); + in=fopen(file,"rb"); if (in == NULL) goto err; for (;;) { - n=(bytes < BUFSIZE)?(int)bytes:BUFSIZE; + if (bytes > 0) + n = (bytes < BUFSIZE)?(int)bytes:BUFSIZE; + else + n = BUFSIZE; i=fread(buf,1,n,in); if (i <= 0) break; /* even if n != i, use the full array */ - RAND_seed(buf,n); + RAND_add(buf,n,i); ret+=i; - bytes-=n; - if (bytes <= 0) break; + if (bytes > 0) + { + bytes-=n; + if (bytes <= 0) break; + } } fclose(in); memset(buf,0,BUFSIZE); @@ -105,23 +129,36 @@ err: return(ret); } -int RAND_write_file(file) -char *file; +int RAND_write_file(const char *file) { unsigned char buf[BUFSIZE]; - int i,ret=0; - FILE *out; + int i,ret=0,rand_err=0; + FILE *out = NULL; int n; - - out=fopen(file,"w"); + +#if defined(O_CREAT) && !defined(OPENSSL_SYS_WIN32) + /* For some reason Win32 can't write to files created this way */ + + /* chmod(..., 0600) is too late to protect the file, + * permissions should be restrictive from the start */ + int fd = open(file, O_CREAT, 0600); + if (fd != -1) + out = fdopen(fd, "wb"); +#endif + if (out == NULL) + out = fopen(file,"wb"); if (out == NULL) goto err; + +#ifndef NO_CHMOD chmod(file,0600); +#endif n=RAND_DATA; for (;;) { i=(n > BUFSIZE)?BUFSIZE:n; n-=BUFSIZE; - RAND_bytes(buf,i); + if (RAND_bytes(buf,i) <= 0) + rand_err=1; i=fwrite(buf,1,i,out); if (i <= 0) { @@ -130,21 +167,40 @@ char *file; } ret+=i; if (n <= 0) break; + } +#ifdef OPENSSL_SYS_VMS + /* Try to delete older versions of the file, until there aren't + any */ + { + char *tmpf; + + tmpf = OPENSSL_malloc(strlen(file) + 4); /* to add ";-1" and a nul */ + if (tmpf) + { + strcpy(tmpf, file); + strcat(tmpf, ";-1"); + while(delete(tmpf) == 0) + ; + rename(file,";1"); /* Make sure it's version 1, or we + will reach the limit (32767) at + some point... */ } + } +#endif /* OPENSSL_SYS_VMS */ + fclose(out); memset(buf,0,BUFSIZE); err: - return(ret); + return (rand_err ? -1 : ret); } -char *RAND_file_name(buf,size) -char *buf; -int size; +const char *RAND_file_name(char *buf, size_t size) { - char *s; + char *s=NULL; char *ret=NULL; - s=getenv("RANDFILE"); + if (OPENSSL_issetugid() == 0) + s=getenv("RANDFILE"); if (s != NULL) { strncpy(buf,s,size-1); @@ -153,14 +209,25 @@ int size; } else { - s=getenv("HOME"); - if (s == NULL) return(RFILE); - if (((int)(strlen(s)+strlen(RFILE)+2)) > size) - return(RFILE); - strcpy(buf,s); - strcat(buf,"/"); - strcat(buf,RFILE); - ret=buf; + if (OPENSSL_issetugid() == 0) + s=getenv("HOME"); +#ifdef DEFAULT_HOME + if (s == NULL) + { + s = DEFAULT_HOME; + } +#endif + if (s != NULL && (strlen(s)+strlen(RFILE)+2 < size)) + { + strcpy(buf,s); +#ifndef OPENSSL_SYS_VMS + strcat(buf,"/"); +#endif + strcat(buf,RFILE); + ret=buf; + } + else + buf[0] = '\0'; /* no file name */ } return(ret); } diff --git a/src/lib/libcrypto/rc2/rc2.h b/src/lib/libcrypto/rc2/rc2.h index 9571efb755..7816b454dc 100644 --- a/src/lib/libcrypto/rc2/rc2.h +++ b/src/lib/libcrypto/rc2/rc2.h @@ -59,11 +59,7 @@ #ifndef HEADER_RC2_H #define HEADER_RC2_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef NO_RC2 +#ifdef OPENSSL_NO_RC2 #error RC2 is disabled. #endif @@ -74,23 +70,29 @@ extern "C" { #define RC2_BLOCK 8 #define RC2_KEY_LENGTH 16 +#ifdef __cplusplus +extern "C" { +#endif + 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); -void RC2_ecb_encrypt(unsigned char *in,unsigned char *out,RC2_KEY *key, - int enc); +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits); +void RC2_ecb_encrypt(const unsigned char *in,unsigned char *out,RC2_KEY *key, + int enc); void RC2_encrypt(unsigned long *data,RC2_KEY *key); void RC2_decrypt(unsigned long *data,RC2_KEY *key); -void RC2_cbc_encrypt(unsigned char *in, unsigned char *out, long length, +void RC2_cbc_encrypt(const 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); +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num); #ifdef __cplusplus } diff --git a/src/lib/libcrypto/rc2/rc2_cbc.c b/src/lib/libcrypto/rc2/rc2_cbc.c index 22e89f0441..74f48d3d87 100644 --- a/src/lib/libcrypto/rc2/rc2_cbc.c +++ b/src/lib/libcrypto/rc2/rc2_cbc.c @@ -56,16 +56,11 @@ * [including the GNU Public Licence.] */ -#include "rc2.h" +#include #include "rc2_locl.h" -void RC2_cbc_encrypt(in, out, length, ks, iv, encrypt) -unsigned char *in; -unsigned char *out; -long length; -RC2_KEY *ks; -unsigned char *iv; -int encrypt; +void RC2_cbc_encrypt(const 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; @@ -138,9 +133,7 @@ int encrypt; tin[0]=tin[1]=0; } -void RC2_encrypt(d,key) -unsigned long *d; -RC2_KEY *key; +void RC2_encrypt(unsigned long *d, RC2_KEY *key) { int i,n; register RC2_INT *p0,*p1; @@ -185,9 +178,7 @@ RC2_KEY *key; d[1]=(unsigned long)(x2&0xffff)|((unsigned long)(x3&0xffff)<<16L); } -void RC2_decrypt(d,key) -unsigned long *d; -RC2_KEY *key; +void RC2_decrypt(unsigned long *d, RC2_KEY *key) { int i,n; register RC2_INT *p0,*p1; diff --git a/src/lib/libcrypto/rc2/rc2_ecb.c b/src/lib/libcrypto/rc2/rc2_ecb.c index 96239cd4e0..d3e8c2718a 100644 --- a/src/lib/libcrypto/rc2/rc2_ecb.c +++ b/src/lib/libcrypto/rc2/rc2_ecb.c @@ -56,10 +56,11 @@ * [including the GNU Public Licence.] */ -#include "rc2.h" +#include #include "rc2_locl.h" +#include -char *RC2_version="RC2 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *RC2_version="RC2" OPENSSL_VERSION_PTEXT; /* RC2 as implemented frm a posting from * Newsgroups: sci.crypt @@ -69,11 +70,8 @@ char *RC2_version="RC2 part of SSLeay 0.9.0b 29-Jun-1998"; * Date: 11 Feb 1996 06:45:03 GMT */ -void RC2_ecb_encrypt(in, out, ks, encrypt) -unsigned char *in; -unsigned char *out; -RC2_KEY *ks; -int encrypt; +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, RC2_KEY *ks, + int encrypt) { unsigned long l,d[2]; diff --git a/src/lib/libcrypto/rc2/rc2_skey.c b/src/lib/libcrypto/rc2/rc2_skey.c index 0f1f253395..cab3080c73 100644 --- a/src/lib/libcrypto/rc2/rc2_skey.c +++ b/src/lib/libcrypto/rc2/rc2_skey.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -#include "rc2.h" +#include #include "rc2_locl.h" static unsigned char key_table[256]={ @@ -90,11 +90,7 @@ static unsigned char key_table[256]={ * 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(key,len,data,bits) -RC2_KEY *key; -int len; -unsigned char *data; -int bits; +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits) { int i,j; unsigned char *k; diff --git a/src/lib/libcrypto/rc2/rc2cfb64.c b/src/lib/libcrypto/rc2/rc2cfb64.c index d409fb77e9..b3a0158a6e 100644 --- a/src/lib/libcrypto/rc2/rc2cfb64.c +++ b/src/lib/libcrypto/rc2/rc2cfb64.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -#include "rc2.h" +#include #include "rc2_locl.h" /* The input and output encrypted as though 64bit cfb mode is being @@ -64,14 +64,9 @@ * 64bit block we have used is contained in *num; */ -void RC2_cfb64_encrypt(in, out, length, schedule, ivec, num, encrypt) -unsigned char *in; -unsigned char *out; -long length; -RC2_KEY *schedule; -unsigned char *ivec; -int *num; -int encrypt; +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int encrypt) { register unsigned long v0,v1,t; register int n= *num; diff --git a/src/lib/libcrypto/rc2/rc2ofb64.c b/src/lib/libcrypto/rc2/rc2ofb64.c index 4f09167447..9e297867ed 100644 --- a/src/lib/libcrypto/rc2/rc2ofb64.c +++ b/src/lib/libcrypto/rc2/rc2ofb64.c @@ -56,20 +56,16 @@ * [including the GNU Public Licence.] */ -#include "rc2.h" +#include #include "rc2_locl.h" /* The input and output encrypted as though 64bit ofb mode is being * used. The extra state information to record how much of the * 64bit block we have used is contained in *num; */ -void RC2_ofb64_encrypt(in, out, length, schedule, ivec, num) -unsigned char *in; -unsigned char *out; -long length; -RC2_KEY *schedule; -unsigned char *ivec; -int *num; +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num) { register unsigned long v0,v1,t; register int n= *num; diff --git a/src/lib/libcrypto/rc4/asm/rc4-586.pl b/src/lib/libcrypto/rc4/asm/rc4-586.pl index 0dd8eb1ba9..7ef889e5a1 100644 --- a/src/lib/libcrypto/rc4/asm/rc4-586.pl +++ b/src/lib/libcrypto/rc4/asm/rc4-586.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # define for pentium pro friendly version diff --git a/src/lib/libcrypto/rc4/rc4.h b/src/lib/libcrypto/rc4/rc4.h index 7418c2a9a2..8722091f2e 100644 --- a/src/lib/libcrypto/rc4/rc4.h +++ b/src/lib/libcrypto/rc4/rc4.h @@ -59,16 +59,16 @@ #ifndef HEADER_RC4_H #define HEADER_RC4_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef NO_RC4 +#ifdef OPENSSL_NO_RC4 #error RC4 is disabled. #endif #include /* RC4_INT */ +#ifdef __cplusplus +extern "C" { +#endif + typedef struct rc4_key_st { RC4_INT x,y; @@ -77,8 +77,8 @@ typedef struct rc4_key_st const char *RC4_options(void); -void RC4_set_key(RC4_KEY *key, int len, unsigned char *data); -void RC4(RC4_KEY *key, unsigned long len, unsigned char *indata, +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata, unsigned char *outdata); #ifdef __cplusplus diff --git a/src/lib/libcrypto/rc4/rc4_enc.c b/src/lib/libcrypto/rc4/rc4_enc.c index ab8a111b52..d5f18a3a70 100644 --- a/src/lib/libcrypto/rc4/rc4_enc.c +++ b/src/lib/libcrypto/rc4/rc4_enc.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ -#include "rc4.h" +#include #include "rc4_locl.h" /* RC4 as implemented from a posting from @@ -67,11 +67,8 @@ * Date: Wed, 14 Sep 1994 06:35:31 GMT */ -void RC4(key, len, indata, outdata) -RC4_KEY *key; -unsigned long len; -unsigned char *indata; -unsigned char *outdata; +void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata, + unsigned char *outdata) { register RC4_INT *d; register RC4_INT x,y,tx,ty; @@ -81,6 +78,190 @@ unsigned char *outdata; y=key->y; d=key->data; +#if defined(RC4_CHUNK) + /* + * The original reason for implementing this(*) was the fact that + * pre-21164a Alpha CPUs don't have byte load/store instructions + * and e.g. a byte store has to be done with 64-bit load, shift, + * and, or and finally 64-bit store. Peaking data and operating + * at natural word size made it possible to reduce amount of + * instructions as well as to perform early read-ahead without + * suffering from RAW (read-after-write) hazard. This resulted + * in ~40%(**) performance improvement on 21064 box with gcc. + * But it's not only Alpha users who win here:-) Thanks to the + * early-n-wide read-ahead this implementation also exhibits + * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending + * on sizeof(RC4_INT)). + * + * (*) "this" means code which recognizes the case when input + * and output pointers appear to be aligned at natural CPU + * word boundary + * (**) i.e. according to 'apps/openssl speed rc4' benchmark, + * crypto/rc4/rc4speed.c exhibits almost 70% speed-up... + * + * Cavets. + * + * - RC4_CHUNK="unsigned long long" should be a #1 choice for + * UltraSPARC. Unfortunately gcc generates very slow code + * (2.5-3 times slower than one generated by Sun's WorkShop + * C) and therefore gcc (at least 2.95 and earlier) should + * always be told that RC4_CHUNK="unsigned long". + * + * + */ + +# define RC4_STEP ( \ + x=(x+1) &0xff, \ + tx=d[x], \ + y=(tx+y)&0xff, \ + ty=d[y], \ + d[y]=tx, \ + d[x]=ty, \ + (RC4_CHUNK)d[(tx+ty)&0xff]\ + ) + + if ( ( ((unsigned long)indata & (sizeof(RC4_CHUNK)-1)) | + ((unsigned long)outdata & (sizeof(RC4_CHUNK)-1)) ) == 0 ) + { + RC4_CHUNK ichunk,otp; + const union { long one; char little; } is_endian = {1}; + + /* + * I reckon we can afford to implement both endian + * cases and to decide which way to take at run-time + * because the machine code appears to be very compact + * and redundant 1-2KB is perfectly tolerable (i.e. + * in case the compiler fails to eliminate it:-). By + * suggestion from Terrel Larson + * who also stands for the is_endian union:-) + * + * Special notes. + * + * - is_endian is declared automatic as doing otherwise + * (declaring static) prevents gcc from eliminating + * the redundant code; + * - compilers (those I've tried) don't seem to have + * problems eliminating either the operators guarded + * by "if (sizeof(RC4_CHUNK)==8)" or the condition + * expressions themselves so I've got 'em to replace + * corresponding #ifdefs from the previous version; + * - I chose to let the redundant switch cases when + * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed + * before); + * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in + * [LB]ESHFT guards against "shift is out of range" + * warnings when sizeof(RC4_CHUNK)!=8 + * + * + */ + if (!is_endian.little) + { /* BIG-ENDIAN CASE */ +# define BESHFT(c) (((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1)) + for (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK)) + { + ichunk = *(RC4_CHUNK *)indata; + otp = RC4_STEP<x=x; + key->y=y; + return; + } + else + { /* LITTLE-ENDIAN CASE */ +# define LESHFT(c) (((c)*8)&(sizeof(RC4_CHUNK)*8-1)) + for (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK)) + { + ichunk = *(RC4_CHUNK *)indata; + otp = RC4_STEP; + otp |= RC4_STEP<<8; + otp |= RC4_STEP<<16; + otp |= RC4_STEP<<24; + if (sizeof(RC4_CHUNK)==8) + { + otp |= RC4_STEP<>= (sizeof(RC4_CHUNK)-len)<<3; + switch (len&(sizeof(RC4_CHUNK)-1)) + { + case 7: otp = RC4_STEP, i+=8; + case 6: otp |= RC4_STEP<x=x; + key->y=y; + return; + } + } +#endif #define LOOP(in,out) \ x=((x+1)&0xff); \ tx=d[x]; \ @@ -95,7 +276,6 @@ unsigned char *outdata; #define RC4_LOOP(a,b,i) LOOP(a[i],b[i]) #endif - i= -(int)len; i=(int)(len>>3L); if (i) { diff --git a/src/lib/libcrypto/rc4/rc4_skey.c b/src/lib/libcrypto/rc4/rc4_skey.c index 0be5fde67b..bb10c1ebe2 100644 --- a/src/lib/libcrypto/rc4/rc4_skey.c +++ b/src/lib/libcrypto/rc4/rc4_skey.c @@ -56,12 +56,13 @@ * [including the GNU Public Licence.] */ -#include "rc4.h" +#include #include "rc4_locl.h" +#include -char *RC4_version="RC4 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *RC4_version="RC4" OPENSSL_VERSION_PTEXT; -char *RC4_options() +const char *RC4_options(void) { #ifdef RC4_INDEX if (sizeof(RC4_INT) == 1) @@ -84,10 +85,7 @@ char *RC4_options() * Date: Wed, 14 Sep 1994 06:35:31 GMT */ -void RC4_set_key(key, len, data) -RC4_KEY *key; -int len; -register unsigned char *data; +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data) { register RC4_INT tmp; register int id1,id2; diff --git a/src/lib/libcrypto/ripemd/asm/rmd-586.pl b/src/lib/libcrypto/ripemd/asm/rmd-586.pl index dc3f6c792e..0ab6f76bff 100644 --- a/src/lib/libcrypto/ripemd/asm/rmd-586.pl +++ b/src/lib/libcrypto/ripemd/asm/rmd-586.pl @@ -1,9 +1,7 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl # Normal is the -# ripemd160_block_x86(MD5_CTX *c, ULONG *X); -# version, non-normal is the -# ripemd160_block_x86(MD5_CTX *c, ULONG *X,int blocks); +# ripemd160_block_asm_host_order(RIPEMD160_CTX *c, ULONG *X,int blocks); $normal=0; @@ -12,13 +10,13 @@ require "x86asm.pl"; &asm_init($ARGV[0],$0); -$A="eax"; -$B="ebx"; -$C="ecx"; -$D="edx"; +$A="ecx"; +$B="esi"; +$C="edi"; +$D="ebx"; $E="ebp"; -$tmp1="esi"; -$tmp2="edi"; +$tmp1="eax"; +$tmp2="edx"; $KL1=0x5A827999; $KL2=0x6ED9EBA1; @@ -58,13 +56,13 @@ $KR3=0x7A6D76E9; 8, 5,12, 9,12, 5,14, 6, 8,13, 6, 5,15,13,11,11, ); -&ripemd160_block("ripemd160_block_x86"); +&ripemd160_block("ripemd160_block_asm_host_order"); &asm_finish(); sub Xv { local($n)=@_; - return(&swtmp($n+1)); + return(&swtmp($n)); # tmp on stack } @@ -82,7 +80,7 @@ sub RIP1 &comment($p++); if ($p & 1) { - &mov($tmp1, $c) if $o == -1; + #&mov($tmp1, $c) if $o == -1; &xor($tmp1, $d) if $o == -1; &mov($tmp2, &Xv($pos)); &xor($tmp1, $b); @@ -290,7 +288,7 @@ sub RIP5 &rotl($c, 10); &lea($a, &DWP($K,$a,$tmp1,1)); &sub($tmp2, &Np($d)) if $o <= 0; - &mov(&swtmp(1+16), $A) if $o == 1; + &mov(&swtmp(16), $A) if $o == 1; &mov($tmp1, &Np($d)) if $o == 2; &rotl($a, $s); &add($a, $e); @@ -310,19 +308,25 @@ sub ripemd160_block # D 12 # E 16 + &mov($tmp2, &wparam(0)); + &mov($tmp1, &wparam(1)); &push("esi"); - &mov($C, &wparam(2)); + &mov($A, &DWP( 0,$tmp2,"",0)); &push("edi"); - &mov($tmp1, &wparam(1)); # edi + &mov($B, &DWP( 4,$tmp2,"",0)); &push("ebp"); - &add($C, $tmp1); # offset we end at + &mov($C, &DWP( 8,$tmp2,"",0)); &push("ebx"); - &sub($C, 64); - &stack_push(16+5+1); - # XXX - - &mov(&swtmp(0), $C); - &mov($tmp2, &wparam(0)); # Done at end of loop + &stack_push(16+5+6); + # Special comment about the figure of 6. + # Idea is to pad the current frame so + # that the top of the stack gets fairly + # aligned. Well, as you realize it would + # always depend on how the frame below is + # aligned. The good news are that gcc-2.95 + # and later does keep first argument at + # least double-wise aligned. + # &set_label("start") unless $normal; &comment(""); @@ -332,16 +336,12 @@ sub ripemd160_block for ($z=0; $z<16; $z+=2) { - &mov($A, &DWP( $z*4,$tmp1,"",0)); - &mov($B, &DWP( ($z+1)*4,$tmp1,"",0)); - &mov(&swtmp(1+$z), $A); - &mov(&swtmp(1+$z+1), $B); + &mov($D, &DWP( $z*4,$tmp1,"",0)); + &mov($E, &DWP( ($z+1)*4,$tmp1,"",0)); + &mov(&swtmp($z), $D); + &mov(&swtmp($z+1), $E); } - &add($tmp1, 64); - &mov($A, &DWP( 0,$tmp2,"",0)); - &mov(&wparam(1),$tmp1); - &mov($B, &DWP( 4,$tmp2,"",0)); - &mov($C, &DWP( 8,$tmp2,"",0)); + &mov($tmp1, $C); &mov($D, &DWP(12,$tmp2,"",0)); &mov($E, &DWP(16,$tmp2,"",0)); @@ -431,14 +431,14 @@ sub ripemd160_block &RIP5($B,$C,$D,$E,$A,$wl[79],$sl[79],$KL4,1); # &mov($tmp2, &wparam(0)); # moved into last RIP5 - # &mov(&swtmp(1+16), $A); + # &mov(&swtmp(16), $A); &mov($A, &DWP( 0,$tmp2,"",0)); - &mov(&swtmp(1+17), $B); - &mov(&swtmp(1+18), $C); + &mov(&swtmp(16+1), $B); + &mov(&swtmp(16+2), $C); &mov($B, &DWP( 4,$tmp2,"",0)); - &mov(&swtmp(1+19), $D); + &mov(&swtmp(16+3), $D); &mov($C, &DWP( 8,$tmp2,"",0)); - &mov(&swtmp(1+20), $E); + &mov(&swtmp(16+4), $E); &mov($D, &DWP(12,$tmp2,"",0)); &mov($E, &DWP(16,$tmp2,"",0)); @@ -530,47 +530,55 @@ sub ripemd160_block # &mov($tmp2, &wparam(0)); # Moved into last round &mov($tmp1, &DWP( 4,$tmp2,"",0)); # ctx->B - &add($D, $tmp1); - &mov($tmp1, &swtmp(1+18)); # $c + &add($D, $tmp1); + &mov($tmp1, &swtmp(16+2)); # $c &add($D, $tmp1); &mov($tmp1, &DWP( 8,$tmp2,"",0)); # ctx->C &add($E, $tmp1); - &mov($tmp1, &swtmp(1+19)); # $d + &mov($tmp1, &swtmp(16+3)); # $d &add($E, $tmp1); &mov($tmp1, &DWP(12,$tmp2,"",0)); # ctx->D &add($A, $tmp1); - &mov($tmp1, &swtmp(1+20)); # $e + &mov($tmp1, &swtmp(16+4)); # $e &add($A, $tmp1); &mov($tmp1, &DWP(16,$tmp2,"",0)); # ctx->E &add($B, $tmp1); - &mov($tmp1, &swtmp(1+16)); # $a + &mov($tmp1, &swtmp(16+0)); # $a &add($B, $tmp1); &mov($tmp1, &DWP( 0,$tmp2,"",0)); # ctx->A &add($C, $tmp1); - &mov($tmp1, &swtmp(1+17)); # $b + &mov($tmp1, &swtmp(16+1)); # $b &add($C, $tmp1); + &mov($tmp1, &wparam(2)); + &mov(&DWP( 0,$tmp2,"",0), $D); &mov(&DWP( 4,$tmp2,"",0), $E); &mov(&DWP( 8,$tmp2,"",0), $A); - &mov(&DWP(12,$tmp2,"",0), $B); - &mov(&DWP(16,$tmp2,"",0), $C); + &sub($tmp1,1); + &mov(&DWP(12,$tmp2,"",0), $B); + &mov(&DWP(16,$tmp2,"",0), $C); - &mov($tmp2, &swtmp(0)); - &mov($tmp1, &wparam(1)); + &jle(&label("get_out")); + + &mov(&wparam(2),$tmp1); + &mov($C, $A); + &mov($tmp1, &wparam(1)); + &mov($A, $D); + &add($tmp1, 64); + &mov($B, $E); + &mov(&wparam(1),$tmp1); - &cmp($tmp2,$tmp1); - &mov($tmp2, &wparam(0)); + &jmp(&label("start")); - # XXX - &jge(&label("start")); + &set_label("get_out"); - &stack_pop(16+5+1); + &stack_pop(16+5+6); &pop("ebx"); &pop("ebp"); diff --git a/src/lib/libcrypto/ripemd/ripemd.h b/src/lib/libcrypto/ripemd/ripemd.h index a3bc6e3ab2..78d5f36560 100644 --- a/src/lib/libcrypto/ripemd/ripemd.h +++ b/src/lib/libcrypto/ripemd/ripemd.h @@ -59,39 +59,43 @@ #ifndef HEADER_RIPEMD_H #define HEADER_RIPEMD_H +#include + #ifdef __cplusplus extern "C" { #endif +#ifdef OPENSSL_NO_RIPEMD +#error RIPEMD is disabled. +#endif + +#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__) +#define RIPEMD160_LONG unsigned long +#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +#define RIPEMD160_LONG unsigned long +#define RIPEMD160_LONG_LOG2 3 +#else +#define RIPEMD160_LONG unsigned int +#endif + #define RIPEMD160_CBLOCK 64 -#define RIPEMD160_LBLOCK 16 -#define RIPEMD160_BLOCK 16 -#define RIPEMD160_LAST_BLOCK 56 -#define RIPEMD160_LENGTH_BLOCK 8 +#define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) #define RIPEMD160_DIGEST_LENGTH 20 typedef struct RIPEMD160state_st { - unsigned long A,B,C,D,E; - unsigned long Nl,Nh; - unsigned long data[RIPEMD160_LBLOCK]; + RIPEMD160_LONG A,B,C,D,E; + RIPEMD160_LONG Nl,Nh; + RIPEMD160_LONG data[RIPEMD160_LBLOCK]; int num; } RIPEMD160_CTX; -#ifndef NOPROTO -void RIPEMD160_Init(RIPEMD160_CTX *c); -void RIPEMD160_Update(RIPEMD160_CTX *c, unsigned char *data, unsigned long len); -void RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c); -unsigned char *RIPEMD160(unsigned char *d, unsigned long n, unsigned char *md); -void RIPEMD160_Transform(RIPEMD160_CTX *c, unsigned char *b); -#else -void RIPEMD160_Init(); -void RIPEMD160_Update(); -void RIPEMD160_Final(); -unsigned char *RIPEMD160(); -void RIPEMD160_Transform(); -#endif - +int RIPEMD160_Init(RIPEMD160_CTX *c); +int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, unsigned long len); +int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c); +unsigned char *RIPEMD160(const unsigned char *d, unsigned long n, + unsigned char *md); +void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b); #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/ripemd/rmd_dgst.c b/src/lib/libcrypto/ripemd/rmd_dgst.c index 210de1977d..a3170f7c8a 100644 --- a/src/lib/libcrypto/ripemd/rmd_dgst.c +++ b/src/lib/libcrypto/ripemd/rmd_dgst.c @@ -58,27 +58,18 @@ #include #include "rmd_locl.h" +#include -char *RMD160_version="RIPEMD160 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *RMD160_version="RIPE-MD160" OPENSSL_VERSION_PTEXT; -#ifndef NOPROTO # ifdef RMD160_ASM void ripemd160_block_x86(RIPEMD160_CTX *c, unsigned long *p,int num); # define ripemd160_block ripemd160_block_x86 # else void ripemd160_block(RIPEMD160_CTX *c, unsigned long *p,int num); # endif -#else -# ifdef RMD160_ASM - void ripemd160_block_x86(); -# define ripemd160_block ripemd160_block_x86 -# else - static void ripemd160_block(); -# endif -#endif -void RIPEMD160_Init(c) -RIPEMD160_CTX *c; +int RIPEMD160_Init(RIPEMD160_CTX *c) { c->A=RIPEMD160_A; c->B=RIPEMD160_B; @@ -88,189 +79,24 @@ RIPEMD160_CTX *c; c->Nl=0; c->Nh=0; c->num=0; + return 1; } -void RIPEMD160_Update(c, data, len) -RIPEMD160_CTX *c; -register unsigned char *data; -unsigned long len; - { - register ULONG *p; - int sw,sc; - ULONG l; - - if (len == 0) return; - - l=(c->Nl+(len<<3))&0xffffffffL; - if (l < c->Nl) /* overflow */ - c->Nh++; - c->Nh+=(len>>29); - c->Nl=l; - - if (c->num != 0) - { - p=c->data; - sw=c->num>>2; - sc=c->num&0x03; - - if ((c->num+len) >= RIPEMD160_CBLOCK) - { - l= p[sw]; - p_c2l(data,l,sc); - p[sw++]=l; - for (; swnum); - - ripemd160_block(c,p,64); - c->num=0; - /* drop through and do the rest */ - } - else - { - int ew,ec; - - c->num+=(int)len; - if ((sc+len) < 4) /* ugly, add char's to a word */ - { - l= p[sw]; - p_c2l_p(data,l,sc,len); - p[sw]=l; - } - else - { - ew=(c->num>>2); - ec=(c->num&0x03); - l= p[sw]; - p_c2l(data,l,sc); - p[sw++]=l; - for (; sw < ew; sw++) - { c2l(data,l); p[sw]=l; } - if (ec) - { - c2l_p(data,l,ec); - p[sw]=l; - } - } - return; - } - } - /* we now can process the input data in blocks of RIPEMD160_CBLOCK - * chars and save the leftovers to c->data. */ -#ifdef L_ENDIAN - if ((((unsigned long)data)%sizeof(ULONG)) == 0) - { - sw=(int)len/RIPEMD160_CBLOCK; - if (sw > 0) - { - sw*=RIPEMD160_CBLOCK; - ripemd160_block(c,(ULONG *)data,sw); - data+=sw; - len-=sw; - } - } +#ifndef ripemd160_block_host_order +#ifdef X +#undef X #endif - p=c->data; - while (len >= RIPEMD160_CBLOCK) - { -#if defined(L_ENDIAN) || defined(B_ENDIAN) - if (p != (unsigned long *)data) - memcpy(p,data,RIPEMD160_CBLOCK); - data+=RIPEMD160_CBLOCK; -#ifdef B_ENDIAN - for (sw=(RIPEMD160_LBLOCK/4); sw; sw--) - { - Endian_Reverse32(p[0]); - Endian_Reverse32(p[1]); - Endian_Reverse32(p[2]); - Endian_Reverse32(p[3]); - p+=4; - } -#endif -#else - for (sw=(RIPEMD160_LBLOCK/4); sw; sw--) - { - c2l(data,l); *(p++)=l; - c2l(data,l); *(p++)=l; - c2l(data,l); *(p++)=l; - c2l(data,l); *(p++)=l; - } -#endif - p=c->data; - ripemd160_block(c,p,64); - len-=RIPEMD160_CBLOCK; - } - sc=(int)len; - c->num=sc; - if (sc) - { - sw=sc>>2; /* words to copy */ -#ifdef L_ENDIAN - p[sw]=0; - memcpy(p,data,sc); -#else - sc&=0x03; - for ( ; sw; sw--) - { c2l(data,l); *(p++)=l; } - c2l_p(data,l,sc); - *p=l; -#endif - } - } - -void RIPEMD160_Transform(c,b) -RIPEMD160_CTX *c; -unsigned char *b; +#define X(i) XX[i] +void ripemd160_block_host_order (RIPEMD160_CTX *ctx, const void *p, int num) { - ULONG p[16]; -#if !defined(L_ENDIAN) - ULONG *q; - int i; -#endif + const RIPEMD160_LONG *XX=p; + register unsigned long A,B,C,D,E; + register unsigned long a,b,c,d,e; -#if defined(B_ENDIAN) || defined(L_ENDIAN) - memcpy(p,b,64); -#ifdef B_ENDIAN - q=p; - for (i=(RIPEMD160_LBLOCK/4); i; i--) - { - Endian_Reverse32(q[0]); - Endian_Reverse32(q[1]); - Endian_Reverse32(q[2]); - Endian_Reverse32(q[3]); - q+=4; - } -#endif -#else - q=p; - for (i=(RIPEMD160_LBLOCK/4); i; i--) + for (;num--;XX+=HASH_LBLOCK) { - ULONG l; - c2l(b,l); *(q++)=l; - c2l(b,l); *(q++)=l; - c2l(b,l); *(q++)=l; - c2l(b,l); *(q++)=l; - } -#endif - ripemd160_block(c,p,64); - } - -#ifndef RMD160_ASM - -void ripemd160_block(ctx, X, num) -RIPEMD160_CTX *ctx; -register ULONG *X; -int num; - { - register ULONG A,B,C,D,E; - ULONG a,b,c,d,e; - for (;;) - { - A=ctx->A; B=ctx->B; C=ctx->C; D=ctx->D; E=ctx->E; + A=ctx->A; B=ctx->B; C=ctx->C; D=ctx->D; E=ctx->E; RIP1(A,B,C,D,E,WL00,SL00); RIP1(E,A,B,C,D,WL01,SL01); @@ -453,83 +279,216 @@ int num; ctx->E=ctx->A+b+C; ctx->A=D; - X+=16; - num-=64; - if (num <= 0) break; } } #endif -void RIPEMD160_Final(md, c) -unsigned char *md; -RIPEMD160_CTX *c; +#ifndef ripemd160_block_data_order +#ifdef X +#undef X +#endif +void ripemd160_block_data_order (RIPEMD160_CTX *ctx, const void *p, int num) { - register int i,j; - register ULONG l; - register ULONG *p; - static unsigned char end[4]={0x80,0x00,0x00,0x00}; - unsigned char *cp=end; - - /* c->num should definitly have room for at least one more byte. */ - p=c->data; - j=c->num; - i=j>>2; - - /* purify often complains about the following line as an - * Uninitialized Memory Read. While this can be true, the - * following p_c2l macro will reset l when that case is true. - * This is because j&0x03 contains the number of 'valid' bytes - * already in p[i]. If and only if j&0x03 == 0, the UMR will - * occur but this is also the only time p_c2l will do - * l= *(cp++) instead of l|= *(cp++) - * Many thanks to Alex Tang for pickup this - * 'potential bug' */ -#ifdef PURIFY - if ((j&0x03) == 0) p[i]=0; + const unsigned char *data=p; + register unsigned long A,B,C,D,E; + unsigned long a,b,c,d,e,l; +#ifndef MD32_XARRAY + /* See comment in crypto/sha/sha_locl.h for details. */ + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +# define X(i) XX##i +#else + RIPEMD160_LONG XX[16]; +# define X(i) XX[i] #endif - l=p[i]; - p_c2l(cp,l,j&0x03); - p[i]=l; - i++; - /* i is the next 'undefined word' */ - if (c->num >= RIPEMD160_LAST_BLOCK) + + for (;num--;) { - for (; iNl; - p[RIPEMD160_LBLOCK-1]=c->Nh; - ripemd160_block(c,p,64); - cp=md; - l=c->A; l2c(l,cp); - l=c->B; l2c(l,cp); - l=c->C; l2c(l,cp); - l=c->D; l2c(l,cp); - l=c->E; l2c(l,cp); - - /* clear stuff, ripemd160_block may be leaving some stuff on the stack - * but I'm not worried :-) */ - c->num=0; -/* memset((char *)&c,0,sizeof(c));*/ - } -#ifdef undef -int printit(l) -unsigned long *l; - { - int i,ii; + A=ctx->A; B=ctx->B; C=ctx->C; D=ctx->D; E=ctx->E; + + HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + RIP1(A,B,C,D,E,WL00,SL00); HOST_c2l(data,l); X( 2)=l; + RIP1(E,A,B,C,D,WL01,SL01); HOST_c2l(data,l); X( 3)=l; + RIP1(D,E,A,B,C,WL02,SL02); HOST_c2l(data,l); X( 4)=l; + RIP1(C,D,E,A,B,WL03,SL03); HOST_c2l(data,l); X( 5)=l; + RIP1(B,C,D,E,A,WL04,SL04); HOST_c2l(data,l); X( 6)=l; + RIP1(A,B,C,D,E,WL05,SL05); HOST_c2l(data,l); X( 7)=l; + RIP1(E,A,B,C,D,WL06,SL06); HOST_c2l(data,l); X( 8)=l; + RIP1(D,E,A,B,C,WL07,SL07); HOST_c2l(data,l); X( 9)=l; + RIP1(C,D,E,A,B,WL08,SL08); HOST_c2l(data,l); X(10)=l; + RIP1(B,C,D,E,A,WL09,SL09); HOST_c2l(data,l); X(11)=l; + RIP1(A,B,C,D,E,WL10,SL10); HOST_c2l(data,l); X(12)=l; + RIP1(E,A,B,C,D,WL11,SL11); HOST_c2l(data,l); X(13)=l; + RIP1(D,E,A,B,C,WL12,SL12); HOST_c2l(data,l); X(14)=l; + RIP1(C,D,E,A,B,WL13,SL13); HOST_c2l(data,l); X(15)=l; + RIP1(B,C,D,E,A,WL14,SL14); + RIP1(A,B,C,D,E,WL15,SL15); + + RIP2(E,A,B,C,D,WL16,SL16,KL1); + RIP2(D,E,A,B,C,WL17,SL17,KL1); + RIP2(C,D,E,A,B,WL18,SL18,KL1); + RIP2(B,C,D,E,A,WL19,SL19,KL1); + RIP2(A,B,C,D,E,WL20,SL20,KL1); + RIP2(E,A,B,C,D,WL21,SL21,KL1); + RIP2(D,E,A,B,C,WL22,SL22,KL1); + RIP2(C,D,E,A,B,WL23,SL23,KL1); + RIP2(B,C,D,E,A,WL24,SL24,KL1); + RIP2(A,B,C,D,E,WL25,SL25,KL1); + RIP2(E,A,B,C,D,WL26,SL26,KL1); + RIP2(D,E,A,B,C,WL27,SL27,KL1); + RIP2(C,D,E,A,B,WL28,SL28,KL1); + RIP2(B,C,D,E,A,WL29,SL29,KL1); + RIP2(A,B,C,D,E,WL30,SL30,KL1); + RIP2(E,A,B,C,D,WL31,SL31,KL1); + + RIP3(D,E,A,B,C,WL32,SL32,KL2); + RIP3(C,D,E,A,B,WL33,SL33,KL2); + RIP3(B,C,D,E,A,WL34,SL34,KL2); + RIP3(A,B,C,D,E,WL35,SL35,KL2); + RIP3(E,A,B,C,D,WL36,SL36,KL2); + RIP3(D,E,A,B,C,WL37,SL37,KL2); + RIP3(C,D,E,A,B,WL38,SL38,KL2); + RIP3(B,C,D,E,A,WL39,SL39,KL2); + RIP3(A,B,C,D,E,WL40,SL40,KL2); + RIP3(E,A,B,C,D,WL41,SL41,KL2); + RIP3(D,E,A,B,C,WL42,SL42,KL2); + RIP3(C,D,E,A,B,WL43,SL43,KL2); + RIP3(B,C,D,E,A,WL44,SL44,KL2); + RIP3(A,B,C,D,E,WL45,SL45,KL2); + RIP3(E,A,B,C,D,WL46,SL46,KL2); + RIP3(D,E,A,B,C,WL47,SL47,KL2); + + RIP4(C,D,E,A,B,WL48,SL48,KL3); + RIP4(B,C,D,E,A,WL49,SL49,KL3); + RIP4(A,B,C,D,E,WL50,SL50,KL3); + RIP4(E,A,B,C,D,WL51,SL51,KL3); + RIP4(D,E,A,B,C,WL52,SL52,KL3); + RIP4(C,D,E,A,B,WL53,SL53,KL3); + RIP4(B,C,D,E,A,WL54,SL54,KL3); + RIP4(A,B,C,D,E,WL55,SL55,KL3); + RIP4(E,A,B,C,D,WL56,SL56,KL3); + RIP4(D,E,A,B,C,WL57,SL57,KL3); + RIP4(C,D,E,A,B,WL58,SL58,KL3); + RIP4(B,C,D,E,A,WL59,SL59,KL3); + RIP4(A,B,C,D,E,WL60,SL60,KL3); + RIP4(E,A,B,C,D,WL61,SL61,KL3); + RIP4(D,E,A,B,C,WL62,SL62,KL3); + RIP4(C,D,E,A,B,WL63,SL63,KL3); + + RIP5(B,C,D,E,A,WL64,SL64,KL4); + RIP5(A,B,C,D,E,WL65,SL65,KL4); + RIP5(E,A,B,C,D,WL66,SL66,KL4); + RIP5(D,E,A,B,C,WL67,SL67,KL4); + RIP5(C,D,E,A,B,WL68,SL68,KL4); + RIP5(B,C,D,E,A,WL69,SL69,KL4); + RIP5(A,B,C,D,E,WL70,SL70,KL4); + RIP5(E,A,B,C,D,WL71,SL71,KL4); + RIP5(D,E,A,B,C,WL72,SL72,KL4); + RIP5(C,D,E,A,B,WL73,SL73,KL4); + RIP5(B,C,D,E,A,WL74,SL74,KL4); + RIP5(A,B,C,D,E,WL75,SL75,KL4); + RIP5(E,A,B,C,D,WL76,SL76,KL4); + RIP5(D,E,A,B,C,WL77,SL77,KL4); + RIP5(C,D,E,A,B,WL78,SL78,KL4); + RIP5(B,C,D,E,A,WL79,SL79,KL4); + + a=A; b=B; c=C; d=D; e=E; + /* Do other half */ + A=ctx->A; B=ctx->B; C=ctx->C; D=ctx->D; E=ctx->E; + + RIP5(A,B,C,D,E,WR00,SR00,KR0); + RIP5(E,A,B,C,D,WR01,SR01,KR0); + RIP5(D,E,A,B,C,WR02,SR02,KR0); + RIP5(C,D,E,A,B,WR03,SR03,KR0); + RIP5(B,C,D,E,A,WR04,SR04,KR0); + RIP5(A,B,C,D,E,WR05,SR05,KR0); + RIP5(E,A,B,C,D,WR06,SR06,KR0); + RIP5(D,E,A,B,C,WR07,SR07,KR0); + RIP5(C,D,E,A,B,WR08,SR08,KR0); + RIP5(B,C,D,E,A,WR09,SR09,KR0); + RIP5(A,B,C,D,E,WR10,SR10,KR0); + RIP5(E,A,B,C,D,WR11,SR11,KR0); + RIP5(D,E,A,B,C,WR12,SR12,KR0); + RIP5(C,D,E,A,B,WR13,SR13,KR0); + RIP5(B,C,D,E,A,WR14,SR14,KR0); + RIP5(A,B,C,D,E,WR15,SR15,KR0); + + RIP4(E,A,B,C,D,WR16,SR16,KR1); + RIP4(D,E,A,B,C,WR17,SR17,KR1); + RIP4(C,D,E,A,B,WR18,SR18,KR1); + RIP4(B,C,D,E,A,WR19,SR19,KR1); + RIP4(A,B,C,D,E,WR20,SR20,KR1); + RIP4(E,A,B,C,D,WR21,SR21,KR1); + RIP4(D,E,A,B,C,WR22,SR22,KR1); + RIP4(C,D,E,A,B,WR23,SR23,KR1); + RIP4(B,C,D,E,A,WR24,SR24,KR1); + RIP4(A,B,C,D,E,WR25,SR25,KR1); + RIP4(E,A,B,C,D,WR26,SR26,KR1); + RIP4(D,E,A,B,C,WR27,SR27,KR1); + RIP4(C,D,E,A,B,WR28,SR28,KR1); + RIP4(B,C,D,E,A,WR29,SR29,KR1); + RIP4(A,B,C,D,E,WR30,SR30,KR1); + RIP4(E,A,B,C,D,WR31,SR31,KR1); + + RIP3(D,E,A,B,C,WR32,SR32,KR2); + RIP3(C,D,E,A,B,WR33,SR33,KR2); + RIP3(B,C,D,E,A,WR34,SR34,KR2); + RIP3(A,B,C,D,E,WR35,SR35,KR2); + RIP3(E,A,B,C,D,WR36,SR36,KR2); + RIP3(D,E,A,B,C,WR37,SR37,KR2); + RIP3(C,D,E,A,B,WR38,SR38,KR2); + RIP3(B,C,D,E,A,WR39,SR39,KR2); + RIP3(A,B,C,D,E,WR40,SR40,KR2); + RIP3(E,A,B,C,D,WR41,SR41,KR2); + RIP3(D,E,A,B,C,WR42,SR42,KR2); + RIP3(C,D,E,A,B,WR43,SR43,KR2); + RIP3(B,C,D,E,A,WR44,SR44,KR2); + RIP3(A,B,C,D,E,WR45,SR45,KR2); + RIP3(E,A,B,C,D,WR46,SR46,KR2); + RIP3(D,E,A,B,C,WR47,SR47,KR2); + + RIP2(C,D,E,A,B,WR48,SR48,KR3); + RIP2(B,C,D,E,A,WR49,SR49,KR3); + RIP2(A,B,C,D,E,WR50,SR50,KR3); + RIP2(E,A,B,C,D,WR51,SR51,KR3); + RIP2(D,E,A,B,C,WR52,SR52,KR3); + RIP2(C,D,E,A,B,WR53,SR53,KR3); + RIP2(B,C,D,E,A,WR54,SR54,KR3); + RIP2(A,B,C,D,E,WR55,SR55,KR3); + RIP2(E,A,B,C,D,WR56,SR56,KR3); + RIP2(D,E,A,B,C,WR57,SR57,KR3); + RIP2(C,D,E,A,B,WR58,SR58,KR3); + RIP2(B,C,D,E,A,WR59,SR59,KR3); + RIP2(A,B,C,D,E,WR60,SR60,KR3); + RIP2(E,A,B,C,D,WR61,SR61,KR3); + RIP2(D,E,A,B,C,WR62,SR62,KR3); + RIP2(C,D,E,A,B,WR63,SR63,KR3); + + RIP1(B,C,D,E,A,WR64,SR64); + RIP1(A,B,C,D,E,WR65,SR65); + RIP1(E,A,B,C,D,WR66,SR66); + RIP1(D,E,A,B,C,WR67,SR67); + RIP1(C,D,E,A,B,WR68,SR68); + RIP1(B,C,D,E,A,WR69,SR69); + RIP1(A,B,C,D,E,WR70,SR70); + RIP1(E,A,B,C,D,WR71,SR71); + RIP1(D,E,A,B,C,WR72,SR72); + RIP1(C,D,E,A,B,WR73,SR73); + RIP1(B,C,D,E,A,WR74,SR74); + RIP1(A,B,C,D,E,WR75,SR75); + RIP1(E,A,B,C,D,WR76,SR76); + RIP1(D,E,A,B,C,WR77,SR77); + RIP1(C,D,E,A,B,WR78,SR78); + RIP1(B,C,D,E,A,WR79,SR79); + + D =ctx->B+c+D; + ctx->B=ctx->C+d+E; + ctx->C=ctx->D+e+A; + ctx->D=ctx->E+a+B; + ctx->E=ctx->A+b+C; + ctx->A=D; - for (i=0; i<2; i++) - { - for (ii=0; ii<8; ii++) - { - fprintf(stderr,"%08lx ",l[i*8+ii]); - } - fprintf(stderr,"\n"); } } #endif diff --git a/src/lib/libcrypto/ripemd/rmd_locl.h b/src/lib/libcrypto/ripemd/rmd_locl.h index a1feccf7c1..7b835dfbd4 100644 --- a/src/lib/libcrypto/ripemd/rmd_locl.h +++ b/src/lib/libcrypto/ripemd/rmd_locl.h @@ -58,138 +58,72 @@ #include #include -#include "ripemd.h" +#include +#include -#define ULONG unsigned long -#define UCHAR unsigned char -#define UINT unsigned int +#ifndef RIPEMD160_LONG_LOG2 +#define RIPEMD160_LONG_LOG2 2 /* default to 32 bits */ +#endif -#ifdef NOCONST -#define const +/* + * DO EXAMINE COMMENTS IN crypto/md5/md5_locl.h & crypto/md5/md5_dgst.c + * FOR EXPLANATIONS ON FOLLOWING "CODE." + * + */ +#ifdef RMD160_ASM +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) +# define ripemd160_block_host_order ripemd160_block_asm_host_order +# endif #endif -#undef c2nl -#define c2nl(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++))) )) - -#undef p_c2nl -#define p_c2nl(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++)))<<24; \ - case 1: l|=((unsigned long)(*((c)++)))<<16; \ - case 2: l|=((unsigned long)(*((c)++)))<< 8; \ - case 3: l|=((unsigned long)(*((c)++))); \ - } \ - } - -#undef c2nl_p -/* NOTE the pointer is not incremented at the end of this */ -#define c2nl_p(c,l,n) { \ - l=0; \ - (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<< 8; \ - case 2: l|=((unsigned long)(*(--(c))))<<16; \ - case 1: l|=((unsigned long)(*(--(c))))<<24; \ - } \ - } - -#undef p_c2nl_p -#define p_c2nl_p(c,l,sc,len) { \ - switch (sc) \ - { \ - case 0: l =((unsigned long)(*((c)++)))<<24; \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<<16; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<< 8; \ - } \ - } - -#undef nl2c -#define nl2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - -#undef c2l -#define c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<<24)) - -#undef p_c2l -#define p_c2l(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++))); \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - case 3: l|=((unsigned long)(*((c)++)))<<24; \ - } \ - } - -#undef c2l_p -/* NOTE the pointer is not incremented at the end of this */ -#define c2l_p(c,l,n) { \ - l=0; \ - (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<<16; \ - case 2: l|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l|=((unsigned long)(*(--(c)))); \ - } \ - } - -#undef p_c2l_p -#define p_c2l_p(c,l,sc,len) { \ - switch (sc) \ - { \ - case 0: l =((unsigned long)(*((c)++))); \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - } \ - } - -#undef l2c -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) - -#undef ROTATE -#if defined(WIN32) -#define ROTATE(a,n) _lrotl(a,n) -#else -#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +void ripemd160_block_host_order (RIPEMD160_CTX *c, const void *p,int num); +void ripemd160_block_data_order (RIPEMD160_CTX *c, const void *p,int num); + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) +#define ripemd160_block_data_order ripemd160_block_host_order #endif -/* A nice byte order reversal from Wei Dai */ -#if defined(WIN32) -/* 5 instructions with rotate instruction, else 9 */ -#define Endian_Reverse32(a) \ - { \ - unsigned long l=(a); \ - (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ - } -#else -/* 6 instructions with rotate instruction, else 8 */ -#define Endian_Reverse32(a) \ - { \ - unsigned long l=(a); \ - l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ - (a)=ROTATE(l,16L); \ - } +#define DATA_ORDER_IS_LITTLE_ENDIAN + +#define HASH_LONG RIPEMD160_LONG +#define HASH_LONG_LOG2 RIPEMD160_LONG_LOG2 +#define HASH_CTX RIPEMD160_CTX +#define HASH_CBLOCK RIPEMD160_CBLOCK +#define HASH_LBLOCK RIPEMD160_LBLOCK +#define HASH_UPDATE RIPEMD160_Update +#define HASH_TRANSFORM RIPEMD160_Transform +#define HASH_FINAL RIPEMD160_Final +#define HASH_BLOCK_HOST_ORDER ripemd160_block_host_order +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->A; HOST_l2c(ll,(s)); \ + ll=(c)->B; HOST_l2c(ll,(s)); \ + ll=(c)->C; HOST_l2c(ll,(s)); \ + ll=(c)->D; HOST_l2c(ll,(s)); \ + ll=(c)->E; HOST_l2c(ll,(s)); \ + } while (0) +#if !defined(L_ENDIAN) || defined(ripemd160_block_data_order) +#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order #endif +#include "md32_common.h" + +#if 0 #define F1(x,y,z) ((x)^(y)^(z)) #define F2(x,y,z) (((x)&(y))|((~x)&z)) #define F3(x,y,z) (((x)|(~y))^(z)) #define F4(x,y,z) (((x)&(z))|((y)&(~(z)))) #define F5(x,y,z) ((x)^((y)|(~(z)))) +#else +/* + * Transformed F2 and F4 are courtesy of Wei Dai + */ +#define F1(x,y,z) ((x) ^ (y) ^ (z)) +#define F2(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) +#define F3(x,y,z) (((~(y)) | (x)) ^ (z)) +#define F4(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) +#define F5(x,y,z) (((~(z)) | (y)) ^ (x)) +#endif #define RIPEMD160_A 0x67452301L #define RIPEMD160_B 0xEFCDAB89L @@ -200,27 +134,27 @@ #include "rmdconst.h" #define RIP1(a,b,c,d,e,w,s) { \ - a+=F1(b,c,d)+X[w]; \ + a+=F1(b,c,d)+X(w); \ a=ROTATE(a,s)+e; \ c=ROTATE(c,10); } #define RIP2(a,b,c,d,e,w,s,K) { \ - a+=F2(b,c,d)+X[w]+K; \ + a+=F2(b,c,d)+X(w)+K; \ a=ROTATE(a,s)+e; \ c=ROTATE(c,10); } #define RIP3(a,b,c,d,e,w,s,K) { \ - a+=F3(b,c,d)+X[w]+K; \ + a+=F3(b,c,d)+X(w)+K; \ a=ROTATE(a,s)+e; \ c=ROTATE(c,10); } #define RIP4(a,b,c,d,e,w,s,K) { \ - a+=F4(b,c,d)+X[w]+K; \ + a+=F4(b,c,d)+X(w)+K; \ a=ROTATE(a,s)+e; \ c=ROTATE(c,10); } #define RIP5(a,b,c,d,e,w,s,K) { \ - a+=F5(b,c,d)+X[w]+K; \ + a+=F5(b,c,d)+X(w)+K; \ a=ROTATE(a,s)+e; \ c=ROTATE(c,10); } diff --git a/src/lib/libcrypto/ripemd/rmd_one.c b/src/lib/libcrypto/ripemd/rmd_one.c index a7626dbcda..efdf2dd6ef 100644 --- a/src/lib/libcrypto/ripemd/rmd_one.c +++ b/src/lib/libcrypto/ripemd/rmd_one.c @@ -57,12 +57,11 @@ */ #include -#include "rmd_locl.h" +#include +#include -unsigned char *RIPEMD160(d, n, md) -unsigned char *d; -unsigned long n; -unsigned char *md; +unsigned char *RIPEMD160(const unsigned char *d, unsigned long n, + unsigned char *md) { RIPEMD160_CTX c; static unsigned char m[RIPEMD160_DIGEST_LENGTH]; diff --git a/src/lib/libcrypto/rsa/rsa.h b/src/lib/libcrypto/rsa/rsa.h index aeb78ffcd3..030a6c88e5 100644 --- a/src/lib/libcrypto/rsa/rsa.h +++ b/src/lib/libcrypto/rsa/rsa.h @@ -59,36 +59,73 @@ #ifndef HEADER_RSA_H #define HEADER_RSA_H +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled. +#endif + #ifdef __cplusplus extern "C" { #endif -#include "bn.h" -#include "crypto.h" +typedef struct rsa_st RSA; typedef struct rsa_meth_st { - char *name; - int (*rsa_pub_enc)(); - int (*rsa_pub_dec)(); - int (*rsa_priv_enc)(); - int (*rsa_priv_dec)(); - int (*rsa_mod_exp)(); /* Can be null */ - int (*bn_mod_exp)(); /* Can be null */ - int (*init)(/* RSA * */); /* called at new */ - int (*finish)(/* RSA * */); /* called at free */ - + const char *name; + int (*rsa_pub_enc)(int flen,const unsigned char *from, + unsigned char *to, + RSA *rsa,int padding); + int (*rsa_pub_dec)(int flen,const unsigned char *from, + unsigned char *to, + RSA *rsa,int padding); + int (*rsa_priv_enc)(int flen,const unsigned char *from, + unsigned char *to, + RSA *rsa,int padding); + int (*rsa_priv_dec)(int flen,const unsigned char *from, + unsigned char *to, + RSA *rsa,int padding); + int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa); /* Can be null */ + int (*bn_mod_exp)(BIGNUM *r, const 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, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); + int (*rsa_verify)(int dtype, + const unsigned char *m, unsigned int m_length, + unsigned char *sigbuf, unsigned int siglen, const RSA *rsa); + } RSA_METHOD; -typedef struct rsa_st +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; - RSA_METHOD *meth; + long version; + const RSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; BIGNUM *n; BIGNUM *e; BIGNUM *d; @@ -97,203 +134,182 @@ typedef struct rsa_st BIGNUM *dmp1; BIGNUM *dmq1; BIGNUM *iqmp; - /* be carefull using this if the RSA structure is shared */ + /* be careful using this if the RSA structure is shared */ CRYPTO_EX_DATA ex_data; int references; int flags; - /* Normally used to cached montgomery values */ - char *method_mod_n; - char *method_mod_p; - char *method_mod_q; + /* 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; BN_BLINDING *blinding; - } RSA; + }; #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,(char *)arg) +#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) -#ifndef NOPROTO RSA * RSA_new(void); -RSA * RSA_new_method(RSA_METHOD *method); -int RSA_size(RSA *); +RSA * RSA_new_method(ENGINE *engine); +int RSA_size(const RSA *); RSA * RSA_generate_key(int bits, unsigned long e,void - (*callback)(int,int,char *),char *cb_arg); + (*callback)(int,int,void *),void *cb_arg); +int RSA_check_key(const RSA *); /* next 4 return -1 on error */ -int RSA_public_encrypt(int flen, unsigned char *from, +int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -int RSA_private_encrypt(int flen, unsigned char *from, +int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -int RSA_public_decrypt(int flen, unsigned char *from, +int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -int RSA_private_decrypt(int flen, unsigned char *from, +int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); void RSA_free (RSA *r); +/* "up" the RSA object's reference count */ +int RSA_up_ref(RSA *r); -int RSA_flags(RSA *r); +int RSA_flags(const RSA *r); -void RSA_set_default_method(RSA_METHOD *meth); +void RSA_set_default_method(const RSA_METHOD *meth); +const RSA_METHOD *RSA_get_default_method(void); +const RSA_METHOD *RSA_get_method(const RSA *rsa); +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); -/* If you have RSAref compiled in. */ -RSA_METHOD *RSA_PKCS1_RSAref(void); +/* This function needs the memory locking malloc callbacks to be installed */ +int RSA_memory_lock(RSA *r); /* these are the actual SSLeay RSA functions */ -RSA_METHOD *RSA_PKCS1_SSLeay(void); +const RSA_METHOD *RSA_PKCS1_SSLeay(void); + +const RSA_METHOD *RSA_null_method(void); -void ERR_load_RSA_strings(void ); +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey) -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); +#ifndef OPENSSL_NO_FP_API +int RSA_print_fp(FILE *fp, const RSA *r,int offset); #endif -#ifdef HEADER_BIO_H -int RSA_print(BIO *bp, RSA *r,int offset); +#ifndef OPENSSL_NO_BIO +int RSA_print(BIO *bp, const 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)()); +int i2d_RSA_NET(const RSA *a, unsigned char **pp, int (*cb)(), int sgckey); +RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length, int (*cb)(), int sgckey); + +int i2d_Netscape_RSA(const RSA *a, unsigned char **pp, int (*cb)()); +RSA *d2i_Netscape_RSA(RSA **a, const 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, +int RSA_sign(int type, const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, RSA *rsa); -int RSA_verify(int type, unsigned char *m, unsigned int m_len, +int RSA_verify(int type, const unsigned char *m, unsigned int m_length, 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, +int RSA_sign_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, RSA *rsa); -int RSA_verify_ASN1_OCTET_STRING(int type, unsigned char *m, unsigned int m_len, +int RSA_verify_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_length, 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); + const unsigned char *f,int fl); int RSA_padding_check_PKCS1_type_1(unsigned char *to,int tlen, - unsigned char *f,int fl); + const 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); + const unsigned char *f,int fl); int RSA_padding_check_PKCS1_type_2(unsigned char *to,int tlen, - unsigned char *f,int fl); + const unsigned char *f,int fl,int rsa_len); +int RSA_padding_add_PKCS1_OAEP(unsigned char *to,int tlen, + const unsigned char *f,int fl, + const unsigned char *p,int pl); +int RSA_padding_check_PKCS1_OAEP(unsigned char *to,int tlen, + const unsigned char *f,int fl,int rsa_len, + const unsigned char *p,int pl); int RSA_padding_add_SSLv23(unsigned char *to,int tlen, - unsigned char *f,int fl); + const unsigned char *f,int fl); int RSA_padding_check_SSLv23(unsigned char *to,int tlen, - unsigned char *f,int fl); + const unsigned char *f,int fl,int rsa_len); int RSA_padding_add_none(unsigned char *to,int tlen, - unsigned char *f,int fl); + const unsigned char *f,int fl); int RSA_padding_check_none(unsigned char *to,int tlen, - unsigned char *f,int fl); - -int RSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); -int RSA_set_ex_data(RSA *r,int idx,char *arg); -char *RSA_get_ex_data(RSA *r, int idx); - -#else - -RSA * RSA_new(); -RSA * RSA_new_method(); -int RSA_size(); -RSA * RSA_generate_key(); -int RSA_public_encrypt(); -int RSA_private_encrypt(); -int RSA_public_decrypt(); -int RSA_private_decrypt(); -void RSA_free (); + const unsigned char *f,int fl,int rsa_len); -int RSA_flags(); - -void RSA_set_default_method(); - -/* RSA_METHOD *RSA_PKCS1_RSAref(); */ -RSA_METHOD *RSA_PKCS1_SSLeay(); - -void ERR_load_RSA_strings(); - -RSA * d2i_RSAPublicKey(); -int i2d_RSAPublicKey(); -RSA * d2i_RSAPrivateKey(); -int i2d_RSAPrivateKey(); -#ifndef NO_FP_API -int RSA_print_fp(); -#endif - -int RSA_print(); - -int i2d_Netscape_RSA(); -RSA *d2i_Netscape_RSA(); -RSA *d2i_Netscape_RSA_2(); - -int RSA_sign(); -int RSA_verify(); - -int RSA_sign_ASN1_OCTET_STRING(); -int RSA_verify_ASN1_OCTET_STRING(); -int RSA_blinding_on(); -void RSA_blinding_off(); - -int RSA_padding_add_PKCS1_type_1(); -int RSA_padding_check_PKCS1_type_1(); -int RSA_padding_add_PKCS1_type_2(); -int RSA_padding_check_PKCS1_type_2(); -int RSA_padding_add_SSLv23(); -int RSA_padding_check_SSLv23(); -int RSA_padding_add_none(); -int RSA_padding_check_none(); - -int RSA_get_ex_new_index(); -int RSA_set_ex_data(); -char *RSA_get_ex_data(); - -#endif +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(const RSA *r, int idx); /* 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. + */ +void ERR_load_RSA_strings(void); + /* Error codes for the RSA functions. */ /* Function codes. */ -#define RSA_F_RSA_EAY_PRIVATE_DECRYPT 100 -#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT 101 -#define RSA_F_RSA_EAY_PUBLIC_DECRYPT 102 -#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 103 -#define RSA_F_RSA_GENERATE_KEY 104 -#define RSA_F_RSA_NEW_METHOD 105 -#define RSA_F_RSA_PADDING_ADD_NONE 106 -#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 107 -#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 108 -#define RSA_F_RSA_PADDING_ADD_SSLV23 109 -#define RSA_F_RSA_PADDING_CHECK_NONE 110 -#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 111 -#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 112 -#define RSA_F_RSA_PADDING_CHECK_SSLV23 113 -#define RSA_F_RSA_PRINT 114 -#define RSA_F_RSA_PRINT_FP 115 -#define RSA_F_RSA_SIGN 116 -#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 117 -#define RSA_F_RSA_VERIFY 118 -#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 119 +#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 @@ -301,24 +317,35 @@ char *RSA_get_ex_data(); #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_BAD_ZERO_BYTE 105 #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_LARGE_FOR_MODULUS 132 #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/src/lib/libcrypto/rsa/rsa_chk.c b/src/lib/libcrypto/rsa/rsa_chk.c index 91b9115798..002f2cb487 100644 --- a/src/lib/libcrypto/rsa/rsa_chk.c +++ b/src/lib/libcrypto/rsa/rsa_chk.c @@ -53,7 +53,7 @@ #include -int RSA_check_key(RSA *key) +int RSA_check_key(const RSA *key) { BIGNUM *i, *j, *k, *l, *m; BN_CTX *ctx; diff --git a/src/lib/libcrypto/rsa/rsa_eay.c b/src/lib/libcrypto/rsa/rsa_eay.c index 42a77f11cd..0eda816081 100644 --- a/src/lib/libcrypto/rsa/rsa_eay.c +++ b/src/lib/libcrypto/rsa/rsa_eay.c @@ -1,13 +1,3 @@ - -/* This file has been explicitly broken by ryker for OpenBSD, July - * 1, 1998. In spite of the title, there is no implementation of the - * RSA algorithm left in this file. All these routines will return an - * error and fail when called. They exist as stubs and can be - * ressurected from the bit bucket by someone in the free world once - * the RSA algorithm is no longer subject to patent problems. Eric - * Young's original copyright is below. - */ - /* crypto/rsa/rsa_eay.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. @@ -68,207 +58,552 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "rand.h" +#include +#include +#include +#include -#ifndef NOPROTO -static int RSA_eay_public_encrypt(int flen, unsigned char *from, +#ifndef RSA_NULL + +static int RSA_eay_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -static int RSA_eay_private_encrypt(int flen, unsigned char *from, +static int RSA_eay_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -static int RSA_eay_public_decrypt(int flen, unsigned char *from, +static int RSA_eay_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -static int RSA_eay_private_decrypt(int flen, unsigned char *from, +static int RSA_eay_private_decrypt(int flen, const 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_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa); static int RSA_eay_init(RSA *rsa); static int RSA_eay_finish(RSA *rsa); -#else -static int RSA_eay_public_encrypt(); -static int RSA_eay_private_encrypt(); -static int RSA_eay_public_decrypt(); -static int RSA_eay_private_decrypt(); -static int RSA_eay_mod_exp(); -static int RSA_eay_init(); -static int RSA_eay_finish(); -#endif - static 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_public_decrypt, /* signature verification */ + RSA_eay_private_encrypt, /* signing */ RSA_eay_private_decrypt, RSA_eay_mod_exp, - BN_mod_exp_mont, + BN_mod_exp_mont, /* XXX probably we should not use Montgomery if e == 3 */ RSA_eay_init, RSA_eay_finish, - 0, + 0, /* flags */ NULL, + 0, /* rsa_sign */ + 0 /* rsa_verify */ }; -RSA_METHOD *RSA_PKCS1_SSLeay() +const RSA_METHOD *RSA_PKCS1_SSLeay(void) { return(&rsa_pkcs1_eay_meth); } -static int RSA_eay_public_encrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +static int RSA_eay_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f=NULL,*ret=NULL; + BIGNUM f,ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; - /* Body of this routine removed for OpenBSD - will return - * when the RSA patent expires - */ + BN_init(&f); + BN_init(&ret); + if ((ctx=BN_CTX_new()) == NULL) goto err; + num=BN_num_bytes(rsa->n); + if ((buf=(unsigned char *)OPENSSL_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_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); + break; +#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 (BN_ucmp(&f, rsa->n) >= 0) + { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + { + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_n == NULL) + { + rsa->_method_mod_n = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + } + + 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); - if (f != NULL) BN_free(f); - if (ret != NULL) BN_free(ret); + BN_clear_free(&f); + BN_clear_free(&ret); if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_private_encrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +/* signing */ +static int RSA_eay_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f=NULL,*ret=NULL; + BIGNUM f,ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; - /* Body of this routine removed for OpenBSD - will return - * when the RSA patent expires - */ + BN_init(&f); + BN_init(&ret); + if ((ctx=BN_CTX_new()) == NULL) goto err; + num=BN_num_bytes(rsa->n); + if ((buf=(unsigned char *)OPENSSL_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 (BN_ucmp(&f, rsa->n) >= 0) + { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL)) + RSA_blinding_on(rsa,ctx); + if (rsa->flags & RSA_FLAG_BLINDING) + if (!BN_BLINDING_convert(&f,rsa->blinding,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->blinding,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); - if (ret != NULL) BN_free(ret); - if (f != NULL) BN_free(f); + BN_clear_free(&ret); + BN_clear_free(&f); if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_private_decrypt(flen, from, to, rsa,padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +static int RSA_eay_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f=NULL,*ret=NULL; + BIGNUM f,ret; int j,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx=NULL; - /* Body of this routine removed for OpenBSD - will return - * when the RSA patent expires - */ + 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 *)OPENSSL_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 (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL)) + RSA_blinding_on(rsa,ctx); + if (rsa->flags & RSA_FLAG_BLINDING) + if (!BN_BLINDING_convert(&f,rsa->blinding,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->blinding,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_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0); + break; +#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); - if (f != NULL) BN_free(f); - if (ret != NULL) BN_free(ret); + BN_clear_free(&f); + BN_clear_free(&ret); if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_public_decrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +/* signature verification */ +static int RSA_eay_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f=NULL,*ret=NULL; + 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 *)OPENSSL_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; + } - /* Body of this routine removed for OpenBSD - will return - * when the RSA patent expires - */ + if (BN_bin2bn(from,flen,&f) == NULL) goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* do the decrypt */ + if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + { + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_n == NULL) + { + rsa->_method_mod_n = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + } + + 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); - if (f != NULL) BN_free(f); - if (ret != NULL) BN_free(ret); + BN_clear_free(&f); + BN_clear_free(&ret); if (buf != NULL) { memset(buf,0,num); - Free(buf); + OPENSSL_free(buf); } return(r); } -static int RSA_eay_mod_exp(r0, I, rsa) -BIGNUM *r0; -BIGNUM *I; -RSA *rsa; +static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) { - BIGNUM *r1=NULL,*m1=NULL; + BIGNUM r1,m1,vrfy; int ret=0; BN_CTX *ctx; + BN_init(&m1); + BN_init(&r1); + BN_init(&vrfy); if ((ctx=BN_CTX_new()) == NULL) goto err; - m1=BN_new(); - r1=BN_new(); - if ((m1 == NULL) || (r1 == NULL)) goto err; - /* Body of this routine removed for OpenBSD - will return - * when the RSA patent expires - */ + if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) + { + if (rsa->_method_mod_p == NULL) + { + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_p == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_p == NULL) + { + rsa->_method_mod_p = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + } + + if (rsa->_method_mod_q == NULL) + { + BN_MONT_CTX* bn_mont_ctx; + if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) + goto err; + if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + goto err; + } + if (rsa->_method_mod_q == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->_method_mod_q == NULL) + { + rsa->_method_mod_q = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + } + } + + 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; + + if (rsa->e && rsa->n) + { + if (!rsa->meth->bn_mod_exp(&vrfy,r0,rsa->e,rsa->n,ctx,NULL)) goto err; + /* If 'I' was greater than (or equal to) rsa->n, the operation + * will be equivalent to using 'I mod n'. However, the result of + * the verify will *always* be less than 'n' so we don't check + * for absolute equality, just congruency. */ + if (!BN_sub(&vrfy, &vrfy, I)) goto err; + if (!BN_mod(&vrfy, &vrfy, rsa->n, ctx)) goto err; + if (vrfy.neg) + if (!BN_add(&vrfy, &vrfy, rsa->n)) goto err; + if (!BN_is_zero(&vrfy)) + /* 'I' and 'vrfy' aren't congruent mod n. Don't leak + * miscalculated CRT output, just do a raw (slower) + * mod_exp and return that instead. */ + if (!rsa->meth->bn_mod_exp(r0,I,rsa->d,rsa->n,ctx,NULL)) goto err; + } + ret=1; err: - if (m1 != NULL) BN_free(m1); - if (r1 != NULL) BN_free(r1); + BN_clear_free(&m1); + BN_clear_free(&r1); + BN_clear_free(&vrfy); BN_CTX_free(ctx); return(ret); } -static int RSA_eay_init(rsa) -RSA *rsa; +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 *rsa; +static int RSA_eay_finish(RSA *rsa) { - if (rsa->method_mod_n != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)rsa->method_mod_n); - if (rsa->method_mod_p != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)rsa->method_mod_p); - if (rsa->method_mod_q != NULL) - BN_MONT_CTX_free((BN_MONT_CTX *)rsa->method_mod_q); + 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/src/lib/libcrypto/rsa/rsa_err.c b/src/lib/libcrypto/rsa/rsa_err.c index 796b3afd47..a7766c3b76 100644 --- a/src/lib/libcrypto/rsa/rsa_err.c +++ b/src/lib/libcrypto/rsa/rsa_err.c @@ -1,79 +1,87 @@ -/* lib/rsa/rsa_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/rsa/rsa_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "rsa.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_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"}, @@ -83,7 +91,7 @@ static ERR_STRING_DATA RSA_str_functs[]= {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}, +{0,NULL} }; static ERR_STRING_DATA RSA_str_reasons[]= @@ -93,34 +101,46 @@ static ERR_STRING_DATA RSA_str_reasons[]= {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_BAD_ZERO_BYTE ,"bad zero byte"}, {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_LARGE_FOR_MODULUS ,"data too large for modulus"}, {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}, +{0,NULL} }; #endif -void ERR_load_RSA_strings() +void ERR_load_RSA_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_RSA,RSA_str_functs); ERR_load_strings(ERR_LIB_RSA,RSA_str_reasons); #endif diff --git a/src/lib/libcrypto/rsa/rsa_gen.c b/src/lib/libcrypto/rsa/rsa_gen.c index 4cbd373829..00c25adbc5 100644 --- a/src/lib/libcrypto/rsa/rsa_gen.c +++ b/src/lib/libcrypto/rsa/rsa_gen.c @@ -59,34 +59,130 @@ #include #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" - -RSA *RSA_generate_key(bits, e_value, callback,cb_arg) -int bits; -unsigned long e_value; -void (*callback)(P_I_I_P); -char *cb_arg; +#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; + int bitsp,bitsq,ok= -1,n=0,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; - /* Body of this routine removed for OpenBSD - will return - * when the RSA patent expires - */ + 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); diff --git a/src/lib/libcrypto/rsa/rsa_lib.c b/src/lib/libcrypto/rsa/rsa_lib.c index 95a56f8a28..93235744f7 100644 --- a/src/lib/libcrypto/rsa/rsa_lib.c +++ b/src/lib/libcrypto/rsa/rsa_lib.c @@ -57,53 +57,103 @@ */ #include -#include "crypto.h" +#include #include "cryptlib.h" -#include "lhash.h" -#include "bn.h" -#include "rsa.h" +#include +#include +#include +#include -char *RSA_version="RSA part of SSLeay 0.9.0b 29-Jun-1998"; +const char *RSA_version="RSA" OPENSSL_VERSION_PTEXT; -static RSA_METHOD *default_RSA_meth=NULL; -static int rsa_meth_num=0; -static STACK *rsa_meth=NULL; +static const RSA_METHOD *default_RSA_meth=NULL; -RSA *RSA_new() +RSA *RSA_new(void) { return(RSA_new_method(NULL)); } -void RSA_set_default_method(meth) -RSA_METHOD *meth; +void RSA_set_default_method(const RSA_METHOD *meth) { - default_RSA_meth=meth; + default_RSA_meth = meth; } -RSA *RSA_new_method(meth) -RSA_METHOD *meth; +const RSA_METHOD *RSA_get_default_method(void) { - RSA *ret; - if (default_RSA_meth == NULL) { -#ifdef RSAref +#ifdef RSA_NULL + default_RSA_meth=RSA_null_method(); +#else +#if 0 /* was: #ifdef RSAref */ default_RSA_meth=RSA_PKCS1_RSAref(); #else default_RSA_meth=RSA_PKCS1_SSLeay(); #endif +#endif + } + + return default_RSA_meth; + } + +const RSA_METHOD *RSA_get_method(const RSA *rsa) + { + return rsa->meth; + } + +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth) + { + /* NB: The caller is specifically setting a method, so it's not up to us + * to deal with which ENGINE it comes from. */ + const RSA_METHOD *mtmp; + mtmp = rsa->meth; + if (mtmp->finish) mtmp->finish(rsa); + if (rsa->engine) + { + ENGINE_finish(rsa->engine); + rsa->engine = NULL; } - ret=(RSA *)Malloc(sizeof(RSA)); + rsa->meth = meth; + if (meth->init) meth->init(rsa); + return 1; + } + +RSA *RSA_new_method(ENGINE *engine) + { + RSA *ret; + + ret=(RSA *)OPENSSL_malloc(sizeof(RSA)); if (ret == NULL) { RSAerr(RSA_F_RSA_NEW_METHOD,ERR_R_MALLOC_FAILURE); - return(NULL); + return NULL; } - if (meth == NULL) - ret->meth=default_RSA_meth; + ret->meth = RSA_get_default_method(); + if (engine) + { + if (!ENGINE_init(engine)) + { + RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB); + OPENSSL_free(ret); + return NULL; + } + ret->engine = engine; + } else - ret->meth=meth; + ret->engine = ENGINE_get_default_RSA(); + if(ret->engine) + { + ret->meth = ENGINE_get_RSA(ret->engine); + if(!ret->meth) + { + RSAerr(RSA_F_RSA_NEW_METHOD, + ERR_R_ENGINE_LIB); + ENGINE_finish(ret->engine); + OPENSSL_free(ret); + return NULL; + } + } ret->pad=0; ret->version=0; @@ -116,22 +166,25 @@ RSA_METHOD *meth; ret->dmq1=NULL; ret->iqmp=NULL; ret->references=1; - ret->method_mod_n=NULL; - ret->method_mod_p=NULL; - ret->method_mod_q=NULL; + ret->_method_mod_n=NULL; + ret->_method_mod_p=NULL; + ret->_method_mod_q=NULL; ret->blinding=NULL; + ret->bignum_data=NULL; ret->flags=ret->meth->flags; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data); if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { - Free(ret); + if (ret->engine) + ENGINE_finish(ret->engine); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data); + OPENSSL_free(ret); ret=NULL; } - CRYPTO_new_ex_data(rsa_meth,(char *)ret,&ret->ex_data); return(ret); } -void RSA_free(r) -RSA *r; +void RSA_free(RSA *r) { int i; @@ -150,10 +203,12 @@ RSA *r; } #endif - CRYPTO_free_ex_data(rsa_meth,(char *)r,&r->ex_data); - - if (r->meth->finish != NULL) + if (r->meth->finish) r->meth->finish(r); + if (r->engine) + ENGINE_finish(r->engine); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data); if (r->n != NULL) BN_clear_free(r->n); if (r->e != NULL) BN_clear_free(r->e); @@ -164,90 +219,78 @@ RSA *r; if (r->dmq1 != NULL) BN_clear_free(r->dmq1); if (r->iqmp != NULL) BN_clear_free(r->iqmp); if (r->blinding != NULL) BN_BLINDING_free(r->blinding); - Free(r); + if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data); + OPENSSL_free(r); } -int RSA_get_ex_new_index(argl,argp,new_func,dup_func,free_func) -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*free_func)(); +int RSA_up_ref(RSA *r) + { + int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_RSA); +#ifdef REF_PRINT + REF_PRINT("RSA",r); +#endif +#ifdef REF_CHECK + if (i < 2) + { + fprintf(stderr, "RSA_up_ref, bad reference count\n"); + abort(); + } +#endif + return ((i > 1) ? 1 : 0); + } + +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)); + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp, + new_func, dup_func, free_func); } -int RSA_set_ex_data(r,idx,arg) -RSA *r; -int idx; -char *arg; +int RSA_set_ex_data(RSA *r, int idx, void *arg) { return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); } -char *RSA_get_ex_data(r,idx) -RSA *r; -int idx; +void *RSA_get_ex_data(const RSA *r, int idx) { return(CRYPTO_get_ex_data(&r->ex_data,idx)); } -int RSA_size(r) -RSA *r; +int RSA_size(const RSA *r) { return(BN_num_bytes(r->n)); } -int RSA_public_encrypt(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +int RSA_public_encrypt(int flen, const 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(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +int RSA_private_encrypt(int flen, const 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(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +int RSA_private_decrypt(int flen, const 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(flen, from, to, rsa, padding) -int flen; -unsigned char *from; -unsigned char *to; -RSA *rsa; -int padding; +int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to, + RSA *rsa, int padding) { return(rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding)); } -int RSA_flags(r) -RSA *r; +int RSA_flags(const RSA *r) { return((r == NULL)?0:r->meth->flags); } -void RSA_blinding_off(rsa) -RSA *rsa; +void RSA_blinding_off(RSA *rsa) { if (rsa->blinding != NULL) { @@ -257,9 +300,7 @@ RSA *rsa; rsa->flags&= ~RSA_FLAG_BLINDING; } -int RSA_blinding_on(rsa,p_ctx) -RSA *rsa; -BN_CTX *p_ctx; +int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx) { BIGNUM *A,*Ai; BN_CTX *ctx; @@ -275,20 +316,64 @@ BN_CTX *p_ctx; if (rsa->blinding != NULL) BN_BLINDING_free(rsa->blinding); - A=ctx->bn[0]; - ctx->tos++; - if (!BN_rand(A,BN_num_bits(rsa->n)-1,1,0)) goto err; - if ((Ai=BN_mod_inverse(A,rsa->n,ctx)) == NULL) goto err; + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + if (!BN_rand_range(A,rsa->n)) 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, - (char *)rsa->method_mod_n)) goto err; + if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) + goto err; rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n); - ctx->tos--; 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=OPENSSL_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); + } diff --git a/src/lib/libcrypto/rsa/rsa_none.c b/src/lib/libcrypto/rsa/rsa_none.c index f0dd943657..e6f3e627ca 100644 --- a/src/lib/libcrypto/rsa/rsa_none.c +++ b/src/lib/libcrypto/rsa/rsa_none.c @@ -58,52 +58,41 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "rand.h" +#include +#include +#include -int RSA_padding_add_none(to,tlen,from,flen) -unsigned char *to; -int tlen; -unsigned char *from; -int flen; +int RSA_padding_add_none(unsigned char *to, int tlen, + const unsigned char *from, int flen) { - if (flen >= tlen) + 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); + } - *(to++)=0; memcpy(to,from,(unsigned int)flen); return(1); } -int RSA_padding_check_none(to,tlen,from,flen) -unsigned char *to; -int tlen; -unsigned char *from; -int flen; +int RSA_padding_check_none(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num) { - int j; - from++; - if (flen+1 > tlen) + if (flen > tlen) { RSAerr(RSA_F_RSA_PADDING_CHECK_NONE,RSA_R_DATA_TOO_LARGE); return(-1); } - if (*(from++) != 0) - { - RSAerr(RSA_F_RSA_PADDING_CHECK_NONE,RSA_R_BAD_ZERO_BYTE); - return(-1); - } - /* scan over padding data */ - j=flen-1; /* one for type and one for the prepended 0. */ - memset(to,0,tlen-j); - to+=(tlen-j); - memcpy(to,from,j); - return(j); + memset(to,0,tlen-flen); + memcpy(to+tlen-flen,from,flen); + return(tlen); } diff --git a/src/lib/libcrypto/rsa/rsa_oaep.c b/src/lib/libcrypto/rsa/rsa_oaep.c index 843c40c864..e3f7c608ec 100644 --- a/src/lib/libcrypto/rsa/rsa_oaep.c +++ b/src/lib/libcrypto/rsa/rsa_oaep.c @@ -2,161 +2,205 @@ /* Written by Ulf Moeller. This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */ -/* EME_OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ - -#if !defined(NO_SHA) && !defined(NO_SHA1) +/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */ + +/* See Victor Shoup, "OAEP reconsidered," Nov. 2000, + * + * for problems with the security proof for the + * original OAEP scheme, which EME-OAEP is based on. + * + * A new proof can be found in E. Fujisaki, T. Okamoto, + * D. Pointcheval, J. Stern, "RSA-OEAP is Still Alive!", + * Dec. 2000, . + * The new proof has stronger requirements for the + * underlying permutation: "partial-one-wayness" instead + * of one-wayness. For the RSA function, this is + * an equivalent notion. + */ + + +#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) #include #include "cryptlib.h" #include #include -#include +#include #include +#include -int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen); +int MGF1(unsigned char *mask, long len, + const unsigned char *seed, long seedlen); int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, - unsigned char *from, int flen, unsigned char *param, int plen) - { - int i, emlen = tlen - 1; - unsigned char *db, *seed; - unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH]; - - if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1) + const unsigned char *from, int flen, + const unsigned char *param, int plen) { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, - RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); - return (0); - } + int i, emlen = tlen - 1; + unsigned char *db, *seed; + unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH]; - if (emlen < 2 * SHA_DIGEST_LENGTH + 1) - { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL); - return (0); - } - - dbmask = Malloc(emlen - SHA_DIGEST_LENGTH); - if (dbmask == NULL) - { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); - return (0); - } + if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return 0; + } + + if (emlen < 2 * SHA_DIGEST_LENGTH + 1) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL); + return 0; + } - to[0] = 0; - seed = to + 1; - db = to + SHA_DIGEST_LENGTH + 1; + dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH); + if (dbmask == NULL) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); + return 0; + } - SHA1(param, plen, db); - memset(db + SHA_DIGEST_LENGTH, 0, - emlen - flen - 2 * SHA_DIGEST_LENGTH - 1); - db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01; - memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen); - RAND_bytes(seed, SHA_DIGEST_LENGTH); + to[0] = 0; + seed = to + 1; + db = to + SHA_DIGEST_LENGTH + 1; + + EVP_Digest((void *)param, plen, db, NULL, EVP_sha1(), NULL); + memset(db + SHA_DIGEST_LENGTH, 0, + emlen - flen - 2 * SHA_DIGEST_LENGTH - 1); + db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01; + memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen); + if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0) + return 0; #ifdef PKCS_TESTVECT - memcpy(seed, + memcpy(seed, "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f", 20); #endif - MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH); - for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) - db[i] ^= dbmask[i]; + MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH); + for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++) + db[i] ^= dbmask[i]; - MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH); - for (i = 0; i < SHA_DIGEST_LENGTH; i++) - seed[i] ^= seedmask[i]; + MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH); + for (i = 0; i < SHA_DIGEST_LENGTH; i++) + seed[i] ^= seedmask[i]; - Free(dbmask); - return (1); - } + OPENSSL_free(dbmask); + return 1; + } int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, - unsigned char *from, int flen, int num, unsigned char *param, - int plen) - { - int i, dblen, mlen = -1; - unsigned char *maskeddb; - int lzero; - unsigned char *db, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; - - if (--num < 2 * SHA_DIGEST_LENGTH + 1) + const unsigned char *from, int flen, int num, + const unsigned char *param, int plen) { - RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); - return (-1); - } + int i, dblen, mlen = -1; + const unsigned char *maskeddb; + int lzero; + unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; + int bad = 0; + + if (--num < 2 * SHA_DIGEST_LENGTH + 1) + /* 'num' is the length of the modulus, i.e. does not depend on the + * particular ciphertext. */ + goto decoding_err; + + lzero = num - flen; + if (lzero < 0) + { + /* lzero == -1 */ + + /* signalling this error immediately after detection might allow + * for side-channel attacks (e.g. timing if 'plen' is huge + * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal + * Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001), + * so we use a 'bad' flag */ + bad = 1; + lzero = 0; + } + maskeddb = from - lzero + SHA_DIGEST_LENGTH; - dblen = num - SHA_DIGEST_LENGTH; - db = Malloc(dblen); - if (db == NULL) - { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); - return (-1); - } + dblen = num - SHA_DIGEST_LENGTH; + db = OPENSSL_malloc(dblen); + if (db == NULL) + { + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); + return -1; + } - lzero = num - flen; - maskeddb = from - lzero + SHA_DIGEST_LENGTH; - - MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen); - for (i = lzero; i < SHA_DIGEST_LENGTH; i++) - seed[i] ^= from[i - lzero]; + MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen); + for (i = lzero; i < SHA_DIGEST_LENGTH; i++) + seed[i] ^= from[i - lzero]; - MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); - for (i = 0; i < dblen; i++) - db[i] ^= maskeddb[i]; + MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); + for (i = 0; i < dblen; i++) + db[i] ^= maskeddb[i]; - SHA1(param, plen, phash); + EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL); - if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0) - RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); - else - { - for (i = SHA_DIGEST_LENGTH; i < dblen; i++) - if (db[i] != 0x00) - break; - if (db[i] != 0x01 || i++ >= dblen) - RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, - RSA_R_OAEP_DECODING_ERROR); + if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad) + goto decoding_err; else - { - mlen = dblen - i; - if (tlen < mlen) { - RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); - mlen = -1; + for (i = SHA_DIGEST_LENGTH; i < dblen; i++) + if (db[i] != 0x00) + break; + if (db[i] != 0x01 || i++ >= dblen) + goto decoding_err; + else + { + /* everything looks OK */ + + mlen = dblen - i; + if (tlen < mlen) + { + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); + mlen = -1; + } + else + memcpy(to, db + i, mlen); + } } - else - memcpy(to, db + i, mlen); - } + OPENSSL_free(db); + return mlen; + +decoding_err: + /* to avoid chosen ciphertext attacks, the error message should not reveal + * which kind of decoding error happened */ + RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR); + if (db != NULL) OPENSSL_free(db); + return -1; } - Free(db); - return (mlen); - } - -int MGF1(unsigned char *mask, long len, unsigned char *seed, long seedlen) - { - long i, outlen = 0; - unsigned char cnt[4]; - SHA_CTX c; - unsigned char md[SHA_DIGEST_LENGTH]; - - for (i = 0; outlen < len; i++) + +int MGF1(unsigned char *mask, long len, + const unsigned char *seed, long seedlen) { - cnt[0] = (i >> 24) & 255, cnt[1] = (i >> 16) & 255, - cnt[2] = (i >> 8) & 255, cnt[3] = i & 255; - SHA1_Init(&c); - SHA1_Update(&c, seed, seedlen); - SHA1_Update(&c, cnt, 4); - if (outlen + SHA_DIGEST_LENGTH <= len) - { - SHA1_Final(mask + outlen, &c); - outlen += SHA_DIGEST_LENGTH; - } - else - { - SHA1_Final(md, &c); - memcpy(mask + outlen, md, len - outlen); - outlen = len; - } + long i, outlen = 0; + unsigned char cnt[4]; + EVP_MD_CTX c; + unsigned char md[SHA_DIGEST_LENGTH]; + + EVP_MD_CTX_init(&c); + for (i = 0; outlen < len; i++) + { + cnt[0] = (unsigned char)((i >> 24) & 255); + cnt[1] = (unsigned char)((i >> 16) & 255); + cnt[2] = (unsigned char)((i >> 8)) & 255; + cnt[3] = (unsigned char)(i & 255); + EVP_DigestInit_ex(&c,EVP_sha1(), NULL); + EVP_DigestUpdate(&c, seed, seedlen); + EVP_DigestUpdate(&c, cnt, 4); + if (outlen + SHA_DIGEST_LENGTH <= len) + { + EVP_DigestFinal_ex(&c, mask + outlen, NULL); + outlen += SHA_DIGEST_LENGTH; + } + else + { + EVP_DigestFinal_ex(&c, md, NULL); + memcpy(mask + outlen, md, len - outlen); + outlen = len; + } + } + EVP_MD_CTX_cleanup(&c); + return 0; } - return (0); - } #endif diff --git a/src/lib/libcrypto/rsa/rsa_pk1.c b/src/lib/libcrypto/rsa/rsa_pk1.c index 2791291b94..c1edd6764f 100644 --- a/src/lib/libcrypto/rsa/rsa_pk1.c +++ b/src/lib/libcrypto/rsa/rsa_pk1.c @@ -58,27 +58,12 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "rand.h" - -#ifndef NOPROTO -int RSA_padding_add_PKCS1_type_1(); -int RSA_padding_check_PKCS1_type_1(); -int RSA_padding_add_PKCS1_type_2(); -int RSA_padding_check_PKCS1_type_2(); -int RSA_padding_add_SSLv23(); -int RSA_padding_check_SSLv23(); -int RSA_padding_add_none(); -int RSA_padding_check_none(); +#include +#include +#include -#endif - -int RSA_padding_add_PKCS1_type_1(to,tlen,from,flen) -unsigned char *to; -int tlen; -unsigned char *from; -int flen; +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *from, int flen) { int j; unsigned char *p; @@ -94,7 +79,7 @@ int flen; *(p++)=0; *(p++)=1; /* Private Key BT (Block Type) */ - /* padd out with 0xff data */ + /* pad out with 0xff data */ j=tlen-3-flen; memset(p,0xff,j); p+=j; @@ -103,17 +88,14 @@ int flen; return(1); } -int RSA_padding_check_PKCS1_type_1(to,tlen,from,flen) -unsigned char *to; -int tlen; -unsigned char *from; -int flen; +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num) { int i,j; - unsigned char *p; + const unsigned char *p; p=from; - if (*(p++) != 01) + if ((num != (flen+1)) || (*(p++) != 01)) { RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,RSA_R_BLOCK_TYPE_IS_NOT_01); return(-1); @@ -148,16 +130,18 @@ int flen; } i++; /* Skip over the '\0' */ j-=i; + if (j > 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(to,tlen,from,flen) -unsigned char *to; -int tlen; -unsigned char *from; -int flen; +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *from, int flen) { int i,j; unsigned char *p; @@ -176,12 +160,14 @@ int flen; /* pad out with non-zero random data */ j=tlen-3-flen; - RAND_bytes(p,j); + 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/src/lib/libcrypto/rsa/rsa_saos.c b/src/lib/libcrypto/rsa/rsa_saos.c index fb0fae5a43..85adacc08f 100644 --- a/src/lib/libcrypto/rsa/rsa_saos.c +++ b/src/lib/libcrypto/rsa/rsa_saos.c @@ -58,18 +58,14 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include -int RSA_sign_ASN1_OCTET_STRING(type,m,m_len,sigret,siglen,rsa) -int type; -unsigned char *m; -unsigned int m_len; -unsigned char *sigret; -unsigned int *siglen; -RSA *rsa; +int RSA_sign_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa) { ASN1_OCTET_STRING sig; int i,j,ret=1; @@ -77,7 +73,7 @@ RSA *rsa; sig.type=V_ASN1_OCTET_STRING; sig.length=m_len; - sig.data=m; + sig.data=(unsigned char *)m; i=i2d_ASN1_OCTET_STRING(&sig,NULL); j=RSA_size(rsa); @@ -86,7 +82,7 @@ RSA *rsa; 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); + s=(unsigned char *)OPENSSL_malloc((unsigned int)j+1); if (s == NULL) { RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING,ERR_R_MALLOC_FAILURE); @@ -101,17 +97,14 @@ RSA *rsa; *siglen=i; memset(s,0,(unsigned int)j+1); - Free(s); + OPENSSL_free(s); return(ret); } -int RSA_verify_ASN1_OCTET_STRING(dtype, m, m_len, sigbuf, siglen, rsa) -int dtype; -unsigned char *m; -unsigned int m_len; -unsigned char *sigbuf; -unsigned int siglen; -RSA *rsa; +int RSA_verify_ASN1_OCTET_STRING(int dtype, + const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + RSA *rsa) { int i,ret=0; unsigned char *p,*s; @@ -123,7 +116,7 @@ RSA *rsa; return(0); } - s=(unsigned char *)Malloc((unsigned int)siglen); + s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen); if (s == NULL) { RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,ERR_R_MALLOC_FAILURE); @@ -145,9 +138,9 @@ RSA *rsa; else ret=1; err: - if (sig != NULL) ASN1_OCTET_STRING_free(sig); + if (sig != NULL) M_ASN1_OCTET_STRING_free(sig); memset(s,0,(unsigned int)siglen); - Free(s); + OPENSSL_free(s); return(ret); } diff --git a/src/lib/libcrypto/rsa/rsa_sign.c b/src/lib/libcrypto/rsa/rsa_sign.c index 28c5571e74..2a440901de 100644 --- a/src/lib/libcrypto/rsa/rsa_sign.c +++ b/src/lib/libcrypto/rsa/rsa_sign.c @@ -58,79 +58,92 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "objects.h" -#include "x509.h" - -int RSA_sign(type,m,m_len,sigret,siglen,rsa) -int type; -unsigned char *m; -unsigned int m_len; -unsigned char *sigret; -unsigned int *siglen; -RSA *rsa; +#include +#include +#include +#include +#include + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +int RSA_sign(int type, const 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; + unsigned char *p, *tmps = NULL; + const unsigned char *s = NULL; X509_ALGOR algor; ASN1_OCTET_STRING digest; - - 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); + if((rsa->flags & RSA_FLAG_SIGN_VER) + && ENGINE_get_RSA(rsa->engine)->rsa_sign) + return ENGINE_get_RSA(rsa->engine)->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); } - parameter.type=V_ASN1_NULL; - parameter.value.ptr=NULL; - sig.algor->parameter= ¶meter; + 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; + sig.digest= &digest; + sig.digest->data=(unsigned char *)m; /* TMP UGLY CAST */ + sig.digest->length=m_len; - i=i2d_X509_SIG(&sig,NULL); + 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); } - 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); + if(type != NID_md5_sha1) { + tmps=(unsigned char *)OPENSSL_malloc((unsigned int)j+1); + if (tmps == NULL) + { + RSAerr(RSA_F_RSA_SIGN,ERR_R_MALLOC_FAILURE); + return(0); + } + p=tmps; + i2d_X509_SIG(&sig,&p); + s=tmps; + } 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); + if(type != NID_md5_sha1) { + memset(tmps,0,(unsigned int)j+1); + OPENSSL_free(tmps); + } return(ret); } -int RSA_verify(dtype, m, m_len, sigbuf, siglen, rsa) -int dtype; -unsigned char *m; -unsigned int m_len; -unsigned char *sigbuf; -unsigned int siglen; -RSA *rsa; +int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len, + unsigned char *sigbuf, unsigned int siglen, RSA *rsa) { int i,ret=0,sigtype; unsigned char *p,*s; @@ -142,55 +155,74 @@ RSA *rsa; return(0); } - s=(unsigned char *)Malloc((unsigned int)siglen); + if((rsa->flags & RSA_FLAG_SIGN_VER) + && ENGINE_get_RSA(rsa->engine)->rsa_verify) + return ENGINE_get_RSA(rsa->engine)->rsa_verify(dtype, + m, m_len, sigbuf, siglen, rsa); + + s=(unsigned char *)OPENSSL_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; - p=s; - sig=d2i_X509_SIG(NULL,&p,(long)i); - if (sig == NULL) goto err; - sigtype=OBJ_obj2nid(sig->algor->algorithm); + /* 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); -#ifdef RSA_DEBUG - /* put a backward compatability 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))) + 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) { - /* ok, we will let it through */ -#if !defined(NO_STDIO) && !defined(WIN16) - fprintf(stderr,"signature has problems, re-make with post SSLeay045\n"); + if (((dtype == NID_md5) && + (sigtype == NID_md5WithRSAEncryption)) || + ((dtype == NID_md2) && + (sigtype == NID_md2WithRSAEncryption))) + { + /* ok, we will let it through */ +#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_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; + } } - else + if ( ((unsigned int)sig->digest->length != m_len) || + (memcmp(m,sig->digest->data,m_len) != 0)) { - RSAerr(RSA_F_RSA_VERIFY,RSA_R_ALGORITHM_MISMATCH); - goto err; + RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE); } - } - 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; + else + ret=1; + } err: if (sig != NULL) X509_SIG_free(sig); memset(s,0,(unsigned int)siglen); - Free(s); + OPENSSL_free(s); return(ret); } diff --git a/src/lib/libcrypto/rsa/rsa_ssl.c b/src/lib/libcrypto/rsa/rsa_ssl.c index 9bcd4b2c03..ea72629494 100644 --- a/src/lib/libcrypto/rsa/rsa_ssl.c +++ b/src/lib/libcrypto/rsa/rsa_ssl.c @@ -58,15 +58,12 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "rsa.h" -#include "rand.h" +#include +#include +#include -int RSA_padding_add_SSLv23(to,tlen,from,flen) -unsigned char *to; -int tlen; -unsigned char *from; -int flen; +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, + const unsigned char *from, int flen) { int i,j; unsigned char *p; @@ -85,12 +82,14 @@ int flen; /* pad out with non-zero random data */ j=tlen-3-8-flen; - RAND_bytes(p,j); + 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/src/lib/libcrypto/sha/asm/sha1-586.pl b/src/lib/libcrypto/sha/asm/sha1-586.pl index d6d998f8ee..fe51fd0794 100644 --- a/src/lib/libcrypto/sha/asm/sha1-586.pl +++ b/src/lib/libcrypto/sha/asm/sha1-586.pl @@ -1,15 +1,15 @@ -#!/usr/bin/perl +#!/usr/local/bin/perl $normal=0; push(@INC,"perlasm","../../perlasm"); require "x86asm.pl"; -&asm_init($ARGV[0],"sha1-586.pl"); +&asm_init($ARGV[0],"sha1-586.pl",$ARGV[$#ARGV] eq "386"); $A="eax"; -$B="ebx"; -$C="ecx"; +$B="ecx"; +$C="ebx"; $D="edx"; $E="edi"; $T="esi"; @@ -19,7 +19,7 @@ $off=9*4; @K=(0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6); -&sha1_block("sha1_block_x86"); +&sha1_block_data("sha1_block_asm_data_order"); &asm_finish(); @@ -53,11 +53,14 @@ sub X_expand local($in)=@_; &comment("First, load the words onto the stack in network byte order"); - for ($i=0; $i<16; $i++) + for ($i=0; $i<16; $i+=2) { - &mov("eax",&DWP(($i+0)*4,$in,"",0)) unless $i == 0; - &bswap("eax"); - &mov(&swtmp($i+0),"eax"); + &mov($A,&DWP(($i+0)*4,$in,"",0));# unless $i == 0; + &mov($B,&DWP(($i+1)*4,$in,"",0)); + &bswap($A); + &bswap($B); + &mov(&swtmp($i+0),$A); + &mov(&swtmp($i+1),$B); } &comment("We now have the X array on the stack"); @@ -312,9 +315,9 @@ sub BODY_60_79 &BODY_20_39(@_); } -sub sha1_block +sub sha1_block_host { - local($name)=@_; + local($name, $sclabel)=@_; &function_begin_B($name,""); @@ -325,35 +328,77 @@ sub sha1_block # D 12 # E 16 - &push("esi"); - &push("ebp"); - &mov("eax", &wparam(2)); + &mov("ecx", &wparam(2)); + &push("esi"); + &shl("ecx",6); &mov("esi", &wparam(1)); - &add("eax", "esi"); # offset to leave on + &push("ebp"); + &add("ecx","esi"); # offset to leave on + &push("ebx"); &mov("ebp", &wparam(0)); + &push("edi"); + &mov($D, &DWP(12,"ebp","",0)); + &stack_push(18+9); + &mov($E, &DWP(16,"ebp","",0)); + &mov($C, &DWP( 8,"ebp","",0)); + &mov(&swtmp(17),"ecx"); + + &comment("First we need to setup the X array"); + + for ($i=0; $i<16; $i+=2) + { + &mov($A,&DWP(($i+0)*4,"esi","",0));# unless $i == 0; + &mov($B,&DWP(($i+1)*4,"esi","",0)); + &mov(&swtmp($i+0),$A); + &mov(&swtmp($i+1),$B); + } + &jmp($sclabel); + &function_end_B($name); + } + + +sub sha1_block_data + { + local($name)=@_; + + &function_begin_B($name,""); + + # parameter 1 is the MD5_CTX structure. + # A 0 + # B 4 + # C 8 + # D 12 + # E 16 + + &mov("ecx", &wparam(2)); + &push("esi"); + &shl("ecx",6); + &mov("esi", &wparam(1)); + &push("ebp"); + &add("ecx","esi"); # offset to leave on &push("ebx"); - &sub("eax", 64); + &mov("ebp", &wparam(0)); &push("edi"); - &mov($B, &DWP( 4,"ebp","",0)); - &stack_push(18); &mov($D, &DWP(12,"ebp","",0)); - &mov($E, &DWP(16,"ebp","",0)); - &mov($C, &DWP( 8,"ebp","",0)); - &mov(&swtmp(17),"eax"); + &stack_push(18+9); + &mov($E, &DWP(16,"ebp","",0)); + &mov($C, &DWP( 8,"ebp","",0)); + &mov(&swtmp(17),"ecx"); &comment("First we need to setup the X array"); - &mov("eax",&DWP(0,"esi","",0)); # pulled out of X_expand &set_label("start") unless $normal; &X_expand("esi"); - &mov(&swtmp(16),"esi"); + &mov(&wparam(1),"esi"); + &set_label("shortcut", 0, 1); &comment(""); &comment("Start processing"); # odd start &mov($A, &DWP( 0,"ebp","",0)); + &mov($B, &DWP( 4,"ebp","",0)); $X="esp"; &BODY_00_15(-2,$K[0],$X, 0,$A,$B,$C,$D,$E,$T); &BODY_00_15( 0,$K[0],$X, 1,$T,$A,$B,$C,$D,$E); @@ -468,24 +513,28 @@ sub sha1_block &add($C,$T); &mov(&DWP( 0,$tmp1,"",0),$A); - &mov("esi",&swtmp(16)); - &mov(&DWP( 8,$tmp1,"",0),$C); # This is for looping + &mov("esi",&wparam(1)); + &mov(&DWP( 8,$tmp1,"",0),$C); &add("esi",64); &mov("eax",&swtmp(17)); &mov(&DWP(16,$tmp1,"",0),$E); - &cmp("eax","esi"); - &mov(&DWP( 4,$tmp1,"",0),$B); # This is for looping - &jl(&label("end")); - &mov("eax",&DWP(0,"esi","",0)); # Pulled down from - &jmp(&label("start")); - - &set_label("end"); - &stack_pop(18); + &cmp("esi","eax"); + &mov(&DWP( 4,$tmp1,"",0),$B); + &jl(&label("start")); + + &stack_pop(18+9); &pop("edi"); &pop("ebx"); &pop("ebp"); &pop("esi"); &ret(); + + # keep a note of shortcut label so it can be used outside + # block. + my $sclabel = &label("shortcut"); + &function_end_B($name); + # Putting this here avoids problems with MASM in debugging mode + &sha1_block_host("sha1_block_asm_host_order", $sclabel); } diff --git a/src/lib/libcrypto/sha/sha.h b/src/lib/libcrypto/sha/sha.h index 4cf0ea0225..3fd54a10cc 100644 --- a/src/lib/libcrypto/sha/sha.h +++ b/src/lib/libcrypto/sha/sha.h @@ -59,49 +59,61 @@ #ifndef HEADER_SHA_H #define HEADER_SHA_H +#include + #ifdef __cplusplus extern "C" { #endif -#define SHA_CBLOCK 64 +#if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1)) +#error SHA is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! SHA_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__) +#define SHA_LONG unsigned long +#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +#define SHA_LONG unsigned long +#define SHA_LONG_LOG2 3 +#else +#define SHA_LONG unsigned int +#endif + #define SHA_LBLOCK 16 -#define SHA_BLOCK 16 -#define SHA_LAST_BLOCK 56 -#define SHA_LENGTH_BLOCK 8 +#define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a + * contiguous array of 32 bit + * wide big-endian values. */ +#define SHA_LAST_BLOCK (SHA_CBLOCK-8) #define SHA_DIGEST_LENGTH 20 typedef struct SHAstate_st { - unsigned long h0,h1,h2,h3,h4; - unsigned long Nl,Nh; - unsigned long data[SHA_LBLOCK]; + SHA_LONG h0,h1,h2,h3,h4; + SHA_LONG Nl,Nh; + SHA_LONG data[SHA_LBLOCK]; int num; } SHA_CTX; -#ifndef NOPROTO -void SHA_Init(SHA_CTX *c); -void SHA_Update(SHA_CTX *c, unsigned char *data, unsigned long len); -void SHA_Final(unsigned char *md, SHA_CTX *c); -unsigned char *SHA(unsigned char *d, unsigned long n,unsigned char *md); -void SHA_Transform(SHA_CTX *c, unsigned char *data); -void SHA1_Init(SHA_CTX *c); -void SHA1_Update(SHA_CTX *c, unsigned char *data, unsigned long len); -void SHA1_Final(unsigned char *md, SHA_CTX *c); -unsigned char *SHA1(unsigned char *d, unsigned long n,unsigned char *md); -void SHA1_Transform(SHA_CTX *c, unsigned char *data); -#else -void SHA_Init(); -void SHA_Update(); -void SHA_Final(); -unsigned char *SHA(); -void SHA_Transform(); -void SHA1_Init(); -void SHA1_Update(); -void SHA1_Final(); -unsigned char *SHA1(); -void SHA1_Transform(); +#ifndef OPENSSL_NO_SHA0 +int SHA_Init(SHA_CTX *c); +int SHA_Update(SHA_CTX *c, const void *data, unsigned long len); +int SHA_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA_Transform(SHA_CTX *c, const unsigned char *data); +#endif +#ifndef OPENSSL_NO_SHA1 +int SHA1_Init(SHA_CTX *c); +int SHA1_Update(SHA_CTX *c, const void *data, unsigned long len); +int SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); #endif - #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/sha/sha1_one.c b/src/lib/libcrypto/sha/sha1_one.c index fe5770d601..e6a24888ed 100644 --- a/src/lib/libcrypto/sha/sha1_one.c +++ b/src/lib/libcrypto/sha/sha1_one.c @@ -58,12 +58,10 @@ #include #include -#include "sha.h" +#include -unsigned char *SHA1(d, n, md) -unsigned char *d; -unsigned long n; -unsigned char *md; +#ifndef OPENSSL_NO_SHA1 +unsigned char *SHA1(const unsigned char *d, unsigned long n, unsigned char *md) { SHA_CTX c; static unsigned char m[SHA_DIGEST_LENGTH]; @@ -75,3 +73,4 @@ unsigned char *md; memset(&c,0,sizeof(c)); return(md); } +#endif diff --git a/src/lib/libcrypto/sha/sha1dgst.c b/src/lib/libcrypto/sha/sha1dgst.c index 2b0ae1f0d4..182f65982a 100644 --- a/src/lib/libcrypto/sha/sha1dgst.c +++ b/src/lib/libcrypto/sha/sha1dgst.c @@ -56,413 +56,18 @@ * [including the GNU Public Licence.] */ -#include -#include +#if !defined(OPENSSL_NO_SHA1) && !defined(OPENSSL_NO_SHA) + #undef SHA_0 #define SHA_1 -#include "sha.h" -#include "sha_locl.h" - -char *SHA1_version="SHA1 part of SSLeay 0.9.0b 29-Jun-1998"; - -/* Implemented from SHA-1 document - The Secure Hash Algorithm - */ - -#define INIT_DATA_h0 (unsigned long)0x67452301L -#define INIT_DATA_h1 (unsigned long)0xefcdab89L -#define INIT_DATA_h2 (unsigned long)0x98badcfeL -#define INIT_DATA_h3 (unsigned long)0x10325476L -#define INIT_DATA_h4 (unsigned long)0xc3d2e1f0L - -#define K_00_19 0x5a827999L -#define K_20_39 0x6ed9eba1L -#define K_40_59 0x8f1bbcdcL -#define K_60_79 0xca62c1d6L - -#ifndef NOPROTO -# ifdef SHA1_ASM - void sha1_block_x86(SHA_CTX *c, register unsigned long *p, int num); -# define sha1_block sha1_block_x86 -# else - void sha1_block(SHA_CTX *c, register unsigned long *p, int num); -# endif -#else -# ifdef SHA1_ASM - void sha1_block_x86(); -# define sha1_block sha1_block_x86 -# else - void sha1_block(); -# endif -#endif - -#if defined(L_ENDIAN) && defined(SHA1_ASM) -# define M_c2nl c2l -# define M_p_c2nl p_c2l -# define M_c2nl_p c2l_p -# define M_p_c2nl_p p_c2l_p -# define M_nl2c l2c -#else -# define M_c2nl c2nl -# define M_p_c2nl p_c2nl -# define M_c2nl_p c2nl_p -# define M_p_c2nl_p p_c2nl_p -# define M_nl2c nl2c -#endif - -void SHA1_Init(c) -SHA_CTX *c; - { - c->h0=INIT_DATA_h0; - c->h1=INIT_DATA_h1; - c->h2=INIT_DATA_h2; - c->h3=INIT_DATA_h3; - c->h4=INIT_DATA_h4; - c->Nl=0; - c->Nh=0; - c->num=0; - } - -void SHA1_Update(c, data, len) -SHA_CTX *c; -register unsigned char *data; -unsigned long len; - { - register ULONG *p; - int ew,ec,sw,sc; - ULONG l; - - if (len == 0) return; - - l=(c->Nl+(len<<3))&0xffffffffL; - if (l < c->Nl) /* overflow */ - c->Nh++; - c->Nh+=(len>>29); - c->Nl=l; +#include - if (c->num != 0) - { - p=c->data; - sw=c->num>>2; - sc=c->num&0x03; - - if ((c->num+len) >= SHA_CBLOCK) - { - l= p[sw]; - M_p_c2nl(data,l,sc); - p[sw++]=l; - for (; swnum); - - sha1_block(c,p,64); - c->num=0; - /* drop through and do the rest */ - } - else - { - c->num+=(int)len; - if ((sc+len) < 4) /* ugly, add char's to a word */ - { - l= p[sw]; - M_p_c2nl_p(data,l,sc,len); - p[sw]=l; - } - else - { - ew=(c->num>>2); - ec=(c->num&0x03); - l= p[sw]; - M_p_c2nl(data,l,sc); - p[sw++]=l; - for (; sw < ew; sw++) - { M_c2nl(data,l); p[sw]=l; } - if (ec) - { - M_c2nl_p(data,l,ec); - p[sw]=l; - } - } - return; - } - } - /* We can only do the following code for assember, the reason - * being that the sha1_block 'C' version changes the values - * in the 'data' array. The assember code avoids this and - * copies it to a local array. I should be able to do this for - * the C version as well.... - */ -#if 1 -#if defined(B_ENDIAN) || defined(SHA1_ASM) - if ((((unsigned int)data)%sizeof(ULONG)) == 0) - { - sw=len/SHA_CBLOCK; - if (sw) - { - sw*=SHA_CBLOCK; - sha1_block(c,(ULONG *)data,sw); - data+=sw; - len-=sw; - } - } -#endif -#endif - /* we now can process the input data in blocks of SHA_CBLOCK - * chars and save the leftovers to c->data. */ - p=c->data; - while (len >= SHA_CBLOCK) - { -#if defined(B_ENDIAN) || defined(L_ENDIAN) - if (p != (unsigned long *)data) - memcpy(p,data,SHA_CBLOCK); - data+=SHA_CBLOCK; -# ifdef L_ENDIAN -# ifndef SHA1_ASM /* Will not happen */ - for (sw=(SHA_LBLOCK/4); sw; sw--) - { - Endian_Reverse32(p[0]); - Endian_Reverse32(p[1]); - Endian_Reverse32(p[2]); - Endian_Reverse32(p[3]); - p+=4; - } - p=c->data; -# endif -# endif -#else - for (sw=(SHA_BLOCK/4); sw; sw--) - { - M_c2nl(data,l); *(p++)=l; - M_c2nl(data,l); *(p++)=l; - M_c2nl(data,l); *(p++)=l; - M_c2nl(data,l); *(p++)=l; - } - p=c->data; -#endif - sha1_block(c,p,64); - len-=SHA_CBLOCK; - } - ec=(int)len; - c->num=ec; - ew=(ec>>2); - ec&=0x03; +const char *SHA1_version="SHA1" OPENSSL_VERSION_PTEXT; - for (sw=0; sw < ew; sw++) - { M_c2nl(data,l); p[sw]=l; } - M_c2nl_p(data,l,ec); - p[sw]=l; - } +/* The implementation is in ../md32_common.h */ -void SHA1_Transform(c,b) -SHA_CTX *c; -unsigned char *b; - { - ULONG p[16]; -#ifndef B_ENDIAN - ULONG *q; - int i; -#endif - -#if defined(B_ENDIAN) || defined(L_ENDIAN) - memcpy(p,b,64); -#ifdef L_ENDIAN - q=p; - for (i=(SHA_LBLOCK/4); i; i--) - { - Endian_Reverse32(q[0]); - Endian_Reverse32(q[1]); - Endian_Reverse32(q[2]); - Endian_Reverse32(q[3]); - q+=4; - } -#endif -#else - q=p; - for (i=(SHA_LBLOCK/4); i; i--) - { - ULONG l; - c2nl(b,l); *(q++)=l; - c2nl(b,l); *(q++)=l; - c2nl(b,l); *(q++)=l; - c2nl(b,l); *(q++)=l; - } -#endif - sha1_block(c,p,64); - } - -#ifndef SHA1_ASM - -void sha1_block(c, W, num) -SHA_CTX *c; -register unsigned long *W; -int num; - { - register ULONG A,B,C,D,E,T; - ULONG X[16]; - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - for (;;) - { - BODY_00_15( 0,A,B,C,D,E,T,W); - BODY_00_15( 1,T,A,B,C,D,E,W); - BODY_00_15( 2,E,T,A,B,C,D,W); - BODY_00_15( 3,D,E,T,A,B,C,W); - BODY_00_15( 4,C,D,E,T,A,B,W); - BODY_00_15( 5,B,C,D,E,T,A,W); - BODY_00_15( 6,A,B,C,D,E,T,W); - BODY_00_15( 7,T,A,B,C,D,E,W); - BODY_00_15( 8,E,T,A,B,C,D,W); - BODY_00_15( 9,D,E,T,A,B,C,W); - BODY_00_15(10,C,D,E,T,A,B,W); - BODY_00_15(11,B,C,D,E,T,A,W); - BODY_00_15(12,A,B,C,D,E,T,W); - BODY_00_15(13,T,A,B,C,D,E,W); - BODY_00_15(14,E,T,A,B,C,D,W); - BODY_00_15(15,D,E,T,A,B,C,W); - BODY_16_19(16,C,D,E,T,A,B,W,W,W,W); - BODY_16_19(17,B,C,D,E,T,A,W,W,W,W); - BODY_16_19(18,A,B,C,D,E,T,W,W,W,W); - BODY_16_19(19,T,A,B,C,D,E,W,W,W,X); - - BODY_20_31(20,E,T,A,B,C,D,W,W,W,X); - BODY_20_31(21,D,E,T,A,B,C,W,W,W,X); - BODY_20_31(22,C,D,E,T,A,B,W,W,W,X); - BODY_20_31(23,B,C,D,E,T,A,W,W,W,X); - BODY_20_31(24,A,B,C,D,E,T,W,W,X,X); - BODY_20_31(25,T,A,B,C,D,E,W,W,X,X); - BODY_20_31(26,E,T,A,B,C,D,W,W,X,X); - BODY_20_31(27,D,E,T,A,B,C,W,W,X,X); - BODY_20_31(28,C,D,E,T,A,B,W,W,X,X); - BODY_20_31(29,B,C,D,E,T,A,W,W,X,X); - BODY_20_31(30,A,B,C,D,E,T,W,X,X,X); - BODY_20_31(31,T,A,B,C,D,E,W,X,X,X); - BODY_32_39(32,E,T,A,B,C,D,X); - BODY_32_39(33,D,E,T,A,B,C,X); - BODY_32_39(34,C,D,E,T,A,B,X); - BODY_32_39(35,B,C,D,E,T,A,X); - BODY_32_39(36,A,B,C,D,E,T,X); - BODY_32_39(37,T,A,B,C,D,E,X); - BODY_32_39(38,E,T,A,B,C,D,X); - BODY_32_39(39,D,E,T,A,B,C,X); - - BODY_40_59(40,C,D,E,T,A,B,X); - BODY_40_59(41,B,C,D,E,T,A,X); - BODY_40_59(42,A,B,C,D,E,T,X); - BODY_40_59(43,T,A,B,C,D,E,X); - BODY_40_59(44,E,T,A,B,C,D,X); - BODY_40_59(45,D,E,T,A,B,C,X); - BODY_40_59(46,C,D,E,T,A,B,X); - BODY_40_59(47,B,C,D,E,T,A,X); - BODY_40_59(48,A,B,C,D,E,T,X); - BODY_40_59(49,T,A,B,C,D,E,X); - BODY_40_59(50,E,T,A,B,C,D,X); - BODY_40_59(51,D,E,T,A,B,C,X); - BODY_40_59(52,C,D,E,T,A,B,X); - BODY_40_59(53,B,C,D,E,T,A,X); - BODY_40_59(54,A,B,C,D,E,T,X); - BODY_40_59(55,T,A,B,C,D,E,X); - BODY_40_59(56,E,T,A,B,C,D,X); - BODY_40_59(57,D,E,T,A,B,C,X); - BODY_40_59(58,C,D,E,T,A,B,X); - BODY_40_59(59,B,C,D,E,T,A,X); - - BODY_60_79(60,A,B,C,D,E,T,X); - BODY_60_79(61,T,A,B,C,D,E,X); - BODY_60_79(62,E,T,A,B,C,D,X); - BODY_60_79(63,D,E,T,A,B,C,X); - BODY_60_79(64,C,D,E,T,A,B,X); - BODY_60_79(65,B,C,D,E,T,A,X); - BODY_60_79(66,A,B,C,D,E,T,X); - BODY_60_79(67,T,A,B,C,D,E,X); - BODY_60_79(68,E,T,A,B,C,D,X); - BODY_60_79(69,D,E,T,A,B,C,X); - BODY_60_79(70,C,D,E,T,A,B,X); - BODY_60_79(71,B,C,D,E,T,A,X); - BODY_60_79(72,A,B,C,D,E,T,X); - BODY_60_79(73,T,A,B,C,D,E,X); - BODY_60_79(74,E,T,A,B,C,D,X); - BODY_60_79(75,D,E,T,A,B,C,X); - BODY_60_79(76,C,D,E,T,A,B,X); - BODY_60_79(77,B,C,D,E,T,A,X); - BODY_60_79(78,A,B,C,D,E,T,X); - BODY_60_79(79,T,A,B,C,D,E,X); - - c->h0=(c->h0+E)&0xffffffffL; - c->h1=(c->h1+T)&0xffffffffL; - c->h2=(c->h2+A)&0xffffffffL; - c->h3=(c->h3+B)&0xffffffffL; - c->h4=(c->h4+C)&0xffffffffL; - - num-=64; - if (num <= 0) break; - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - W+=16; - } - } -#endif - -void SHA1_Final(md, c) -unsigned char *md; -SHA_CTX *c; - { - register int i,j; - register ULONG l; - register ULONG *p; - static unsigned char end[4]={0x80,0x00,0x00,0x00}; - unsigned char *cp=end; +#include "sha_locl.h" - /* c->num should definitly have room for at least one more byte. */ - p=c->data; - j=c->num; - i=j>>2; -#ifdef PURIFY - if ((j&0x03) == 0) p[i]=0; #endif - l=p[i]; - M_p_c2nl(cp,l,j&0x03); - p[i]=l; - i++; - /* i is the next 'undefined word' */ - if (c->num >= SHA_LAST_BLOCK) - { - for (; iNh; - p[SHA_LBLOCK-1]=c->Nl; -#if defined(L_ENDIAN) && defined(SHA1_ASM) - Endian_Reverse32(p[SHA_LBLOCK-2]); - Endian_Reverse32(p[SHA_LBLOCK-1]); -#endif - sha1_block(c,p,64); - cp=md; - l=c->h0; nl2c(l,cp); - l=c->h1; nl2c(l,cp); - l=c->h2; nl2c(l,cp); - l=c->h3; nl2c(l,cp); - l=c->h4; nl2c(l,cp); - - /* clear stuff, sha1_block may be leaving some stuff on the stack - * but I'm not worried :-) */ - c->num=0; -/* memset((char *)&c,0,sizeof(c));*/ - } diff --git a/src/lib/libcrypto/sha/sha_locl.h b/src/lib/libcrypto/sha/sha_locl.h index 2814ad15fa..471dfb9f8f 100644 --- a/src/lib/libcrypto/sha/sha_locl.h +++ b/src/lib/libcrypto/sha/sha_locl.h @@ -59,137 +59,102 @@ #include #include -#ifdef undef -/* one or the other needs to be defined */ -#ifndef SHA_1 /* FIPE 180-1 */ -#define SHA_0 /* FIPS 180 */ -#endif +#include +#include + +#ifndef SHA_LONG_LOG2 +#define SHA_LONG_LOG2 2 /* default to 32 bits */ #endif -#define ULONG unsigned long -#define UCHAR unsigned char -#define UINT unsigned int +#define DATA_ORDER_IS_BIG_ENDIAN -#ifdef NOCONST -#define const -#endif +#define HASH_LONG SHA_LONG +#define HASH_LONG_LOG2 SHA_LONG_LOG2 +#define HASH_CTX SHA_CTX +#define HASH_CBLOCK SHA_CBLOCK +#define HASH_LBLOCK SHA_LBLOCK +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->h0; HOST_l2c(ll,(s)); \ + ll=(c)->h1; HOST_l2c(ll,(s)); \ + ll=(c)->h2; HOST_l2c(ll,(s)); \ + ll=(c)->h3; HOST_l2c(ll,(s)); \ + ll=(c)->h4; HOST_l2c(ll,(s)); \ + } while (0) + +#if defined(SHA_0) + +# define HASH_UPDATE SHA_Update +# define HASH_TRANSFORM SHA_Transform +# define HASH_FINAL SHA_Final +# define HASH_INIT SHA_Init +# define HASH_BLOCK_HOST_ORDER sha_block_host_order +# define HASH_BLOCK_DATA_ORDER sha_block_data_order +# define Xupdate(a,ix,ia,ib,ic,id) (ix=(a)=(ia^ib^ic^id)) + + void sha_block_host_order (SHA_CTX *c, const void *p,int num); + void sha_block_data_order (SHA_CTX *c, const void *p,int num); + +#elif defined(SHA_1) + +# define HASH_UPDATE SHA1_Update +# define HASH_TRANSFORM SHA1_Transform +# define HASH_FINAL SHA1_Final +# define HASH_INIT SHA1_Init +# define HASH_BLOCK_HOST_ORDER sha1_block_host_order +# define HASH_BLOCK_DATA_ORDER sha1_block_data_order +# if defined(__MWERKS__) && defined(__MC68K__) + /* Metrowerks for Motorola fails otherwise:-( */ +# define Xupdate(a,ix,ia,ib,ic,id) do { (a)=(ia^ib^ic^id); \ + ix=(a)=ROTATE((a),1); \ + } while (0) +# else +# define Xupdate(a,ix,ia,ib,ic,id) ( (a)=(ia^ib^ic^id), \ + ix=(a)=ROTATE((a),1) \ + ) +# endif + +# ifdef SHA1_ASM +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) +# define sha1_block_host_order sha1_block_asm_host_order +# define DONT_IMPLEMENT_BLOCK_HOST_ORDER +# define sha1_block_data_order sha1_block_asm_data_order +# define DONT_IMPLEMENT_BLOCK_DATA_ORDER +# define HASH_BLOCK_DATA_ORDER_ALIGNED sha1_block_asm_data_order +# endif +# endif + void sha1_block_host_order (SHA_CTX *c, const void *p,int num); + void sha1_block_data_order (SHA_CTX *c, const void *p,int num); -#undef c2nl -#define c2nl(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++))) )) - -#undef p_c2nl -#define p_c2nl(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++)))<<24; \ - case 1: l|=((unsigned long)(*((c)++)))<<16; \ - case 2: l|=((unsigned long)(*((c)++)))<< 8; \ - case 3: l|=((unsigned long)(*((c)++))); \ - } \ - } - -#undef c2nl_p -/* NOTE the pointer is not incremented at the end of this */ -#define c2nl_p(c,l,n) { \ - l=0; \ - (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<< 8; \ - case 2: l|=((unsigned long)(*(--(c))))<<16; \ - case 1: l|=((unsigned long)(*(--(c))))<<24; \ - } \ - } - -#undef p_c2nl_p -#define p_c2nl_p(c,l,sc,len) { \ - switch (sc) \ - { \ - case 0: l =((unsigned long)(*((c)++)))<<24; \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<<16; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<< 8; \ - } \ - } - -#undef nl2c -#define nl2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - -#undef c2l -#define c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<<24)) - -#undef p_c2l -#define p_c2l(c,l,n) { \ - switch (n) { \ - case 0: l =((unsigned long)(*((c)++))); \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - case 3: l|=((unsigned long)(*((c)++)))<<24; \ - } \ - } - -#undef c2l_p -/* NOTE the pointer is not incremented at the end of this */ -#define c2l_p(c,l,n) { \ - l=0; \ - (c)+=n; \ - switch (n) { \ - case 3: l =((unsigned long)(*(--(c))))<<16; \ - case 2: l|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l|=((unsigned long)(*(--(c)))); \ - } \ - } - -#undef p_c2l_p -#define p_c2l_p(c,l,sc,len) { \ - switch (sc) \ - { \ - case 0: l =((unsigned long)(*((c)++))); \ - if (--len == 0) break; \ - case 1: l|=((unsigned long)(*((c)++)))<< 8; \ - if (--len == 0) break; \ - case 2: l|=((unsigned long)(*((c)++)))<<16; \ - } \ - } - -#undef l2c -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) - -#undef ROTATE -#if defined(WIN32) -#define ROTATE(a,n) _lrotl(a,n) #else -#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +# error "Either SHA_0 or SHA_1 must be defined." #endif -/* A nice byte order reversal from Wei Dai */ -#if defined(WIN32) -/* 5 instructions with rotate instruction, else 9 */ -#define Endian_Reverse32(a) \ - { \ - unsigned long l=(a); \ - (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ - } -#else -/* 6 instructions with rotate instruction, else 8 */ -#define Endian_Reverse32(a) \ - { \ - unsigned long l=(a); \ - l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ - (a)=ROTATE(l,16L); \ +#include "md32_common.h" + +#define INIT_DATA_h0 0x67452301UL +#define INIT_DATA_h1 0xefcdab89UL +#define INIT_DATA_h2 0x98badcfeUL +#define INIT_DATA_h3 0x10325476UL +#define INIT_DATA_h4 0xc3d2e1f0UL + +int HASH_INIT (SHA_CTX *c) + { + c->h0=INIT_DATA_h0; + c->h1=INIT_DATA_h1; + c->h2=INIT_DATA_h2; + c->h3=INIT_DATA_h3; + c->h4=INIT_DATA_h4; + c->Nl=0; + c->Nh=0; + c->num=0; + return 1; } -#endif + +#define K_00_19 0x5a827999UL +#define K_20_39 0x6ed9eba1UL +#define K_40_59 0x8f1bbcdcUL +#define K_60_79 0xca62c1d6UL /* As pointed out by Wei Dai , F() below can be * simplified to the code in F_00_19. Wei attributes these optimisations @@ -203,44 +168,305 @@ #define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) #define F_60_79(b,c,d) F_20_39(b,c,d) -#ifdef SHA_0 -#undef Xupdate -#define Xupdate(a,i,ia,ib,ic,id) X[(i)&0x0f]=(a)=\ - (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]); -#endif -#ifdef SHA_1 -#undef Xupdate -#define Xupdate(a,i,ia,ib,ic,id) (a)=\ - (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]);\ - X[(i)&0x0f]=(a)=ROTATE((a),1); -#endif - -#define BODY_00_15(i,a,b,c,d,e,f,xa) \ - (f)=xa[i]+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ +#define BODY_00_15(i,a,b,c,d,e,f,xi) \ + (f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ (b)=ROTATE((b),30); -#define BODY_16_19(i,a,b,c,d,e,f,xa,xb,xc,xd) \ - Xupdate(f,i,xa,xb,xc,xd); \ +#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ (b)=ROTATE((b),30); -#define BODY_20_31(i,a,b,c,d,e,f,xa,xb,xc,xd) \ - Xupdate(f,i,xa,xb,xc,xd); \ +#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ (b)=ROTATE((b),30); -#define BODY_32_39(i,a,b,c,d,e,f,xa) \ - Xupdate(f,i,xa,xa,xa,xa); \ +#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ (b)=ROTATE((b),30); -#define BODY_40_59(i,a,b,c,d,e,f,xa) \ - Xupdate(f,i,xa,xa,xa,xa); \ +#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ (b)=ROTATE((b),30); -#define BODY_60_79(i,a,b,c,d,e,f,xa) \ - Xupdate(f,i,xa,xa,xa,xa); \ - (f)=X[(i)&0x0f]+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ +#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ (b)=ROTATE((b),30); +#ifdef X +#undef X +#endif +#ifndef MD32_XARRAY + /* + * Originally X was an array. As it's automatic it's natural + * to expect RISC compiler to accomodate at least part of it in + * the register bank, isn't it? Unfortunately not all compilers + * "find" this expectation reasonable:-( On order to make such + * compilers generate better code I replace X[] with a bunch of + * X0, X1, etc. See the function body below... + * + */ +# define X(i) XX##i +#else + /* + * However! Some compilers (most notably HP C) get overwhelmed by + * that many local variables so that we have to have the way to + * fall down to the original behavior. + */ +# define X(i) XX[i] +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER +void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, int num) + { + const SHA_LONG *W=d; + register unsigned long A,B,C,D,E,T; +#ifndef MD32_XARRAY + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +#else + SHA_LONG XX[16]; +#endif + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + BODY_00_15( 0,A,B,C,D,E,T,W[ 0]); + BODY_00_15( 1,T,A,B,C,D,E,W[ 1]); + BODY_00_15( 2,E,T,A,B,C,D,W[ 2]); + BODY_00_15( 3,D,E,T,A,B,C,W[ 3]); + BODY_00_15( 4,C,D,E,T,A,B,W[ 4]); + BODY_00_15( 5,B,C,D,E,T,A,W[ 5]); + BODY_00_15( 6,A,B,C,D,E,T,W[ 6]); + BODY_00_15( 7,T,A,B,C,D,E,W[ 7]); + BODY_00_15( 8,E,T,A,B,C,D,W[ 8]); + BODY_00_15( 9,D,E,T,A,B,C,W[ 9]); + BODY_00_15(10,C,D,E,T,A,B,W[10]); + BODY_00_15(11,B,C,D,E,T,A,W[11]); + BODY_00_15(12,A,B,C,D,E,T,W[12]); + BODY_00_15(13,T,A,B,C,D,E,W[13]); + BODY_00_15(14,E,T,A,B,C,D,W[14]); + BODY_00_15(15,D,E,T,A,B,C,W[15]); + + BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]); + BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]); + BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]); + BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0)); + + BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1)); + BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2)); + BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3)); + BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4)); + BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5)); + BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6)); + BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7)); + BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8)); + BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9)); + BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10)); + BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11)); + BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12)); + + BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); + BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); + BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); + BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); + BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); + BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); + BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); + BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); + + BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); + BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); + BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); + BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); + BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); + BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); + BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); + BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); + BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); + BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); + BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); + BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); + BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); + BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); + BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); + BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); + + BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); + BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); + BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); + BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); + BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); + BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); + BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); + BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); + BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); + BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); + BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); + BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); + BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); + BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); + BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); + BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); + BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); + BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); + BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); + BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + if (--num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=SHA_LBLOCK; + } + } +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER +void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, int num) + { + const unsigned char *data=p; + register unsigned long A,B,C,D,E,T,l; +#ifndef MD32_XARRAY + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +#else + SHA_LONG XX[16]; +#endif + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + + HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + BODY_00_15( 0,A,B,C,D,E,T,X( 0)); HOST_c2l(data,l); X( 2)=l; + BODY_00_15( 1,T,A,B,C,D,E,X( 1)); HOST_c2l(data,l); X( 3)=l; + BODY_00_15( 2,E,T,A,B,C,D,X( 2)); HOST_c2l(data,l); X( 4)=l; + BODY_00_15( 3,D,E,T,A,B,C,X( 3)); HOST_c2l(data,l); X( 5)=l; + BODY_00_15( 4,C,D,E,T,A,B,X( 4)); HOST_c2l(data,l); X( 6)=l; + BODY_00_15( 5,B,C,D,E,T,A,X( 5)); HOST_c2l(data,l); X( 7)=l; + BODY_00_15( 6,A,B,C,D,E,T,X( 6)); HOST_c2l(data,l); X( 8)=l; + BODY_00_15( 7,T,A,B,C,D,E,X( 7)); HOST_c2l(data,l); X( 9)=l; + BODY_00_15( 8,E,T,A,B,C,D,X( 8)); HOST_c2l(data,l); X(10)=l; + BODY_00_15( 9,D,E,T,A,B,C,X( 9)); HOST_c2l(data,l); X(11)=l; + BODY_00_15(10,C,D,E,T,A,B,X(10)); HOST_c2l(data,l); X(12)=l; + BODY_00_15(11,B,C,D,E,T,A,X(11)); HOST_c2l(data,l); X(13)=l; + BODY_00_15(12,A,B,C,D,E,T,X(12)); HOST_c2l(data,l); X(14)=l; + BODY_00_15(13,T,A,B,C,D,E,X(13)); HOST_c2l(data,l); X(15)=l; + BODY_00_15(14,E,T,A,B,C,D,X(14)); + BODY_00_15(15,D,E,T,A,B,C,X(15)); + + BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13)); + BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14)); + BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15)); + BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0)); + + BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1)); + BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2)); + BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3)); + BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4)); + BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5)); + BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6)); + BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7)); + BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8)); + BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9)); + BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10)); + BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11)); + BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12)); + + BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); + BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); + BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); + BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); + BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); + BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); + BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); + BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); + + BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); + BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); + BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); + BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); + BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); + BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); + BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); + BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); + BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); + BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); + BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); + BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); + BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); + BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); + BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); + BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); + + BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); + BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); + BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); + BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); + BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); + BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); + BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); + BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); + BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); + BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); + BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); + BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); + BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); + BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); + BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); + BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); + BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); + BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); + BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); + BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + if (--num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + } + } +#endif diff --git a/src/lib/libcrypto/stack/safestack.h b/src/lib/libcrypto/stack/safestack.h index 38934981e3..ed9ed2c23a 100644 --- a/src/lib/libcrypto/stack/safestack.h +++ b/src/lib/libcrypto/stack/safestack.h @@ -57,73 +57,1456 @@ #include -#define STACK_OF(type) STACK_##type +#ifdef DEBUG_SAFESTACK + +#define STACK_OF(type) struct stack_st_##type +#define PREDECLARE_STACK_OF(type) STACK_OF(type); #define DECLARE_STACK_OF(type) \ -typedef struct stack_st_##type \ +STACK_OF(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 */ + }; + +#define IMPLEMENT_STACK_OF(type) /* nada (obsolete in new safestack approach)*/ + +/* SKM_sk_... stack macros are internal to safestack.h: + * never use them directly, use sk__... instead */ +#define SKM_sk_new(type, cmp) \ + ((STACK_OF(type) * (*)(int (*)(const type * const *, const type * const *)))sk_new)(cmp) +#define SKM_sk_new_null(type) \ + ((STACK_OF(type) * (*)(void))sk_new_null)() +#define SKM_sk_free(type, st) \ + ((void (*)(STACK_OF(type) *))sk_free)(st) +#define SKM_sk_num(type, st) \ + ((int (*)(const STACK_OF(type) *))sk_num)(st) +#define SKM_sk_value(type, st,i) \ + ((type * (*)(const STACK_OF(type) *, int))sk_value)(st, i) +#define SKM_sk_set(type, st,i,val) \ + ((type * (*)(STACK_OF(type) *, int, type *))sk_set)(st, i, val) +#define SKM_sk_zero(type, st) \ + ((void (*)(STACK_OF(type) *))sk_zero)(st) +#define SKM_sk_push(type, st,val) \ + ((int (*)(STACK_OF(type) *, type *))sk_push)(st, val) +#define SKM_sk_unshift(type, st,val) \ + ((int (*)(STACK_OF(type) *, type *))sk_unshift)(st, val) +#define SKM_sk_find(type, st,val) \ + ((int (*)(STACK_OF(type) *, type *))sk_find)(st, val) +#define SKM_sk_delete(type, st,i) \ + ((type * (*)(STACK_OF(type) *, int))sk_delete)(st, i) +#define SKM_sk_delete_ptr(type, st,ptr) \ + ((type * (*)(STACK_OF(type) *, type *))sk_delete_ptr)(st, ptr) +#define SKM_sk_insert(type, st,val,i) \ + ((int (*)(STACK_OF(type) *, type *, int))sk_insert)(st, val, i) +#define SKM_sk_set_cmp_func(type, st,cmp) \ + ((int (*(*)(STACK_OF(type) *, int (*)(const type * const *, const type * const *))) \ + (const type * const *, const type * const *))sk_set_cmp_func)\ + (st, cmp) +#define SKM_sk_dup(type, st) \ + ((STACK_OF(type) *(*)(STACK_OF(type) *))sk_dup)(st) +#define SKM_sk_pop_free(type, st,free_func) \ + ((void (*)(STACK_OF(type) *, void (*)(type *)))sk_pop_free)\ + (st, free_func) +#define SKM_sk_shift(type, st) \ + ((type * (*)(STACK_OF(type) *))sk_shift)(st) +#define SKM_sk_pop(type, st) \ + ((type * (*)(STACK_OF(type) *))sk_pop)(st) +#define SKM_sk_sort(type, st) \ + ((void (*)(STACK_OF(type) *))sk_sort)(st) + +#define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + ((STACK_OF(type) * (*) (STACK_OF(type) **,unsigned char **, long , \ + type *(*)(type **, unsigned char **,long), \ + void (*)(type *), int ,int )) d2i_ASN1_SET) \ + (st,pp,length, d2i_func, free_func, ex_tag,ex_class) +#define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \ + ((int (*)(STACK_OF(type) *,unsigned char **, \ + int (*)(type *,unsigned char **), int , int , int)) i2d_ASN1_SET) \ + (st,pp,i2d_func,ex_tag,ex_class,is_set) + +#define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \ + ((unsigned char *(*)(STACK_OF(type) *, \ + int (*)(type *,unsigned char **), unsigned char **,int *)) ASN1_seq_pack) \ + (st, i2d_func, buf, len) +#define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \ + ((STACK_OF(type) * (*)(unsigned char *,int, \ + type *(*)(type **,unsigned char **, long), \ + void (*)(type *)))ASN1_seq_unpack) \ + (buf,len,d2i_func, free_func) + +#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \ + ((STACK_OF(type) * (*)(X509_ALGOR *, \ + type *(*)(type **, unsigned char **, long), void (*)(type *), \ + const char *, int, \ + ASN1_STRING *, int))PKCS12_decrypt_d2i) \ + (algor,d2i_func,free_func,pass,passlen,oct,seq) + +#else + +#define STACK_OF(type) STACK +#define PREDECLARE_STACK_OF(type) /* nada */ +#define DECLARE_STACK_OF(type) /* nada */ +#define IMPLEMENT_STACK_OF(type) /* nada */ + +#define SKM_sk_new(type, cmp) \ + sk_new((int (*)(const char * const *, const char * const *))(cmp)) +#define SKM_sk_new_null(type) \ + sk_new_null() +#define SKM_sk_free(type, st) \ + sk_free(st) +#define SKM_sk_num(type, st) \ + sk_num(st) +#define SKM_sk_value(type, st,i) \ + ((type *)sk_value(st, i)) +#define SKM_sk_set(type, st,i,val) \ + ((type *)sk_set(st, i,(char *)val)) +#define SKM_sk_zero(type, st) \ + sk_zero(st) +#define SKM_sk_push(type, st,val) \ + sk_push(st, (char *)val) +#define SKM_sk_unshift(type, st,val) \ + sk_unshift(st, val) +#define SKM_sk_find(type, st,val) \ + sk_find(st, (char *)val) +#define SKM_sk_delete(type, st,i) \ + ((type *)sk_delete(st, i)) +#define SKM_sk_delete_ptr(type, st,ptr) \ + ((type *)sk_delete_ptr(st,(char *)ptr)) +#define SKM_sk_insert(type, st,val,i) \ + sk_insert(st, (char *)val, i) +#define SKM_sk_set_cmp_func(type, st,cmp) \ + ((int (*)(const type * const *,const type * const *)) \ + sk_set_cmp_func(st, (int (*)(const char * const *, const char * const *))(cmp))) +#define SKM_sk_dup(type, st) \ + sk_dup(st) +#define SKM_sk_pop_free(type, st,free_func) \ + sk_pop_free(st, (void (*)(void *))free_func) +#define SKM_sk_shift(type, st) \ + ((type *)sk_shift(st)) +#define SKM_sk_pop(type, st) \ + ((type *)sk_pop(st)) +#define SKM_sk_sort(type, st) \ + sk_sort(st) + +#define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + d2i_ASN1_SET(st,pp,length, (char *(*)())d2i_func, (void (*)(void *))free_func, ex_tag,ex_class) +#define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \ + i2d_ASN1_SET(st,pp,i2d_func,ex_tag,ex_class,is_set) + +#define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \ + ASN1_seq_pack(st, i2d_func, buf, len) +#define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \ + ASN1_seq_unpack(buf,len,(char *(*)())d2i_func, (void(*)(void *))free_func) + +#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \ + ((STACK *)PKCS12_decrypt_d2i(algor,(char *(*)())d2i_func, (void(*)(void *))free_func,pass,passlen,oct,seq)) + +#endif + +/* This block of defines is updated by util/mkstack.pl, please do not touch! */ +#define sk_ACCESS_DESCRIPTION_new(st) SKM_sk_new(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_new_null() SKM_sk_new_null(ACCESS_DESCRIPTION) +#define sk_ACCESS_DESCRIPTION_free(st) SKM_sk_free(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_num(st) SKM_sk_num(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_value(st, i) SKM_sk_value(ACCESS_DESCRIPTION, (st), (i)) +#define sk_ACCESS_DESCRIPTION_set(st, i, val) SKM_sk_set(ACCESS_DESCRIPTION, (st), (i), (val)) +#define sk_ACCESS_DESCRIPTION_zero(st) SKM_sk_zero(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_push(st, val) SKM_sk_push(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_unshift(st, val) SKM_sk_unshift(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_find(st, val) SKM_sk_find(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_delete(st, i) SKM_sk_delete(ACCESS_DESCRIPTION, (st), (i)) +#define sk_ACCESS_DESCRIPTION_delete_ptr(st, ptr) SKM_sk_delete_ptr(ACCESS_DESCRIPTION, (st), (ptr)) +#define sk_ACCESS_DESCRIPTION_insert(st, val, i) SKM_sk_insert(ACCESS_DESCRIPTION, (st), (val), (i)) +#define sk_ACCESS_DESCRIPTION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ACCESS_DESCRIPTION, (st), (cmp)) +#define sk_ACCESS_DESCRIPTION_dup(st) SKM_sk_dup(ACCESS_DESCRIPTION, st) +#define sk_ACCESS_DESCRIPTION_pop_free(st, free_func) SKM_sk_pop_free(ACCESS_DESCRIPTION, (st), (free_func)) +#define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st)) + +#define sk_ASN1_GENERALSTRING_new(st) SKM_sk_new(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING) +#define sk_ASN1_GENERALSTRING_free(st) SKM_sk_free(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_num(st) SKM_sk_num(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_value(st, i) SKM_sk_value(ASN1_GENERALSTRING, (st), (i)) +#define sk_ASN1_GENERALSTRING_set(st, i, val) SKM_sk_set(ASN1_GENERALSTRING, (st), (i), (val)) +#define sk_ASN1_GENERALSTRING_zero(st) SKM_sk_zero(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_push(st, val) SKM_sk_push(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_unshift(st, val) SKM_sk_unshift(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_find(st, val) SKM_sk_find(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_delete(st, i) SKM_sk_delete(ASN1_GENERALSTRING, (st), (i)) +#define sk_ASN1_GENERALSTRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_GENERALSTRING, (st), (ptr)) +#define sk_ASN1_GENERALSTRING_insert(st, val, i) SKM_sk_insert(ASN1_GENERALSTRING, (st), (val), (i)) +#define sk_ASN1_GENERALSTRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_GENERALSTRING, (st), (cmp)) +#define sk_ASN1_GENERALSTRING_dup(st) SKM_sk_dup(ASN1_GENERALSTRING, st) +#define sk_ASN1_GENERALSTRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_GENERALSTRING, (st), (free_func)) +#define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st)) + +#define sk_ASN1_INTEGER_new(st) SKM_sk_new(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER) +#define sk_ASN1_INTEGER_free(st) SKM_sk_free(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_num(st) SKM_sk_num(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_value(st, i) SKM_sk_value(ASN1_INTEGER, (st), (i)) +#define sk_ASN1_INTEGER_set(st, i, val) SKM_sk_set(ASN1_INTEGER, (st), (i), (val)) +#define sk_ASN1_INTEGER_zero(st) SKM_sk_zero(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_push(st, val) SKM_sk_push(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_unshift(st, val) SKM_sk_unshift(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_find(st, val) SKM_sk_find(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_delete(st, i) SKM_sk_delete(ASN1_INTEGER, (st), (i)) +#define sk_ASN1_INTEGER_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_INTEGER, (st), (ptr)) +#define sk_ASN1_INTEGER_insert(st, val, i) SKM_sk_insert(ASN1_INTEGER, (st), (val), (i)) +#define sk_ASN1_INTEGER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_INTEGER, (st), (cmp)) +#define sk_ASN1_INTEGER_dup(st) SKM_sk_dup(ASN1_INTEGER, st) +#define sk_ASN1_INTEGER_pop_free(st, free_func) SKM_sk_pop_free(ASN1_INTEGER, (st), (free_func)) +#define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st)) + +#define sk_ASN1_OBJECT_new(st) SKM_sk_new(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT) +#define sk_ASN1_OBJECT_free(st) SKM_sk_free(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_num(st) SKM_sk_num(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_value(st, i) SKM_sk_value(ASN1_OBJECT, (st), (i)) +#define sk_ASN1_OBJECT_set(st, i, val) SKM_sk_set(ASN1_OBJECT, (st), (i), (val)) +#define sk_ASN1_OBJECT_zero(st) SKM_sk_zero(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_push(st, val) SKM_sk_push(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_unshift(st, val) SKM_sk_unshift(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_find(st, val) SKM_sk_find(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_delete(st, i) SKM_sk_delete(ASN1_OBJECT, (st), (i)) +#define sk_ASN1_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_OBJECT, (st), (ptr)) +#define sk_ASN1_OBJECT_insert(st, val, i) SKM_sk_insert(ASN1_OBJECT, (st), (val), (i)) +#define sk_ASN1_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_OBJECT, (st), (cmp)) +#define sk_ASN1_OBJECT_dup(st) SKM_sk_dup(ASN1_OBJECT, st) +#define sk_ASN1_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(ASN1_OBJECT, (st), (free_func)) +#define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st)) + +#define sk_ASN1_STRING_TABLE_new(st) SKM_sk_new(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE) +#define sk_ASN1_STRING_TABLE_free(st) SKM_sk_free(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_num(st) SKM_sk_num(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_value(st, i) SKM_sk_value(ASN1_STRING_TABLE, (st), (i)) +#define sk_ASN1_STRING_TABLE_set(st, i, val) SKM_sk_set(ASN1_STRING_TABLE, (st), (i), (val)) +#define sk_ASN1_STRING_TABLE_zero(st) SKM_sk_zero(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_push(st, val) SKM_sk_push(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_unshift(st, val) SKM_sk_unshift(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_find(st, val) SKM_sk_find(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_delete(st, i) SKM_sk_delete(ASN1_STRING_TABLE, (st), (i)) +#define sk_ASN1_STRING_TABLE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_STRING_TABLE, (st), (ptr)) +#define sk_ASN1_STRING_TABLE_insert(st, val, i) SKM_sk_insert(ASN1_STRING_TABLE, (st), (val), (i)) +#define sk_ASN1_STRING_TABLE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_STRING_TABLE, (st), (cmp)) +#define sk_ASN1_STRING_TABLE_dup(st) SKM_sk_dup(ASN1_STRING_TABLE, st) +#define sk_ASN1_STRING_TABLE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_STRING_TABLE, (st), (free_func)) +#define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st)) + +#define sk_ASN1_TYPE_new(st) SKM_sk_new(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE) +#define sk_ASN1_TYPE_free(st) SKM_sk_free(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_num(st) SKM_sk_num(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_value(st, i) SKM_sk_value(ASN1_TYPE, (st), (i)) +#define sk_ASN1_TYPE_set(st, i, val) SKM_sk_set(ASN1_TYPE, (st), (i), (val)) +#define sk_ASN1_TYPE_zero(st) SKM_sk_zero(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_push(st, val) SKM_sk_push(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_unshift(st, val) SKM_sk_unshift(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_find(st, val) SKM_sk_find(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_delete(st, i) SKM_sk_delete(ASN1_TYPE, (st), (i)) +#define sk_ASN1_TYPE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_TYPE, (st), (ptr)) +#define sk_ASN1_TYPE_insert(st, val, i) SKM_sk_insert(ASN1_TYPE, (st), (val), (i)) +#define sk_ASN1_TYPE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_TYPE, (st), (cmp)) +#define sk_ASN1_TYPE_dup(st) SKM_sk_dup(ASN1_TYPE, st) +#define sk_ASN1_TYPE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_TYPE, (st), (free_func)) +#define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st)) + +#define sk_ASN1_VALUE_new(st) SKM_sk_new(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE) +#define sk_ASN1_VALUE_free(st) SKM_sk_free(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_num(st) SKM_sk_num(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_value(st, i) SKM_sk_value(ASN1_VALUE, (st), (i)) +#define sk_ASN1_VALUE_set(st, i, val) SKM_sk_set(ASN1_VALUE, (st), (i), (val)) +#define sk_ASN1_VALUE_zero(st) SKM_sk_zero(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_push(st, val) SKM_sk_push(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_unshift(st, val) SKM_sk_unshift(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_find(st, val) SKM_sk_find(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_delete(st, i) SKM_sk_delete(ASN1_VALUE, (st), (i)) +#define sk_ASN1_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_VALUE, (st), (ptr)) +#define sk_ASN1_VALUE_insert(st, val, i) SKM_sk_insert(ASN1_VALUE, (st), (val), (i)) +#define sk_ASN1_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_VALUE, (st), (cmp)) +#define sk_ASN1_VALUE_dup(st) SKM_sk_dup(ASN1_VALUE, st) +#define sk_ASN1_VALUE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_VALUE, (st), (free_func)) +#define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st)) + +#define sk_BIO_new(st) SKM_sk_new(BIO, (st)) +#define sk_BIO_new_null() SKM_sk_new_null(BIO) +#define sk_BIO_free(st) SKM_sk_free(BIO, (st)) +#define sk_BIO_num(st) SKM_sk_num(BIO, (st)) +#define sk_BIO_value(st, i) SKM_sk_value(BIO, (st), (i)) +#define sk_BIO_set(st, i, val) SKM_sk_set(BIO, (st), (i), (val)) +#define sk_BIO_zero(st) SKM_sk_zero(BIO, (st)) +#define sk_BIO_push(st, val) SKM_sk_push(BIO, (st), (val)) +#define sk_BIO_unshift(st, val) SKM_sk_unshift(BIO, (st), (val)) +#define sk_BIO_find(st, val) SKM_sk_find(BIO, (st), (val)) +#define sk_BIO_delete(st, i) SKM_sk_delete(BIO, (st), (i)) +#define sk_BIO_delete_ptr(st, ptr) SKM_sk_delete_ptr(BIO, (st), (ptr)) +#define sk_BIO_insert(st, val, i) SKM_sk_insert(BIO, (st), (val), (i)) +#define sk_BIO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BIO, (st), (cmp)) +#define sk_BIO_dup(st) SKM_sk_dup(BIO, st) +#define sk_BIO_pop_free(st, free_func) SKM_sk_pop_free(BIO, (st), (free_func)) +#define sk_BIO_shift(st) SKM_sk_shift(BIO, (st)) +#define sk_BIO_pop(st) SKM_sk_pop(BIO, (st)) +#define sk_BIO_sort(st) SKM_sk_sort(BIO, (st)) + +#define sk_CONF_IMODULE_new(st) SKM_sk_new(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE) +#define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_num(st) SKM_sk_num(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_value(st, i) SKM_sk_value(CONF_IMODULE, (st), (i)) +#define sk_CONF_IMODULE_set(st, i, val) SKM_sk_set(CONF_IMODULE, (st), (i), (val)) +#define sk_CONF_IMODULE_zero(st) SKM_sk_zero(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_push(st, val) SKM_sk_push(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_unshift(st, val) SKM_sk_unshift(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_find(st, val) SKM_sk_find(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_delete(st, i) SKM_sk_delete(CONF_IMODULE, (st), (i)) +#define sk_CONF_IMODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_IMODULE, (st), (ptr)) +#define sk_CONF_IMODULE_insert(st, val, i) SKM_sk_insert(CONF_IMODULE, (st), (val), (i)) +#define sk_CONF_IMODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_IMODULE, (st), (cmp)) +#define sk_CONF_IMODULE_dup(st) SKM_sk_dup(CONF_IMODULE, st) +#define sk_CONF_IMODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_IMODULE, (st), (free_func)) +#define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st)) + +#define sk_CONF_MODULE_new(st) SKM_sk_new(CONF_MODULE, (st)) +#define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE) +#define sk_CONF_MODULE_free(st) SKM_sk_free(CONF_MODULE, (st)) +#define sk_CONF_MODULE_num(st) SKM_sk_num(CONF_MODULE, (st)) +#define sk_CONF_MODULE_value(st, i) SKM_sk_value(CONF_MODULE, (st), (i)) +#define sk_CONF_MODULE_set(st, i, val) SKM_sk_set(CONF_MODULE, (st), (i), (val)) +#define sk_CONF_MODULE_zero(st) SKM_sk_zero(CONF_MODULE, (st)) +#define sk_CONF_MODULE_push(st, val) SKM_sk_push(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_unshift(st, val) SKM_sk_unshift(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_find(st, val) SKM_sk_find(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_delete(st, i) SKM_sk_delete(CONF_MODULE, (st), (i)) +#define sk_CONF_MODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_MODULE, (st), (ptr)) +#define sk_CONF_MODULE_insert(st, val, i) SKM_sk_insert(CONF_MODULE, (st), (val), (i)) +#define sk_CONF_MODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_MODULE, (st), (cmp)) +#define sk_CONF_MODULE_dup(st) SKM_sk_dup(CONF_MODULE, st) +#define sk_CONF_MODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_MODULE, (st), (free_func)) +#define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st)) +#define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st)) +#define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st)) + +#define sk_CONF_VALUE_new(st) SKM_sk_new(CONF_VALUE, (st)) +#define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE) +#define sk_CONF_VALUE_free(st) SKM_sk_free(CONF_VALUE, (st)) +#define sk_CONF_VALUE_num(st) SKM_sk_num(CONF_VALUE, (st)) +#define sk_CONF_VALUE_value(st, i) SKM_sk_value(CONF_VALUE, (st), (i)) +#define sk_CONF_VALUE_set(st, i, val) SKM_sk_set(CONF_VALUE, (st), (i), (val)) +#define sk_CONF_VALUE_zero(st) SKM_sk_zero(CONF_VALUE, (st)) +#define sk_CONF_VALUE_push(st, val) SKM_sk_push(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_unshift(st, val) SKM_sk_unshift(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_find(st, val) SKM_sk_find(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_delete(st, i) SKM_sk_delete(CONF_VALUE, (st), (i)) +#define sk_CONF_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_VALUE, (st), (ptr)) +#define sk_CONF_VALUE_insert(st, val, i) SKM_sk_insert(CONF_VALUE, (st), (val), (i)) +#define sk_CONF_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_VALUE, (st), (cmp)) +#define sk_CONF_VALUE_dup(st) SKM_sk_dup(CONF_VALUE, st) +#define sk_CONF_VALUE_pop_free(st, free_func) SKM_sk_pop_free(CONF_VALUE, (st), (free_func)) +#define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st)) +#define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st)) +#define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st)) + +#define sk_CRYPTO_EX_DATA_FUNCS_new(st) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (st)) +#define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS) +#define sk_CRYPTO_EX_DATA_FUNCS_free(st) SKM_sk_free(CRYPTO_EX_DATA_FUNCS, (st)) +#define sk_CRYPTO_EX_DATA_FUNCS_num(st) SKM_sk_num(CRYPTO_EX_DATA_FUNCS, (st)) +#define sk_CRYPTO_EX_DATA_FUNCS_value(st, i) SKM_sk_value(CRYPTO_EX_DATA_FUNCS, (st), (i)) +#define sk_CRYPTO_EX_DATA_FUNCS_set(st, i, val) SKM_sk_set(CRYPTO_EX_DATA_FUNCS, (st), (i), (val)) +#define sk_CRYPTO_EX_DATA_FUNCS_zero(st) SKM_sk_zero(CRYPTO_EX_DATA_FUNCS, (st)) +#define sk_CRYPTO_EX_DATA_FUNCS_push(st, val) SKM_sk_push(CRYPTO_EX_DATA_FUNCS, (st), (val)) +#define sk_CRYPTO_EX_DATA_FUNCS_unshift(st, val) SKM_sk_unshift(CRYPTO_EX_DATA_FUNCS, (st), (val)) +#define sk_CRYPTO_EX_DATA_FUNCS_find(st, val) SKM_sk_find(CRYPTO_EX_DATA_FUNCS, (st), (val)) +#define sk_CRYPTO_EX_DATA_FUNCS_delete(st, i) SKM_sk_delete(CRYPTO_EX_DATA_FUNCS, (st), (i)) +#define sk_CRYPTO_EX_DATA_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_EX_DATA_FUNCS, (st), (ptr)) +#define sk_CRYPTO_EX_DATA_FUNCS_insert(st, val, i) SKM_sk_insert(CRYPTO_EX_DATA_FUNCS, (st), (val), (i)) +#define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_EX_DATA_FUNCS, (st), (cmp)) +#define sk_CRYPTO_EX_DATA_FUNCS_dup(st) SKM_sk_dup(CRYPTO_EX_DATA_FUNCS, st) +#define sk_CRYPTO_EX_DATA_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_EX_DATA_FUNCS, (st), (free_func)) +#define sk_CRYPTO_EX_DATA_FUNCS_shift(st) SKM_sk_shift(CRYPTO_EX_DATA_FUNCS, (st)) +#define sk_CRYPTO_EX_DATA_FUNCS_pop(st) SKM_sk_pop(CRYPTO_EX_DATA_FUNCS, (st)) +#define sk_CRYPTO_EX_DATA_FUNCS_sort(st) SKM_sk_sort(CRYPTO_EX_DATA_FUNCS, (st)) + +#define sk_CRYPTO_dynlock_new(st) SKM_sk_new(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock) +#define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i)) +#define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val)) +#define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i)) +#define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr)) +#define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i)) +#define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp)) +#define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st) +#define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func)) +#define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st)) + +#define sk_DIST_POINT_new(st) SKM_sk_new(DIST_POINT, (st)) +#define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT) +#define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st)) +#define sk_DIST_POINT_num(st) SKM_sk_num(DIST_POINT, (st)) +#define sk_DIST_POINT_value(st, i) SKM_sk_value(DIST_POINT, (st), (i)) +#define sk_DIST_POINT_set(st, i, val) SKM_sk_set(DIST_POINT, (st), (i), (val)) +#define sk_DIST_POINT_zero(st) SKM_sk_zero(DIST_POINT, (st)) +#define sk_DIST_POINT_push(st, val) SKM_sk_push(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_unshift(st, val) SKM_sk_unshift(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_find(st, val) SKM_sk_find(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_delete(st, i) SKM_sk_delete(DIST_POINT, (st), (i)) +#define sk_DIST_POINT_delete_ptr(st, ptr) SKM_sk_delete_ptr(DIST_POINT, (st), (ptr)) +#define sk_DIST_POINT_insert(st, val, i) SKM_sk_insert(DIST_POINT, (st), (val), (i)) +#define sk_DIST_POINT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(DIST_POINT, (st), (cmp)) +#define sk_DIST_POINT_dup(st) SKM_sk_dup(DIST_POINT, st) +#define sk_DIST_POINT_pop_free(st, free_func) SKM_sk_pop_free(DIST_POINT, (st), (free_func)) +#define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st)) +#define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st)) +#define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st)) + +#define sk_ENGINE_new(st) SKM_sk_new(ENGINE, (st)) +#define sk_ENGINE_new_null() SKM_sk_new_null(ENGINE) +#define sk_ENGINE_free(st) SKM_sk_free(ENGINE, (st)) +#define sk_ENGINE_num(st) SKM_sk_num(ENGINE, (st)) +#define sk_ENGINE_value(st, i) SKM_sk_value(ENGINE, (st), (i)) +#define sk_ENGINE_set(st, i, val) SKM_sk_set(ENGINE, (st), (i), (val)) +#define sk_ENGINE_zero(st) SKM_sk_zero(ENGINE, (st)) +#define sk_ENGINE_push(st, val) SKM_sk_push(ENGINE, (st), (val)) +#define sk_ENGINE_unshift(st, val) SKM_sk_unshift(ENGINE, (st), (val)) +#define sk_ENGINE_find(st, val) SKM_sk_find(ENGINE, (st), (val)) +#define sk_ENGINE_delete(st, i) SKM_sk_delete(ENGINE, (st), (i)) +#define sk_ENGINE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE, (st), (ptr)) +#define sk_ENGINE_insert(st, val, i) SKM_sk_insert(ENGINE, (st), (val), (i)) +#define sk_ENGINE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE, (st), (cmp)) +#define sk_ENGINE_dup(st) SKM_sk_dup(ENGINE, st) +#define sk_ENGINE_pop_free(st, free_func) SKM_sk_pop_free(ENGINE, (st), (free_func)) +#define sk_ENGINE_shift(st) SKM_sk_shift(ENGINE, (st)) +#define sk_ENGINE_pop(st) SKM_sk_pop(ENGINE, (st)) +#define sk_ENGINE_sort(st) SKM_sk_sort(ENGINE, (st)) + +#define sk_ENGINE_CLEANUP_ITEM_new(st) SKM_sk_new(ENGINE_CLEANUP_ITEM, (st)) +#define sk_ENGINE_CLEANUP_ITEM_new_null() SKM_sk_new_null(ENGINE_CLEANUP_ITEM) +#define sk_ENGINE_CLEANUP_ITEM_free(st) SKM_sk_free(ENGINE_CLEANUP_ITEM, (st)) +#define sk_ENGINE_CLEANUP_ITEM_num(st) SKM_sk_num(ENGINE_CLEANUP_ITEM, (st)) +#define sk_ENGINE_CLEANUP_ITEM_value(st, i) SKM_sk_value(ENGINE_CLEANUP_ITEM, (st), (i)) +#define sk_ENGINE_CLEANUP_ITEM_set(st, i, val) SKM_sk_set(ENGINE_CLEANUP_ITEM, (st), (i), (val)) +#define sk_ENGINE_CLEANUP_ITEM_zero(st) SKM_sk_zero(ENGINE_CLEANUP_ITEM, (st)) +#define sk_ENGINE_CLEANUP_ITEM_push(st, val) SKM_sk_push(ENGINE_CLEANUP_ITEM, (st), (val)) +#define sk_ENGINE_CLEANUP_ITEM_unshift(st, val) SKM_sk_unshift(ENGINE_CLEANUP_ITEM, (st), (val)) +#define sk_ENGINE_CLEANUP_ITEM_find(st, val) SKM_sk_find(ENGINE_CLEANUP_ITEM, (st), (val)) +#define sk_ENGINE_CLEANUP_ITEM_delete(st, i) SKM_sk_delete(ENGINE_CLEANUP_ITEM, (st), (i)) +#define sk_ENGINE_CLEANUP_ITEM_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE_CLEANUP_ITEM, (st), (ptr)) +#define sk_ENGINE_CLEANUP_ITEM_insert(st, val, i) SKM_sk_insert(ENGINE_CLEANUP_ITEM, (st), (val), (i)) +#define sk_ENGINE_CLEANUP_ITEM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE_CLEANUP_ITEM, (st), (cmp)) +#define sk_ENGINE_CLEANUP_ITEM_dup(st) SKM_sk_dup(ENGINE_CLEANUP_ITEM, st) +#define sk_ENGINE_CLEANUP_ITEM_pop_free(st, free_func) SKM_sk_pop_free(ENGINE_CLEANUP_ITEM, (st), (free_func)) +#define sk_ENGINE_CLEANUP_ITEM_shift(st) SKM_sk_shift(ENGINE_CLEANUP_ITEM, (st)) +#define sk_ENGINE_CLEANUP_ITEM_pop(st) SKM_sk_pop(ENGINE_CLEANUP_ITEM, (st)) +#define sk_ENGINE_CLEANUP_ITEM_sort(st) SKM_sk_sort(ENGINE_CLEANUP_ITEM, (st)) + +#define sk_GENERAL_NAME_new(st) SKM_sk_new(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME) +#define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME, (st), (i)) +#define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME, (st), (i), (val)) +#define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME, (st), (i)) +#define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME, (st), (ptr)) +#define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME, (st), (val), (i)) +#define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME, (st), (cmp)) +#define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st) +#define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME, (st), (free_func)) +#define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st)) + +#define sk_KRB5_APREQBODY_new(st) SKM_sk_new(KRB5_APREQBODY, (st)) +#define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY) +#define sk_KRB5_APREQBODY_free(st) SKM_sk_free(KRB5_APREQBODY, (st)) +#define sk_KRB5_APREQBODY_num(st) SKM_sk_num(KRB5_APREQBODY, (st)) +#define sk_KRB5_APREQBODY_value(st, i) SKM_sk_value(KRB5_APREQBODY, (st), (i)) +#define sk_KRB5_APREQBODY_set(st, i, val) SKM_sk_set(KRB5_APREQBODY, (st), (i), (val)) +#define sk_KRB5_APREQBODY_zero(st) SKM_sk_zero(KRB5_APREQBODY, (st)) +#define sk_KRB5_APREQBODY_push(st, val) SKM_sk_push(KRB5_APREQBODY, (st), (val)) +#define sk_KRB5_APREQBODY_unshift(st, val) SKM_sk_unshift(KRB5_APREQBODY, (st), (val)) +#define sk_KRB5_APREQBODY_find(st, val) SKM_sk_find(KRB5_APREQBODY, (st), (val)) +#define sk_KRB5_APREQBODY_delete(st, i) SKM_sk_delete(KRB5_APREQBODY, (st), (i)) +#define sk_KRB5_APREQBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_APREQBODY, (st), (ptr)) +#define sk_KRB5_APREQBODY_insert(st, val, i) SKM_sk_insert(KRB5_APREQBODY, (st), (val), (i)) +#define sk_KRB5_APREQBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_APREQBODY, (st), (cmp)) +#define sk_KRB5_APREQBODY_dup(st) SKM_sk_dup(KRB5_APREQBODY, st) +#define sk_KRB5_APREQBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_APREQBODY, (st), (free_func)) +#define sk_KRB5_APREQBODY_shift(st) SKM_sk_shift(KRB5_APREQBODY, (st)) +#define sk_KRB5_APREQBODY_pop(st) SKM_sk_pop(KRB5_APREQBODY, (st)) +#define sk_KRB5_APREQBODY_sort(st) SKM_sk_sort(KRB5_APREQBODY, (st)) + +#define sk_KRB5_AUTHDATA_new(st) SKM_sk_new(KRB5_AUTHDATA, (st)) +#define sk_KRB5_AUTHDATA_new_null() SKM_sk_new_null(KRB5_AUTHDATA) +#define sk_KRB5_AUTHDATA_free(st) SKM_sk_free(KRB5_AUTHDATA, (st)) +#define sk_KRB5_AUTHDATA_num(st) SKM_sk_num(KRB5_AUTHDATA, (st)) +#define sk_KRB5_AUTHDATA_value(st, i) SKM_sk_value(KRB5_AUTHDATA, (st), (i)) +#define sk_KRB5_AUTHDATA_set(st, i, val) SKM_sk_set(KRB5_AUTHDATA, (st), (i), (val)) +#define sk_KRB5_AUTHDATA_zero(st) SKM_sk_zero(KRB5_AUTHDATA, (st)) +#define sk_KRB5_AUTHDATA_push(st, val) SKM_sk_push(KRB5_AUTHDATA, (st), (val)) +#define sk_KRB5_AUTHDATA_unshift(st, val) SKM_sk_unshift(KRB5_AUTHDATA, (st), (val)) +#define sk_KRB5_AUTHDATA_find(st, val) SKM_sk_find(KRB5_AUTHDATA, (st), (val)) +#define sk_KRB5_AUTHDATA_delete(st, i) SKM_sk_delete(KRB5_AUTHDATA, (st), (i)) +#define sk_KRB5_AUTHDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHDATA, (st), (ptr)) +#define sk_KRB5_AUTHDATA_insert(st, val, i) SKM_sk_insert(KRB5_AUTHDATA, (st), (val), (i)) +#define sk_KRB5_AUTHDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHDATA, (st), (cmp)) +#define sk_KRB5_AUTHDATA_dup(st) SKM_sk_dup(KRB5_AUTHDATA, st) +#define sk_KRB5_AUTHDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHDATA, (st), (free_func)) +#define sk_KRB5_AUTHDATA_shift(st) SKM_sk_shift(KRB5_AUTHDATA, (st)) +#define sk_KRB5_AUTHDATA_pop(st) SKM_sk_pop(KRB5_AUTHDATA, (st)) +#define sk_KRB5_AUTHDATA_sort(st) SKM_sk_sort(KRB5_AUTHDATA, (st)) + +#define sk_KRB5_AUTHENTBODY_new(st) SKM_sk_new(KRB5_AUTHENTBODY, (st)) +#define sk_KRB5_AUTHENTBODY_new_null() SKM_sk_new_null(KRB5_AUTHENTBODY) +#define sk_KRB5_AUTHENTBODY_free(st) SKM_sk_free(KRB5_AUTHENTBODY, (st)) +#define sk_KRB5_AUTHENTBODY_num(st) SKM_sk_num(KRB5_AUTHENTBODY, (st)) +#define sk_KRB5_AUTHENTBODY_value(st, i) SKM_sk_value(KRB5_AUTHENTBODY, (st), (i)) +#define sk_KRB5_AUTHENTBODY_set(st, i, val) SKM_sk_set(KRB5_AUTHENTBODY, (st), (i), (val)) +#define sk_KRB5_AUTHENTBODY_zero(st) SKM_sk_zero(KRB5_AUTHENTBODY, (st)) +#define sk_KRB5_AUTHENTBODY_push(st, val) SKM_sk_push(KRB5_AUTHENTBODY, (st), (val)) +#define sk_KRB5_AUTHENTBODY_unshift(st, val) SKM_sk_unshift(KRB5_AUTHENTBODY, (st), (val)) +#define sk_KRB5_AUTHENTBODY_find(st, val) SKM_sk_find(KRB5_AUTHENTBODY, (st), (val)) +#define sk_KRB5_AUTHENTBODY_delete(st, i) SKM_sk_delete(KRB5_AUTHENTBODY, (st), (i)) +#define sk_KRB5_AUTHENTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHENTBODY, (st), (ptr)) +#define sk_KRB5_AUTHENTBODY_insert(st, val, i) SKM_sk_insert(KRB5_AUTHENTBODY, (st), (val), (i)) +#define sk_KRB5_AUTHENTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHENTBODY, (st), (cmp)) +#define sk_KRB5_AUTHENTBODY_dup(st) SKM_sk_dup(KRB5_AUTHENTBODY, st) +#define sk_KRB5_AUTHENTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHENTBODY, (st), (free_func)) +#define sk_KRB5_AUTHENTBODY_shift(st) SKM_sk_shift(KRB5_AUTHENTBODY, (st)) +#define sk_KRB5_AUTHENTBODY_pop(st) SKM_sk_pop(KRB5_AUTHENTBODY, (st)) +#define sk_KRB5_AUTHENTBODY_sort(st) SKM_sk_sort(KRB5_AUTHENTBODY, (st)) + +#define sk_KRB5_CHECKSUM_new(st) SKM_sk_new(KRB5_CHECKSUM, (st)) +#define sk_KRB5_CHECKSUM_new_null() SKM_sk_new_null(KRB5_CHECKSUM) +#define sk_KRB5_CHECKSUM_free(st) SKM_sk_free(KRB5_CHECKSUM, (st)) +#define sk_KRB5_CHECKSUM_num(st) SKM_sk_num(KRB5_CHECKSUM, (st)) +#define sk_KRB5_CHECKSUM_value(st, i) SKM_sk_value(KRB5_CHECKSUM, (st), (i)) +#define sk_KRB5_CHECKSUM_set(st, i, val) SKM_sk_set(KRB5_CHECKSUM, (st), (i), (val)) +#define sk_KRB5_CHECKSUM_zero(st) SKM_sk_zero(KRB5_CHECKSUM, (st)) +#define sk_KRB5_CHECKSUM_push(st, val) SKM_sk_push(KRB5_CHECKSUM, (st), (val)) +#define sk_KRB5_CHECKSUM_unshift(st, val) SKM_sk_unshift(KRB5_CHECKSUM, (st), (val)) +#define sk_KRB5_CHECKSUM_find(st, val) SKM_sk_find(KRB5_CHECKSUM, (st), (val)) +#define sk_KRB5_CHECKSUM_delete(st, i) SKM_sk_delete(KRB5_CHECKSUM, (st), (i)) +#define sk_KRB5_CHECKSUM_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_CHECKSUM, (st), (ptr)) +#define sk_KRB5_CHECKSUM_insert(st, val, i) SKM_sk_insert(KRB5_CHECKSUM, (st), (val), (i)) +#define sk_KRB5_CHECKSUM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_CHECKSUM, (st), (cmp)) +#define sk_KRB5_CHECKSUM_dup(st) SKM_sk_dup(KRB5_CHECKSUM, st) +#define sk_KRB5_CHECKSUM_pop_free(st, free_func) SKM_sk_pop_free(KRB5_CHECKSUM, (st), (free_func)) +#define sk_KRB5_CHECKSUM_shift(st) SKM_sk_shift(KRB5_CHECKSUM, (st)) +#define sk_KRB5_CHECKSUM_pop(st) SKM_sk_pop(KRB5_CHECKSUM, (st)) +#define sk_KRB5_CHECKSUM_sort(st) SKM_sk_sort(KRB5_CHECKSUM, (st)) + +#define sk_KRB5_ENCDATA_new(st) SKM_sk_new(KRB5_ENCDATA, (st)) +#define sk_KRB5_ENCDATA_new_null() SKM_sk_new_null(KRB5_ENCDATA) +#define sk_KRB5_ENCDATA_free(st) SKM_sk_free(KRB5_ENCDATA, (st)) +#define sk_KRB5_ENCDATA_num(st) SKM_sk_num(KRB5_ENCDATA, (st)) +#define sk_KRB5_ENCDATA_value(st, i) SKM_sk_value(KRB5_ENCDATA, (st), (i)) +#define sk_KRB5_ENCDATA_set(st, i, val) SKM_sk_set(KRB5_ENCDATA, (st), (i), (val)) +#define sk_KRB5_ENCDATA_zero(st) SKM_sk_zero(KRB5_ENCDATA, (st)) +#define sk_KRB5_ENCDATA_push(st, val) SKM_sk_push(KRB5_ENCDATA, (st), (val)) +#define sk_KRB5_ENCDATA_unshift(st, val) SKM_sk_unshift(KRB5_ENCDATA, (st), (val)) +#define sk_KRB5_ENCDATA_find(st, val) SKM_sk_find(KRB5_ENCDATA, (st), (val)) +#define sk_KRB5_ENCDATA_delete(st, i) SKM_sk_delete(KRB5_ENCDATA, (st), (i)) +#define sk_KRB5_ENCDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCDATA, (st), (ptr)) +#define sk_KRB5_ENCDATA_insert(st, val, i) SKM_sk_insert(KRB5_ENCDATA, (st), (val), (i)) +#define sk_KRB5_ENCDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCDATA, (st), (cmp)) +#define sk_KRB5_ENCDATA_dup(st) SKM_sk_dup(KRB5_ENCDATA, st) +#define sk_KRB5_ENCDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCDATA, (st), (free_func)) +#define sk_KRB5_ENCDATA_shift(st) SKM_sk_shift(KRB5_ENCDATA, (st)) +#define sk_KRB5_ENCDATA_pop(st) SKM_sk_pop(KRB5_ENCDATA, (st)) +#define sk_KRB5_ENCDATA_sort(st) SKM_sk_sort(KRB5_ENCDATA, (st)) + +#define sk_KRB5_ENCKEY_new(st) SKM_sk_new(KRB5_ENCKEY, (st)) +#define sk_KRB5_ENCKEY_new_null() SKM_sk_new_null(KRB5_ENCKEY) +#define sk_KRB5_ENCKEY_free(st) SKM_sk_free(KRB5_ENCKEY, (st)) +#define sk_KRB5_ENCKEY_num(st) SKM_sk_num(KRB5_ENCKEY, (st)) +#define sk_KRB5_ENCKEY_value(st, i) SKM_sk_value(KRB5_ENCKEY, (st), (i)) +#define sk_KRB5_ENCKEY_set(st, i, val) SKM_sk_set(KRB5_ENCKEY, (st), (i), (val)) +#define sk_KRB5_ENCKEY_zero(st) SKM_sk_zero(KRB5_ENCKEY, (st)) +#define sk_KRB5_ENCKEY_push(st, val) SKM_sk_push(KRB5_ENCKEY, (st), (val)) +#define sk_KRB5_ENCKEY_unshift(st, val) SKM_sk_unshift(KRB5_ENCKEY, (st), (val)) +#define sk_KRB5_ENCKEY_find(st, val) SKM_sk_find(KRB5_ENCKEY, (st), (val)) +#define sk_KRB5_ENCKEY_delete(st, i) SKM_sk_delete(KRB5_ENCKEY, (st), (i)) +#define sk_KRB5_ENCKEY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCKEY, (st), (ptr)) +#define sk_KRB5_ENCKEY_insert(st, val, i) SKM_sk_insert(KRB5_ENCKEY, (st), (val), (i)) +#define sk_KRB5_ENCKEY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCKEY, (st), (cmp)) +#define sk_KRB5_ENCKEY_dup(st) SKM_sk_dup(KRB5_ENCKEY, st) +#define sk_KRB5_ENCKEY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCKEY, (st), (free_func)) +#define sk_KRB5_ENCKEY_shift(st) SKM_sk_shift(KRB5_ENCKEY, (st)) +#define sk_KRB5_ENCKEY_pop(st) SKM_sk_pop(KRB5_ENCKEY, (st)) +#define sk_KRB5_ENCKEY_sort(st) SKM_sk_sort(KRB5_ENCKEY, (st)) + +#define sk_KRB5_PRINCNAME_new(st) SKM_sk_new(KRB5_PRINCNAME, (st)) +#define sk_KRB5_PRINCNAME_new_null() SKM_sk_new_null(KRB5_PRINCNAME) +#define sk_KRB5_PRINCNAME_free(st) SKM_sk_free(KRB5_PRINCNAME, (st)) +#define sk_KRB5_PRINCNAME_num(st) SKM_sk_num(KRB5_PRINCNAME, (st)) +#define sk_KRB5_PRINCNAME_value(st, i) SKM_sk_value(KRB5_PRINCNAME, (st), (i)) +#define sk_KRB5_PRINCNAME_set(st, i, val) SKM_sk_set(KRB5_PRINCNAME, (st), (i), (val)) +#define sk_KRB5_PRINCNAME_zero(st) SKM_sk_zero(KRB5_PRINCNAME, (st)) +#define sk_KRB5_PRINCNAME_push(st, val) SKM_sk_push(KRB5_PRINCNAME, (st), (val)) +#define sk_KRB5_PRINCNAME_unshift(st, val) SKM_sk_unshift(KRB5_PRINCNAME, (st), (val)) +#define sk_KRB5_PRINCNAME_find(st, val) SKM_sk_find(KRB5_PRINCNAME, (st), (val)) +#define sk_KRB5_PRINCNAME_delete(st, i) SKM_sk_delete(KRB5_PRINCNAME, (st), (i)) +#define sk_KRB5_PRINCNAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_PRINCNAME, (st), (ptr)) +#define sk_KRB5_PRINCNAME_insert(st, val, i) SKM_sk_insert(KRB5_PRINCNAME, (st), (val), (i)) +#define sk_KRB5_PRINCNAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_PRINCNAME, (st), (cmp)) +#define sk_KRB5_PRINCNAME_dup(st) SKM_sk_dup(KRB5_PRINCNAME, st) +#define sk_KRB5_PRINCNAME_pop_free(st, free_func) SKM_sk_pop_free(KRB5_PRINCNAME, (st), (free_func)) +#define sk_KRB5_PRINCNAME_shift(st) SKM_sk_shift(KRB5_PRINCNAME, (st)) +#define sk_KRB5_PRINCNAME_pop(st) SKM_sk_pop(KRB5_PRINCNAME, (st)) +#define sk_KRB5_PRINCNAME_sort(st) SKM_sk_sort(KRB5_PRINCNAME, (st)) + +#define sk_KRB5_TKTBODY_new(st) SKM_sk_new(KRB5_TKTBODY, (st)) +#define sk_KRB5_TKTBODY_new_null() SKM_sk_new_null(KRB5_TKTBODY) +#define sk_KRB5_TKTBODY_free(st) SKM_sk_free(KRB5_TKTBODY, (st)) +#define sk_KRB5_TKTBODY_num(st) SKM_sk_num(KRB5_TKTBODY, (st)) +#define sk_KRB5_TKTBODY_value(st, i) SKM_sk_value(KRB5_TKTBODY, (st), (i)) +#define sk_KRB5_TKTBODY_set(st, i, val) SKM_sk_set(KRB5_TKTBODY, (st), (i), (val)) +#define sk_KRB5_TKTBODY_zero(st) SKM_sk_zero(KRB5_TKTBODY, (st)) +#define sk_KRB5_TKTBODY_push(st, val) SKM_sk_push(KRB5_TKTBODY, (st), (val)) +#define sk_KRB5_TKTBODY_unshift(st, val) SKM_sk_unshift(KRB5_TKTBODY, (st), (val)) +#define sk_KRB5_TKTBODY_find(st, val) SKM_sk_find(KRB5_TKTBODY, (st), (val)) +#define sk_KRB5_TKTBODY_delete(st, i) SKM_sk_delete(KRB5_TKTBODY, (st), (i)) +#define sk_KRB5_TKTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_TKTBODY, (st), (ptr)) +#define sk_KRB5_TKTBODY_insert(st, val, i) SKM_sk_insert(KRB5_TKTBODY, (st), (val), (i)) +#define sk_KRB5_TKTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_TKTBODY, (st), (cmp)) +#define sk_KRB5_TKTBODY_dup(st) SKM_sk_dup(KRB5_TKTBODY, st) +#define sk_KRB5_TKTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_TKTBODY, (st), (free_func)) +#define sk_KRB5_TKTBODY_shift(st) SKM_sk_shift(KRB5_TKTBODY, (st)) +#define sk_KRB5_TKTBODY_pop(st) SKM_sk_pop(KRB5_TKTBODY, (st)) +#define sk_KRB5_TKTBODY_sort(st) SKM_sk_sort(KRB5_TKTBODY, (st)) + +#define sk_MIME_HEADER_new(st) SKM_sk_new(MIME_HEADER, (st)) +#define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER) +#define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st)) +#define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st)) +#define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i)) +#define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val)) +#define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st)) +#define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i)) +#define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr)) +#define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i)) +#define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp)) +#define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st) +#define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func)) +#define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st)) +#define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st)) +#define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st)) + +#define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st)) +#define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM) +#define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st)) +#define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st)) +#define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i)) +#define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val)) +#define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st)) +#define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i)) +#define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr)) +#define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i)) +#define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp)) +#define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st) +#define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func)) +#define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st)) +#define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st)) +#define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st)) + +#define sk_NAME_FUNCS_new(st) SKM_sk_new(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS) +#define sk_NAME_FUNCS_free(st) SKM_sk_free(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_num(st) SKM_sk_num(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_value(st, i) SKM_sk_value(NAME_FUNCS, (st), (i)) +#define sk_NAME_FUNCS_set(st, i, val) SKM_sk_set(NAME_FUNCS, (st), (i), (val)) +#define sk_NAME_FUNCS_zero(st) SKM_sk_zero(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_push(st, val) SKM_sk_push(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_unshift(st, val) SKM_sk_unshift(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_find(st, val) SKM_sk_find(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_delete(st, i) SKM_sk_delete(NAME_FUNCS, (st), (i)) +#define sk_NAME_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(NAME_FUNCS, (st), (ptr)) +#define sk_NAME_FUNCS_insert(st, val, i) SKM_sk_insert(NAME_FUNCS, (st), (val), (i)) +#define sk_NAME_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(NAME_FUNCS, (st), (cmp)) +#define sk_NAME_FUNCS_dup(st) SKM_sk_dup(NAME_FUNCS, st) +#define sk_NAME_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(NAME_FUNCS, (st), (free_func)) +#define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st)) + +#define sk_OCSP_CERTID_new(st) SKM_sk_new(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID) +#define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i)) +#define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val)) +#define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i)) +#define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr)) +#define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i)) +#define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp)) +#define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st) +#define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func)) +#define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st)) + +#define sk_OCSP_ONEREQ_new(st) SKM_sk_new(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ) +#define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_num(st) SKM_sk_num(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_value(st, i) SKM_sk_value(OCSP_ONEREQ, (st), (i)) +#define sk_OCSP_ONEREQ_set(st, i, val) SKM_sk_set(OCSP_ONEREQ, (st), (i), (val)) +#define sk_OCSP_ONEREQ_zero(st) SKM_sk_zero(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_push(st, val) SKM_sk_push(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_unshift(st, val) SKM_sk_unshift(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_find(st, val) SKM_sk_find(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_delete(st, i) SKM_sk_delete(OCSP_ONEREQ, (st), (i)) +#define sk_OCSP_ONEREQ_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_ONEREQ, (st), (ptr)) +#define sk_OCSP_ONEREQ_insert(st, val, i) SKM_sk_insert(OCSP_ONEREQ, (st), (val), (i)) +#define sk_OCSP_ONEREQ_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_ONEREQ, (st), (cmp)) +#define sk_OCSP_ONEREQ_dup(st) SKM_sk_dup(OCSP_ONEREQ, st) +#define sk_OCSP_ONEREQ_pop_free(st, free_func) SKM_sk_pop_free(OCSP_ONEREQ, (st), (free_func)) +#define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st)) + +#define sk_OCSP_SINGLERESP_new(st) SKM_sk_new(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP) +#define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_num(st) SKM_sk_num(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_value(st, i) SKM_sk_value(OCSP_SINGLERESP, (st), (i)) +#define sk_OCSP_SINGLERESP_set(st, i, val) SKM_sk_set(OCSP_SINGLERESP, (st), (i), (val)) +#define sk_OCSP_SINGLERESP_zero(st) SKM_sk_zero(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_push(st, val) SKM_sk_push(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_unshift(st, val) SKM_sk_unshift(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_find(st, val) SKM_sk_find(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_delete(st, i) SKM_sk_delete(OCSP_SINGLERESP, (st), (i)) +#define sk_OCSP_SINGLERESP_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_SINGLERESP, (st), (ptr)) +#define sk_OCSP_SINGLERESP_insert(st, val, i) SKM_sk_insert(OCSP_SINGLERESP, (st), (val), (i)) +#define sk_OCSP_SINGLERESP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_SINGLERESP, (st), (cmp)) +#define sk_OCSP_SINGLERESP_dup(st) SKM_sk_dup(OCSP_SINGLERESP, st) +#define sk_OCSP_SINGLERESP_pop_free(st, free_func) SKM_sk_pop_free(OCSP_SINGLERESP, (st), (free_func)) +#define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st)) + +#define sk_PKCS12_SAFEBAG_new(st) SKM_sk_new(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG) +#define sk_PKCS12_SAFEBAG_free(st) SKM_sk_free(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_num(st) SKM_sk_num(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_value(st, i) SKM_sk_value(PKCS12_SAFEBAG, (st), (i)) +#define sk_PKCS12_SAFEBAG_set(st, i, val) SKM_sk_set(PKCS12_SAFEBAG, (st), (i), (val)) +#define sk_PKCS12_SAFEBAG_zero(st) SKM_sk_zero(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_push(st, val) SKM_sk_push(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_unshift(st, val) SKM_sk_unshift(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_find(st, val) SKM_sk_find(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_delete(st, i) SKM_sk_delete(PKCS12_SAFEBAG, (st), (i)) +#define sk_PKCS12_SAFEBAG_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS12_SAFEBAG, (st), (ptr)) +#define sk_PKCS12_SAFEBAG_insert(st, val, i) SKM_sk_insert(PKCS12_SAFEBAG, (st), (val), (i)) +#define sk_PKCS12_SAFEBAG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS12_SAFEBAG, (st), (cmp)) +#define sk_PKCS12_SAFEBAG_dup(st) SKM_sk_dup(PKCS12_SAFEBAG, st) +#define sk_PKCS12_SAFEBAG_pop_free(st, free_func) SKM_sk_pop_free(PKCS12_SAFEBAG, (st), (free_func)) +#define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st)) + +#define sk_PKCS7_new(st) SKM_sk_new(PKCS7, (st)) +#define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7) +#define sk_PKCS7_free(st) SKM_sk_free(PKCS7, (st)) +#define sk_PKCS7_num(st) SKM_sk_num(PKCS7, (st)) +#define sk_PKCS7_value(st, i) SKM_sk_value(PKCS7, (st), (i)) +#define sk_PKCS7_set(st, i, val) SKM_sk_set(PKCS7, (st), (i), (val)) +#define sk_PKCS7_zero(st) SKM_sk_zero(PKCS7, (st)) +#define sk_PKCS7_push(st, val) SKM_sk_push(PKCS7, (st), (val)) +#define sk_PKCS7_unshift(st, val) SKM_sk_unshift(PKCS7, (st), (val)) +#define sk_PKCS7_find(st, val) SKM_sk_find(PKCS7, (st), (val)) +#define sk_PKCS7_delete(st, i) SKM_sk_delete(PKCS7, (st), (i)) +#define sk_PKCS7_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7, (st), (ptr)) +#define sk_PKCS7_insert(st, val, i) SKM_sk_insert(PKCS7, (st), (val), (i)) +#define sk_PKCS7_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7, (st), (cmp)) +#define sk_PKCS7_dup(st) SKM_sk_dup(PKCS7, st) +#define sk_PKCS7_pop_free(st, free_func) SKM_sk_pop_free(PKCS7, (st), (free_func)) +#define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st)) +#define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st)) +#define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st)) + +#define sk_PKCS7_RECIP_INFO_new(st) SKM_sk_new(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO) +#define sk_PKCS7_RECIP_INFO_free(st) SKM_sk_free(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_num(st) SKM_sk_num(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_value(st, i) SKM_sk_value(PKCS7_RECIP_INFO, (st), (i)) +#define sk_PKCS7_RECIP_INFO_set(st, i, val) SKM_sk_set(PKCS7_RECIP_INFO, (st), (i), (val)) +#define sk_PKCS7_RECIP_INFO_zero(st) SKM_sk_zero(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_push(st, val) SKM_sk_push(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_find(st, val) SKM_sk_find(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_delete(st, i) SKM_sk_delete(PKCS7_RECIP_INFO, (st), (i)) +#define sk_PKCS7_RECIP_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_RECIP_INFO, (st), (ptr)) +#define sk_PKCS7_RECIP_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_RECIP_INFO, (st), (val), (i)) +#define sk_PKCS7_RECIP_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_RECIP_INFO, (st), (cmp)) +#define sk_PKCS7_RECIP_INFO_dup(st) SKM_sk_dup(PKCS7_RECIP_INFO, st) +#define sk_PKCS7_RECIP_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_RECIP_INFO, (st), (free_func)) +#define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st)) + +#define sk_PKCS7_SIGNER_INFO_new(st) SKM_sk_new(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO) +#define sk_PKCS7_SIGNER_INFO_free(st) SKM_sk_free(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_num(st) SKM_sk_num(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_value(st, i) SKM_sk_value(PKCS7_SIGNER_INFO, (st), (i)) +#define sk_PKCS7_SIGNER_INFO_set(st, i, val) SKM_sk_set(PKCS7_SIGNER_INFO, (st), (i), (val)) +#define sk_PKCS7_SIGNER_INFO_zero(st) SKM_sk_zero(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_push(st, val) SKM_sk_push(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_find(st, val) SKM_sk_find(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_delete(st, i) SKM_sk_delete(PKCS7_SIGNER_INFO, (st), (i)) +#define sk_PKCS7_SIGNER_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_SIGNER_INFO, (st), (ptr)) +#define sk_PKCS7_SIGNER_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_SIGNER_INFO, (st), (val), (i)) +#define sk_PKCS7_SIGNER_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_SIGNER_INFO, (st), (cmp)) +#define sk_PKCS7_SIGNER_INFO_dup(st) SKM_sk_dup(PKCS7_SIGNER_INFO, st) +#define sk_PKCS7_SIGNER_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_SIGNER_INFO, (st), (free_func)) +#define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st)) + +#define sk_POLICYINFO_new(st) SKM_sk_new(POLICYINFO, (st)) +#define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO) +#define sk_POLICYINFO_free(st) SKM_sk_free(POLICYINFO, (st)) +#define sk_POLICYINFO_num(st) SKM_sk_num(POLICYINFO, (st)) +#define sk_POLICYINFO_value(st, i) SKM_sk_value(POLICYINFO, (st), (i)) +#define sk_POLICYINFO_set(st, i, val) SKM_sk_set(POLICYINFO, (st), (i), (val)) +#define sk_POLICYINFO_zero(st) SKM_sk_zero(POLICYINFO, (st)) +#define sk_POLICYINFO_push(st, val) SKM_sk_push(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_unshift(st, val) SKM_sk_unshift(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_find(st, val) SKM_sk_find(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_delete(st, i) SKM_sk_delete(POLICYINFO, (st), (i)) +#define sk_POLICYINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYINFO, (st), (ptr)) +#define sk_POLICYINFO_insert(st, val, i) SKM_sk_insert(POLICYINFO, (st), (val), (i)) +#define sk_POLICYINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYINFO, (st), (cmp)) +#define sk_POLICYINFO_dup(st) SKM_sk_dup(POLICYINFO, st) +#define sk_POLICYINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYINFO, (st), (free_func)) +#define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st)) +#define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st)) +#define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st)) + +#define sk_POLICYQUALINFO_new(st) SKM_sk_new(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO) +#define sk_POLICYQUALINFO_free(st) SKM_sk_free(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_num(st) SKM_sk_num(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_value(st, i) SKM_sk_value(POLICYQUALINFO, (st), (i)) +#define sk_POLICYQUALINFO_set(st, i, val) SKM_sk_set(POLICYQUALINFO, (st), (i), (val)) +#define sk_POLICYQUALINFO_zero(st) SKM_sk_zero(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_push(st, val) SKM_sk_push(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_unshift(st, val) SKM_sk_unshift(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_find(st, val) SKM_sk_find(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_delete(st, i) SKM_sk_delete(POLICYQUALINFO, (st), (i)) +#define sk_POLICYQUALINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYQUALINFO, (st), (ptr)) +#define sk_POLICYQUALINFO_insert(st, val, i) SKM_sk_insert(POLICYQUALINFO, (st), (val), (i)) +#define sk_POLICYQUALINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYQUALINFO, (st), (cmp)) +#define sk_POLICYQUALINFO_dup(st) SKM_sk_dup(POLICYQUALINFO, st) +#define sk_POLICYQUALINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYQUALINFO, (st), (free_func)) +#define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st)) + +#define sk_SSL_CIPHER_new(st) SKM_sk_new(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER) +#define sk_SSL_CIPHER_free(st) SKM_sk_free(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_num(st) SKM_sk_num(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_value(st, i) SKM_sk_value(SSL_CIPHER, (st), (i)) +#define sk_SSL_CIPHER_set(st, i, val) SKM_sk_set(SSL_CIPHER, (st), (i), (val)) +#define sk_SSL_CIPHER_zero(st) SKM_sk_zero(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_push(st, val) SKM_sk_push(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_unshift(st, val) SKM_sk_unshift(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_find(st, val) SKM_sk_find(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_delete(st, i) SKM_sk_delete(SSL_CIPHER, (st), (i)) +#define sk_SSL_CIPHER_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_CIPHER, (st), (ptr)) +#define sk_SSL_CIPHER_insert(st, val, i) SKM_sk_insert(SSL_CIPHER, (st), (val), (i)) +#define sk_SSL_CIPHER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_CIPHER, (st), (cmp)) +#define sk_SSL_CIPHER_dup(st) SKM_sk_dup(SSL_CIPHER, st) +#define sk_SSL_CIPHER_pop_free(st, free_func) SKM_sk_pop_free(SSL_CIPHER, (st), (free_func)) +#define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st)) + +#define sk_SSL_COMP_new(st) SKM_sk_new(SSL_COMP, (st)) +#define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP) +#define sk_SSL_COMP_free(st) SKM_sk_free(SSL_COMP, (st)) +#define sk_SSL_COMP_num(st) SKM_sk_num(SSL_COMP, (st)) +#define sk_SSL_COMP_value(st, i) SKM_sk_value(SSL_COMP, (st), (i)) +#define sk_SSL_COMP_set(st, i, val) SKM_sk_set(SSL_COMP, (st), (i), (val)) +#define sk_SSL_COMP_zero(st) SKM_sk_zero(SSL_COMP, (st)) +#define sk_SSL_COMP_push(st, val) SKM_sk_push(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_unshift(st, val) SKM_sk_unshift(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_find(st, val) SKM_sk_find(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_delete(st, i) SKM_sk_delete(SSL_COMP, (st), (i)) +#define sk_SSL_COMP_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_COMP, (st), (ptr)) +#define sk_SSL_COMP_insert(st, val, i) SKM_sk_insert(SSL_COMP, (st), (val), (i)) +#define sk_SSL_COMP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_COMP, (st), (cmp)) +#define sk_SSL_COMP_dup(st) SKM_sk_dup(SSL_COMP, st) +#define sk_SSL_COMP_pop_free(st, free_func) SKM_sk_pop_free(SSL_COMP, (st), (free_func)) +#define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st)) +#define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st)) +#define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st)) + +#define sk_SXNETID_new(st) SKM_sk_new(SXNETID, (st)) +#define sk_SXNETID_new_null() SKM_sk_new_null(SXNETID) +#define sk_SXNETID_free(st) SKM_sk_free(SXNETID, (st)) +#define sk_SXNETID_num(st) SKM_sk_num(SXNETID, (st)) +#define sk_SXNETID_value(st, i) SKM_sk_value(SXNETID, (st), (i)) +#define sk_SXNETID_set(st, i, val) SKM_sk_set(SXNETID, (st), (i), (val)) +#define sk_SXNETID_zero(st) SKM_sk_zero(SXNETID, (st)) +#define sk_SXNETID_push(st, val) SKM_sk_push(SXNETID, (st), (val)) +#define sk_SXNETID_unshift(st, val) SKM_sk_unshift(SXNETID, (st), (val)) +#define sk_SXNETID_find(st, val) SKM_sk_find(SXNETID, (st), (val)) +#define sk_SXNETID_delete(st, i) SKM_sk_delete(SXNETID, (st), (i)) +#define sk_SXNETID_delete_ptr(st, ptr) SKM_sk_delete_ptr(SXNETID, (st), (ptr)) +#define sk_SXNETID_insert(st, val, i) SKM_sk_insert(SXNETID, (st), (val), (i)) +#define sk_SXNETID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SXNETID, (st), (cmp)) +#define sk_SXNETID_dup(st) SKM_sk_dup(SXNETID, st) +#define sk_SXNETID_pop_free(st, free_func) SKM_sk_pop_free(SXNETID, (st), (free_func)) +#define sk_SXNETID_shift(st) SKM_sk_shift(SXNETID, (st)) +#define sk_SXNETID_pop(st) SKM_sk_pop(SXNETID, (st)) +#define sk_SXNETID_sort(st) SKM_sk_sort(SXNETID, (st)) + +#define sk_UI_STRING_new(st) SKM_sk_new(UI_STRING, (st)) +#define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING) +#define sk_UI_STRING_free(st) SKM_sk_free(UI_STRING, (st)) +#define sk_UI_STRING_num(st) SKM_sk_num(UI_STRING, (st)) +#define sk_UI_STRING_value(st, i) SKM_sk_value(UI_STRING, (st), (i)) +#define sk_UI_STRING_set(st, i, val) SKM_sk_set(UI_STRING, (st), (i), (val)) +#define sk_UI_STRING_zero(st) SKM_sk_zero(UI_STRING, (st)) +#define sk_UI_STRING_push(st, val) SKM_sk_push(UI_STRING, (st), (val)) +#define sk_UI_STRING_unshift(st, val) SKM_sk_unshift(UI_STRING, (st), (val)) +#define sk_UI_STRING_find(st, val) SKM_sk_find(UI_STRING, (st), (val)) +#define sk_UI_STRING_delete(st, i) SKM_sk_delete(UI_STRING, (st), (i)) +#define sk_UI_STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(UI_STRING, (st), (ptr)) +#define sk_UI_STRING_insert(st, val, i) SKM_sk_insert(UI_STRING, (st), (val), (i)) +#define sk_UI_STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(UI_STRING, (st), (cmp)) +#define sk_UI_STRING_dup(st) SKM_sk_dup(UI_STRING, st) +#define sk_UI_STRING_pop_free(st, free_func) SKM_sk_pop_free(UI_STRING, (st), (free_func)) +#define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st)) +#define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st)) +#define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st)) + +#define sk_X509_new(st) SKM_sk_new(X509, (st)) +#define sk_X509_new_null() SKM_sk_new_null(X509) +#define sk_X509_free(st) SKM_sk_free(X509, (st)) +#define sk_X509_num(st) SKM_sk_num(X509, (st)) +#define sk_X509_value(st, i) SKM_sk_value(X509, (st), (i)) +#define sk_X509_set(st, i, val) SKM_sk_set(X509, (st), (i), (val)) +#define sk_X509_zero(st) SKM_sk_zero(X509, (st)) +#define sk_X509_push(st, val) SKM_sk_push(X509, (st), (val)) +#define sk_X509_unshift(st, val) SKM_sk_unshift(X509, (st), (val)) +#define sk_X509_find(st, val) SKM_sk_find(X509, (st), (val)) +#define sk_X509_delete(st, i) SKM_sk_delete(X509, (st), (i)) +#define sk_X509_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509, (st), (ptr)) +#define sk_X509_insert(st, val, i) SKM_sk_insert(X509, (st), (val), (i)) +#define sk_X509_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509, (st), (cmp)) +#define sk_X509_dup(st) SKM_sk_dup(X509, st) +#define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func)) +#define sk_X509_shift(st) SKM_sk_shift(X509, (st)) +#define sk_X509_pop(st) SKM_sk_pop(X509, (st)) +#define sk_X509_sort(st) SKM_sk_sort(X509, (st)) + +#define sk_X509V3_EXT_METHOD_new(st) SKM_sk_new(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD) +#define sk_X509V3_EXT_METHOD_free(st) SKM_sk_free(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_num(st) SKM_sk_num(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_value(st, i) SKM_sk_value(X509V3_EXT_METHOD, (st), (i)) +#define sk_X509V3_EXT_METHOD_set(st, i, val) SKM_sk_set(X509V3_EXT_METHOD, (st), (i), (val)) +#define sk_X509V3_EXT_METHOD_zero(st) SKM_sk_zero(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_push(st, val) SKM_sk_push(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_unshift(st, val) SKM_sk_unshift(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_find(st, val) SKM_sk_find(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_delete(st, i) SKM_sk_delete(X509V3_EXT_METHOD, (st), (i)) +#define sk_X509V3_EXT_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509V3_EXT_METHOD, (st), (ptr)) +#define sk_X509V3_EXT_METHOD_insert(st, val, i) SKM_sk_insert(X509V3_EXT_METHOD, (st), (val), (i)) +#define sk_X509V3_EXT_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509V3_EXT_METHOD, (st), (cmp)) +#define sk_X509V3_EXT_METHOD_dup(st) SKM_sk_dup(X509V3_EXT_METHOD, st) +#define sk_X509V3_EXT_METHOD_pop_free(st, free_func) SKM_sk_pop_free(X509V3_EXT_METHOD, (st), (free_func)) +#define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st)) + +#define sk_X509_ALGOR_new(st) SKM_sk_new(X509_ALGOR, (st)) +#define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR) +#define sk_X509_ALGOR_free(st) SKM_sk_free(X509_ALGOR, (st)) +#define sk_X509_ALGOR_num(st) SKM_sk_num(X509_ALGOR, (st)) +#define sk_X509_ALGOR_value(st, i) SKM_sk_value(X509_ALGOR, (st), (i)) +#define sk_X509_ALGOR_set(st, i, val) SKM_sk_set(X509_ALGOR, (st), (i), (val)) +#define sk_X509_ALGOR_zero(st) SKM_sk_zero(X509_ALGOR, (st)) +#define sk_X509_ALGOR_push(st, val) SKM_sk_push(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_unshift(st, val) SKM_sk_unshift(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_find(st, val) SKM_sk_find(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_delete(st, i) SKM_sk_delete(X509_ALGOR, (st), (i)) +#define sk_X509_ALGOR_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ALGOR, (st), (ptr)) +#define sk_X509_ALGOR_insert(st, val, i) SKM_sk_insert(X509_ALGOR, (st), (val), (i)) +#define sk_X509_ALGOR_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ALGOR, (st), (cmp)) +#define sk_X509_ALGOR_dup(st) SKM_sk_dup(X509_ALGOR, st) +#define sk_X509_ALGOR_pop_free(st, free_func) SKM_sk_pop_free(X509_ALGOR, (st), (free_func)) +#define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st)) +#define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st)) +#define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st)) + +#define sk_X509_ATTRIBUTE_new(st) SKM_sk_new(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE) +#define sk_X509_ATTRIBUTE_free(st) SKM_sk_free(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_num(st) SKM_sk_num(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_value(st, i) SKM_sk_value(X509_ATTRIBUTE, (st), (i)) +#define sk_X509_ATTRIBUTE_set(st, i, val) SKM_sk_set(X509_ATTRIBUTE, (st), (i), (val)) +#define sk_X509_ATTRIBUTE_zero(st) SKM_sk_zero(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_push(st, val) SKM_sk_push(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_unshift(st, val) SKM_sk_unshift(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_find(st, val) SKM_sk_find(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_delete(st, i) SKM_sk_delete(X509_ATTRIBUTE, (st), (i)) +#define sk_X509_ATTRIBUTE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ATTRIBUTE, (st), (ptr)) +#define sk_X509_ATTRIBUTE_insert(st, val, i) SKM_sk_insert(X509_ATTRIBUTE, (st), (val), (i)) +#define sk_X509_ATTRIBUTE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ATTRIBUTE, (st), (cmp)) +#define sk_X509_ATTRIBUTE_dup(st) SKM_sk_dup(X509_ATTRIBUTE, st) +#define sk_X509_ATTRIBUTE_pop_free(st, free_func) SKM_sk_pop_free(X509_ATTRIBUTE, (st), (free_func)) +#define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st)) + +#define sk_X509_CRL_new(st) SKM_sk_new(X509_CRL, (st)) +#define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL) +#define sk_X509_CRL_free(st) SKM_sk_free(X509_CRL, (st)) +#define sk_X509_CRL_num(st) SKM_sk_num(X509_CRL, (st)) +#define sk_X509_CRL_value(st, i) SKM_sk_value(X509_CRL, (st), (i)) +#define sk_X509_CRL_set(st, i, val) SKM_sk_set(X509_CRL, (st), (i), (val)) +#define sk_X509_CRL_zero(st) SKM_sk_zero(X509_CRL, (st)) +#define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val)) +#define sk_X509_CRL_unshift(st, val) SKM_sk_unshift(X509_CRL, (st), (val)) +#define sk_X509_CRL_find(st, val) SKM_sk_find(X509_CRL, (st), (val)) +#define sk_X509_CRL_delete(st, i) SKM_sk_delete(X509_CRL, (st), (i)) +#define sk_X509_CRL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_CRL, (st), (ptr)) +#define sk_X509_CRL_insert(st, val, i) SKM_sk_insert(X509_CRL, (st), (val), (i)) +#define sk_X509_CRL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_CRL, (st), (cmp)) +#define sk_X509_CRL_dup(st) SKM_sk_dup(X509_CRL, st) +#define sk_X509_CRL_pop_free(st, free_func) SKM_sk_pop_free(X509_CRL, (st), (free_func)) +#define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st)) +#define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st)) +#define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st)) + +#define sk_X509_EXTENSION_new(st) SKM_sk_new(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION) +#define sk_X509_EXTENSION_free(st) SKM_sk_free(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_num(st) SKM_sk_num(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_value(st, i) SKM_sk_value(X509_EXTENSION, (st), (i)) +#define sk_X509_EXTENSION_set(st, i, val) SKM_sk_set(X509_EXTENSION, (st), (i), (val)) +#define sk_X509_EXTENSION_zero(st) SKM_sk_zero(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_push(st, val) SKM_sk_push(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_unshift(st, val) SKM_sk_unshift(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_find(st, val) SKM_sk_find(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_delete(st, i) SKM_sk_delete(X509_EXTENSION, (st), (i)) +#define sk_X509_EXTENSION_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_EXTENSION, (st), (ptr)) +#define sk_X509_EXTENSION_insert(st, val, i) SKM_sk_insert(X509_EXTENSION, (st), (val), (i)) +#define sk_X509_EXTENSION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_EXTENSION, (st), (cmp)) +#define sk_X509_EXTENSION_dup(st) SKM_sk_dup(X509_EXTENSION, st) +#define sk_X509_EXTENSION_pop_free(st, free_func) SKM_sk_pop_free(X509_EXTENSION, (st), (free_func)) +#define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st)) + +#define sk_X509_INFO_new(st) SKM_sk_new(X509_INFO, (st)) +#define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO) +#define sk_X509_INFO_free(st) SKM_sk_free(X509_INFO, (st)) +#define sk_X509_INFO_num(st) SKM_sk_num(X509_INFO, (st)) +#define sk_X509_INFO_value(st, i) SKM_sk_value(X509_INFO, (st), (i)) +#define sk_X509_INFO_set(st, i, val) SKM_sk_set(X509_INFO, (st), (i), (val)) +#define sk_X509_INFO_zero(st) SKM_sk_zero(X509_INFO, (st)) +#define sk_X509_INFO_push(st, val) SKM_sk_push(X509_INFO, (st), (val)) +#define sk_X509_INFO_unshift(st, val) SKM_sk_unshift(X509_INFO, (st), (val)) +#define sk_X509_INFO_find(st, val) SKM_sk_find(X509_INFO, (st), (val)) +#define sk_X509_INFO_delete(st, i) SKM_sk_delete(X509_INFO, (st), (i)) +#define sk_X509_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_INFO, (st), (ptr)) +#define sk_X509_INFO_insert(st, val, i) SKM_sk_insert(X509_INFO, (st), (val), (i)) +#define sk_X509_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_INFO, (st), (cmp)) +#define sk_X509_INFO_dup(st) SKM_sk_dup(X509_INFO, st) +#define sk_X509_INFO_pop_free(st, free_func) SKM_sk_pop_free(X509_INFO, (st), (free_func)) +#define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st)) +#define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st)) +#define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st)) + +#define sk_X509_LOOKUP_new(st) SKM_sk_new(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP) +#define sk_X509_LOOKUP_free(st) SKM_sk_free(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_num(st) SKM_sk_num(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_value(st, i) SKM_sk_value(X509_LOOKUP, (st), (i)) +#define sk_X509_LOOKUP_set(st, i, val) SKM_sk_set(X509_LOOKUP, (st), (i), (val)) +#define sk_X509_LOOKUP_zero(st) SKM_sk_zero(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_push(st, val) SKM_sk_push(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_unshift(st, val) SKM_sk_unshift(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_find(st, val) SKM_sk_find(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_delete(st, i) SKM_sk_delete(X509_LOOKUP, (st), (i)) +#define sk_X509_LOOKUP_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_LOOKUP, (st), (ptr)) +#define sk_X509_LOOKUP_insert(st, val, i) SKM_sk_insert(X509_LOOKUP, (st), (val), (i)) +#define sk_X509_LOOKUP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_LOOKUP, (st), (cmp)) +#define sk_X509_LOOKUP_dup(st) SKM_sk_dup(X509_LOOKUP, st) +#define sk_X509_LOOKUP_pop_free(st, free_func) SKM_sk_pop_free(X509_LOOKUP, (st), (free_func)) +#define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st)) + +#define sk_X509_NAME_new(st) SKM_sk_new(X509_NAME, (st)) +#define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME) +#define sk_X509_NAME_free(st) SKM_sk_free(X509_NAME, (st)) +#define sk_X509_NAME_num(st) SKM_sk_num(X509_NAME, (st)) +#define sk_X509_NAME_value(st, i) SKM_sk_value(X509_NAME, (st), (i)) +#define sk_X509_NAME_set(st, i, val) SKM_sk_set(X509_NAME, (st), (i), (val)) +#define sk_X509_NAME_zero(st) SKM_sk_zero(X509_NAME, (st)) +#define sk_X509_NAME_push(st, val) SKM_sk_push(X509_NAME, (st), (val)) +#define sk_X509_NAME_unshift(st, val) SKM_sk_unshift(X509_NAME, (st), (val)) +#define sk_X509_NAME_find(st, val) SKM_sk_find(X509_NAME, (st), (val)) +#define sk_X509_NAME_delete(st, i) SKM_sk_delete(X509_NAME, (st), (i)) +#define sk_X509_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME, (st), (ptr)) +#define sk_X509_NAME_insert(st, val, i) SKM_sk_insert(X509_NAME, (st), (val), (i)) +#define sk_X509_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME, (st), (cmp)) +#define sk_X509_NAME_dup(st) SKM_sk_dup(X509_NAME, st) +#define sk_X509_NAME_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME, (st), (free_func)) +#define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st)) +#define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st)) +#define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st)) + +#define sk_X509_NAME_ENTRY_new(st) SKM_sk_new(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY) +#define sk_X509_NAME_ENTRY_free(st) SKM_sk_free(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_num(st) SKM_sk_num(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_value(st, i) SKM_sk_value(X509_NAME_ENTRY, (st), (i)) +#define sk_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(X509_NAME_ENTRY, (st), (i), (val)) +#define sk_X509_NAME_ENTRY_zero(st) SKM_sk_zero(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_push(st, val) SKM_sk_push(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_find(st, val) SKM_sk_find(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(X509_NAME_ENTRY, (st), (i)) +#define sk_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME_ENTRY, (st), (ptr)) +#define sk_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(X509_NAME_ENTRY, (st), (val), (i)) +#define sk_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME_ENTRY, (st), (cmp)) +#define sk_X509_NAME_ENTRY_dup(st) SKM_sk_dup(X509_NAME_ENTRY, st) +#define sk_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME_ENTRY, (st), (free_func)) +#define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st)) + +#define sk_X509_OBJECT_new(st) SKM_sk_new(X509_OBJECT, (st)) +#define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT) +#define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st)) +#define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st)) +#define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i)) +#define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val)) +#define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st)) +#define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i)) +#define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr)) +#define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i)) +#define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp)) +#define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st) +#define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func)) +#define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st)) +#define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st)) +#define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st)) + +#define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE) +#define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_num(st) SKM_sk_num(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_value(st, i) SKM_sk_value(X509_PURPOSE, (st), (i)) +#define sk_X509_PURPOSE_set(st, i, val) SKM_sk_set(X509_PURPOSE, (st), (i), (val)) +#define sk_X509_PURPOSE_zero(st) SKM_sk_zero(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_push(st, val) SKM_sk_push(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_unshift(st, val) SKM_sk_unshift(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_find(st, val) SKM_sk_find(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_delete(st, i) SKM_sk_delete(X509_PURPOSE, (st), (i)) +#define sk_X509_PURPOSE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_PURPOSE, (st), (ptr)) +#define sk_X509_PURPOSE_insert(st, val, i) SKM_sk_insert(X509_PURPOSE, (st), (val), (i)) +#define sk_X509_PURPOSE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_PURPOSE, (st), (cmp)) +#define sk_X509_PURPOSE_dup(st) SKM_sk_dup(X509_PURPOSE, st) +#define sk_X509_PURPOSE_pop_free(st, free_func) SKM_sk_pop_free(X509_PURPOSE, (st), (free_func)) +#define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st)) + +#define sk_X509_REVOKED_new(st) SKM_sk_new(X509_REVOKED, (st)) +#define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED) +#define sk_X509_REVOKED_free(st) SKM_sk_free(X509_REVOKED, (st)) +#define sk_X509_REVOKED_num(st) SKM_sk_num(X509_REVOKED, (st)) +#define sk_X509_REVOKED_value(st, i) SKM_sk_value(X509_REVOKED, (st), (i)) +#define sk_X509_REVOKED_set(st, i, val) SKM_sk_set(X509_REVOKED, (st), (i), (val)) +#define sk_X509_REVOKED_zero(st) SKM_sk_zero(X509_REVOKED, (st)) +#define sk_X509_REVOKED_push(st, val) SKM_sk_push(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_unshift(st, val) SKM_sk_unshift(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_find(st, val) SKM_sk_find(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_delete(st, i) SKM_sk_delete(X509_REVOKED, (st), (i)) +#define sk_X509_REVOKED_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_REVOKED, (st), (ptr)) +#define sk_X509_REVOKED_insert(st, val, i) SKM_sk_insert(X509_REVOKED, (st), (val), (i)) +#define sk_X509_REVOKED_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_REVOKED, (st), (cmp)) +#define sk_X509_REVOKED_dup(st) SKM_sk_dup(X509_REVOKED, st) +#define sk_X509_REVOKED_pop_free(st, free_func) SKM_sk_pop_free(X509_REVOKED, (st), (free_func)) +#define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st)) +#define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st)) +#define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st)) + +#define sk_X509_TRUST_new(st) SKM_sk_new(X509_TRUST, (st)) +#define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST) +#define sk_X509_TRUST_free(st) SKM_sk_free(X509_TRUST, (st)) +#define sk_X509_TRUST_num(st) SKM_sk_num(X509_TRUST, (st)) +#define sk_X509_TRUST_value(st, i) SKM_sk_value(X509_TRUST, (st), (i)) +#define sk_X509_TRUST_set(st, i, val) SKM_sk_set(X509_TRUST, (st), (i), (val)) +#define sk_X509_TRUST_zero(st) SKM_sk_zero(X509_TRUST, (st)) +#define sk_X509_TRUST_push(st, val) SKM_sk_push(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_unshift(st, val) SKM_sk_unshift(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_find(st, val) SKM_sk_find(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_delete(st, i) SKM_sk_delete(X509_TRUST, (st), (i)) +#define sk_X509_TRUST_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_TRUST, (st), (ptr)) +#define sk_X509_TRUST_insert(st, val, i) SKM_sk_insert(X509_TRUST, (st), (val), (i)) +#define sk_X509_TRUST_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_TRUST, (st), (cmp)) +#define sk_X509_TRUST_dup(st) SKM_sk_dup(X509_TRUST, st) +#define sk_X509_TRUST_pop_free(st, free_func) SKM_sk_pop_free(X509_TRUST, (st), (free_func)) +#define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st)) +#define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st)) +#define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st)) + +#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ACCESS_DESCRIPTION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_ACCESS_DESCRIPTION(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ACCESS_DESCRIPTION, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_ACCESS_DESCRIPTION(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ACCESS_DESCRIPTION, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_ASN1_INTEGER(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_INTEGER, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_ASN1_INTEGER(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_INTEGER, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_ASN1_INTEGER(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_INTEGER, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_ASN1_INTEGER(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_INTEGER, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_ASN1_OBJECT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_OBJECT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_ASN1_OBJECT(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_OBJECT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_ASN1_OBJECT(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_OBJECT, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_ASN1_OBJECT(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_OBJECT, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_ASN1_TYPE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_TYPE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_ASN1_TYPE(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_TYPE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_ASN1_TYPE(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_TYPE, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_ASN1_TYPE(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_TYPE, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_DIST_POINT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(DIST_POINT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_DIST_POINT(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(DIST_POINT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_DIST_POINT(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(DIST_POINT, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_DIST_POINT(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(DIST_POINT, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_GENERAL_NAME(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(GENERAL_NAME, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_GENERAL_NAME(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(GENERAL_NAME, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_GENERAL_NAME(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(GENERAL_NAME, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_GENERAL_NAME(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(GENERAL_NAME, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_OCSP_ONEREQ(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(OCSP_ONEREQ, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_OCSP_ONEREQ(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(OCSP_ONEREQ, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_OCSP_ONEREQ(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(OCSP_ONEREQ, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_OCSP_ONEREQ(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(OCSP_ONEREQ, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(OCSP_SINGLERESP, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(OCSP_SINGLERESP, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_OCSP_SINGLERESP(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(OCSP_SINGLERESP, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_OCSP_SINGLERESP(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(OCSP_SINGLERESP, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS12_SAFEBAG, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS12_SAFEBAG, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_PKCS12_SAFEBAG(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS12_SAFEBAG, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_PKCS12_SAFEBAG(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS12_SAFEBAG, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_PKCS7(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS7, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_PKCS7(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS7, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_PKCS7(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS7, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_PKCS7(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS7, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS7_RECIP_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS7_RECIP_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_PKCS7_RECIP_INFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS7_RECIP_INFO, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_PKCS7_RECIP_INFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS7_RECIP_INFO, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS7_SIGNER_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS7_SIGNER_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_PKCS7_SIGNER_INFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS7_SIGNER_INFO, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_PKCS7_SIGNER_INFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS7_SIGNER_INFO, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_POLICYINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(POLICYINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_POLICYINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(POLICYINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_POLICYINFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(POLICYINFO, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_POLICYINFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(POLICYINFO, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_POLICYQUALINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(POLICYQUALINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_POLICYQUALINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(POLICYQUALINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_POLICYQUALINFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(POLICYQUALINFO, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_POLICYQUALINFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(POLICYQUALINFO, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_SXNETID(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(SXNETID, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_SXNETID(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(SXNETID, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_SXNETID(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(SXNETID, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_SXNETID(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(SXNETID, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509_ALGOR(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_ALGOR, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509_ALGOR(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_ALGOR, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509_ALGOR(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_ALGOR, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509_ALGOR(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_ALGOR, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_ATTRIBUTE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_ATTRIBUTE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509_ATTRIBUTE(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_ATTRIBUTE, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509_ATTRIBUTE(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_ATTRIBUTE, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509_CRL(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_CRL, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509_CRL(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_CRL, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509_CRL(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_CRL, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509_CRL(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_CRL, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509_EXTENSION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_EXTENSION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509_EXTENSION(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_EXTENSION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509_EXTENSION(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_EXTENSION, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509_EXTENSION(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_EXTENSION, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_NAME_ENTRY, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_NAME_ENTRY, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509_NAME_ENTRY(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_NAME_ENTRY, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509_NAME_ENTRY(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_NAME_ENTRY, (buf), (len), (d2i_func), (free_func)) + +#define d2i_ASN1_SET_OF_X509_REVOKED(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_REVOKED, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +#define i2d_ASN1_SET_OF_X509_REVOKED(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_REVOKED, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +#define ASN1_seq_pack_X509_REVOKED(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_REVOKED, (st), (i2d_func), (buf), (len)) +#define ASN1_seq_unpack_X509_REVOKED(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_REVOKED, (buf), (len), (d2i_func), (free_func)) + +#define PKCS12_decrypt_d2i_PKCS12_SAFEBAG(algor, d2i_func, free_func, pass, passlen, oct, seq) \ + SKM_PKCS12_decrypt_d2i(PKCS12_SAFEBAG, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq)) + +#define PKCS12_decrypt_d2i_PKCS7(algor, d2i_func, free_func, pass, passlen, oct, seq) \ + SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq)) +/* End of util/mkstack.pl block, you may now edit :-) */ + +#endif /* !defined HEADER_SAFESTACK_H */ diff --git a/src/lib/libcrypto/stack/stack.c b/src/lib/libcrypto/stack/stack.c index 610ccbb756..2496f28a8c 100644 --- a/src/lib/libcrypto/stack/stack.c +++ b/src/lib/libcrypto/stack/stack.c @@ -59,7 +59,7 @@ /* 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 seached item. + * lowest index for the searched item. * * 1.1 eay - Take from netdb and added to SSLeay * @@ -67,38 +67,34 @@ */ #include #include "cryptlib.h" -#include "stack.h" +#include #undef MIN_NODES #define MIN_NODES 4 -char *STACK_version="STACK part of SSLeay 0.9.0b 29-Jun-1998"; - -#ifndef NOPROTO -#define FP_ICC (int (*)(const void *,const void *)) -#else -#define FP_ICC -#endif +const char *STACK_version="Stack" OPENSSL_VERSION_PTEXT; #include -void sk_set_cmp_func(sk,c) -STACK *sk; -int (*c)(); +int (*sk_set_cmp_func(STACK *sk, int (*c)(const char * const *,const char * const *))) + (const char * const *, const char * const *) { + int (*old)(const char * const *,const char * const *)=sk->comp; + if (sk->comp != c) sk->sorted=0; sk->comp=c; + + return old; } -STACK *sk_dup(sk) -STACK *sk; +STACK *sk_dup(STACK *sk) { STACK *ret; char **s; if ((ret=sk_new(sk->comp)) == NULL) goto err; - s=(char **)Realloc((char *)ret->data, + s=(char **)OPENSSL_realloc((char *)ret->data, (unsigned int)sizeof(char *)*sk->num_alloc); if (s == NULL) goto err; ret->data=s; @@ -110,19 +106,25 @@ STACK *sk; ret->comp=sk->comp; return(ret); err: + if(ret) + sk_free(ret); return(NULL); } -STACK *sk_new(c) -int (*c)(); +STACK *sk_new_null(void) + { + return sk_new((int (*)(const char * const *, const char * const *))0); + } + +STACK *sk_new(int (*c)(const char * const *, const char * const *)) { 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; + if ((ret=(STACK *)OPENSSL_malloc(sizeof(STACK))) == NULL) + goto err; + if ((ret->data=(char **)OPENSSL_malloc(sizeof(char *)*MIN_NODES)) == NULL) + goto err; for (i=0; idata[i]=NULL; ret->comp=c; @@ -130,22 +132,20 @@ int (*c)(); ret->num=0; ret->sorted=0; return(ret); -err1: - Free((char *)ret); -err0: +err: + if(ret) + OPENSSL_free(ret); return(NULL); } -int sk_insert(st,data,loc) -STACK *st; -char *data; -int loc; +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, + s=(char **)OPENSSL_realloc((char *)st->data, (unsigned int)sizeof(char *)*st->num_alloc*2); if (s == NULL) return(0); @@ -161,7 +161,7 @@ int loc; f=(char **)st->data; t=(char **)&(st->data[1]); - for (i=st->num; i>loc; i--) + for (i=st->num; i>=loc; i--) t[i]=f[i]; #ifdef undef /* no memmove on sunos :-( */ @@ -176,9 +176,7 @@ int loc; return(st->num); } -char *sk_delete_ptr(st,p) -STACK *st; -char *p; +char *sk_delete_ptr(STACK *st, char *p) { int i; @@ -188,14 +186,13 @@ char *p; return(NULL); } -char *sk_delete(st,loc) -STACK *st; -int loc; +char *sk_delete(STACK *st, int loc) { char *ret; int i,j; - if ((st->num == 0) || (loc < 0) || (loc >= st->num)) return(NULL); + if ((st == NULL) || (st->num == 0) || (loc < 0) + || (loc >= st->num)) return(NULL); ret=st->data[loc]; if (loc != st->num-1) @@ -213,13 +210,12 @@ int loc; return(ret); } -int sk_find(st,data) -STACK *st; -char *data; +int sk_find(STACK *st, char *data) { char **r; int i; - int (*comp_func)(); + int (*comp_func)(const void *,const void *); + if(st == NULL) return -1; if (st->comp == NULL) { @@ -228,55 +224,55 @@ char *data; return(i); return(-1); } - comp_func=(int (*)())st->comp; - if (!st->sorted) - { - qsort((char *)st->data,st->num,sizeof(char *),FP_ICC comp_func); - st->sorted=1; - } + sk_sort(st); if (data == NULL) return(-1); + /* This (and the "qsort" below) are the two places in OpenSSL + * where we need to convert from our standard (type **,type **) + * compare callback type to the (void *,void *) type required by + * bsearch. However, the "data" it is being called(back) with are + * not (type *) pointers, but the *pointers* to (type *) pointers, + * so we get our extra level of pointer dereferencing that way. */ + comp_func=(int (*)(const void *,const void *))(st->comp); r=(char **)bsearch(&data,(char *)st->data, - st->num,sizeof(char *),FP_ICC comp_func); + st->num,sizeof(char *), 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) + /* This needs a cast because the type being pointed to from + * the "&" expressions are (char *) rather than (const char *). + * For an explanation, read: + * http://www.eskimo.com/~scs/C-faq/q11.10.html :-) */ + if ((*st->comp)((const char * const *)&(st->data[i-1]), + (const char * const *)&data) < 0) break; return(i); } -int sk_push(st,data) -STACK *st; -char *data; +int sk_push(STACK *st, char *data) { return(sk_insert(st,data,st->num)); } -int sk_unshift(st,data) -STACK *st; -char *data; +int sk_unshift(STACK *st, char *data) { return(sk_insert(st,data,0)); } -char *sk_shift(st) -STACK *st; +char *sk_shift(STACK *st) { if (st == NULL) return(NULL); if (st->num <= 0) return(NULL); return(sk_delete(st,0)); } -char *sk_pop(st) -STACK *st; +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(st) -STACK *st; +void sk_zero(STACK *st) { if (st == NULL) return; if (st->num <= 0) return; @@ -284,9 +280,7 @@ STACK *st; st->num=0; } -void sk_pop_free(st,func) -STACK *st; -void (*func)(); +void sk_pop_free(STACK *st, void (*func)(void *)) { int i; @@ -297,11 +291,44 @@ void (*func)(); sk_free(st); } -void sk_free(st) -STACK *st; +void sk_free(STACK *st) { if (st == NULL) return; - if (st->data != NULL) Free((char *)st->data); - Free((char *)st); + if (st->data != NULL) OPENSSL_free(st->data); + OPENSSL_free(st); } +int sk_num(const STACK *st) +{ + if(st == NULL) return -1; + return st->num; +} + +char *sk_value(const 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 && !st->sorted) + { + int (*comp_func)(const void *,const void *); + + /* same comment as in sk_find ... previously st->comp was declared + * as a (void*,void*) callback type, but this made the population + * of the callback pointer illogical - our callbacks compare + * type** with type**, so we leave the casting until absolutely + * necessary (ie. "now"). */ + comp_func=(int (*)(const void *,const void *))(st->comp); + qsort(st->data,st->num,sizeof(char *), comp_func); + st->sorted=1; + } + } diff --git a/src/lib/libcrypto/stack/stack.h b/src/lib/libcrypto/stack/stack.h index 615eb6ff94..8b436ca4b9 100644 --- a/src/lib/libcrypto/stack/stack.h +++ b/src/lib/libcrypto/stack/stack.h @@ -70,18 +70,21 @@ typedef struct stack_st int sorted; int num_alloc; - int (*comp)(); + int (*comp)(const char * const *, const char * const *); } STACK; -#define sk_num(sk) ((sk)->num) -#define sk_value(sk,n) ((sk)->data[n]) +#define M_sk_num(sk) ((sk) ? (sk)->num:-1) +#define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL) -#define sk_new_null() sk_new(NULL) -#ifndef NOPROTO +int sk_num(const STACK *); +char *sk_value(const STACK *, int); -STACK *sk_new(int (*cmp)()); +char *sk_set(STACK *, int, char *); + +STACK *sk_new(int (*cmp)(const char * const *, const char * const *)); +STACK *sk_new_null(void); void sk_free(STACK *); -void sk_pop_free(STACK *st, void (*func)()); +void sk_pop_free(STACK *st, void (*func)(void *)); int sk_insert(STACK *sk,char *data,int where); char *sk_delete(STACK *st,int loc); char *sk_delete_ptr(STACK *st, char *p); @@ -91,27 +94,11 @@ int sk_unshift(STACK *st,char *data); char *sk_shift(STACK *st); char *sk_pop(STACK *st); void sk_zero(STACK *st); -void sk_set_cmp_func(STACK *sk, int (*c)()); +int (*sk_set_cmp_func(STACK *sk, int (*c)(const char * const *, + const char * const *))) + (const char * const *, const char * const *); STACK *sk_dup(STACK *st); - -#else - -STACK *sk_new(); -void sk_free(); -void sk_pop_free(); -int sk_insert(); -char *sk_delete(); -char *sk_delete_ptr(); -int sk_find(); -int sk_push(); -int sk_unshift(); -char *sk_shift(); -char *sk_pop(); -void sk_zero(); -void sk_set_cmp_func(); -STACK *sk_dup(); - -#endif +void sk_sort(STACK *st); #ifdef __cplusplus } diff --git a/src/lib/libcrypto/txt_db/txt_db.c b/src/lib/libcrypto/txt_db/txt_db.c index e34ce4efa9..9b186f2da5 100644 --- a/src/lib/libcrypto/txt_db/txt_db.c +++ b/src/lib/libcrypto/txt_db/txt_db.c @@ -60,17 +60,15 @@ #include #include #include "cryptlib.h" -#include "buffer.h" -#include "txt_db.h" +#include +#include #undef BUFSIZE #define BUFSIZE 512 -char *TXT_DB_version="TXT_DB part of SSLeay 0.9.0b 29-Jun-1998"; +const char *TXT_DB_version="TXT_DB" OPENSSL_VERSION_PTEXT; -TXT_DB *TXT_DB_read(in,num) -BIO *in; -int num; +TXT_DB *TXT_DB_read(BIO *in, int num) { TXT_DB *ret=NULL; int er=1; @@ -85,16 +83,16 @@ int num; if ((buf=BUF_MEM_new()) == NULL) goto err; if (!BUF_MEM_grow(buf,size)) goto err; - if ((ret=(TXT_DB *)Malloc(sizeof(TXT_DB))) == NULL) + if ((ret=(TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL) goto err; ret->num_fields=num; ret->index=NULL; ret->qual=NULL; if ((ret->data=sk_new_null()) == NULL) goto err; - if ((ret->index=(LHASH **)Malloc(sizeof(LHASH *)*num)) == NULL) + if ((ret->index=(LHASH **)OPENSSL_malloc(sizeof(LHASH *)*num)) == NULL) goto err; - if ((ret->qual=(int (**)())Malloc(sizeof(int (**)())*num)) == NULL) + if ((ret->qual=(int (**)())OPENSSL_malloc(sizeof(int (**)())*num)) == NULL) goto err; for (i=0; idata[offset-1]='\0'; /* blat the '\n' */ - p=(char *)Malloc(add+offset); + if (!(p=(char *)OPENSSL_malloc(add+offset))) goto err; offset=0; } pp=(char **)p; @@ -157,8 +155,8 @@ int num; *(p++)='\0'; if ((n != num) || (*f != '\0')) { -#if !defined(NO_STDIO) && !defined(WIN16) /* temporaty fix :-( */ - fprintf(stderr,"wrong number of fields on line %ld\n",ln); +#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty fix :-( */ + fprintf(stderr,"wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",ln,num,n,f); #endif er=2; goto err; @@ -166,7 +164,7 @@ int num; pp[n]=p; if (!sk_push(ret->data,(char *)pp)) { -#if !defined(NO_STDIO) && !defined(WIN16) /* temporaty fix :-( */ +#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty fix :-( */ fprintf(stderr,"failure in sk_push\n"); #endif er=2; @@ -178,23 +176,20 @@ err: BUF_MEM_free(buf); if (er) { -#if !defined(NO_STDIO) && !defined(WIN16) - if (er == 1) fprintf(stderr,"Malloc failure\n"); +#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) + if (er == 1) fprintf(stderr,"OPENSSL_malloc failure\n"); #endif if (ret->data != NULL) sk_free(ret->data); - if (ret->index != NULL) Free(ret->index); - if (ret->qual != NULL) Free((char *)ret->qual); - if (ret != NULL) Free(ret); + if (ret->index != NULL) OPENSSL_free(ret->index); + if (ret->qual != NULL) OPENSSL_free(ret->qual); + if (ret != NULL) OPENSSL_free(ret); return(NULL); } else return(ret); } -char **TXT_DB_get_by_index(db,idx,value) -TXT_DB *db; -int idx; -char **value; +char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value) { char **ret; LHASH *lh; @@ -210,17 +205,13 @@ char **value; db->error=DB_ERROR_NO_INDEX; return(NULL); } - ret=(char **)lh_retrieve(lh,(char *)value); + ret=(char **)lh_retrieve(lh,value); db->error=DB_ERROR_OK; return(ret); } -int TXT_DB_create_index(db,field,qual,hash,cmp) -TXT_DB *db; -int field; -int (*qual)(); -unsigned long (*hash)(); -int (*cmp)(); +int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(), + LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp) { LHASH *idx; char *r; @@ -256,9 +247,7 @@ int (*cmp)(); return(1); } -long TXT_DB_write(out,db) -BIO *out; -TXT_DB *db; +long TXT_DB_write(BIO *out, TXT_DB *db) { long i,j,n,nn,l,tot=0; char *p,**pp,*f; @@ -306,9 +295,7 @@ err: return(ret); } -int TXT_DB_insert(db,row) -TXT_DB *db; -char **row; +int TXT_DB_insert(TXT_DB *db, char **row) { int i; char **r; @@ -319,7 +306,7 @@ char **row; { if ((db->qual[i] != NULL) && (db->qual[i](row) == 0)) continue; - r=(char **)lh_retrieve(db->index[i],(char *)row); + r=(char **)lh_retrieve(db->index[i],row); if (r != NULL) { db->error=DB_ERROR_INDEX_CLASH; @@ -342,7 +329,7 @@ char **row; { if ((db->qual[i] != NULL) && (db->qual[i](row) == 0)) continue; - lh_insert(db->index[i],(char *)row); + lh_insert(db->index[i],row); } } return(1); @@ -350,20 +337,22 @@ err: return(0); } -void TXT_DB_free(db) -TXT_DB *db; +void TXT_DB_free(TXT_DB *db) { int i,n; char **p,*max; + if(db == NULL) + return; + if (db->index != NULL) { for (i=db->num_fields-1; i>=0; i--) if (db->index[i] != NULL) lh_free(db->index[i]); - Free(db->index); + OPENSSL_free(db->index); } if (db->qual != NULL) - Free(db->qual); + OPENSSL_free(db->qual); if (db->data != NULL) { for (i=sk_num(db->data)-1; i>=0; i--) @@ -375,7 +364,7 @@ TXT_DB *db; if (max == NULL) /* new row */ { for (n=0; nnum_fields; n++) - if (p[n] != NULL) Free(p[n]); + if (p[n] != NULL) OPENSSL_free(p[n]); } else { @@ -383,12 +372,12 @@ TXT_DB *db; { if (((p[n] < (char *)p) || (p[n] > max)) && (p[n] != NULL)) - Free(p[n]); + OPENSSL_free(p[n]); } } - Free(sk_value(db->data,i)); + OPENSSL_free(sk_value(db->data,i)); } sk_free(db->data); } - Free(db); + OPENSSL_free(db); } diff --git a/src/lib/libcrypto/txt_db/txt_db.h b/src/lib/libcrypto/txt_db/txt_db.h index aca6dae393..563392aeff 100644 --- a/src/lib/libcrypto/txt_db/txt_db.h +++ b/src/lib/libcrypto/txt_db/txt_db.h @@ -59,12 +59,11 @@ #ifndef HEADER_TXT_DB_H #define HEADER_TXT_DB_H -#ifdef __cplusplus -extern "C" { +#ifndef OPENSSL_NO_BIO +#include #endif - -#include "stack.h" -#include "lhash.h" +#include +#include #define DB_ERROR_OK 0 #define DB_ERROR_MALLOC 1 @@ -73,6 +72,10 @@ extern "C" { #define DB_ERROR_NO_INDEX 4 #define DB_ERROR_INSERT_INDEX_CLASH 5 +#ifdef __cplusplus +extern "C" { +#endif + typedef struct txt_db_st { int num_fields; @@ -85,8 +88,7 @@ typedef struct txt_db_st char **arg_row; } TXT_DB; -#ifndef NOPROTO -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO TXT_DB *TXT_DB_read(BIO *in, int num); long TXT_DB_write(BIO *out, TXT_DB *db); #else @@ -94,22 +96,11 @@ TXT_DB *TXT_DB_read(char *in, int num); long TXT_DB_write(char *out, TXT_DB *db); #endif int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(), - unsigned long (*hash)(),int (*cmp)()); + LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp); void TXT_DB_free(TXT_DB *db); char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value); int TXT_DB_insert(TXT_DB *db,char **value); -#else - -TXT_DB *TXT_DB_read(); -long TXT_DB_write(); -int TXT_DB_create_index(); -void TXT_DB_free(); -char **TXT_DB_get_by_index(); -int TXT_DB_insert(); - -#endif - #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/ui/ui_openssl.c b/src/lib/libcrypto/ui/ui_openssl.c index 3aa03f74aa..4e12165410 100644 --- a/src/lib/libcrypto/ui/ui_openssl.c +++ b/src/lib/libcrypto/ui/ui_openssl.c @@ -465,7 +465,7 @@ static int open_console(UI *ui) tty_out=stderr; #endif -#if defined(TTY_get) && !defined(VMS) +#if defined(TTY_get) && !defined(OPENSSL_SYS_VMS) if (TTY_get(fileno(tty_in),&tty_orig) == -1) { #ifdef ENOTTY diff --git a/src/lib/libcrypto/util/mkerr.pl b/src/lib/libcrypto/util/mkerr.pl index 4b3bccb13e..4105047b21 100644 --- a/src/lib/libcrypto/util/mkerr.pl +++ b/src/lib/libcrypto/util/mkerr.pl @@ -7,7 +7,7 @@ my $static = 1; my $recurse = 0; my $reindex = 0; my $dowrite = 0; - +my $staticloader = ""; while (@ARGV) { my $arg = $ARGV[0]; @@ -29,6 +29,9 @@ while (@ARGV) { } elsif($arg eq "-nostatic") { $static = 0; shift @ARGV; + } elsif($arg eq "-staticloader") { + $staticloader = "static "; + shift @ARGV; } elsif($arg eq "-write") { $dowrite = 1; shift @ARGV; @@ -38,7 +41,7 @@ while (@ARGV) { } if($recurse) { - @source = (, , ,, ); + @source = (, , ); } else { @source = @ARGV; } @@ -53,6 +56,7 @@ while() { if(/^L\s+(\S+)\s+(\S+)\s+(\S+)/) { $hinc{$1} = $2; + $libinc{$2} = $1; $cskip{$3} = $1; if($3 ne "NONE") { $csrc{$1} = $3; @@ -74,43 +78,53 @@ close IN; # Scan each header file in turn and make a list of error codes # and function names -while (($lib, $hdr) = each %hinc) +while (($hdr, $lib) = each %libinc) { next if($hdr eq "NONE"); print STDERR "Scanning header file $hdr\n" if $debug; - open(IN, "<$hdr") || die "Can't open Header file $hdr\n"; - my $line = "", $def= ""; - while() { - last if(/BEGIN\s+ERROR\s+CODES/); - if ($line ne '') { - $_ = $line . $_; - $line = ''; - } + my $line = "", $def= "", $linenr = 0, $gotfile = 0; + if (open(IN, "<$hdr")) { + $gotfile = 1; + while() { + $linenr++; + print STDERR "line: $linenr\r" if $debug; + + last if(/BEGIN\s+ERROR\s+CODES/); + if ($line ne '') { + $_ = $line . $_; + $line = ''; + } - if (/\\$/) { - $line = $_; - next; - } + if (/\\$/) { + $line = $_; + next; + } - $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration - if ($cpp) { - $cpp = 0 if /^#.*endif/; - next; - } + $cpp = 1 if /^#.*ifdef.*cplusplus/; # skip "C" declaration + if ($cpp) { + $cpp = 0 if /^#.*endif/; + next; + } - next if (/^#/); # skip preprocessor directives + next if (/^\#/); # skip preprocessor directives - s/\/\*.*?\*\///gs; # ignore comments - s/{[^{}]*}//gs; # ignore {} blocks + s/\/\*.*?\*\///gs; # ignore comments + s/{[^{}]*}//gs; # ignore {} blocks - if (/{|\/\*/) { # Add a } so editor works... - $line = $_; - } else { - $def .= $_; + if (/\{|\/\*/) { # Add a } so editor works... + $line = $_; + } else { + $def .= $_; + } } } + print STDERR " \r" if $debug; + $defnr = 0; foreach (split /;/, $def) { + $defnr++; + print STDERR "def: $defnr\r" if $debug; + s/^[\n\s]*//g; s/[\n\s]*$//g; next if(/typedef\W/); @@ -136,15 +150,19 @@ while (($lib, $hdr) = each %hinc) } } + print STDERR " \r" if $debug; + next if $reindex; # Scan function and reason codes and store them: keep a note of the # maximum code used. - while() { - if(/^#define\s+(\S+)\s+(\S+)/) { + if ($gotfile) { + while() { + if(/^\#define\s+(\S+)\s+(\S+)/) { $name = $1; $code = $2; + next if $name =~ /^${lib}err/; unless($name =~ /^${lib}_([RF])_(\w+)$/) { print STDERR "Invalid error code $name\n"; next; @@ -162,6 +180,7 @@ while (($lib, $hdr) = each %hinc) $fcodes{$name} = $code; } } + } } close IN; } @@ -178,9 +197,11 @@ while (($lib, $hdr) = each %hinc) # so all those unreferenced can be printed out. +print STDERR "Files loaded: " if $debug; foreach $file (@source) { # Don't parse the error source file. next if exists $cskip{$file}; + print STDERR $file if $debug; open(IN, "<$file") || die "Can't open source file $file\n"; while() { if(/(([A-Z0-9]+)_F_([A-Z0-9_]+))/) { @@ -204,6 +225,7 @@ foreach $file (@source) { } close IN; } +print STDERR "\n" if $debug; # Now process each library in turn. @@ -230,15 +252,74 @@ foreach $lib (keys %csrc) # Rewrite the header file - open(IN, "<$hfile") || die "Can't Open Header File $hfile\n"; - - # Copy across the old file - while() { + if (open(IN, "<$hfile")) { + # Copy across the old file + while() { push @out, $_; last if (/BEGIN ERROR CODES/); + } + close IN; + } else { + push @out, +"/* ====================================================================\n", +" * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.\n", +" *\n", +" * Redistribution and use in source and binary forms, with or without\n", +" * modification, are permitted provided that the following conditions\n", +" * are met:\n", +" *\n", +" * 1. Redistributions of source code must retain the above copyright\n", +" * notice, this list of conditions and the following disclaimer. \n", +" *\n", +" * 2. Redistributions in binary form must reproduce the above copyright\n", +" * notice, this list of conditions and the following disclaimer in\n", +" * the documentation and/or other materials provided with the\n", +" * distribution.\n", +" *\n", +" * 3. All advertising materials mentioning features or use of this\n", +" * software must display the following acknowledgment:\n", +" * \"This product includes software developed by the OpenSSL Project\n", +" * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n", +" *\n", +" * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n", +" * endorse or promote products derived from this software without\n", +" * prior written permission. For written permission, please contact\n", +" * openssl-core\@openssl.org.\n", +" *\n", +" * 5. Products derived from this software may not be called \"OpenSSL\"\n", +" * nor may \"OpenSSL\" appear in their names without prior written\n", +" * permission of the OpenSSL Project.\n", +" *\n", +" * 6. Redistributions of any form whatsoever must retain the following\n", +" * acknowledgment:\n", +" * \"This product includes software developed by the OpenSSL Project\n", +" * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n", +" *\n", +" * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n", +" * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n", +" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n", +" * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n", +" * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n", +" * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n", +" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n", +" * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n", +" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n", +" * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n", +" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n", +" * OF THE POSSIBILITY OF SUCH DAMAGE.\n", +" * ====================================================================\n", +" *\n", +" * This product includes cryptographic software written by Eric Young\n", +" * (eay\@cryptsoft.com). This product includes software written by Tim\n", +" * Hudson (tjh\@cryptsoft.com).\n", +" *\n", +" */\n", +"\n", +"#ifndef HEADER_${lib}_ERR_H\n", +"#define HEADER_${lib}_ERR_H\n", +"\n", +"/* BEGIN ERROR CODES */\n"; } - close IN; - open (OUT, ">$hfile") || die "Can't Open File $hfile for writing\n"; print OUT @out; @@ -247,7 +328,22 @@ foreach $lib (keys %csrc) /* 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. */ +EOF + if($static) { + print OUT <<"EOF"; +${staticloader}void ERR_load_${lib}_strings(void); + +EOF + } else { + print OUT <<"EOF"; +${staticloader}void ERR_load_${lib}_strings(void); +${staticloader}void ERR_unload_${lib}_strings(void); +${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line); +#define ${lib}err(f,r) ERR_${lib}_error((f),(r),__FILE__,__LINE__) +EOF + } + print OUT <<"EOF"; /* Error codes for the $lib functions. */ /* Function codes. */ @@ -278,12 +374,22 @@ EOF } #endif #endif - EOF close OUT; # Rewrite the C source file containing the error details. + # First, read any existing reason string definitions: + my %err_reason_strings; + if (open(IN,"<$cfile")) { + while () { + if (/\b(${lib}_R_\w*)\b.*\"(.*)\"/) { + $err_reason_strings{$1} = $2; + } + } + close(IN); + } + my $hincf; if($static) { $hfile =~ /([^\/]+)$/; @@ -298,7 +404,7 @@ EOF print OUT <<"EOF"; /* $cfile */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2002 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 @@ -352,7 +458,8 @@ EOF */ /* 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. + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. */ #include @@ -360,7 +467,7 @@ EOF #include $hincf /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA ${lib}_str_functs[]= { EOF @@ -385,9 +492,13 @@ EOF foreach $i (@reasons) { my $rn; my $nspc = 0; - $i =~ /^${lib}_R_(\S+)$/; - $rn = $1; - $rn =~ tr/_[A-Z]/ [a-z]/; + if (exists $err_reason_strings{$i}) { + $rn = $err_reason_strings{$i}; + } else { + $i =~ /^${lib}_R_(\S+)$/; + $rn = $1; + $rn =~ tr/_[A-Z]/ [a-z]/; + } $nspc = 40 - length($i) unless length($i) > 40; $nspc = " " x $nspc; print OUT "{${i}${nspc},\"$rn\"},\n"; @@ -399,14 +510,14 @@ if($static) { #endif -void ERR_load_${lib}_strings(void) +${staticloader}void ERR_load_${lib}_strings(void) { static int init=1; if (init) { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_${lib},${lib}_str_functs); ERR_load_strings(ERR_LIB_${lib},${lib}_str_reasons); #endif @@ -430,19 +541,18 @@ static ERR_STRING_DATA ${lib}_lib_name[]= #endif -int ${lib}_lib_error_code=0; +static int ${lib}_lib_error_code=0; +static int ${lib}_error_init=1; -void ERR_load_${lib}_strings(void) +${staticloader}void ERR_load_${lib}_strings(void) { - static int init=1; - if (${lib}_lib_error_code == 0) ${lib}_lib_error_code=ERR_get_next_error_library(); - if (init) + if (${lib}_error_init) { - init=0; -#ifndef NO_ERR + ${lib}_error_init=0; +#ifndef OPENSSL_NO_ERR ERR_load_strings(${lib}_lib_error_code,${lib}_str_functs); ERR_load_strings(${lib}_lib_error_code,${lib}_str_reasons); #endif @@ -450,11 +560,27 @@ void ERR_load_${lib}_strings(void) #ifdef ${lib}_LIB_NAME ${lib}_lib_name->error = ERR_PACK(${lib}_lib_error_code,0,0); ERR_load_strings(0,${lib}_lib_name); -#endif; +#endif + } + } + +${staticloader}void ERR_unload_${lib}_strings(void) + { + if (${lib}_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(${lib}_lib_error_code,${lib}_str_functs); + ERR_unload_strings(${lib}_lib_error_code,${lib}_str_reasons); +#endif + +#ifdef ${lib}_LIB_NAME + ERR_unload_strings(0,${lib}_lib_name); +#endif + ${lib}_error_init=1; } } -void ERR_${lib}_error(int function, int reason, char *file, int line) +${staticloader}void ERR_${lib}_error(int function, int reason, char *file, int line) { if (${lib}_lib_error_code == 0) ${lib}_lib_error_code=ERR_get_next_error_library(); @@ -465,7 +591,7 @@ EOF } close OUT; - + undef %err_reason_strings; } if($debug && defined(%notrans)) { diff --git a/src/lib/libcrypto/util/mkstack.pl b/src/lib/libcrypto/util/mkstack.pl index 3ee13fe7c9..085c50f790 100644 --- a/src/lib/libcrypto/util/mkstack.pl +++ b/src/lib/libcrypto/util/mkstack.pl @@ -21,7 +21,7 @@ while (@ARGV) { } -@source = (, , , ); +@source = (, , ); foreach $file (@source) { next if -l $file; diff --git a/src/lib/libcrypto/x509/by_dir.c b/src/lib/libcrypto/x509/by_dir.c index 11725ec94c..448bd7e69c 100644 --- a/src/lib/libcrypto/x509/by_dir.c +++ b/src/lib/libcrypto/x509/by_dir.c @@ -59,13 +59,20 @@ #include #include #include -#include -#include #include "cryptlib.h" -#include "lhash.h" -#include "x509.h" -#include "pem.h" + +#ifndef NO_SYS_TYPES_H +# include +#endif +#ifdef MAC_OS_pre_X +# include +#else +# include +#endif + +#include +#include typedef struct lookup_dir_st { @@ -76,21 +83,13 @@ typedef struct lookup_dir_st int num_dirs_alloced; } BY_DIR; -#ifndef NOPROTO -static int dir_ctrl(X509_LOOKUP *ctx,int cmd,char *argp,long argl,char **ret); +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret); static int new_dir(X509_LOOKUP *lu); static void free_dir(X509_LOOKUP *lu); -static int add_cert_dir(BY_DIR *ctx,char *dir,int type); +static int add_cert_dir(BY_DIR *ctx,const char *dir,int type); static int get_cert_by_subject(X509_LOOKUP *xl,int type,X509_NAME *name, X509_OBJECT *ret); -#else -static int dir_ctrl(); -static int new_dir(); -static void free_dir(); -static int add_cert_dir(); -static int get_cert_by_subject(); -#endif - X509_LOOKUP_METHOD x509_dir_lookup= { "Load certs from files in a directory", @@ -105,17 +104,13 @@ X509_LOOKUP_METHOD x509_dir_lookup= NULL, /* get_by_alias */ }; -X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir() +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) { return(&x509_dir_lookup); } -static int dir_ctrl(ctx,cmd,argp,argl,retp) -X509_LOOKUP *ctx; -int cmd; -long argl; -char *argp; -char **retp; +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **retp) { int ret=0; BY_DIR *ld; @@ -147,16 +142,15 @@ char **retp; return(ret); } -static int new_dir(lu) -X509_LOOKUP *lu; +static int new_dir(X509_LOOKUP *lu) { BY_DIR *a; - if ((a=(BY_DIR *)Malloc(sizeof(BY_DIR))) == NULL) + if ((a=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL) return(0); if ((a->buffer=BUF_MEM_new()) == NULL) { - Free(a); + OPENSSL_free(a); return(0); } a->num_dirs=0; @@ -167,32 +161,32 @@ X509_LOOKUP *lu; return(1); } -static void free_dir(lu) -X509_LOOKUP *lu; +static void free_dir(X509_LOOKUP *lu) { BY_DIR *a; int i; a=(BY_DIR *)lu->method_data; for (i=0; inum_dirs; i++) - if (a->dirs[i] != NULL) Free(a->dirs[i]); - if (a->dirs != NULL) Free(a->dirs); - if (a->dirs_type != NULL) Free(a->dirs_type); + if (a->dirs[i] != NULL) OPENSSL_free(a->dirs[i]); + if (a->dirs != NULL) OPENSSL_free(a->dirs); + if (a->dirs_type != NULL) OPENSSL_free(a->dirs_type); if (a->buffer != NULL) BUF_MEM_free(a->buffer); - Free(a); + OPENSSL_free(a); } -static int add_cert_dir(ctx,dir, type) -BY_DIR *ctx; -char *dir; -int type; +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) { int j,len; int *ip; - char *s,*ss,*p; + const char *s,*ss,*p; char **pp; - if (dir == NULL) return(0); + if (dir == NULL || !*dir) + { + X509err(X509_F_ADD_CERT_DIR,X509_R_INVALID_DIRECTORY); + return 0; + } s=dir; p=s; @@ -210,9 +204,9 @@ int type; if (ctx->num_dirs_alloced < (ctx->num_dirs+1)) { ctx->num_dirs_alloced+=10; - pp=(char **)Malloc(ctx->num_dirs_alloced* + pp=(char **)OPENSSL_malloc(ctx->num_dirs_alloced* sizeof(char *)); - ip=(int *)Malloc(ctx->num_dirs_alloced* + ip=(int *)OPENSSL_malloc(ctx->num_dirs_alloced* sizeof(int)); if ((pp == NULL) || (ip == NULL)) { @@ -224,14 +218,14 @@ int type; memcpy(ip,ctx->dirs_type,(ctx->num_dirs_alloced-10)* sizeof(int)); if (ctx->dirs != NULL) - Free((char *)ctx->dirs); + OPENSSL_free(ctx->dirs); if (ctx->dirs_type != NULL) - Free((char *)ctx->dirs_type); + OPENSSL_free(ctx->dirs_type); ctx->dirs=pp; ctx->dirs_type=ip; } ctx->dirs_type[ctx->num_dirs]=type; - ctx->dirs[ctx->num_dirs]=(char *)Malloc((unsigned int)len+1); + ctx->dirs[ctx->num_dirs]=(char *)OPENSSL_malloc((unsigned int)len+1); if (ctx->dirs[ctx->num_dirs] == NULL) return(0); strncpy(ctx->dirs[ctx->num_dirs],ss,(unsigned int)len); ctx->dirs[ctx->num_dirs][len]='\0'; @@ -243,11 +237,8 @@ int type; return(1); } -static int get_cert_by_subject(xl,type,name,ret) -X509_LOOKUP *xl; -int type; -X509_NAME *name; -X509_OBJECT *ret; +static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, + X509_OBJECT *ret) { BY_DIR *ctx; union { @@ -266,7 +257,7 @@ X509_OBJECT *ret; BUF_MEM *b=NULL; struct stat st; X509_OBJECT stmp,*tmp; - char *postfix=""; + const char *postfix=""; if (name == NULL) return(0); @@ -335,8 +326,9 @@ X509_OBJECT *ret; /* we have added it to the cache so now pull * it out again */ CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); - tmp=(X509_OBJECT *)lh_retrieve(xl->store_ctx->certs, - (char *)&stmp); + j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp); + if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j); + else tmp = NULL; CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); if (tmp != NULL) diff --git a/src/lib/libcrypto/x509/by_file.c b/src/lib/libcrypto/x509/by_file.c index 09ebb9bf08..92e00d2d73 100644 --- a/src/lib/libcrypto/x509/by_file.c +++ b/src/lib/libcrypto/x509/by_file.c @@ -59,24 +59,17 @@ #include #include #include -#include -#include #include "cryptlib.h" -#include "lhash.h" -#include "buffer.h" -#include "x509.h" -#include "pem.h" +#include +#include +#include +#include -#ifndef NO_STDIO - -#ifndef NOPROTO -static int by_file_ctrl(X509_LOOKUP *ctx,int cmd,char *argc, - long argl,char **ret); -#else -static int by_file_ctrl(); -#endif +#ifndef OPENSSL_NO_STDIO +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); X509_LOOKUP_METHOD x509_file_lookup= { "Load file into cache", @@ -91,19 +84,15 @@ X509_LOOKUP_METHOD x509_file_lookup= NULL, /* get_by_alias */ }; -X509_LOOKUP_METHOD *X509_LOOKUP_file() +X509_LOOKUP_METHOD *X509_LOOKUP_file(void) { return(&x509_file_lookup); } -static int by_file_ctrl(ctx,cmd,argp,argl,ret) -X509_LOOKUP *ctx; -int cmd; -char *argp; -long argl; -char **ret; +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret) { - int ok=0,ok2=0; + int ok=0; char *file; switch (cmd) @@ -111,37 +100,33 @@ char **ret; case X509_L_FILE_LOAD: if (argl == X509_FILETYPE_DEFAULT) { - ok=X509_load_cert_file(ctx,X509_get_default_cert_file(), - X509_FILETYPE_PEM); - ok2=X509_load_crl_file(ctx,X509_get_default_cert_file(), - X509_FILETYPE_PEM); - if (!ok || !ok2) + ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(), + X509_FILETYPE_PEM) != 0); + if (!ok) { X509err(X509_F_BY_FILE_CTRL,X509_R_LOADING_DEFAULTS); } else { file=(char *)Getenv(X509_get_default_cert_file_env()); - ok=X509_load_cert_file(ctx,file, - X509_FILETYPE_PEM); - ok2=X509_load_crl_file(ctx,file, - X509_FILETYPE_PEM); + ok = (X509_load_cert_crl_file(ctx,file, + X509_FILETYPE_PEM) != 0); } } else { - ok=X509_load_cert_file(ctx,argp,(int)argl); - ok2=X509_load_crl_file(ctx,argp,(int)argl); + if(argl == X509_FILETYPE_PEM) + ok = (X509_load_cert_crl_file(ctx,argp, + X509_FILETYPE_PEM) != 0); + else + ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0); } break; } - return((ok && ok2)?ok:0); + return(ok); } -int X509_load_cert_file(ctx,file,type) -X509_LOOKUP *ctx; -char *file; -int type; +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) { int ret=0; BIO *in=NULL; @@ -161,7 +146,7 @@ int type; { for (;;) { - x=PEM_read_bio_X509(in,NULL,NULL); + x=PEM_read_bio_X509_AUX(in,NULL,NULL,NULL); if (x == NULL) { if ((ERR_GET_REASON(ERR_peek_error()) == @@ -208,10 +193,7 @@ err: return(ret); } -int X509_load_crl_file(ctx,file,type) -X509_LOOKUP *ctx; -char *file; -int type; +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) { int ret=0; BIO *in=NULL; @@ -231,7 +213,7 @@ int type; { for (;;) { - x=PEM_read_bio_X509_CRL(in,NULL,NULL); + x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); if (x == NULL) { if ((ERR_GET_REASON(ERR_peek_error()) == @@ -278,5 +260,39 @@ err: return(ret); } -#endif /* NO_STDIO */ +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + BIO *in; + int i, count = 0; + if(type != X509_FILETYPE_PEM) + return X509_load_cert_file(ctx, file, type); + in = BIO_new_file(file, "r"); + if(!in) { + X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_SYS_LIB); + return 0; + } + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + BIO_free(in); + if(!inf) { + X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB); + return 0; + } + for(i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if(itmp->x509) { + X509_STORE_add_cert(ctx->store_ctx, itmp->x509); + count++; + } else if(itmp->crl) { + X509_STORE_add_crl(ctx->store_ctx, itmp->crl); + count++; + } + } + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return count; +} + + +#endif /* OPENSSL_NO_STDIO */ diff --git a/src/lib/libcrypto/x509/x509.h b/src/lib/libcrypto/x509/x509.h index 95114f7c43..c75aa0c717 100644 --- a/src/lib/libcrypto/x509/x509.h +++ b/src/lib/libcrypto/x509/x509.h @@ -59,32 +59,46 @@ #ifndef HEADER_X509_H #define HEADER_X509_H -#ifdef __cplusplus -extern "C" { +#include +#ifndef OPENSSL_NO_BUFFER +#include +#endif +#ifndef OPENSSL_NO_EVP +#include #endif +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include -#include "stack.h" -#include "asn1.h" +#ifndef OPENSSL_NO_RSA +#include +#endif -#ifndef NO_RSA -#include "rsa.h" -#else -#define RSA long +#ifndef OPENSSL_NO_DSA +#include #endif -#ifndef NO_DSA -#include "dsa.h" -#else -#define DSA long +#ifndef OPENSSL_NO_DH +#include +#endif +#ifndef OPENSSL_NO_SHA +#include #endif +#include +#include +#include -#ifndef NO_DH -#include "dh.h" -#else -#define DH long +#ifdef __cplusplus +extern "C" { #endif -#include "evp.h" +#ifdef OPENSSL_SYS_WIN32 +/* Under Win32 this is defined in wincrypt.h */ +#undef X509_NAME +#endif #define X509_FILETYPE_PEM 1 #define X509_FILETYPE_ASN1 2 @@ -108,23 +122,26 @@ typedef struct X509_objects_st int (*i2a)(); } X509_OBJECTS; -typedef struct X509_algor_st +struct X509_algor_st { ASN1_OBJECT *algorithm; ASN1_TYPE *parameter; - } X509_ALGOR; + } /* X509_ALGOR */; + +DECLARE_STACK_OF(X509_ALGOR) +DECLARE_ASN1_SET_OF(X509_ALGOR) typedef struct X509_val_st { - ASN1_UTCTIME *notBefore; - ASN1_UTCTIME *notAfter; + ASN1_TIME *notBefore; + ASN1_TIME *notAfter; } X509_VAL; typedef struct X509_pubkey_st { X509_ALGOR *algor; ASN1_BIT_STRING *public_key; - struct evp_pkey_st /* EVP_PKEY*/ *pkey; + EVP_PKEY *pkey; } X509_PUBKEY; typedef struct X509_sig_st @@ -141,58 +158,60 @@ typedef struct X509_name_entry_st 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 +struct X509_name_st { - STACK *entries; /* of X509_NAME_ENTRY */ + STACK_OF(X509_NAME_ENTRY) *entries; int modified; /* true if 'bytes' needs to be built */ -#ifdef HEADER_BUFFER_H +#ifndef OPENSSL_NO_BUFFER BUF_MEM *bytes; #else char *bytes; #endif unsigned long hash; /* Keep the hash around for lookups */ - } X509_NAME; + } /* 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_BOOLEAN critical; ASN1_OCTET_STRING *value; - long argl; /* used when decoding */ - char *argp; /* used when decoding */ - void (*ex_free)(); /* clear argp stuff */ } X509_EXTENSION; -/* #if 1 */ -typedef struct x509_extension_method_st +DECLARE_STACK_OF(X509_EXTENSION) +DECLARE_ASN1_SET_OF(X509_EXTENSION) + +/* a sequence of these are used */ +typedef struct x509_attributes_st { - int nid; - int data_type; - int pack_type; - void (*ex_clear)(); - int (*ex_get_bool)(); - int (*ex_set_bool)(); - int (*ex_get_str)(); - int (*ex_set_str)(); - char *(*ex_get_struct)(); - int (*ex_set_struct)(); - int (*a2i)(); - int (*i2a)(); - } X509_EXTENSION_METHOD; -/* #endif */ + ASN1_OBJECT *object; + int single; /* 0 for a set, 1 for a single item (which is wrong) */ + union { + char *ptr; +/* 0 */ STACK_OF(ASN1_TYPE) *set; +/* 1 */ ASN1_TYPE *single; + } value; + } X509_ATTRIBUTE; + +DECLARE_STACK_OF(X509_ATTRIBUTE) +DECLARE_ASN1_SET_OF(X509_ATTRIBUTE) + typedef struct X509_req_info_st { + ASN1_ENCODING enc; ASN1_INTEGER *version; X509_NAME *subject; X509_PUBKEY *pubkey; /* d=2 hl=2 l= 0 cons: cont: 00 */ - STACK /* X509_ATTRIBUTE */ *attributes; /* [ 0 ] */ - int req_kludge; + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ } X509_REQ_INFO; typedef struct X509_req_st @@ -214,10 +233,25 @@ typedef struct x509_cinf_st X509_PUBKEY *key; ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ - STACK /* X509_EXTENSION */ *extensions; /* [ 3 ] optional in v3 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ } X509_CINF; -typedef struct x509_st +/* 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; + +struct x509_st { X509_CINF *cert_info; X509_ALGOR *sig_alg; @@ -225,47 +259,170 @@ typedef struct x509_st int valid; int references; char *name; - } X509; + 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; + ASN1_OCTET_STRING *skid; + struct AUTHORITY_KEYID_st *akid; +#ifndef OPENSSL_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 +#define X509_TRUST_OCSP_SIGN 6 +#define X509_TRUST_OCSP_REQUEST 7 + +/* Keep these up to date! */ +#define X509_TRUST_MIN 1 +#define X509_TRUST_MAX 7 + + +/* 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 + +/* Flags for X509_print_ex() */ + +#define X509_FLAG_COMPAT 0 +#define X509_FLAG_NO_HEADER 1L +#define X509_FLAG_NO_VERSION (1L << 1) +#define X509_FLAG_NO_SERIAL (1L << 2) +#define X509_FLAG_NO_SIGNAME (1L << 3) +#define X509_FLAG_NO_ISSUER (1L << 4) +#define X509_FLAG_NO_VALIDITY (1L << 5) +#define X509_FLAG_NO_SUBJECT (1L << 6) +#define X509_FLAG_NO_PUBKEY (1L << 7) +#define X509_FLAG_NO_EXTENSIONS (1L << 8) +#define X509_FLAG_NO_SIGDUMP (1L << 9) +#define X509_FLAG_NO_AUX (1L << 10) + +/* Flags specific to X509_NAME_print_ex() */ + +/* The field separator information */ + +#define XN_FLAG_SEP_MASK (0xf << 16) + +#define XN_FLAG_COMPAT 0 /* Traditional SSLeay: use old X509_NAME_print */ +#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) /* RFC2253 ,+ */ +#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) /* ,+ spaced: more readable */ +#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) /* ;+ spaced */ +#define XN_FLAG_SEP_MULTILINE (4 << 16) /* One line per field */ + +#define XN_FLAG_DN_REV (1 << 20) /* Reverse DN order */ + +/* How the field name is shown */ + +#define XN_FLAG_FN_MASK (0x3 << 21) + +#define XN_FLAG_FN_SN 0 /* Object short name */ +#define XN_FLAG_FN_LN (1 << 21) /* Object long name */ +#define XN_FLAG_FN_OID (2 << 21) /* Always use OIDs */ +#define XN_FLAG_FN_NONE (3 << 21) /* No field names */ + +#define XN_FLAG_SPC_EQ (1 << 23) /* Put spaces round '=' */ + +/* This determines if we dump fields we don't recognise: + * RFC2253 requires this. + */ + +#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +#define XN_FLAG_FN_ALIGN (1 << 25) /* Align field names to 20 characters */ + +/* Complete set of RFC2253 flags */ + +#define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ + XN_FLAG_SEP_COMMA_PLUS | \ + XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | \ + XN_FLAG_DUMP_UNKNOWN_FIELDS) + +/* readable oneline form */ + +#define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_SN) + +/* readable multiline form */ + +#define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + XN_FLAG_SEP_MULTILINE | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_LN | \ + XN_FLAG_FN_ALIGN) typedef struct X509_revoked_st { ASN1_INTEGER *serialNumber; - ASN1_UTCTIME *revocationDate; - STACK /* optional X509_EXTENSION */ *extensions; + ASN1_TIME *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 /* X509_REVOKED */ *revoked; - STACK /* [0] X509_EXTENSION */ *extensions; + ASN1_TIME *lastUpdate; + ASN1_TIME *nextUpdate; + STACK_OF(X509_REVOKED) *revoked; + STACK_OF(X509_EXTENSION) /* [0] */ *extensions; } X509_CRL_INFO; -typedef struct X509_crl_st +struct X509_crl_st { /* actual signature */ X509_CRL_INFO *crl; X509_ALGOR *sig_alg; ASN1_BIT_STRING *signature; int references; - } X509_CRL; + } /* X509_CRL */; -/* 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 /* ASN1_TYPE */ *set; -/* 0 */ ASN1_TYPE *single; - } value; - } X509_ATTRIBUTE; +DECLARE_STACK_OF(X509_CRL) +DECLARE_ASN1_SET_OF(X509_CRL) typedef struct private_key_st { @@ -288,7 +445,7 @@ typedef struct private_key_st int references; } X509_PKEY; -#ifdef HEADER_ENVELOPE_H +#ifndef OPENSSL_NO_EVP typedef struct X509_info_st { X509 *x509; @@ -301,11 +458,13 @@ typedef struct X509_info_st 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 strucutres - usefull if you are writing a CA web page + * Netscapes spki structures - useful if you are writing a CA web page */ typedef struct Netscape_spkac_st { @@ -320,17 +479,65 @@ typedef struct Netscape_spki_st ASN1_BIT_STRING *signature; } NETSCAPE_SPKI; -#ifndef HEADER_BN_H -#define BIGNUM char -#endif +/* 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; -#include "x509_vfy.h" -#include "pkcs7.h" +/* 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; + +#ifdef __cplusplus +} +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif #ifdef SSLEAY_MACROS #define X509_verify(a,r) ASN1_verify((int (*)())i2d_X509_CINF,a->sig_alg,\ @@ -355,6 +562,9 @@ typedef struct CBCParameter_st #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) @@ -442,6 +652,9 @@ typedef struct CBCParameter_st #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( \ @@ -453,10 +666,12 @@ typedef struct CBCParameter_st 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 @@ -472,193 +687,225 @@ typedef struct CBCParameter_st #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) -#ifndef NOPROTO + +const char *X509_verify_cert_error_string(long n); #ifndef SSLEAY_MACROS -#ifdef HEADER_ENVELOPE_H +#ifndef OPENSSL_NO_EVP int X509_verify(X509 *a, EVP_PKEY *r); -char *X509_verify_cert_error_string(long n); 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); -int X509_sign(X509 *x, EVP_PKEY *pkey, EVP_MD *md); -int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, EVP_MD *md); -int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, EVP_MD *md); -int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, EVP_MD *md); - -int X509_digest(X509 *data,EVP_MD *type,unsigned char *md,unsigned int *len); -int X509_NAME_digest(X509_NAME *data,EVP_MD *type, - unsigned char *md,unsigned int *len); +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_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig); + +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_pubkey_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_NAME_digest(const 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); +#ifndef OPENSSL_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); +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); +X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req); int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req); -RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA *rsa); +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa); int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa); -DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA *dsa); -int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); -RSA *d2i_RSAPublicKey_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 OPENSSL_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); +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); #endif -#ifdef HEADER_BIO_H -X509 *d2i_X509_bio(BIO *bp,X509 *x509); +#ifndef OPENSSL_NO_BIO +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); +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); +X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req); int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req); -RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA *rsa); +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa); int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa); -DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA *dsa); -int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); -RSA *d2i_RSAPublicKey_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 OPENSSL_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); +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_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 OPENSSL_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); +int X509_cmp_time(ASN1_TIME *s, time_t *t); +int X509_cmp_current_time(ASN1_TIME *s); +ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t); +ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj); -char * X509_get_default_cert_area(void ); -char * X509_get_default_cert_dir(void ); -char * X509_get_default_cert_file(void ); -char * X509_get_default_cert_dir_env(void ); -char * X509_get_default_cert_file_env(void ); -char * X509_get_default_private_dir(void ); +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, EVP_MD *md); +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); +DECLARE_ASN1_FUNCTIONS(X509_ALGOR) +DECLARE_ASN1_FUNCTIONS(X509_VAL) -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); +DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) -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 *chain); - - -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, +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 OPENSSL_NO_RSA +int i2d_RSA_PUBKEY(RSA *a,unsigned char **pp); +RSA * d2i_RSA_PUBKEY(RSA **a,unsigned char **pp, + long length); +#endif +#ifndef OPENSSL_NO_DSA +int i2d_DSA_PUBKEY(DSA *a,unsigned char **pp); +DSA * d2i_DSA_PUBKEY(DSA **a,unsigned char **pp, + long length); +#endif -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); +DECLARE_ASN1_FUNCTIONS(X509_SIG) +DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) +DECLARE_ASN1_FUNCTIONS(X509_REQ) -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); +DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) +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); +DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) -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); +DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY) + +DECLARE_ASN1_FUNCTIONS(X509_NAME) -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); +DECLARE_ASN1_FUNCTIONS(X509_CINF) -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); +DECLARE_ASN1_FUNCTIONS(X509) +DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX) -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_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); +int X509_alias_set1(X509 *x, unsigned char *name, int len); +int X509_keyid_set1(X509 *x, unsigned char *id, 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_TRUST_set(int *t, int trust); +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_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); +DECLARE_ASN1_FUNCTIONS(X509_REVOKED) +DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO) +DECLARE_ASN1_FUNCTIONS(X509_CRL) -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); +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); 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); +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) -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); - -#ifdef HEADER_ENVELOPE_H +#ifndef OPENSSL_NO_EVP X509_INFO * X509_INFO_new(void); void X509_INFO_free(X509_INFO *a); char * X509_NAME_oneline(X509_NAME *a,char *buf,int size); @@ -666,12 +913,22 @@ 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)(),EVP_MD *type,char *data, +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, EVP_MD *type); + char *data,EVP_PKEY *pkey, const EVP_MD *type); + +int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data, + unsigned char *md,unsigned int *len); + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey); + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, + void *data, EVP_PKEY *pkey, const EVP_MD *type); #endif int X509_set_version(X509 *x,long version); @@ -681,40 +938,83 @@ 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_notBefore(X509 *x, ASN1_TIME *tm); +int X509_set_notAfter(X509 *x, ASN1_TIME *tm); int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); EVP_PKEY * X509_get_pubkey(X509 *x); +ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const 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, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_CRL_set_version(X509_CRL *x, long version); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +int X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm); +int X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm); +int X509_CRL_sort(X509_CRL *crl); + +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); +int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); int X509_check_private_key(X509 *x509,EVP_PKEY *pkey); -int X509_issuer_and_serial_cmp(X509 *a, X509 *b); +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); unsigned long X509_issuer_and_serial_hash(X509 *a); -int X509_issuer_name_cmp(X509 *a, X509 *b); +int X509_issuer_name_cmp(const X509 *a, const X509 *b); unsigned long X509_issuer_name_hash(X509 *a); -int X509_subject_name_cmp(X509 *a,X509 *b); +int X509_subject_name_cmp(const X509 *a, const X509 *b); unsigned long X509_subject_name_hash(X509 *x); -int X509_NAME_cmp (X509_NAME *a, X509_NAME *b); +int X509_cmp(const X509 *a, const X509 *b); +int X509_NAME_cmp(const X509_NAME *a, const 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_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +#ifndef OPENSSL_NO_FP_API +int X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag); 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); +int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags); #endif -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO int X509_NAME_print(BIO *bp, X509_NAME *name, int obase); +int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags); +int X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag); int X509_print(BIO *bp,X509 *x); +int X509_ocspid_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 @@ -725,7 +1025,7 @@ 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, seach after that position on. */ + * 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); @@ -733,8 +1033,16 @@ 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); @@ -745,18 +1053,17 @@ int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, 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(STACK *x); -int X509v3_get_ext_by_NID(STACK *x, int nid, int lastpos); -int X509v3_get_ext_by_OBJ(STACK *x,ASN1_OBJECT *obj,int lastpos); -int X509v3_get_ext_by_critical(STACK *x, int crit, int lastpos); -X509_EXTENSION *X509v3_get_ext(STACK *x, int loc); -X509_EXTENSION *X509v3_delete_ext(STACK *x, int loc); -STACK * X509v3_add_ext(STACK **x, X509_EXTENSION *ex, int loc); - -int X509v3_data_type_by_OBJ(ASN1_OBJECT *obj); -int X509v3_data_type_by_NID(int nid); -int X509v3_pack_type_by_OBJ(ASN1_OBJECT *obj); -int X509v3_pack_type_by_NID(int nid); +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); @@ -765,6 +1072,9 @@ 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_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); int X509_CRL_get_ext_count(X509_CRL *x); int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos); @@ -773,6 +1083,9 @@ 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_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags); int X509_REVOKED_get_ext_count(X509_REVOKED *x); int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos); @@ -781,6 +1094,9 @@ 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); +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags); X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit, ASN1_OCTET_STRING *data); @@ -793,311 +1109,80 @@ int X509_EXTENSION_set_data(X509_EXTENSION *ex, 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); -ASN1_OCTET_STRING *X509v3_pack_string(ASN1_OCTET_STRING **ex,int type, - unsigned char *bytes, int len); -ASN1_STRING * X509v3_unpack_string(ASN1_STRING **ex,int type, - ASN1_OCTET_STRING *os); -int X509_verify_cert(X509_STORE_CTX *ctx); - -/* lookup a cert from a X509 STACK */ -X509 *X509_find_by_issuer_and_serial(STACK *sk,X509_NAME *name, - ASN1_INTEGER *serial); -X509 *X509_find_by_subject(STACK *sk,X509_NAME *name); - -#else - -#ifndef SSLEAY_MACROS -#ifdef HEADER_ENVELOPE_H -int X509_verify(); -int X509_REQ_verify(); -int X509_CRL_verify(); -int NETSCAPE_SPKI_verify(); - -int X509_sign(); -int X509_REQ_sign(); -int X509_CRL_sign(); -int NETSCAPE_SPKI_sign(); - -int X509_digest(); -int X509_NAME_digest(); -#endif - -#ifndef NO_FP_API -X509 *d2i_X509_fp(); -int i2d_X509_fp(); -X509_CRL *d2i_X509_CRL_fp(); -int i2d_X509_CRL_fp(); -X509_REQ *d2i_X509_REQ_fp(); -int i2d_X509_REQ_fp(); -RSA *d2i_RSAPrivateKey_fp(); -int i2d_RSAPrivateKey_fp(); -DSA *d2i_DSAPrivateKey_fp(); -int i2d_DSAPrivateKey_fp(); -RSA *d2i_RSAPublicKey_fp(); -int i2d_RSAPublicKey_fp(); -#endif - -X509 *d2i_X509_bio(); -int i2d_X509_bio(); -X509_CRL *d2i_X509_CRL_bio(); -int i2d_X509_CRL_bio(); -X509_REQ *d2i_X509_REQ_bio(); -int i2d_X509_REQ_bio(); -RSA *d2i_RSAPrivateKey_bio(); -int i2d_RSAPrivateKey_bio(); -DSA *d2i_DSAPrivateKey_bio(); -int i2d_DSAPrivateKey_bio(); -RSA *d2i_RSAPublicKey_bio(); -int i2d_RSAPublicKey_bio(); - -X509 *X509_dup(); -X509_EXTENSION *X509_EXTENSION_dup(); -X509_CRL *X509_CRL_dup(); -X509_REQ *X509_REQ_dup(); -X509_NAME *X509_NAME_dup(); -X509_NAME_ENTRY *X509_NAME_ENTRY_dup(); -RSA *RSAPublicKey_dup(); -RSA *RSAPrivateKey_dup(); - -#endif /* !SSLEAY_MACROS */ +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, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, + int nid, int type, + const unsigned char *bytes, int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, + const char *attrname, int type, + const unsigned char *bytes, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, int atrtype, const void *data, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, const unsigned char *bytes, int len); +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const 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_cmp_current_time(); -ASN1_UTCTIME * X509_gmtime_adj(); - -char * X509_get_default_cert_area(); -char * X509_get_default_cert_dir(); -char * X509_get_default_cert_file(); -char * X509_get_default_cert_dir_env(); -char * X509_get_default_cert_file_env(); -char * X509_get_default_private_dir(); - -X509_REQ * X509_to_X509_REQ(); -X509 * X509_REQ_to_X509(); -void ERR_load_X509_strings(); - -X509_ALGOR * X509_ALGOR_new(); -void X509_ALGOR_free(); -int i2d_X509_ALGOR(); -X509_ALGOR * d2i_X509_ALGOR(); - -X509_VAL * X509_VAL_new(); -void X509_VAL_free(); -int i2d_X509_VAL(); -X509_VAL * d2i_X509_VAL(); - -X509_PUBKEY * X509_PUBKEY_new(); -void X509_PUBKEY_free(); -int i2d_X509_PUBKEY(); -X509_PUBKEY * d2i_X509_PUBKEY(); -int X509_PUBKEY_set(); -EVP_PKEY * X509_PUBKEY_get(); -int X509_get_pubkey_parameters(); - -X509_SIG * X509_SIG_new(); -void X509_SIG_free(); -int i2d_X509_SIG(); -X509_SIG * d2i_X509_SIG(); - -X509_REQ_INFO *X509_REQ_INFO_new(); -void X509_REQ_INFO_free(); -int i2d_X509_REQ_INFO(); -X509_REQ_INFO *d2i_X509_REQ_INFO(); - -X509_REQ * X509_REQ_new(); -void X509_REQ_free(); -int i2d_X509_REQ(); -X509_REQ * d2i_X509_REQ(); - -X509_ATTRIBUTE *X509_ATTRIBUTE_new(); -void X509_ATTRIBUTE_free(); -int i2d_X509_ATTRIBUTE(); -X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(); - -X509_EXTENSION *X509_EXTENSION_new(); -void X509_EXTENSION_free(); -int i2d_X509_EXTENSION(); -X509_EXTENSION *d2i_X509_EXTENSION(); - -X509_NAME_ENTRY *X509_NAME_ENTRY_new(); -void X509_NAME_ENTRY_free(); -int i2d_X509_NAME_ENTRY(); -X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(); - -X509_NAME * X509_NAME_new(); -void X509_NAME_free(); -int i2d_X509_NAME(); -X509_NAME * d2i_X509_NAME(); -int X509_NAME_set(); - - -X509_CINF * X509_CINF_new(); -void X509_CINF_free(); -int i2d_X509_CINF(); -X509_CINF * d2i_X509_CINF(); - -X509 * X509_new(); -void X509_free(); -int i2d_X509(); -X509 * d2i_X509(); - -X509_REVOKED * X509_REVOKED_new(); -void X509_REVOKED_free(); -int i2d_X509_REVOKED(); -X509_REVOKED * d2i_X509_REVOKED(); - -X509_CRL_INFO *X509_CRL_INFO_new(); -void X509_CRL_INFO_free(); -int i2d_X509_CRL_INFO(); -X509_CRL_INFO *d2i_X509_CRL_INFO(); - -X509_CRL * X509_CRL_new(); -void X509_CRL_free(); -int i2d_X509_CRL(); -X509_CRL * d2i_X509_CRL(); - -X509_PKEY * X509_PKEY_new(); -void X509_PKEY_free(); -int i2d_X509_PKEY(); -X509_PKEY * d2i_X509_PKEY(); - -NETSCAPE_SPKI * NETSCAPE_SPKI_new(); -void NETSCAPE_SPKI_free(); -int i2d_NETSCAPE_SPKI(); -NETSCAPE_SPKI * d2i_NETSCAPE_SPKI(); - -NETSCAPE_SPKAC *NETSCAPE_SPKAC_new(); -void NETSCAPE_SPKAC_free(); -int i2d_NETSCAPE_SPKAC(); -NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(); - -#ifdef HEADER_ENVELOPE_H -X509_INFO * X509_INFO_new(); -void X509_INFO_free(); -#endif - -char * X509_NAME_oneline(); - -int ASN1_verify(); -int ASN1_digest(); -int ASN1_sign(); - -int X509_set_version(); -int X509_set_serialNumber(); -ASN1_INTEGER * X509_get_serialNumber(); -int X509_set_issuer_name(); -X509_NAME * X509_get_issuer_name(); -int X509_set_subject_name(); -X509_NAME * X509_get_subject_name(); -int X509_set_notBefore(); -int X509_set_notAfter(); -int X509_set_pubkey(); -EVP_PKEY * X509_get_pubkey(); -int X509_certificate_type(); - -int X509_REQ_set_version(); -int X509_REQ_set_subject_name(); -int X509_REQ_set_pubkey(); -EVP_PKEY * X509_REQ_get_pubkey(); - -int X509_check_private_key(); - -int X509_issuer_and_serial_cmp(); -unsigned long X509_issuer_and_serial_hash(); - -int X509_issuer_name_cmp(); -unsigned long X509_issuer_name_hash(); - -int X509_subject_name_cmp(); -unsigned long X509_subject_name_hash(); - -int X509_NAME_cmp (); -unsigned long X509_NAME_hash(); - -int X509_CRL_cmp(); -#ifndef NO_FP_API -int X509_print_fp(); -int X509_REQ_print_fp(); -#endif - -int X509_NAME_print(); -int X509_print(); -int X509_REQ_print(); - -int X509_NAME_entry_count(); -int X509_NAME_get_text_by_NID(); -int X509_NAME_get_text_by_OBJ(); - -int X509_NAME_get_index_by_NID(); -int X509_NAME_get_index_by_OBJ(); -X509_NAME_ENTRY *X509_NAME_get_entry(); -X509_NAME_ENTRY *X509_NAME_delete_entry(); -int X509_NAME_add_entry(); -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(); -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(); -int X509_NAME_ENTRY_set_object(); -int X509_NAME_ENTRY_set_data(); -ASN1_OBJECT * X509_NAME_ENTRY_get_object(); -ASN1_STRING * X509_NAME_ENTRY_get_data(); - -int X509v3_get_ext_count(); -int X509v3_get_ext_by_NID(); -int X509v3_get_ext_by_OBJ(); -int X509v3_get_ext_by_critical(); -X509_EXTENSION *X509v3_get_ext(); -X509_EXTENSION *X509v3_delete_ext(); -STACK * X509v3_add_ext(); - -int X509v3_data_type_by_OBJ(); -int X509v3_data_type_by_NID(); -int X509v3_pack_type_by_OBJ(); -int X509v3_pack_type_by_NID(); - -int X509_get_ext_count(); -int X509_get_ext_by_NID(); -int X509_get_ext_by_OBJ(); -int X509_get_ext_by_critical(); -X509_EXTENSION *X509_get_ext(); -X509_EXTENSION *X509_delete_ext(); -int X509_add_ext(); - -int X509_CRL_get_ext_count(); -int X509_CRL_get_ext_by_NID(); -int X509_CRL_get_ext_by_OBJ(); -int X509_CRL_get_ext_by_critical(); -X509_EXTENSION *X509_CRL_get_ext(); -X509_EXTENSION *X509_CRL_delete_ext(); -int X509_CRL_add_ext(); - -int X509_REVOKED_get_ext_count(); -int X509_REVOKED_get_ext_by_NID(); -int X509_REVOKED_get_ext_by_OBJ(); -int X509_REVOKED_get_ext_by_critical(); -X509_EXTENSION *X509_REVOKED_get_ext(); -X509_EXTENSION *X509_REVOKED_delete_ext(); -int X509_REVOKED_add_ext(); - -X509_EXTENSION *X509_EXTENSION_create_by_NID(); -X509_EXTENSION *X509_EXTENSION_create_by_OBJ(); -int X509_EXTENSION_set_object(); -int X509_EXTENSION_set_critical(); -int X509_EXTENSION_set_data(); -ASN1_OBJECT * X509_EXTENSION_get_object(); -ASN1_OCTET_STRING *X509_EXTENSION_get_data(); -int X509_EXTENSION_get_critical(); -ASN1_OCTET_STRING *X509v3_pack_string(); -ASN1_STRING * X509v3_unpack_string(); - -int X509_verify_cert(); -char * X509_verify_cert_error_string(); +int X509_verify_cert(X509_STORE_CTX *ctx); /* lookup a cert from a X509 STACK */ -X509 *X509_find_by_issuer_and_serial(); -X509 *X509_find_by_subject(); - -#endif +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); + +DECLARE_ASN1_FUNCTIONS(PBEPARAM) +DECLARE_ASN1_FUNCTIONS(PBE2PARAM) +DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM) + +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); + +/* PKCS#8 utilities */ + +DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +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. + */ +void ERR_load_X509_strings(void); + /* Error codes for the X509 functions. */ /* Function codes. */ @@ -1105,17 +1190,25 @@ X509 *X509_find_by_subject(); #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_X509V3_ADD_EXTENSION 105 -#define X509_F_X509V3_PACK_STRING 106 -#define X509_F_X509V3_UNPACK_STRING 107 +#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 @@ -1127,26 +1220,40 @@ X509 *X509_find_by_subject(); #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_INIT 143 +#define X509_F_X509_STORE_CTX_NEW 142 +#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_TRUST_SET 141 #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_INVALID_TRUST 123 +#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_STRING_TYPE 110 +#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/src/lib/libcrypto/x509/x509_att.c b/src/lib/libcrypto/x509/x509_att.c index caafde658f..0bae3d32a1 100644 --- a/src/lib/libcrypto/x509/x509_att.c +++ b/src/lib/libcrypto/x509/x509_att.c @@ -149,8 +149,8 @@ err2: } STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, - ASN1_OBJECT *obj, int type, - unsigned char *bytes, int len) + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) { X509_ATTRIBUTE *attr; STACK_OF(X509_ATTRIBUTE) *ret; @@ -163,7 +163,7 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, int nid, int type, - unsigned char *bytes, int len) + const unsigned char *bytes, int len) { X509_ATTRIBUTE *attr; STACK_OF(X509_ATTRIBUTE) *ret; @@ -175,8 +175,8 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, } STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, - char *attrname, int type, - unsigned char *bytes, int len) + const char *attrname, int type, + const unsigned char *bytes, int len) { X509_ATTRIBUTE *attr; STACK_OF(X509_ATTRIBUTE) *ret; @@ -188,7 +188,7 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, - int atrtype, void *data, int len) + int atrtype, const void *data, int len) { ASN1_OBJECT *obj; X509_ATTRIBUTE *ret; @@ -205,7 +205,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, - ASN1_OBJECT *obj, int atrtype, void *data, int len) + const ASN1_OBJECT *obj, int atrtype, const void *data, int len) { X509_ATTRIBUTE *ret; @@ -234,7 +234,7 @@ err: } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, - char *atrname, int type, unsigned char *bytes, int len) + const char *atrname, int type, const unsigned char *bytes, int len) { ASN1_OBJECT *obj; X509_ATTRIBUTE *nattr; @@ -252,7 +252,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, return nattr; } -int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, ASN1_OBJECT *obj) +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) { if ((attr == NULL) || (obj == NULL)) return(0); @@ -261,7 +261,7 @@ int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, ASN1_OBJECT *obj) return(1); } -int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, void *data, int len) +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len) { ASN1_TYPE *ttmp; ASN1_STRING *stmp; @@ -283,7 +283,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, void *data, int if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err; if(!(ttmp = ASN1_TYPE_new())) goto err; if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err; - attr->set = 1; + attr->single = 0; ASN1_TYPE_set(ttmp, atype, stmp); return 1; err: @@ -293,7 +293,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, void *data, int int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) { - if(attr->set) return sk_ASN1_TYPE_num(attr->value.set); + if(!attr->single) return sk_ASN1_TYPE_num(attr->value.set); if(attr->value.single) return 1; return 0; } @@ -321,6 +321,6 @@ ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) { if (attr == NULL) return(NULL); if(idx >= X509_ATTRIBUTE_count(attr)) return NULL; - if(attr->set) return sk_ASN1_TYPE_value(attr->value.set, idx); + if(!attr->single) return sk_ASN1_TYPE_value(attr->value.set, idx); else return attr->value.single; } diff --git a/src/lib/libcrypto/x509/x509_cmp.c b/src/lib/libcrypto/x509/x509_cmp.c index f9d9510ac5..cd20b6d66f 100644 --- a/src/lib/libcrypto/x509/x509_cmp.c +++ b/src/lib/libcrypto/x509/x509_cmp.c @@ -57,114 +57,121 @@ */ #include -#include -#include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include +#include -int X509_issuer_and_serial_cmp(a,b) -X509 *a; -X509 *b; +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) { int i; X509_CINF *ai,*bi; ai=a->cert_info; bi=b->cert_info; - i=ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber); + i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber); if (i) return(i); return(X509_NAME_cmp(ai->issuer,bi->issuer)); } -#ifndef NO_MD5 -unsigned long X509_issuer_and_serial_hash(a) -X509 *a; +#ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_and_serial_hash(X509 *a) { unsigned long ret=0; - MD5_CTX ctx; + EVP_MD_CTX ctx; unsigned char md[16]; char str[256]; + EVP_MD_CTX_init(&ctx); X509_NAME_oneline(a->cert_info->issuer,str,256); ret=strlen(str); - MD5_Init(&ctx); - MD5_Update(&ctx,(unsigned char *)str,ret); - MD5_Update(&ctx,(unsigned char *)a->cert_info->serialNumber->data, + EVP_DigestInit_ex(&ctx, EVP_md5(), NULL); + EVP_DigestUpdate(&ctx,(unsigned char *)str,ret); + EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data, (unsigned long)a->cert_info->serialNumber->length); - MD5_Final(&(md[0]),&ctx); + EVP_DigestFinal_ex(&ctx,&(md[0]),NULL); ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) )&0xffffffffL; + EVP_MD_CTX_cleanup(&ctx); return(ret); } #endif -int X509_issuer_name_cmp(a, b) -X509 *a; -X509 *b; +int X509_issuer_name_cmp(const X509 *a, const X509 *b) { return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer)); } -int X509_subject_name_cmp(a, b) -X509 *a; -X509 *b; +int X509_subject_name_cmp(const X509 *a, const X509 *b) { return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject)); } -int X509_CRL_cmp(a, b) -X509_CRL *a; -X509_CRL *b; +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) { return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer)); } -X509_NAME *X509_get_issuer_name(a) -X509 *a; +X509_NAME *X509_get_issuer_name(X509 *a) { return(a->cert_info->issuer); } -unsigned long X509_issuer_name_hash(x) -X509 *x; +unsigned long X509_issuer_name_hash(X509 *x) { return(X509_NAME_hash(x->cert_info->issuer)); } -X509_NAME *X509_get_subject_name(a) -X509 *a; +X509_NAME *X509_get_subject_name(X509 *a) { return(a->cert_info->subject); } -ASN1_INTEGER *X509_get_serialNumber(a) -X509 *a; +ASN1_INTEGER *X509_get_serialNumber(X509 *a) { return(a->cert_info->serialNumber); } -unsigned long X509_subject_name_hash(x) -X509 *x; +unsigned long X509_subject_name_hash(X509 *x) { return(X509_NAME_hash(x->cert_info->subject)); } -int X509_NAME_cmp(a, b) -X509_NAME *a; -X509_NAME *b; +#ifndef OPENSSL_NO_SHA +/* Compare two certificates: they must be identical for + * this to work. NB: Although "cmp" operations are generally + * prototyped to take "const" arguments (eg. for use in + * STACKs), the way X509 handling is - these operations may + * involve ensuring the hashes are up-to-date and ensuring + * certain cert information is cached. So this is the point + * where the "depth-first" constification tree has to halt + * with an evil cast. + */ +int X509_cmp(const X509 *a, const X509 *b) +{ + /* ensure hash is valid */ + X509_check_purpose((X509 *)a, -1, 0); + X509_check_purpose((X509 *)b, -1, 0); + + return memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); +} +#endif + +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { int i,j; X509_NAME_ENTRY *na,*nb; - if (sk_num(a->entries) != sk_num(b->entries)) - return(sk_num(a->entries)-sk_num(b->entries)); - for (i=sk_num(a->entries)-1; i>=0; i--) + if (sk_X509_NAME_ENTRY_num(a->entries) + != sk_X509_NAME_ENTRY_num(b->entries)) + return sk_X509_NAME_ENTRY_num(a->entries) + -sk_X509_NAME_ENTRY_num(b->entries); + for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { - na=(X509_NAME_ENTRY *)sk_value(a->entries,i); - nb=(X509_NAME_ENTRY *)sk_value(b->entries,i); + na=sk_X509_NAME_ENTRY_value(a->entries,i); + nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=na->value->length-nb->value->length; if (j) return(j); j=memcmp(na->value->data,nb->value->data, @@ -177,37 +184,27 @@ X509_NAME *b; /* We will check the object types after checking the values * since the values will more often be different than the object * types. */ - for (i=sk_num(a->entries)-1; i>=0; i--) + for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) { - na=(X509_NAME_ENTRY *)sk_value(a->entries,i); - nb=(X509_NAME_ENTRY *)sk_value(b->entries,i); + na=sk_X509_NAME_ENTRY_value(a->entries,i); + nb=sk_X509_NAME_ENTRY_value(b->entries,i); j=OBJ_cmp(na->object,nb->object); if (j) return(j); } return(0); } -#ifndef NO_MD5 +#ifndef OPENSSL_NO_MD5 /* I now DER encode the name and hash it. Since I cache the DER encoding, - * this is reasonably effiecent. */ -unsigned long X509_NAME_hash(x) -X509_NAME *x; + * this is reasonably efficient. */ +unsigned long X509_NAME_hash(X509_NAME *x) { unsigned long ret=0; unsigned char md[16]; - unsigned char str[256],*p,*pp; - int i; - - i=i2d_X509_NAME(x,NULL); - if (i > sizeof(str)) - p=Malloc(i); - else - p=str; - pp=p; - i2d_X509_NAME(x,&pp); - MD5((unsigned char *)p,i,&(md[0])); - if (p != str) Free(p); + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x,NULL); + EVP_Digest(x->bytes->data, x->bytes->length, md, NULL, EVP_md5(), NULL); ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) @@ -217,41 +214,100 @@ X509_NAME *x; #endif /* Search a stack of X509 for a match */ -X509 *X509_find_by_issuer_and_serial(sk,name,serial) -STACK *sk; -X509_NAME *name; -ASN1_INTEGER *serial; +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial) { int i; X509_CINF cinf; X509 x,*x509=NULL; + if(!sk) return NULL; + x.cert_info= &cinf; cinf.serialNumber=serial; cinf.issuer=name; - for (i=0; icert_info == NULL)) + return(NULL); + return(X509_PUBKEY_get(x->cert_info->key)); + } + +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) + { + if(!x) return NULL; + return x->cert_info->key->public_key; + } + +int X509_check_private_key(X509 *x, EVP_PKEY *k) + { + EVP_PKEY *xk=NULL; + int ok=0; + + xk=X509_get_pubkey(x); + if (xk->type != k->type) + { + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_TYPE_MISMATCH); + goto err; + } + switch (k->type) + { +#ifndef OPENSSL_NO_RSA + case EVP_PKEY_RSA: + if (BN_cmp(xk->pkey.rsa->n,k->pkey.rsa->n) != 0 + || BN_cmp(xk->pkey.rsa->e,k->pkey.rsa->e) != 0) + { + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH); + goto err; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case EVP_PKEY_DSA: + if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0) + { + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_KEY_VALUES_MISMATCH); + goto err; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case EVP_PKEY_DH: + /* No idea */ + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_CANT_CHECK_DH_KEY); + goto err; +#endif + default: + X509err(X509_F_X509_CHECK_PRIVATE_KEY,X509_R_UNKNOWN_KEY_TYPE); + goto err; + } + + ok=1; +err: + EVP_PKEY_free(xk); + return(ok); + } diff --git a/src/lib/libcrypto/x509/x509_d2.c b/src/lib/libcrypto/x509/x509_d2.c index 01e22f4cb4..51410cfd1a 100644 --- a/src/lib/libcrypto/x509/x509_d2.c +++ b/src/lib/libcrypto/x509/x509_d2.c @@ -57,15 +57,12 @@ */ #include -#include -#include #include "cryptlib.h" -#include "crypto.h" -#include "x509.h" +#include +#include -#ifndef NO_STDIO -int X509_STORE_set_default_paths(ctx) -X509_STORE *ctx; +#ifndef OPENSSL_NO_STDIO +int X509_STORE_set_default_paths(X509_STORE *ctx) { X509_LOOKUP *lookup; @@ -83,10 +80,8 @@ X509_STORE *ctx; return(1); } -int X509_STORE_load_locations(ctx,file,path) -X509_STORE *ctx; -char *file; -char *path; +int X509_STORE_load_locations(X509_STORE *ctx, const char *file, + const char *path) { X509_LOOKUP *lookup; @@ -94,13 +89,15 @@ char *path; { lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file()); if (lookup == NULL) return(0); - X509_LOOKUP_load_file(lookup,file,X509_FILETYPE_PEM); + if (X509_LOOKUP_load_file(lookup,file,X509_FILETYPE_PEM) != 1) + return(0); } if (path != NULL) { lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir()); if (lookup == NULL) return(0); - X509_LOOKUP_add_dir(lookup,path,X509_FILETYPE_PEM); + if (X509_LOOKUP_add_dir(lookup,path,X509_FILETYPE_PEM) != 1) + return(0); } if ((path == NULL) && (file == NULL)) return(0); diff --git a/src/lib/libcrypto/x509/x509_def.c b/src/lib/libcrypto/x509/x509_def.c index d9ab39b15a..e0ac151a76 100644 --- a/src/lib/libcrypto/x509/x509_def.c +++ b/src/lib/libcrypto/x509/x509_def.c @@ -57,27 +57,25 @@ */ #include -#include -#include #include "cryptlib.h" -#include "crypto.h" -#include "x509.h" +#include +#include -char *X509_get_default_private_dir() +const char *X509_get_default_private_dir(void) { return(X509_PRIVATE_DIR); } -char *X509_get_default_cert_area() +const char *X509_get_default_cert_area(void) { return(X509_CERT_AREA); } -char *X509_get_default_cert_dir() +const char *X509_get_default_cert_dir(void) { return(X509_CERT_DIR); } -char *X509_get_default_cert_file() +const char *X509_get_default_cert_file(void) { return(X509_CERT_FILE); } -char *X509_get_default_cert_dir_env() +const char *X509_get_default_cert_dir_env(void) { return(X509_CERT_DIR_EVP); } -char *X509_get_default_cert_file_env() +const char *X509_get_default_cert_file_env(void) { return(X509_CERT_FILE_EVP); } diff --git a/src/lib/libcrypto/x509/x509_err.c b/src/lib/libcrypto/x509/x509_err.c index 9304721612..5bbf4acf76 100644 --- a/src/lib/libcrypto/x509/x509_err.c +++ b/src/lib/libcrypto/x509/x509_err.c @@ -1,83 +1,94 @@ -/* lib/x509/x509_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* crypto/x509/x509_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "x509.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA X509_str_functs[]= { {ERR_PACK(0,X509_F_ADD_CERT_DIR,0), "ADD_CERT_DIR"}, {ERR_PACK(0,X509_F_BY_FILE_CTRL,0), "BY_FILE_CTRL"}, {ERR_PACK(0,X509_F_DIR_CTRL,0), "DIR_CTRL"}, {ERR_PACK(0,X509_F_GET_CERT_BY_SUBJECT,0), "GET_CERT_BY_SUBJECT"}, +{ERR_PACK(0,X509_F_NETSCAPE_SPKI_B64_DECODE,0), "NETSCAPE_SPKI_b64_decode"}, +{ERR_PACK(0,X509_F_NETSCAPE_SPKI_B64_ENCODE,0), "NETSCAPE_SPKI_b64_encode"}, {ERR_PACK(0,X509_F_X509V3_ADD_EXT,0), "X509v3_add_ext"}, -{ERR_PACK(0,X509_F_X509V3_ADD_EXTENSION,0), "X509V3_ADD_EXTENSION"}, -{ERR_PACK(0,X509_F_X509V3_PACK_STRING,0), "X509v3_pack_string"}, -{ERR_PACK(0,X509_F_X509V3_UNPACK_STRING,0), "X509v3_unpack_string"}, +{ERR_PACK(0,X509_F_X509_ADD_ATTR,0), "X509_ADD_ATTR"}, +{ERR_PACK(0,X509_F_X509_ATTRIBUTE_CREATE_BY_NID,0), "X509_ATTRIBUTE_create_by_NID"}, +{ERR_PACK(0,X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ,0), "X509_ATTRIBUTE_create_by_OBJ"}, +{ERR_PACK(0,X509_F_X509_ATTRIBUTE_CREATE_BY_TXT,0), "X509_ATTRIBUTE_create_by_txt"}, +{ERR_PACK(0,X509_F_X509_ATTRIBUTE_GET0_DATA,0), "X509_ATTRIBUTE_get0_data"}, +{ERR_PACK(0,X509_F_X509_ATTRIBUTE_SET1_DATA,0), "X509_ATTRIBUTE_set1_data"}, +{ERR_PACK(0,X509_F_X509_CHECK_PRIVATE_KEY,0), "X509_check_private_key"}, {ERR_PACK(0,X509_F_X509_EXTENSION_CREATE_BY_NID,0), "X509_EXTENSION_create_by_NID"}, {ERR_PACK(0,X509_F_X509_EXTENSION_CREATE_BY_OBJ,0), "X509_EXTENSION_create_by_OBJ"}, {ERR_PACK(0,X509_F_X509_GET_PUBKEY_PARAMETERS,0), "X509_get_pubkey_parameters"}, -{ERR_PACK(0,X509_F_X509_LOAD_CERT_FILE,0), "X509_LOAD_CERT_FILE"}, -{ERR_PACK(0,X509_F_X509_LOAD_CRL_FILE,0), "X509_LOAD_CRL_FILE"}, +{ERR_PACK(0,X509_F_X509_LOAD_CERT_CRL_FILE,0), "X509_load_cert_crl_file"}, +{ERR_PACK(0,X509_F_X509_LOAD_CERT_FILE,0), "X509_load_cert_file"}, +{ERR_PACK(0,X509_F_X509_LOAD_CRL_FILE,0), "X509_load_crl_file"}, {ERR_PACK(0,X509_F_X509_NAME_ADD_ENTRY,0), "X509_NAME_add_entry"}, {ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_NID,0), "X509_NAME_ENTRY_create_by_NID"}, +{ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,0), "X509_NAME_ENTRY_create_by_txt"}, {ERR_PACK(0,X509_F_X509_NAME_ENTRY_SET_OBJECT,0), "X509_NAME_ENTRY_set_object"}, {ERR_PACK(0,X509_F_X509_NAME_ONELINE,0), "X509_NAME_oneline"}, {ERR_PACK(0,X509_F_X509_NAME_PRINT,0), "X509_NAME_print"}, @@ -87,41 +98,56 @@ static ERR_STRING_DATA X509_str_functs[]= {ERR_PACK(0,X509_F_X509_REQ_PRINT,0), "X509_REQ_print"}, {ERR_PACK(0,X509_F_X509_REQ_PRINT_FP,0), "X509_REQ_print_fp"}, {ERR_PACK(0,X509_F_X509_REQ_TO_X509,0), "X509_REQ_to_X509"}, -{ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0), "X509_STORE_ADD_CERT"}, -{ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0), "X509_STORE_ADD_CRL"}, +{ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0), "X509_STORE_add_cert"}, +{ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0), "X509_STORE_add_crl"}, +{ERR_PACK(0,X509_F_X509_STORE_CTX_INIT,0), "X509_STORE_CTX_init"}, +{ERR_PACK(0,X509_F_X509_STORE_CTX_NEW,0), "X509_STORE_CTX_new"}, +{ERR_PACK(0,X509_F_X509_STORE_CTX_PURPOSE_INHERIT,0), "X509_STORE_CTX_purpose_inherit"}, {ERR_PACK(0,X509_F_X509_TO_X509_REQ,0), "X509_to_X509_REQ"}, +{ERR_PACK(0,X509_F_X509_TRUST_ADD,0), "X509_TRUST_add"}, +{ERR_PACK(0,X509_F_X509_TRUST_SET,0), "X509_TRUST_set"}, {ERR_PACK(0,X509_F_X509_VERIFY_CERT,0), "X509_verify_cert"}, -{0,NULL}, +{0,NULL} }; static ERR_STRING_DATA X509_str_reasons[]= { {X509_R_BAD_X509_FILETYPE ,"bad x509 filetype"}, +{X509_R_BASE64_DECODE_ERROR ,"base64 decode error"}, +{X509_R_CANT_CHECK_DH_KEY ,"cant check dh key"}, {X509_R_CERT_ALREADY_IN_HASH_TABLE ,"cert already in hash table"}, {X509_R_ERR_ASN1_LIB ,"err asn1 lib"}, +{X509_R_INVALID_DIRECTORY ,"invalid directory"}, +{X509_R_INVALID_FIELD_NAME ,"invalid field name"}, +{X509_R_INVALID_TRUST ,"invalid trust"}, +{X509_R_KEY_TYPE_MISMATCH ,"key type mismatch"}, +{X509_R_KEY_VALUES_MISMATCH ,"key values mismatch"}, {X509_R_LOADING_CERT_DIR ,"loading cert dir"}, {X509_R_LOADING_DEFAULTS ,"loading defaults"}, {X509_R_NO_CERT_SET_FOR_US_TO_VERIFY ,"no cert set for us to verify"}, {X509_R_SHOULD_RETRY ,"should retry"}, {X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN,"unable to find parameters in chain"}, {X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY ,"unable to get certs public key"}, +{X509_R_UNKNOWN_KEY_TYPE ,"unknown key type"}, {X509_R_UNKNOWN_NID ,"unknown nid"}, -{X509_R_UNKNOWN_STRING_TYPE ,"unknown string type"}, +{X509_R_UNKNOWN_PURPOSE_ID ,"unknown purpose id"}, +{X509_R_UNKNOWN_TRUST_ID ,"unknown trust id"}, {X509_R_UNSUPPORTED_ALGORITHM ,"unsupported algorithm"}, {X509_R_WRONG_LOOKUP_TYPE ,"wrong lookup type"}, -{0,NULL}, +{X509_R_WRONG_TYPE ,"wrong type"}, +{0,NULL} }; #endif -void ERR_load_X509_strings() +void ERR_load_X509_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_X509,X509_str_functs); ERR_load_strings(ERR_LIB_X509,X509_str_reasons); #endif diff --git a/src/lib/libcrypto/x509/x509_ext.c b/src/lib/libcrypto/x509/x509_ext.c index 1d76ecfcfd..e7fdacb5e4 100644 --- a/src/lib/libcrypto/x509/x509_ext.c +++ b/src/lib/libcrypto/x509/x509_ext.c @@ -57,166 +57,154 @@ */ #include -#include "stack.h" +#include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include -int X509_CRL_get_ext_count(x) -X509_CRL *x; + +int X509_CRL_get_ext_count(X509_CRL *x) { return(X509v3_get_ext_count(x->crl->extensions)); } -int X509_CRL_get_ext_by_NID(x,nid,lastpos) -X509_CRL *x; -int nid; -int lastpos; +int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos) { return(X509v3_get_ext_by_NID(x->crl->extensions,nid,lastpos)); } -int X509_CRL_get_ext_by_OBJ(x,obj,lastpos) -X509_CRL *x; -ASN1_OBJECT *obj; -int lastpos; +int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos) { return(X509v3_get_ext_by_OBJ(x->crl->extensions,obj,lastpos)); } -int X509_CRL_get_ext_by_critical(x,crit,lastpos) -X509_CRL *x; -int crit; -int lastpos; +int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos) { return(X509v3_get_ext_by_critical(x->crl->extensions,crit,lastpos)); } -X509_EXTENSION *X509_CRL_get_ext(x,loc) -X509_CRL *x; -int loc; +X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc) { return(X509v3_get_ext(x->crl->extensions,loc)); } -X509_EXTENSION *X509_CRL_delete_ext(x,loc) -X509_CRL *x; -int loc; +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc) { return(X509v3_delete_ext(x->crl->extensions,loc)); } -int X509_CRL_add_ext(x,ex,loc) -X509_CRL *x; -X509_EXTENSION *ex; -int loc; +void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->crl->extensions, nid, crit, idx); +} + +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags); +} + +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) { return(X509v3_add_ext(&(x->crl->extensions),ex,loc) != NULL); } -int X509_get_ext_count(x) -X509 *x; +int X509_get_ext_count(X509 *x) { return(X509v3_get_ext_count(x->cert_info->extensions)); } -int X509_get_ext_by_NID(x,nid,lastpos) -X509 *x; -int nid; -int lastpos; +int X509_get_ext_by_NID(X509 *x, int nid, int lastpos) { return(X509v3_get_ext_by_NID(x->cert_info->extensions,nid,lastpos)); } -int X509_get_ext_by_OBJ(x,obj,lastpos) -X509 *x; -ASN1_OBJECT *obj; -int lastpos; +int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos) { return(X509v3_get_ext_by_OBJ(x->cert_info->extensions,obj,lastpos)); } -int X509_get_ext_by_critical(x,crit,lastpos) -X509 *x; -int crit; -int lastpos; +int X509_get_ext_by_critical(X509 *x, int crit, int lastpos) { return(X509v3_get_ext_by_critical(x->cert_info->extensions,crit,lastpos)); } -X509_EXTENSION *X509_get_ext(x,loc) -X509 *x; -int loc; +X509_EXTENSION *X509_get_ext(X509 *x, int loc) { return(X509v3_get_ext(x->cert_info->extensions,loc)); } -X509_EXTENSION *X509_delete_ext(x,loc) -X509 *x; -int loc; +X509_EXTENSION *X509_delete_ext(X509 *x, int loc) { return(X509v3_delete_ext(x->cert_info->extensions,loc)); } -int X509_add_ext(x,ex,loc) -X509 *x; -X509_EXTENSION *ex; -int loc; +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) { return(X509v3_add_ext(&(x->cert_info->extensions),ex,loc) != NULL); } -int X509_REVOKED_get_ext_count(x) -X509_REVOKED *x; +void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx); +} + +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, + flags); +} + +int X509_REVOKED_get_ext_count(X509_REVOKED *x) { return(X509v3_get_ext_count(x->extensions)); } -int X509_REVOKED_get_ext_by_NID(x,nid,lastpos) -X509_REVOKED *x; -int nid; -int lastpos; +int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos) { return(X509v3_get_ext_by_NID(x->extensions,nid,lastpos)); } -int X509_REVOKED_get_ext_by_OBJ(x,obj,lastpos) -X509_REVOKED *x; -ASN1_OBJECT *obj; -int lastpos; +int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj, + int lastpos) { return(X509v3_get_ext_by_OBJ(x->extensions,obj,lastpos)); } -int X509_REVOKED_get_ext_by_critical(x,crit,lastpos) -X509_REVOKED *x; -int crit; -int lastpos; +int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos) { return(X509v3_get_ext_by_critical(x->extensions,crit,lastpos)); } -X509_EXTENSION *X509_REVOKED_get_ext(x,loc) -X509_REVOKED *x; -int loc; +X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc) { return(X509v3_get_ext(x->extensions,loc)); } -X509_EXTENSION *X509_REVOKED_delete_ext(x,loc) -X509_REVOKED *x; -int loc; +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) { return(X509v3_delete_ext(x->extensions,loc)); } -int X509_REVOKED_add_ext(x,ex,loc) -X509_REVOKED *x; -X509_EXTENSION *ex; -int loc; +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) { return(X509v3_add_ext(&(x->extensions),ex,loc) != NULL); } +void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->extensions, nid, crit, idx); +} + +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); +} + +IMPLEMENT_STACK_OF(X509_EXTENSION) +IMPLEMENT_ASN1_SET_OF(X509_EXTENSION) diff --git a/src/lib/libcrypto/x509/x509_lu.c b/src/lib/libcrypto/x509/x509_lu.c index 2c7e10a46e..b780dae5e2 100644 --- a/src/lib/libcrypto/x509/x509_lu.c +++ b/src/lib/libcrypto/x509/x509_lu.c @@ -58,19 +58,16 @@ #include #include "cryptlib.h" -#include "lhash.h" -#include "x509.h" +#include +#include +#include -static STACK *x509_store_meth=NULL; -static STACK *x509_store_ctx_meth=NULL; - -X509_LOOKUP *X509_LOOKUP_new(method) -X509_LOOKUP_METHOD *method; +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) { X509_LOOKUP *ret; - ret=(X509_LOOKUP *)Malloc(sizeof(X509_LOOKUP)); - if (ret == NULL) return(NULL); + ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP)); + if (ret == NULL) return NULL; ret->init=0; ret->skip=0; @@ -79,163 +76,137 @@ X509_LOOKUP_METHOD *method; ret->store_ctx=NULL; if ((method->new_item != NULL) && !method->new_item(ret)) { - Free(ret); - return(NULL); + OPENSSL_free(ret); + return NULL; } - return(ret); + return ret; } -void X509_LOOKUP_free(ctx) -X509_LOOKUP *ctx; +void X509_LOOKUP_free(X509_LOOKUP *ctx) { if (ctx == NULL) return; if ( (ctx->method != NULL) && (ctx->method->free != NULL)) ctx->method->free(ctx); - Free(ctx); + OPENSSL_free(ctx); } -int X509_LOOKUP_init(ctx) -X509_LOOKUP *ctx; +int X509_LOOKUP_init(X509_LOOKUP *ctx) { - if (ctx->method == NULL) return(0); + if (ctx->method == NULL) return 0; if (ctx->method->init != NULL) - return(ctx->method->init(ctx)); + return ctx->method->init(ctx); else - return(1); + return 1; } -int X509_LOOKUP_shutdown(ctx) -X509_LOOKUP *ctx; +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) { - if (ctx->method == NULL) return(0); - if (ctx->method->init != NULL) - return(ctx->method->shutdown(ctx)); + if (ctx->method == NULL) return 0; + if (ctx->method->shutdown != NULL) + return ctx->method->shutdown(ctx); else - return(1); + return 1; } -int X509_LOOKUP_ctrl(ctx,cmd,argc,argl,ret) -X509_LOOKUP *ctx; -int cmd; -char *argc; -long argl; -char **ret; +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret) { - if (ctx->method == NULL) return(-1); + if (ctx->method == NULL) return -1; if (ctx->method->ctrl != NULL) - return(ctx->method->ctrl(ctx,cmd,argc,argl,ret)); + return ctx->method->ctrl(ctx,cmd,argc,argl,ret); else - return(1); + return 1; } -int X509_LOOKUP_by_subject(ctx,type,name,ret) -X509_LOOKUP *ctx; -int type; -X509_NAME *name; -X509_OBJECT *ret; +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) - return(X509_LU_FAIL); - if (ctx->skip) return(0); - return(ctx->method->get_by_subject(ctx,type,name,ret)); + return X509_LU_FAIL; + if (ctx->skip) return 0; + return ctx->method->get_by_subject(ctx,type,name,ret); } -int X509_LOOKUP_by_issuer_serial(ctx,type,name,serial,ret) -X509_LOOKUP *ctx; -int type; -X509_NAME *name; -ASN1_INTEGER *serial; -X509_OBJECT *ret; +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) - return(X509_LU_FAIL); - return(ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret)); + return X509_LU_FAIL; + return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret); } -int X509_LOOKUP_by_fingerprint(ctx,type,bytes,len,ret) -X509_LOOKUP *ctx; -int type; -unsigned char *bytes; -int len; -X509_OBJECT *ret; +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, + unsigned char *bytes, int len, X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) - return(X509_LU_FAIL); - return(ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret)); + return X509_LU_FAIL; + return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret); } -int X509_LOOKUP_by_alias(ctx,type,str,len,ret) -X509_LOOKUP *ctx; -int type; -char *str; -int len; -X509_OBJECT *ret; +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, + X509_OBJECT *ret) { if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) - return(X509_LU_FAIL); - return(ctx->method->get_by_alias(ctx,str,len,ret)); + return X509_LU_FAIL; + return ctx->method->get_by_alias(ctx,type,str,len,ret); } -static unsigned long x509_object_hash(a) -X509_OBJECT *a; - { - unsigned long h; - - switch (a->type) - { - case X509_LU_X509: - h=X509_NAME_hash(a->data.x509->cert_info->subject); - break; - case X509_LU_CRL: - h=X509_NAME_hash(a->data.crl->crl->issuer); - break; + +static int x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b) + { + int ret; + + ret=((*a)->type - (*b)->type); + if (ret) return ret; + switch ((*a)->type) + { + case X509_LU_X509: + ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509); + break; + case X509_LU_CRL: + ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl); + break; default: - abort(); + /* abort(); */ + return 0; } - return(h); + return ret; } -static int x509_object_cmp(a,b) -X509_OBJECT *a,*b; - { - int ret; - - ret=(a->type - b->type); - if (ret) return(ret); - switch (a->type) - { - case X509_LU_X509: - ret=X509_subject_name_cmp(a->data.x509,b->data.x509); - break; - case X509_LU_CRL: - ret=X509_CRL_cmp(a->data.crl,b->data.crl); - break; - default: - abort(); - } - return(ret); - } - -X509_STORE *X509_STORE_new() +X509_STORE *X509_STORE_new(void) { X509_STORE *ret; - if ((ret=(X509_STORE *)Malloc(sizeof(X509_STORE))) == NULL) - return(NULL); - ret->certs=lh_new(x509_object_hash,x509_object_cmp); + if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL) + return NULL; + ret->objs = sk_X509_OBJECT_new(x509_object_cmp); ret->cache=1; - ret->get_cert_methods=sk_new_null(); - ret->verify=NULL; - ret->verify_cb=NULL; - memset(&ret->ex_data,0,sizeof(CRYPTO_EX_DATA)); + ret->get_cert_methods=sk_X509_LOOKUP_new_null(); + ret->verify=0; + ret->verify_cb=0; + + ret->purpose = 0; + ret->trust = 0; + + ret->flags = 0; + + ret->get_issuer = 0; + ret->check_issued = 0; + ret->check_revocation = 0; + ret->get_crl = 0; + ret->check_crl = 0; + ret->cert_crl = 0; + ret->cleanup = 0; + + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data); ret->references=1; - return(ret); + ret->depth=0; + return ret; } -static void cleanup(a) -X509_OBJECT *a; +static void cleanup(X509_OBJECT *a) { if (a->type == X509_LU_X509) { @@ -246,90 +217,88 @@ X509_OBJECT *a; X509_CRL_free(a->data.crl); } else - abort(); + { + /* abort(); */ + } - Free(a); + OPENSSL_free(a); } -void X509_STORE_free(vfy) -X509_STORE *vfy; +void X509_STORE_free(X509_STORE *vfy) { int i; - STACK *sk; + STACK_OF(X509_LOOKUP) *sk; X509_LOOKUP *lu; + if (vfy == NULL) + return; + sk=vfy->get_cert_methods; - for (i=0; iobjs, cleanup); - CRYPTO_free_ex_data(x509_store_meth,(char *)vfy,&vfy->ex_data); - lh_doall(vfy->certs,cleanup); - lh_free(vfy->certs); - Free(vfy); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); + OPENSSL_free(vfy); } -X509_LOOKUP *X509_STORE_add_lookup(v,m) -X509_STORE *v; -X509_LOOKUP_METHOD *m; +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { int i; - STACK *sk; + STACK_OF(X509_LOOKUP) *sk; X509_LOOKUP *lu; sk=v->get_cert_methods; - for (i=0; imethod) { - return(lu); + return lu; } } /* a new one */ lu=X509_LOOKUP_new(m); if (lu == NULL) - return(NULL); + return NULL; else { lu->store_ctx=v; - if (sk_push(v->get_cert_methods,(char *)lu)) - return(lu); + if (sk_X509_LOOKUP_push(v->get_cert_methods,lu)) + return lu; else { X509_LOOKUP_free(lu); - return(NULL); + return NULL; } } } -int X509_STORE_get_by_subject(vs,type,name,ret) -X509_STORE_CTX *vs; -int type; -X509_NAME *name; -X509_OBJECT *ret; +int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, + X509_OBJECT *ret) { X509_STORE *ctx=vs->ctx; X509_LOOKUP *lu; X509_OBJECT stmp,*tmp; int i,j; - tmp=X509_OBJECT_retrive_by_subject(ctx->certs,type,name); + tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name); if (tmp == NULL) { - for (i=vs->current_method; iget_cert_methods); i++) + for (i=vs->current_method; iget_cert_methods); i++) { - lu=(X509_LOOKUP *)sk_value(ctx->get_cert_methods,i); + lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i); j=X509_LOOKUP_by_subject(lu,type,name,&stmp); if (j < 0) { vs->current_method=j; - return(j); + return j; } else if (j) { @@ -339,7 +308,7 @@ X509_OBJECT *ret; } vs->current_method=0; if (tmp == NULL) - return(0); + return 0; } /* if (ret->data.ptr != NULL) @@ -350,11 +319,77 @@ X509_OBJECT *ret; X509_OBJECT_up_ref_count(ret); - return(1); + return 1; + } + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) + { + X509_OBJECT *obj; + int ret=1; + + if (x == NULL) return 0; + obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); + if (obj == NULL) + { + X509err(X509_F_X509_STORE_ADD_CERT,ERR_R_MALLOC_FAILURE); + return 0; + } + obj->type=X509_LU_X509; + obj->data.x509=x; + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + + X509_OBJECT_up_ref_count(obj); + + + if (X509_OBJECT_retrieve_match(ctx->objs, obj)) + { + X509_OBJECT_free_contents(obj); + OPENSSL_free(obj); + X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE); + ret=0; + } + else sk_X509_OBJECT_push(ctx->objs, obj); + + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + + return ret; } -void X509_OBJECT_up_ref_count(a) -X509_OBJECT *a; +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) + { + X509_OBJECT *obj; + int ret=1; + + if (x == NULL) return 0; + obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT)); + if (obj == NULL) + { + X509err(X509_F_X509_STORE_ADD_CRL,ERR_R_MALLOC_FAILURE); + return 0; + } + obj->type=X509_LU_CRL; + obj->data.crl=x; + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + + X509_OBJECT_up_ref_count(obj); + + if (X509_OBJECT_retrieve_match(ctx->objs, obj)) + { + X509_OBJECT_free_contents(obj); + OPENSSL_free(obj); + X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE); + ret=0; + } + else sk_X509_OBJECT_push(ctx->objs, obj); + + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + + return ret; + } + +void X509_OBJECT_up_ref_count(X509_OBJECT *a) { switch (a->type) { @@ -367,8 +402,7 @@ X509_OBJECT *a; } } -void X509_OBJECT_free_contents(a) -X509_OBJECT *a; +void X509_OBJECT_free_contents(X509_OBJECT *a) { switch (a->type) { @@ -381,12 +415,10 @@ X509_OBJECT *a; } } -X509_OBJECT *X509_OBJECT_retrive_by_subject(h,type,name) -LHASH *h; -int type; -X509_NAME *name; +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name) { - X509_OBJECT stmp,*tmp; + X509_OBJECT stmp; X509 x509_s; X509_CINF cinf_s; X509_CRL crl_s; @@ -406,41 +438,120 @@ X509_NAME *name; crl_info_s.issuer=name; break; default: - abort(); + /* abort(); */ + return -1; } - tmp=(X509_OBJECT *)lh_retrieve(h,(char *)&stmp); - return(tmp); + return sk_X509_OBJECT_find(h,&stmp); } -void X509_STORE_CTX_init(ctx,store,x509,chain) -X509_STORE_CTX *ctx; -X509_STORE *store; -X509 *x509; -STACK *chain; +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name) +{ + int idx; + idx = X509_OBJECT_idx_by_subject(h, type, name); + if (idx==-1) return NULL; + return sk_X509_OBJECT_value(h, idx); +} + +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x) +{ + int idx, i; + X509_OBJECT *obj; + idx = sk_X509_OBJECT_find(h, x); + if (idx == -1) return NULL; + if (x->type != X509_LU_X509) return sk_X509_OBJECT_value(h, idx); + for (i = idx; i < sk_X509_OBJECT_num(h); i++) + { + obj = sk_X509_OBJECT_value(h, i); + if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x)) + return NULL; + if ((x->type != X509_LU_X509) || !X509_cmp(obj->data.x509, x->data.x509)) + return obj; + } + return NULL; +} + + +/* Try to get issuer certificate from store. Due to limitations + * of the API this can only retrieve a single certificate matching + * a given subject name. However it will fill the cache with all + * matching certificates, so we can examine the cache for all + * matches. + * + * Return values are: + * 1 lookup successful. + * 0 certificate not found. + * -1 some other error. + */ + + +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + X509_NAME *xn; + X509_OBJECT obj, *pobj; + int i, ok, idx; + xn=X509_get_issuer_name(x); + ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj); + if (ok != X509_LU_X509) + { + if (ok == X509_LU_RETRY) + { + X509_OBJECT_free_contents(&obj); + X509err(X509_F_X509_VERIFY_CERT,X509_R_SHOULD_RETRY); + return -1; + } + else if (ok != X509_LU_FAIL) + { + X509_OBJECT_free_contents(&obj); + /* not good :-(, break anyway */ + return -1; + } + return 0; + } + /* If certificate matches all OK */ + if (ctx->check_issued(ctx, x, obj.data.x509)) + { + *issuer = obj.data.x509; + return 1; + } + X509_OBJECT_free_contents(&obj); + /* Else find index of first matching cert */ + idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); + /* This shouldn't normally happen since we already have one match */ + if (idx == -1) return 0; + + /* Look through all matching certificates for a suitable issuer */ + for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) + { + pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); + /* See if we've ran out of matches */ + if (pobj->type != X509_LU_X509) return 0; + if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) return 0; + if (ctx->check_issued(ctx, x, pobj->data.x509)) + { + *issuer = pobj->data.x509; + X509_OBJECT_up_ref_count(pobj); + return 1; + } + } + return 0; +} + +void X509_STORE_set_flags(X509_STORE *ctx, long flags) { - ctx->ctx=store; - ctx->current_method=0; - ctx->cert=x509; - ctx->untrusted=chain; - ctx->last_untrusted=0; - ctx->valid=0; - ctx->chain=NULL; - ctx->depth=10; - ctx->error=0; - ctx->current_cert=NULL; - memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); + ctx->flags |= flags; } -void X509_STORE_CTX_cleanup(ctx) -X509_STORE_CTX *ctx; +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) { - if (ctx->chain != NULL) - { - sk_pop_free(ctx->chain,X509_free); - ctx->chain=NULL; - } - CRYPTO_free_ex_data(x509_store_ctx_meth,(char *)ctx,&(ctx->ex_data)); - memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA)); + return X509_PURPOSE_set(&ctx->purpose, purpose); + } + +int X509_STORE_set_trust(X509_STORE *ctx, int trust) + { + return X509_TRUST_set(&ctx->trust, trust); } +IMPLEMENT_STACK_OF(X509_LOOKUP) +IMPLEMENT_STACK_OF(X509_OBJECT) diff --git a/src/lib/libcrypto/x509/x509_obj.c b/src/lib/libcrypto/x509/x509_obj.c index c0576fd6f6..1e718f76eb 100644 --- a/src/lib/libcrypto/x509/x509_obj.c +++ b/src/lib/libcrypto/x509/x509_obj.c @@ -58,27 +58,27 @@ #include #include "cryptlib.h" -#include "lhash.h" -#include "objects.h" -#include "x509.h" -#include "buffer.h" +#include +#include +#include +#include -char *X509_NAME_oneline(a,buf,len) -X509_NAME *a; -char *buf; -int len; +char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) { X509_NAME_ENTRY *ne; - unsigned int i; +int i; int n,lold,l,l1,l2,num,j,type; - char *s,*p; + const char *s; + char *p; unsigned char *q; BUF_MEM *b=NULL; static char hex[17]="0123456789ABCDEF"; int gs_doit[4]; char tmp_buf[80]; +#ifdef CHARSET_EBCDIC + char ebcdic_buf[1024]; +#endif - if (a == NULL) return("NO X509_NAME"); if (buf == NULL) { if ((b=BUF_MEM_new()) == NULL) goto err; @@ -86,12 +86,23 @@ int len; b->data[0]='\0'; len=200; } + if (a == NULL) + { + if(b) + { + buf=b->data; + OPENSSL_free(b); + } + strncpy(buf,"NO X509_NAME",len); + buf[len-1]='\0'; + return buf; + } len--; /* space for '\0' */ l=0; - for (i=0; (int)ientries); i++) + for (i=0; ientries); i++) { - ne=(X509_NAME_ENTRY *)sk_value(a->entries,i); + ne=sk_X509_NAME_ENTRY_value(a->entries,i); n=OBJ_obj2nid(ne->object); if ((n == NID_undef) || ((s=OBJ_nid2sn(n)) == NULL)) { @@ -103,6 +114,19 @@ int len; type=ne->value->type; num=ne->value->length; q=ne->value->data; +#ifdef CHARSET_EBCDIC + if (type == V_ASN1_GENERALSTRING || + type == V_ASN1_VISIBLESTRING || + type == V_ASN1_PRINTABLESTRING || + type == V_ASN1_TELETEXSTRING || + type == V_ASN1_VISIBLESTRING || + type == V_ASN1_IA5STRING) { + ascii2ebcdic(ebcdic_buf, q, + (num > sizeof ebcdic_buf) + ? sizeof ebcdic_buf : num); + q=ebcdic_buf; + } +#endif if ((type == V_ASN1_GENERALSTRING) && ((num%4) == 0)) { @@ -125,7 +149,12 @@ int len; { if (!gs_doit[j&3]) continue; l2++; +#ifndef CHARSET_EBCDIC if ((q[j] < ' ') || (q[j] > '~')) l2+=3; +#else + if ((os_toascii[q[j]] < os_toascii[' ']) || + (os_toascii[q[j]] > os_toascii['~'])) l2+=3; +#endif } lold=l; @@ -145,11 +174,14 @@ int len; memcpy(p,s,(unsigned int)l1); p+=l1; *(p++)='='; +#ifndef CHARSET_EBCDIC /* q was assigned above already. */ q=ne->value->data; +#endif for (j=0; j '~')) { @@ -160,16 +192,31 @@ int len; } else *(p++)=n; +#else + n=os_toascii[q[j]]; + if ((n < os_toascii[' ']) || + (n > os_toascii['~'])) + { + *(p++)='\\'; + *(p++)='x'; + *(p++)=hex[(n>>4)&0x0f]; + *(p++)=hex[n&0x0f]; + } + else + *(p++)=q[j]; +#endif } *p='\0'; } if (b != NULL) { p=b->data; - Free((char *)b); + OPENSSL_free(b); } else p=buf; + if (i == 0) + *p = '\0'; return(p); err: X509err(X509_F_X509_NAME_ONELINE,ERR_R_MALLOC_FAILURE); diff --git a/src/lib/libcrypto/x509/x509_r2x.c b/src/lib/libcrypto/x509/x509_r2x.c index 6aec2427f7..db051033d9 100644 --- a/src/lib/libcrypto/x509/x509_r2x.c +++ b/src/lib/libcrypto/x509/x509_r2x.c @@ -58,22 +58,16 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "asn1.h" -#include "x509.h" -#include "objects.h" -#include "buffer.h" -#include "pem.h" +#include +#include +#include +#include +#include +#include -X509 *X509_REQ_to_X509(r,days,pkey) -X509_REQ *r; -int days; -EVP_PKEY *pkey; +X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) { X509 *ret=NULL; - int er=1; - X509_REQ_INFO *ri=NULL; X509_CINF *xi=NULL; X509_NAME *xn; @@ -84,15 +78,11 @@ EVP_PKEY *pkey; } /* duplicate the request */ - ri=(X509_REQ_INFO *)ASN1_dup(i2d_X509_REQ_INFO, - (char *(*)())d2i_X509_REQ_INFO,(char *)r->req_info); - if (ri == NULL) goto err; - xi=ret->cert_info; - if (sk_num(ri->attributes) != 0) + if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) { - if ((xi->version=ASN1_INTEGER_new()) == NULL) goto err; + if ((xi->version=M_ASN1_INTEGER_new()) == NULL) goto err; if (!ASN1_INTEGER_set(xi->version,2)) goto err; /* xi->extensions=ri->attributes; <- bad, should not ever be done ri->attributes=NULL; */ @@ -109,13 +99,11 @@ EVP_PKEY *pkey; if (!X509_sign(ret,pkey,EVP_md5())) goto err; - er=0; -err: - if (er) + if (0) { +err: X509_free(ret); - X509_REQ_INFO_free(ri); - return(NULL); + ret=NULL; } return(ret); } diff --git a/src/lib/libcrypto/x509/x509_req.c b/src/lib/libcrypto/x509/x509_req.c index 5004365bad..0affa3bf30 100644 --- a/src/lib/libcrypto/x509/x509_req.c +++ b/src/lib/libcrypto/x509/x509_req.c @@ -58,22 +58,20 @@ #include #include "cryptlib.h" -#include "bn.h" -#include "evp.h" -#include "asn1.h" -#include "x509.h" -#include "objects.h" -#include "buffer.h" -#include "pem.h" - -X509_REQ *X509_to_X509_REQ(x,pkey,md) -X509 *x; -EVP_PKEY *pkey; -EVP_MD *md; +#include +#include +#include +#include +#include +#include +#include + +X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { X509_REQ *ret; X509_REQ_INFO *ri; int i; + EVP_PKEY *pktmp; ret=X509_REQ_new(); if (ret == NULL) @@ -85,14 +83,16 @@ EVP_MD *md; ri=ret->req_info; ri->version->length=1; - ri->version->data=(unsigned char *)Malloc(1); + ri->version->data=(unsigned char *)OPENSSL_malloc(1); if (ri->version->data == NULL) goto err; ri->version->data[0]=0; /* version == 0 */ if (!X509_REQ_set_subject_name(ret,X509_get_subject_name(x))) goto err; - i=X509_REQ_set_pubkey(ret,X509_get_pubkey(x)); + pktmp = X509_get_pubkey(x); + i=X509_REQ_set_pubkey(ret,pktmp); + EVP_PKEY_free(pktmp); if (!i) goto err; if (pkey != NULL) @@ -106,11 +106,173 @@ err: return(NULL); } -EVP_PKEY *X509_REQ_get_pubkey(req) -X509_REQ *req; +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) { if ((req == NULL) || (req->req_info == NULL)) return(NULL); return(X509_PUBKEY_get(req->req_info->pubkey)); } +/* It seems several organisations had the same idea of including a list of + * extensions in a certificate request. There are at least two OIDs that are + * used and there may be more: so the list is configurable. + */ + +static int ext_nid_list[] = { NID_ms_ext_req, NID_ext_req, NID_undef}; + +static int *ext_nids = ext_nid_list; + +int X509_REQ_extension_nid(int req_nid) +{ + int i, nid; + for(i = 0; ; i++) { + nid = ext_nids[i]; + if(nid == NID_undef) return 0; + else if (req_nid == nid) return 1; + } +} + +int *X509_REQ_get_extension_nids(void) +{ + return ext_nids; +} + +void X509_REQ_set_extension_nids(int *nids) +{ + ext_nids = nids; +} + +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *sk; + ASN1_TYPE *ext = NULL; + int i; + unsigned char *p; + if ((req == NULL) || (req->req_info == NULL)) + return(NULL); + sk=req->req_info->attributes; + if (!sk) return NULL; + for(i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { + attr = sk_X509_ATTRIBUTE_value(sk, i); + if(X509_REQ_extension_nid(OBJ_obj2nid(attr->object))) { + if(attr->single) ext = attr->value.single; + else if(sk_ASN1_TYPE_num(attr->value.set)) + ext = sk_ASN1_TYPE_value(attr->value.set, 0); + break; + } + } + if(!ext || (ext->type != V_ASN1_SEQUENCE)) return NULL; + p = ext->value.sequence->data; + return d2i_ASN1_SET_OF_X509_EXTENSION(NULL, &p, + ext->value.sequence->length, + d2i_X509_EXTENSION, X509_EXTENSION_free, + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); +} + +/* Add a STACK_OF extensions to a certificate request: allow alternative OIDs + * in case we want to create a non standard one. + */ + +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid) +{ + unsigned char *p = NULL, *q; + long len; + ASN1_TYPE *at = NULL; + X509_ATTRIBUTE *attr = NULL; + if(!(at = ASN1_TYPE_new()) || + !(at->value.sequence = ASN1_STRING_new())) goto err; + + at->type = V_ASN1_SEQUENCE; + /* Generate encoding of extensions */ + len = i2d_ASN1_SET_OF_X509_EXTENSION(exts, NULL, i2d_X509_EXTENSION, + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, IS_SEQUENCE); + if(!(p = OPENSSL_malloc(len))) goto err; + q = p; + i2d_ASN1_SET_OF_X509_EXTENSION(exts, &q, i2d_X509_EXTENSION, + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, IS_SEQUENCE); + at->value.sequence->data = p; + p = NULL; + at->value.sequence->length = len; + if(!(attr = X509_ATTRIBUTE_new())) goto err; + if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err; + if(!sk_ASN1_TYPE_push(attr->value.set, at)) goto err; + at = NULL; + attr->single = 0; + attr->object = OBJ_nid2obj(nid); + if(!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) goto err; + return 1; + err: + if(p) OPENSSL_free(p); + X509_ATTRIBUTE_free(attr); + ASN1_TYPE_free(at); + return 0; +} +/* This is the normal usage: use the "official" OID */ +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) +{ + return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); +} + +/* Request attribute functions */ + +int X509_REQ_get_attr_count(const X509_REQ *req) +{ + return X509at_get_attr_count(req->req_info->attributes); +} + +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, + int lastpos) +{ + return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); +} + +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); +} + +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) +{ + return X509at_get_attr(req->req_info->attributes, loc); +} + +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) +{ + return X509at_delete_attr(req->req_info->attributes, loc); +} + +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) +{ + if(X509at_add1_attr(&req->req_info->attributes, attr)) return 1; + return 0; +} + +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) +{ + if(X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, + type, bytes, len)) return 1; + return 0; +} + +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len) +{ + if(X509at_add1_attr_by_NID(&req->req_info->attributes, nid, + type, bytes, len)) return 1; + return 0; +} + +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len) +{ + if(X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, + type, bytes, len)) return 1; + return 0; +} diff --git a/src/lib/libcrypto/x509/x509_set.c b/src/lib/libcrypto/x509/x509_set.c index 5d0a3a0c0e..aaf61ca062 100644 --- a/src/lib/libcrypto/x509/x509_set.c +++ b/src/lib/libcrypto/x509/x509_set.c @@ -58,27 +58,23 @@ #include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include -int X509_set_version(x,version) -X509 *x; -long version; +int X509_set_version(X509 *x, long version) { if (x == NULL) return(0); if (x->cert_info->version == NULL) { - if ((x->cert_info->version=ASN1_INTEGER_new()) == NULL) + if ((x->cert_info->version=M_ASN1_INTEGER_new()) == NULL) return(0); } return(ASN1_INTEGER_set(x->cert_info->version,version)); } -int X509_set_serialNumber(x,serial) -X509 *x; -ASN1_INTEGER *serial; +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) { ASN1_INTEGER *in; @@ -86,75 +82,65 @@ ASN1_INTEGER *serial; in=x->cert_info->serialNumber; if (in != serial) { - in=ASN1_INTEGER_dup(serial); + in=M_ASN1_INTEGER_dup(serial); if (in != NULL) { - ASN1_INTEGER_free(x->cert_info->serialNumber); + M_ASN1_INTEGER_free(x->cert_info->serialNumber); x->cert_info->serialNumber=in; } } return(in != NULL); } -int X509_set_issuer_name(x,name) -X509 *x; -X509_NAME *name; +int X509_set_issuer_name(X509 *x, X509_NAME *name) { if ((x == NULL) || (x->cert_info == NULL)) return(0); return(X509_NAME_set(&x->cert_info->issuer,name)); } -int X509_set_subject_name(x,name) -X509 *x; -X509_NAME *name; +int X509_set_subject_name(X509 *x, X509_NAME *name) { if ((x == NULL) || (x->cert_info == NULL)) return(0); return(X509_NAME_set(&x->cert_info->subject,name)); } -int X509_set_notBefore(x,tm) -X509 *x; -ASN1_UTCTIME *tm; +int X509_set_notBefore(X509 *x, ASN1_TIME *tm) { - ASN1_UTCTIME *in; + ASN1_TIME *in; if ((x == NULL) || (x->cert_info->validity == NULL)) return(0); in=x->cert_info->validity->notBefore; if (in != tm) { - in=ASN1_UTCTIME_dup(tm); + in=M_ASN1_TIME_dup(tm); if (in != NULL) { - ASN1_UTCTIME_free(x->cert_info->validity->notBefore); + M_ASN1_TIME_free(x->cert_info->validity->notBefore); x->cert_info->validity->notBefore=in; } } return(in != NULL); } -int X509_set_notAfter(x,tm) -X509 *x; -ASN1_UTCTIME *tm; +int X509_set_notAfter(X509 *x, ASN1_TIME *tm) { - ASN1_UTCTIME *in; + ASN1_TIME *in; if ((x == NULL) || (x->cert_info->validity == NULL)) return(0); in=x->cert_info->validity->notAfter; if (in != tm) { - in=ASN1_UTCTIME_dup(tm); + in=M_ASN1_TIME_dup(tm); if (in != NULL) { - ASN1_UTCTIME_free(x->cert_info->validity->notAfter); + M_ASN1_TIME_free(x->cert_info->validity->notAfter); x->cert_info->validity->notAfter=in; } } return(in != NULL); } -int X509_set_pubkey(x,pkey) -X509 *x; -EVP_PKEY *pkey; +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) { if ((x == NULL) || (x->cert_info == NULL)) return(0); return(X509_PUBKEY_set(&(x->cert_info->key),pkey)); diff --git a/src/lib/libcrypto/x509/x509_trs.c b/src/lib/libcrypto/x509/x509_trs.c index 9f7d67952d..17d69ac005 100644 --- a/src/lib/libcrypto/x509/x509_trs.c +++ b/src/lib/libcrypto/x509/x509_trs.c @@ -61,11 +61,13 @@ #include -static int tr_cmp(X509_TRUST **a, X509_TRUST **b); +static int tr_cmp(const X509_TRUST * const *a, + const X509_TRUST * const *b); static void trtable_free(X509_TRUST *p); static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); -static int trust_any(X509_TRUST *trust, X509 *x, int flags); +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags); +static int trust_compat(X509_TRUST *trust, X509 *x, int flags); static int obj_trust(int id, X509 *x, int flags); static int (*default_trust)(int id, X509 *x, int flags) = obj_trust; @@ -76,10 +78,12 @@ static int (*default_trust)(int id, X509 *x, int flags) = obj_trust; */ static X509_TRUST trstandard[] = { -{X509_TRUST_ANY, 0, trust_any, "Any", 0, NULL}, +{X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL}, {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth, NULL}, -{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Client", NID_server_auth, NULL}, +{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth, NULL}, {X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect, NULL}, +{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign, NULL}, +{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP, NULL} }; #define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST)) @@ -88,17 +92,18 @@ IMPLEMENT_STACK_OF(X509_TRUST) static STACK_OF(X509_TRUST) *trtable = NULL; -static int tr_cmp(X509_TRUST **a, X509_TRUST **b) +static int tr_cmp(const X509_TRUST * const *a, + const X509_TRUST * const *b) { return (*a)->trust - (*b)->trust; } int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int) { -int (*oldtrust)(int , X509 *, int); -oldtrust = default_trust; -default_trust = trust; -return oldtrust; + int (*oldtrust)(int , X509 *, int); + oldtrust = default_trust; + default_trust = trust; + return oldtrust; } @@ -107,8 +112,8 @@ int X509_check_trust(X509 *x, int id, int flags) X509_TRUST *pt; int idx; if(id == -1) return 1; - if(!(idx = X509_TRUST_get_by_id(id))) - return default_trust(id, x, flags); + idx = X509_TRUST_get_by_id(id); + if(idx == -1) return default_trust(id, x, flags); pt = X509_TRUST_get0(idx); return pt->check_trust(pt, x, flags); } @@ -139,6 +144,16 @@ int X509_TRUST_get_by_id(int id) return idx + X509_TRUST_COUNT; } +int X509_TRUST_set(int *t, int trust) +{ + if(X509_TRUST_get_by_id(trust) == -1) { + X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST); + return 0; + } + *t = trust; + return 1; +} + int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), char *name, int arg1, void *arg2) { @@ -152,15 +167,15 @@ int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), idx = X509_TRUST_get_by_id(id); /* Need a new entry */ if(idx == -1) { - if(!(trtmp = Malloc(sizeof(X509_TRUST)))) { + if(!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) { X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); return 0; } trtmp->flags = X509_TRUST_DYNAMIC; } else trtmp = X509_TRUST_get0(idx); - /* Free existing name if dynamic */ - if(trtmp->flags & X509_TRUST_DYNAMIC_NAME) Free(trtmp->name); + /* OPENSSL_free existing name if dynamic */ + if(trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name); /* dup supplied name */ if(!(trtmp->name = BUF_strdup(name))) { X509err(X509_F_X509_TRUST_ADD,ERR_R_MALLOC_FAILURE); @@ -196,8 +211,8 @@ static void trtable_free(X509_TRUST *p) if (p->flags & X509_TRUST_DYNAMIC) { if (p->flags & X509_TRUST_DYNAMIC_NAME) - Free(p->name); - Free(p); + OPENSSL_free(p->name); + OPENSSL_free(p); } } @@ -226,10 +241,22 @@ int X509_TRUST_get_trust(X509_TRUST *xp) static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags) { - if(x->aux) return obj_trust(trust->arg1, x, flags); + if(x->aux && (x->aux->trust || x->aux->reject)) + return obj_trust(trust->arg1, x, flags); /* we don't have any trust settings: for compatibility * we return trusted if it is self signed */ + return trust_compat(trust, x, flags); +} + +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags) +{ + if(x->aux) return obj_trust(trust->arg1, x, flags); + return X509_TRUST_UNTRUSTED; +} + +static int trust_compat(X509_TRUST *trust, X509 *x, int flags) +{ X509_check_purpose(x, -1, 0); if(x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED; else return X509_TRUST_UNTRUSTED; @@ -257,7 +284,3 @@ static int obj_trust(int id, X509 *x, int flags) return X509_TRUST_UNTRUSTED; } -static int trust_any(X509_TRUST *trust, X509 *x, int flags) -{ - return X509_TRUST_TRUSTED; -} diff --git a/src/lib/libcrypto/x509/x509_txt.c b/src/lib/libcrypto/x509/x509_txt.c index 408d1c277c..4f83db8ba2 100644 --- a/src/lib/libcrypto/x509/x509_txt.c +++ b/src/lib/libcrypto/x509/x509_txt.c @@ -59,19 +59,16 @@ #include #include #include -#include #include "cryptlib.h" -#include "lhash.h" -#include "buffer.h" -#include "evp.h" -#include "asn1.h" -#include "x509.h" -#include "objects.h" -#include "pem.h" +#include +#include +#include +#include +#include +#include -char *X509_verify_cert_error_string(n) -long n; +const char *X509_verify_cert_error_string(long n) { static char buf[100]; @@ -86,7 +83,7 @@ long n; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: return("unable to decrypt certificate's signature"); case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - return("unable to decrypt CRL's's signature"); + return("unable to decrypt CRL's signature"); case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: return("unable to decode issuer public key"); case X509_V_ERR_CERT_SIGNATURE_FAILURE: @@ -98,7 +95,7 @@ long n; case X509_V_ERR_CRL_NOT_YET_VALID: return("CRL is not yet valid"); case X509_V_ERR_CERT_HAS_EXPIRED: - return("Certificate has expired"); + return("certificate has expired"); case X509_V_ERR_CRL_HAS_EXPIRED: return("CRL has expired"); case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: @@ -121,8 +118,35 @@ long n; return("unable to verify the first certificate"); case X509_V_ERR_CERT_CHAIN_TOO_LONG: return("certificate chain too long"); + case X509_V_ERR_CERT_REVOKED: + return("certificate revoked"); + case X509_V_ERR_INVALID_CA: + return ("invalid CA certificate"); + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + return ("path length constraint exceeded"); + case X509_V_ERR_INVALID_PURPOSE: + return ("unsupported certificate purpose"); + case X509_V_ERR_CERT_UNTRUSTED: + return ("certificate not trusted"); + case X509_V_ERR_CERT_REJECTED: + return ("certificate rejected"); case X509_V_ERR_APPLICATION_VERIFICATION: return("application verification failure"); + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + return("subject issuer mismatch"); + case X509_V_ERR_AKID_SKID_MISMATCH: + return("authority and subject key identifier mismatch"); + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + return("authority and issuer serial number mismatch"); + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return("key usage does not include certificate signing"); + + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + return("unable to get CRL issuer certificate"); + + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + return("unhandled critical extension"); + default: sprintf(buf,"error number %ld",n); return(buf); diff --git a/src/lib/libcrypto/x509/x509_v3.c b/src/lib/libcrypto/x509/x509_v3.c index 1c03602f0b..b5f7daa2e5 100644 --- a/src/lib/libcrypto/x509/x509_v3.c +++ b/src/lib/libcrypto/x509/x509_v3.c @@ -57,34 +57,22 @@ */ #include -#include "stack.h" +#include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include -#ifndef NOPROTO -static X509_EXTENSION_METHOD *find_by_nid(int nid); -static int xem_cmp(X509_EXTENSION_METHOD **a, X509_EXTENSION_METHOD **b); -#else -static X509_EXTENSION_METHOD *find_by_nid(); -static int xem_cmp(); -#endif - -static STACK *extensions=NULL; - -int X509v3_get_ext_count(x) -STACK *x; +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) { if (x == NULL) return(0); - return(sk_num(x)); + return(sk_X509_EXTENSION_num(x)); } -int X509v3_get_ext_by_NID(x,nid,lastpos) -STACK *x; -int nid; -int lastpos; +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, + int lastpos) { ASN1_OBJECT *obj; @@ -93,10 +81,8 @@ int lastpos; return(X509v3_get_ext_by_OBJ(x,obj,lastpos)); } -int X509v3_get_ext_by_OBJ(sk,obj,lastpos) -STACK *sk; -ASN1_OBJECT *obj; -int lastpos; +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, ASN1_OBJECT *obj, + int lastpos) { int n; X509_EXTENSION *ex; @@ -105,20 +91,18 @@ int lastpos; lastpos++; if (lastpos < 0) lastpos=0; - n=sk_num(sk); + n=sk_X509_EXTENSION_num(sk); for ( ; lastpos < n; lastpos++) { - ex=(X509_EXTENSION *)sk_value(sk,lastpos); + ex=sk_X509_EXTENSION_value(sk,lastpos); if (OBJ_cmp(ex->object,obj) == 0) return(lastpos); } return(-1); } -int X509v3_get_ext_by_critical(sk,crit,lastpos) -STACK *sk; -int crit; -int lastpos; +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, + int lastpos) { int n; X509_EXTENSION *ex; @@ -127,63 +111,57 @@ int lastpos; lastpos++; if (lastpos < 0) lastpos=0; - n=sk_num(sk); + n=sk_X509_EXTENSION_num(sk); for ( ; lastpos < n; lastpos++) { - ex=(X509_EXTENSION *)sk_value(sk,lastpos); - if ( (ex->critical && crit) || - (!ex->critical && !crit)) + ex=sk_X509_EXTENSION_value(sk,lastpos); + if ( ((ex->critical > 0) && crit) || + (!(ex->critical <= 0) && !crit)) return(lastpos); } return(-1); } -X509_EXTENSION *X509v3_get_ext(x,loc) -STACK *x; -int loc; +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) { - if ((x == NULL) || (sk_num(x) <= loc) || (loc < 0)) - return(NULL); + if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) + return NULL; else - return((X509_EXTENSION *)sk_value(x,loc)); + return sk_X509_EXTENSION_value(x,loc); } -X509_EXTENSION *X509v3_delete_ext(x,loc) -STACK *x; -int loc; +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) { X509_EXTENSION *ret; - if ((x == NULL) || (sk_num(x) <= loc) || (loc < 0)) + if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) return(NULL); - ret=(X509_EXTENSION *)sk_delete(x,loc); + ret=sk_X509_EXTENSION_delete(x,loc); return(ret); } -STACK *X509v3_add_ext(x,ex,loc) -STACK **x; -X509_EXTENSION *ex; -int loc; +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc) { X509_EXTENSION *new_ex=NULL; int n; - STACK *sk=NULL; + STACK_OF(X509_EXTENSION) *sk=NULL; if ((x != NULL) && (*x == NULL)) { - if ((sk=sk_new_null()) == NULL) + if ((sk=sk_X509_EXTENSION_new_null()) == NULL) goto err; } else sk= *x; - n=sk_num(sk); + n=sk_X509_EXTENSION_num(sk); if (loc > n) loc=n; else if (loc < 0) loc=n; if ((new_ex=X509_EXTENSION_dup(ex)) == NULL) goto err2; - if (!sk_insert(sk,(char *)new_ex,loc)) + if (!sk_X509_EXTENSION_insert(sk,new_ex,loc)) goto err; if ((x != NULL) && (*x == NULL)) *x=sk; @@ -192,15 +170,12 @@ err: X509err(X509_F_X509V3_ADD_EXT,ERR_R_MALLOC_FAILURE); err2: if (new_ex != NULL) X509_EXTENSION_free(new_ex); - if (sk != NULL) sk_free(sk); + if (sk != NULL) sk_X509_EXTENSION_free(sk); return(NULL); } -X509_EXTENSION *X509_EXTENSION_create_by_NID(ex,nid,crit,data) -X509_EXTENSION **ex; -int nid; -int crit; -ASN1_OCTET_STRING *data; +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, + int crit, ASN1_OCTET_STRING *data) { ASN1_OBJECT *obj; X509_EXTENSION *ret; @@ -216,11 +191,8 @@ ASN1_OCTET_STRING *data; return(ret); } -X509_EXTENSION *X509_EXTENSION_create_by_OBJ(ex,obj,crit,data) -X509_EXTENSION **ex; -ASN1_OBJECT *obj; -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) { X509_EXTENSION *ret; @@ -250,9 +222,7 @@ err: return(NULL); } -int X509_EXTENSION_set_object(ex,obj) -X509_EXTENSION *ex; -ASN1_OBJECT *obj; +int X509_EXTENSION_set_object(X509_EXTENSION *ex, ASN1_OBJECT *obj) { if ((ex == NULL) || (obj == NULL)) return(0); @@ -261,149 +231,38 @@ ASN1_OBJECT *obj; return(1); } -int X509_EXTENSION_set_critical(ex,crit) -X509_EXTENSION *ex; -int crit; +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) { if (ex == NULL) return(0); - ex->critical=(crit)?0xFF:0; + ex->critical=(crit)?0xFF:-1; return(1); } -int X509_EXTENSION_set_data(ex,data) -X509_EXTENSION *ex; -ASN1_OCTET_STRING *data; +int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data) { int i; if (ex == NULL) return(0); - i=ASN1_OCTET_STRING_set(ex->value,data->data,data->length); + i=M_ASN1_OCTET_STRING_set(ex->value,data->data,data->length); if (!i) return(0); return(1); } -ASN1_OBJECT *X509_EXTENSION_get_object(ex) -X509_EXTENSION *ex; +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) { if (ex == NULL) return(NULL); return(ex->object); } -ASN1_OCTET_STRING *X509_EXTENSION_get_data(ex) -X509_EXTENSION *ex; +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) { if (ex == NULL) return(NULL); return(ex->value); } -int X509_EXTENSION_get_critical(ex) -X509_EXTENSION *ex; +int X509_EXTENSION_get_critical(X509_EXTENSION *ex) { if (ex == NULL) return(0); - return(ex->critical); - } - -int X509v3_data_type_by_OBJ(obj) -ASN1_OBJECT *obj; - { - int nid; - - nid=OBJ_obj2nid(obj); - if (nid == V_ASN1_UNDEF) return(V_ASN1_UNDEF); - return(X509v3_data_type_by_NID(nid)); - } - -int X509v3_data_type_by_NID(nid) -int nid; - { - X509_EXTENSION_METHOD *x; - - x=find_by_nid(nid); - if (x == NULL) - return(V_ASN1_UNDEF); - else - return(x->data_type); - } - -int X509v3_pack_type_by_OBJ(obj) -ASN1_OBJECT *obj; - { - int nid; - - nid=OBJ_obj2nid(obj); - if (nid == NID_undef) return(X509_EXT_PACK_UNKNOWN); - return(X509v3_pack_type_by_NID(nid)); - } - -int X509v3_pack_type_by_NID(nid) -int nid; - { - X509_EXTENSION_METHOD *x; - - x=find_by_nid(nid); - if (x == NULL) - return(X509_EXT_PACK_UNKNOWN); - else - return(x->pack_type); - } - -static X509_EXTENSION_METHOD *find_by_nid(nid) -int nid; - { - X509_EXTENSION_METHOD x; - int i; - - x.nid=nid; - if (extensions == NULL) return(NULL); - i=sk_find(extensions,(char *)&x); - if (i < 0) - return(NULL); - else - return((X509_EXTENSION_METHOD *)sk_value(extensions,i)); - } - -static int xem_cmp(a,b) -X509_EXTENSION_METHOD **a,**b; - { - return((*a)->nid-(*b)->nid); - } - -void X509v3_cleanup_extensions() - { - int i; - - if (extensions != NULL) - { - for (i=0; icritical > 0) return 1; + return 0; } - -int X509v3_add_extension(x) -X509_EXTENSION_METHOD *x; - { - X509_EXTENSION_METHOD *newx; - - if (extensions == NULL) - { - extensions=sk_new(xem_cmp); - if (extensions == NULL) goto err; - } - newx=(X509_EXTENSION_METHOD *)Malloc(sizeof(X509_EXTENSION_METHOD)); - if (newx == NULL) goto err; - newx->nid=x->nid; - newx->data_type=x->data_type; - newx->pack_type=x->pack_type; - if (!sk_push(extensions,(char *)newx)) - { - Free(newx); - goto err; - } - return(1); -err: - X509err(X509_F_X509V3_ADD_EXTENSION,ERR_R_MALLOC_FAILURE); - return(0); - } - diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index c1be91edba..db12f7bd35 100644 --- a/src/lib/libcrypto/x509/x509_vfy.c +++ b/src/lib/libcrypto/x509/x509_vfy.c @@ -59,76 +59,63 @@ #include #include #include -#include -#include -#include "crypto.h" #include "cryptlib.h" -#include "lhash.h" -#include "buffer.h" -#include "evp.h" -#include "asn1.h" -#include "x509.h" -#include "objects.h" -#include "pem.h" - -#ifndef NOPROTO +#include +#include +#include +#include +#include +#include +#include +#include + static int null_callback(int ok,X509_STORE_CTX *e); +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); +static int check_chain_purpose(X509_STORE_CTX *ctx); +static int check_trust(X509_STORE_CTX *ctx); +static int check_revocation(X509_STORE_CTX *ctx); +static int check_cert(X509_STORE_CTX *ctx); static int internal_verify(X509_STORE_CTX *ctx); -#else -static int null_callback(); -static int internal_verify(); -#endif +const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; -char *X509_version="X509 part of SSLeay 0.9.0b 29-Jun-1998"; -static STACK *x509_store_ctx_method=NULL; -static int x509_store_ctx_num=0; -#if 0 -static int x509_store_num=1; -static STACK *x509_store_method=NULL; -#endif -static int null_callback(ok,e) -int ok; -X509_STORE_CTX *e; +static int null_callback(int ok, X509_STORE_CTX *e) { - return(ok); + return ok; } #if 0 -static int x509_subject_cmp(a,b) -X509 **a,**b; +static int x509_subject_cmp(X509 **a, X509 **b) { - return(X509_subject_name_cmp(*a,*b)); + return X509_subject_name_cmp(*a,*b); } #endif -int X509_verify_cert(ctx) -X509_STORE_CTX *ctx; +int X509_verify_cert(X509_STORE_CTX *ctx) { X509 *x,*xtmp,*chain_ss=NULL; X509_NAME *xn; - X509_OBJECT obj; int depth,i,ok=0; int num; int (*cb)(); - STACK *sktmp=NULL; + STACK_OF(X509) *sktmp=NULL; if (ctx->cert == NULL) { X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); - return(-1); + return -1; } - cb=ctx->ctx->verify_cb; - if (cb == NULL) cb=null_callback; + cb=ctx->verify_cb; /* first we make sure the chain we are going to build is * present and that the first entry is in place */ if (ctx->chain == NULL) { - if ( ((ctx->chain=sk_new_null()) == NULL) || - (!sk_push(ctx->chain,(char *)ctx->cert))) + if ( ((ctx->chain=sk_X509_new_null()) == NULL) || + (!sk_X509_push(ctx->chain,ctx->cert))) { X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); goto end; @@ -137,41 +124,45 @@ X509_STORE_CTX *ctx; ctx->last_untrusted=1; } - /* We use a temporary so we can chop and hack at it */ - if ((ctx->untrusted != NULL) && (sktmp=sk_dup(ctx->untrusted)) == NULL) + /* We use a temporary STACK so we can chop and hack at it */ + if (ctx->untrusted != NULL + && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) { X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); goto end; } - num=sk_num(ctx->chain); - x=(X509 *)sk_value(ctx->chain,num-1); + num=sk_X509_num(ctx->chain); + x=sk_X509_value(ctx->chain,num-1); depth=ctx->depth; for (;;) { /* If we have enough, we break */ - if (depth <= num) break; + if (depth < num) break; /* FIXME: If this happens, we should take + * note of it and, if appropriate, use the + * X509_V_ERR_CERT_CHAIN_TOO_LONG error + * code later. + */ /* If we are self signed, we break */ xn=X509_get_issuer_name(x); - if (X509_NAME_cmp(X509_get_subject_name(x),xn) == 0) - break; + if (ctx->check_issued(ctx, x,x)) break; /* If we were passed a cert chain, use it first */ if (ctx->untrusted != NULL) { - xtmp=X509_find_by_subject(sktmp,xn); + xtmp=find_issuer(ctx, sktmp,x); if (xtmp != NULL) { - if (!sk_push(ctx->chain,(char *)xtmp)) + if (!sk_X509_push(ctx->chain,xtmp)) { X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); goto end; } CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509); - sk_delete_ptr(sktmp,(char *)xtmp); + sk_X509_delete_ptr(sktmp,xtmp); ctx->last_untrusted++; x=xtmp; num++; @@ -187,27 +178,50 @@ X509_STORE_CTX *ctx; * certificates. We now need to add at least one trusted one, * if possible, otherwise we complain. */ - i=sk_num(ctx->chain); - x=(X509 *)sk_value(ctx->chain,i-1); - if (X509_NAME_cmp(X509_get_subject_name(x),X509_get_issuer_name(x)) - == 0) + /* Examine last certificate in chain and see if it + * is self signed. + */ + + i=sk_X509_num(ctx->chain); + x=sk_X509_value(ctx->chain,i-1); + xn = X509_get_subject_name(x); + if (ctx->check_issued(ctx, x, x)) { /* we have a self signed certificate */ - if (sk_num(ctx->chain) == 1) + if (sk_X509_num(ctx->chain) == 1) { - ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert=x; - ctx->error_depth=i-1; - ok=cb(0,ctx); - if (!ok) goto end; + /* We have a single self signed certificate: see if + * we can find it in the store. We must have an exact + * match to avoid possible impersonation. + */ + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) + { + ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert=x; + ctx->error_depth=i-1; + if (ok == 1) X509_free(xtmp); + ok=cb(0,ctx); + if (!ok) goto end; + } + else + { + /* We have a match: replace certificate with store version + * so we get any trust settings. + */ + X509_free(x); + x = xtmp; + sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted=0; + } } else { - /* worry more about this one elsewhere */ - chain_ss=(X509 *)sk_pop(ctx->chain); + /* extract and save self signed certificate for later use */ + chain_ss=sk_X509_pop(ctx->chain); ctx->last_untrusted--; num--; - x=(X509 *)sk_value(ctx->chain,num-1); + x=sk_X509_value(ctx->chain,num-1); } } @@ -215,45 +229,34 @@ X509_STORE_CTX *ctx; for (;;) { /* If we have enough, we break */ - if (depth <= num) break; + if (depth < num) break; /* If we are self signed, we break */ xn=X509_get_issuer_name(x); - if (X509_NAME_cmp(X509_get_subject_name(x),xn) == 0) - break; + if (ctx->check_issued(ctx,x,x)) break; - ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj); - if (ok != X509_LU_X509) - { - if (ok == X509_LU_RETRY) - { - X509_OBJECT_free_contents(&obj); - X509err(X509_F_X509_VERIFY_CERT,X509_R_SHOULD_RETRY); - return(ok); - } - else if (ok != X509_LU_FAIL) - { - X509_OBJECT_free_contents(&obj); - /* not good :-(, break anyway */ - return(ok); - } - break; - } - x=obj.data.x509; - if (!sk_push(ctx->chain,(char *)obj.data.x509)) + ok = ctx->get_issuer(&xtmp, ctx, x); + + if (ok < 0) return ok; + if (ok == 0) break; + + x = xtmp; + if (!sk_X509_push(ctx->chain,x)) { - X509_OBJECT_free_contents(&obj); + X509_free(xtmp); X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE); - return(0); + return 0; } num++; } /* we now have our chain, lets check it... */ xn=X509_get_issuer_name(x); - if (X509_NAME_cmp(X509_get_subject_name(x),xn) != 0) + + /* Is last certificate looked up self signed? */ + if (!ctx->check_issued(ctx,x,x)) { - if ((chain_ss == NULL) || (X509_NAME_cmp(X509_get_subject_name(chain_ss),xn) != 0)) + if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { if (ctx->last_untrusted >= num) ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; @@ -264,7 +267,7 @@ X509_STORE_CTX *ctx; else { - sk_push(ctx->chain,(char *)chain_ss); + sk_X509_push(ctx->chain,chain_ss); num++; ctx->last_untrusted=num; ctx->current_cert=chain_ss; @@ -277,37 +280,369 @@ X509_STORE_CTX *ctx; if (!ok) goto end; } + /* We have the chain complete: now we need to check its purpose */ + if (ctx->purpose > 0) ok = check_chain_purpose(ctx); + + if (!ok) goto end; + + /* The chain extensions are OK: check trust */ + + if (ctx->trust > 0) ok = check_trust(ctx); + + if (!ok) goto end; + /* We may as well copy down any DSA parameters that are required */ X509_get_pubkey_parameters(NULL,ctx->chain); + /* Check revocation status: we do this after copying parameters + * because they may be needed for CRL signature verification. + */ + + ok = ctx->check_revocation(ctx); + if(!ok) goto end; + /* At this point, we have a chain and just need to verify it */ - if (ctx->ctx->verify != NULL) - ok=ctx->ctx->verify(ctx); + if (ctx->verify != NULL) + ok=ctx->verify(ctx); else ok=internal_verify(ctx); + if (0) + { end: - if (sktmp != NULL) sk_free(sktmp); + X509_get_pubkey_parameters(NULL,ctx->chain); + } + if (sktmp != NULL) sk_X509_free(sktmp); if (chain_ss != NULL) X509_free(chain_ss); - return(ok); + return ok; + } + + +/* Given a STACK_OF(X509) find the issuer of cert (if any) + */ + +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) +{ + int i; + X509 *issuer; + for (i = 0; i < sk_X509_num(sk); i++) + { + issuer = sk_X509_value(sk, i); + if (ctx->check_issued(ctx, x, issuer)) + return issuer; + } + return NULL; +} + +/* Given a possible certificate and issuer check them */ + +static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) +{ + int ret; + ret = X509_check_issued(issuer, x); + if (ret == X509_V_OK) + return 1; + /* If we haven't asked for issuer errors don't set ctx */ + if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK)) + return 0; + + ctx->error = ret; + ctx->current_cert = x; + ctx->current_issuer = issuer; + return ctx->verify_cb(0, ctx); + return 0; +} + +/* Alternative lookup method: look from a STACK stored in other_ctx */ + +static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + *issuer = find_issuer(ctx, ctx->other_ctx, x); + if (*issuer) + { + CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509); + return 1; + } + else + return 0; +} + + +/* Check a certificate chains extensions for consistency + * with the supplied purpose + */ + +static int check_chain_purpose(X509_STORE_CTX *ctx) +{ +#ifdef OPENSSL_NO_CHAIN_VERIFY + return 1; +#else + int i, ok=0; + X509 *x; + int (*cb)(); + cb=ctx->verify_cb; + /* Check all untrusted certificates */ + for (i = 0; i < ctx->last_untrusted; i++) + { + x = sk_X509_value(ctx->chain, i); + if (!(ctx->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (x->ex_flags & EXFLAG_CRITICAL)) + { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; + ctx->error_depth = i; + ctx->current_cert = x; + ok=cb(0,ctx); + if (!ok) goto end; + } + if (!X509_check_purpose(x, ctx->purpose, i)) + { + if (i) + ctx->error = X509_V_ERR_INVALID_CA; + else + ctx->error = X509_V_ERR_INVALID_PURPOSE; + ctx->error_depth = i; + ctx->current_cert = x; + ok=cb(0,ctx); + if (!ok) goto end; + } + /* Check pathlen */ + if ((i > 1) && (x->ex_pathlen != -1) + && (i > (x->ex_pathlen + 1))) + { + ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; + ctx->error_depth = i; + ctx->current_cert = x; + ok=cb(0,ctx); + if (!ok) goto end; + } + } + ok = 1; + end: + return ok; +#endif +} + +static int check_trust(X509_STORE_CTX *ctx) +{ +#ifdef OPENSSL_NO_CHAIN_VERIFY + return 1; +#else + int i, ok; + X509 *x; + int (*cb)(); + cb=ctx->verify_cb; +/* For now just check the last certificate in the chain */ + i = sk_X509_num(ctx->chain) - 1; + x = sk_X509_value(ctx->chain, i); + ok = X509_check_trust(x, ctx->trust, 0); + if (ok == X509_TRUST_TRUSTED) + return 1; + ctx->error_depth = i; + ctx->current_cert = x; + if (ok == X509_TRUST_REJECTED) + ctx->error = X509_V_ERR_CERT_REJECTED; + else + ctx->error = X509_V_ERR_CERT_UNTRUSTED; + ok = cb(0, ctx); + return ok; +#endif +} + +static int check_revocation(X509_STORE_CTX *ctx) + { + int i, last, ok; + if (!(ctx->flags & X509_V_FLAG_CRL_CHECK)) + return 1; + if (ctx->flags & X509_V_FLAG_CRL_CHECK_ALL) + last = 0; + else + last = sk_X509_num(ctx->chain) - 1; + for(i = 0; i <= last; i++) + { + ctx->error_depth = i; + ok = check_cert(ctx); + if (!ok) return ok; + } + return 1; + } + +static int check_cert(X509_STORE_CTX *ctx) + { + X509_CRL *crl = NULL; + X509 *x; + int ok, cnum; + cnum = ctx->error_depth; + x = sk_X509_value(ctx->chain, cnum); + ctx->current_cert = x; + /* Try to retrieve relevant CRL */ + ok = ctx->get_crl(ctx, &crl, x); + /* If error looking up CRL, nothing we can do except + * notify callback + */ + if(!ok) + { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + ctx->current_crl = crl; + ok = ctx->check_crl(ctx, crl); + if (!ok) goto err; + ok = ctx->cert_crl(ctx, crl, x); + err: + ctx->current_crl = NULL; + X509_CRL_free(crl); + return ok; + + } + +/* Retrieve CRL corresponding to certificate: currently just a + * subject lookup: maybe use AKID later... + * Also might look up any included CRLs too (e.g PKCS#7 signedData). + */ +static int get_crl(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x) + { + int ok; + X509_OBJECT xobj; + ok = X509_STORE_get_by_subject(ctx, X509_LU_CRL, X509_get_issuer_name(x), &xobj); + if (!ok) return 0; + *crl = xobj.data.crl; + return 1; + } + +/* Check CRL validity */ +static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) + { + X509 *issuer = NULL; + EVP_PKEY *ikey = NULL; + int ok = 0, chnum, cnum, i; + time_t *ptime; + cnum = ctx->error_depth; + chnum = sk_X509_num(ctx->chain) - 1; + /* Find CRL issuer: if not last certificate then issuer + * is next certificate in chain. + */ + if(cnum < chnum) + issuer = sk_X509_value(ctx->chain, cnum + 1); + else + { + issuer = sk_X509_value(ctx->chain, chnum); + /* If not self signed, can't check signature */ + if(!ctx->check_issued(ctx, issuer, issuer)) + { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; + ok = ctx->verify_cb(0, ctx); + if(!ok) goto err; + } + } + + if(issuer) + { + + /* Attempt to get issuer certificate public key */ + ikey = X509_get_pubkey(issuer); + + if(!ikey) + { + ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ok = ctx->verify_cb(0, ctx); + if (!ok) goto err; + } + else + { + /* Verify CRL signature */ + if(X509_CRL_verify(crl, ikey) <= 0) + { + ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE; + ok = ctx->verify_cb(0, ctx); + if (!ok) goto err; + } + } + } + + /* OK, CRL signature valid check times */ + if (ctx->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->check_time; + else + ptime = NULL; + + i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); + if (i == 0) + { + ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; + ok = ctx->verify_cb(0, ctx); + if (!ok) goto err; + } + + if (i > 0) + { + ctx->error=X509_V_ERR_CRL_NOT_YET_VALID; + ok = ctx->verify_cb(0, ctx); + if (!ok) goto err; + } + + if(X509_CRL_get_nextUpdate(crl)) + { + i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime); + + if (i == 0) + { + ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; + ok = ctx->verify_cb(0, ctx); + if (!ok) goto err; + } + + if (i < 0) + { + ctx->error=X509_V_ERR_CRL_HAS_EXPIRED; + ok = ctx->verify_cb(0, ctx); + if (!ok) goto err; + } + } + + ok = 1; + + err: + EVP_PKEY_free(ikey); + return ok; + } + +/* Check certificate against CRL */ +static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) + { + int idx, ok; + X509_REVOKED rtmp; + /* Look for serial number of certificate in CRL */ + rtmp.serialNumber = X509_get_serialNumber(x); + idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp); + /* Not found: OK */ + if(idx == -1) return 1; + /* Otherwise revoked: want something cleverer than + * this to handle entry extensions in V2 CRLs. + */ + ctx->error = X509_V_ERR_CERT_REVOKED; + ok = ctx->verify_cb(0, ctx); + return ok; } -static int internal_verify(ctx) -X509_STORE_CTX *ctx; +static int internal_verify(X509_STORE_CTX *ctx) { int i,ok=0,n; X509 *xs,*xi; EVP_PKEY *pkey=NULL; + time_t *ptime; int (*cb)(); - cb=ctx->ctx->verify_cb; - if (cb == NULL) cb=null_callback; + cb=ctx->verify_cb; - n=sk_num(ctx->chain); + n=sk_X509_num(ctx->chain); ctx->error_depth=n-1; n--; - xi=(X509 *)sk_value(ctx->chain,n); - if (X509_NAME_cmp(X509_get_subject_name(xi), - X509_get_issuer_name(xi)) == 0) + xi=sk_X509_value(ctx->chain,n); + if (ctx->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->check_time; + else + ptime = NULL; + if (ctx->check_issued(ctx, xi, xi)) xs=xi; else { @@ -322,7 +657,7 @@ X509_STORE_CTX *ctx; { n--; ctx->error_depth=n; - xs=(X509 *)sk_value(ctx->chain,n); + xs=sk_X509_value(ctx->chain,n); } } @@ -340,15 +675,27 @@ X509_STORE_CTX *ctx; if (!ok) goto end; } if (X509_verify(xs,pkey) <= 0) + /* XXX For the final trusted self-signed cert, + * this is a waste of time. That check should + * optional so that e.g. 'openssl x509' can be + * used to detect invalid self-signatures, but + * we don't verify again and again in SSL + * handshakes and the like once the cert has + * been declared trusted. */ { ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE; ctx->current_cert=xs; ok=(*cb)(0,ctx); - if (!ok) goto end; + if (!ok) + { + EVP_PKEY_free(pkey); + goto end; + } } + EVP_PKEY_free(pkey); pkey=NULL; - i=X509_cmp_current_time(X509_get_notBefore(xs)); + i=X509_cmp_time(X509_get_notBefore(xs), ptime); if (i == 0) { ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; @@ -366,7 +713,7 @@ X509_STORE_CTX *ctx; xs->valid=1; } - i=X509_cmp_current_time(X509_get_notAfter(xs)); + i=X509_cmp_time(X509_get_notAfter(xs), ptime); if (i == 0) { ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; @@ -383,8 +730,6 @@ X509_STORE_CTX *ctx; if (!ok) goto end; } - /* CRL CHECK */ - /* The last error (if any) is still in the error value */ ctx->current_cert=xs; ok=(*cb)(1,ctx); @@ -394,19 +739,23 @@ X509_STORE_CTX *ctx; if (n >= 0) { xi=xs; - xs=(X509 *)sk_value(ctx->chain,n); + xs=sk_X509_value(ctx->chain,n); } } ok=1; end: - return(ok); + return ok; } -int X509_cmp_current_time(ctm) -ASN1_UTCTIME *ctm; +int X509_cmp_current_time(ASN1_TIME *ctm) +{ + return X509_cmp_time(ctm, NULL); +} + +int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time) { char *str; - ASN1_UTCTIME atm; + ASN1_TIME atm; time_t offset; char buff1[24],buff2[24],*p; int i,j; @@ -414,14 +763,35 @@ ASN1_UTCTIME *ctm; p=buff1; i=ctm->length; str=(char *)ctm->data; - if ((i < 11) || (i > 17)) return(0); - memcpy(p,str,10); - p+=10; - str+=10; + if (ctm->type == V_ASN1_UTCTIME) + { + if ((i < 11) || (i > 17)) return 0; + memcpy(p,str,10); + p+=10; + str+=10; + } + else + { + if (i < 13) return 0; + memcpy(p,str,12); + p+=12; + str+=12; + } if ((*str == 'Z') || (*str == '-') || (*str == '+')) { *(p++)='0'; *(p++)='0'; } - else { *(p++)= *(str++); *(p++)= *(str++); } + else + { + *(p++)= *(str++); + *(p++)= *(str++); + /* Skip any fractional seconds... */ + if (*str == '.') + { + str++; + while ((*str >= '0') && (*str <= '9')) str++; + } + + } *(p++)='Z'; *(p++)='\0'; @@ -430,275 +800,388 @@ ASN1_UTCTIME *ctm; else { if ((*str != '+') && (str[5] != '-')) - return(0); + return 0; offset=((str[1]-'0')*10+(str[2]-'0'))*60; offset+=(str[3]-'0')*10+(str[4]-'0'); if (*str == '-') - offset=-offset; + offset= -offset; } - atm.type=V_ASN1_UTCTIME; + atm.type=ctm->type; atm.length=sizeof(buff2); atm.data=(unsigned char *)buff2; - X509_gmtime_adj(&atm,-offset); + X509_time_adj(&atm,-offset*60, cmp_time); - i=(buff1[0]-'0')*10+(buff1[1]-'0'); - if (i < 70) i+=100; - j=(buff2[0]-'0')*10+(buff2[1]-'0'); - if (j < 70) j+=100; + if (ctm->type == V_ASN1_UTCTIME) + { + i=(buff1[0]-'0')*10+(buff1[1]-'0'); + if (i < 50) i+=100; /* cf. RFC 2459 */ + j=(buff2[0]-'0')*10+(buff2[1]-'0'); + if (j < 50) j+=100; - if (i < j) return (-1); - if (i > j) return (1); + if (i < j) return -1; + if (i > j) return 1; + } i=strcmp(buff1,buff2); if (i == 0) /* wait a second then return younger :-) */ - return(-1); + return -1; else - return(i); + return i; } -ASN1_UTCTIME *X509_gmtime_adj(s, adj) -ASN1_UTCTIME *s; -long adj; +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) +{ + return X509_time_adj(s, adj, NULL); +} + +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm) { time_t t; + int type = -1; + + if (in_tm) t = *in_tm; + else time(&t); - time(&t); t+=adj; - return(ASN1_UTCTIME_set(s,t)); + if (s) type = s->type; + if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t); + if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t); + return ASN1_TIME_set(s, t); } -int X509_get_pubkey_parameters(pkey,chain) -EVP_PKEY *pkey; -STACK *chain; +int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) { EVP_PKEY *ktmp=NULL,*ktmp2; int i,j; - if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return(1); + if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1; - for (i=0; i= 0; j--) { - ktmp2=X509_get_pubkey((X509 *)sk_value(chain,j)); + ktmp2=X509_get_pubkey(sk_X509_value(chain,j)); EVP_PKEY_copy_parameters(ktmp2,ktmp); + EVP_PKEY_free(ktmp2); } - if (pkey != NULL) - EVP_PKEY_copy_parameters(pkey,ktmp); - return(1); + if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp); + EVP_PKEY_free(ktmp); + return 1; } -EVP_PKEY *X509_get_pubkey(x) -X509 *x; +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) { - if ((x == NULL) || (x->cert_info == NULL)) - return(NULL); - return(X509_PUBKEY_get(x->cert_info->key)); + /* This function is (usually) called only once, by + * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */ + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp, + new_func, dup_func, free_func); } -int X509_check_private_key(x,k) -X509 *x; -EVP_PKEY *k; +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) { - EVP_PKEY *xk=NULL; - int ok=0; - - xk=X509_get_pubkey(x); - if (xk->type != k->type) goto err; - switch (k->type) - { -#ifndef NO_RSA - case EVP_PKEY_RSA: - if (BN_cmp(xk->pkey.rsa->n,k->pkey.rsa->n) != 0) goto err; - if (BN_cmp(xk->pkey.rsa->e,k->pkey.rsa->e) != 0) goto err; - break; -#endif -#ifndef NO_DSA - case EVP_PKEY_DSA: - if (BN_cmp(xk->pkey.dsa->pub_key,k->pkey.dsa->pub_key) != 0) - goto err; - break; -#endif -#ifndef NO_DH - case EVP_PKEY_DH: - /* No idea */ - goto err; -#endif - default: - goto err; - } - - ok=1; -err: - return(ok); + return CRYPTO_set_ex_data(&ctx->ex_data,idx,data); } -int X509_STORE_add_cert(ctx,x) -X509_STORE *ctx; -X509 *x; +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) { - X509_OBJECT *obj,*r; - int ret=1; - - if (x == NULL) return(0); - obj=(X509_OBJECT *)Malloc(sizeof(X509_OBJECT)); - if (obj == NULL) - { - X509err(X509_F_X509_STORE_ADD_CERT,ERR_R_MALLOC_FAILURE); - return(0); - } - obj->type=X509_LU_X509; - obj->data.x509=x; - - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + return CRYPTO_get_ex_data(&ctx->ex_data,idx); + } - X509_OBJECT_up_ref_count(obj); +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) + { + return ctx->error; + } - r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj); - if (r != NULL) - { /* oops, put it back */ - lh_delete(ctx->certs,(char *)obj); - X509_OBJECT_free_contents(obj); - Free(obj); - lh_insert(ctx->certs,(char *)r); - X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE); - ret=0; - } +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) + { + ctx->error=err; + } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) + { + return ctx->error_depth; + } - return(ret); +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) + { + return ctx->current_cert; } -int X509_STORE_add_crl(ctx,x) -X509_STORE *ctx; -X509_CRL *x; +STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) { - X509_OBJECT *obj,*r; - int ret=1; + return ctx->chain; + } - if (x == NULL) return(0); - obj=(X509_OBJECT *)Malloc(sizeof(X509_OBJECT)); - if (obj == NULL) +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) + { + int i; + X509 *x; + STACK_OF(X509) *chain; + if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL; + for (i = 0; i < sk_X509_num(chain); i++) { - X509err(X509_F_X509_STORE_ADD_CRL,ERR_R_MALLOC_FAILURE); - return(0); + x = sk_X509_value(chain, i); + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); } - obj->type=X509_LU_CRL; - obj->data.crl=x; - - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - - X509_OBJECT_up_ref_count(obj); - - r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj); - if (r != NULL) - { /* oops, put it back */ - lh_delete(ctx->certs,(char *)obj); - X509_OBJECT_free_contents(obj); - Free(obj); - lh_insert(ctx->certs,(char *)r); - X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE); - ret=0; - } - - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - - return(ret); + return chain; } -int X509_STORE_CTX_get_ex_new_index(argl,argp,new_func,dup_func,free_func) -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*free_func)(); - { - x509_store_ctx_num++; - return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1, - &x509_store_ctx_method, - argl,argp,new_func,dup_func,free_func)); - } - -int X509_STORE_CTX_set_ex_data(ctx,idx,data) -X509_STORE_CTX *ctx; -int idx; -char *data; +void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) { - return(CRYPTO_set_ex_data(&ctx->ex_data,idx,data)); + ctx->cert=x; } -char *X509_STORE_CTX_get_ex_data(ctx,idx) -X509_STORE_CTX *ctx; -int idx; +void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) { - return(CRYPTO_get_ex_data(&ctx->ex_data,idx)); + ctx->untrusted=sk; } -int X509_STORE_CTX_get_error(ctx) -X509_STORE_CTX *ctx; +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) { - return(ctx->error); + return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); } -void X509_STORE_CTX_set_error(ctx,err) -X509_STORE_CTX *ctx; -int err; +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) { - ctx->error=err; + return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); } -int X509_STORE_CTX_get_error_depth(ctx) -X509_STORE_CTX *ctx; +/* This function is used to set the X509_STORE_CTX purpose and trust + * values. This is intended to be used when another structure has its + * own trust and purpose values which (if set) will be inherited by + * the ctx. If they aren't set then we will usually have a default + * purpose in mind which should then be used to set the trust value. + * An example of this is SSL use: an SSL structure will have its own + * purpose and trust settings which the application can set: if they + * aren't set then we use the default of SSL client/server. + */ + +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust) +{ + int idx; + /* If purpose not set use default */ + if (!purpose) purpose = def_purpose; + /* If we have a purpose then check it is valid */ + if (purpose) + { + X509_PURPOSE *ptmp; + idx = X509_PURPOSE_get_by_id(purpose); + if (idx == -1) + { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + if (ptmp->trust == X509_TRUST_DEFAULT) + { + idx = X509_PURPOSE_get_by_id(def_purpose); + if (idx == -1) + { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + } + /* If trust not set then get from purpose default */ + if (!trust) trust = ptmp->trust; + } + if (trust) + { + idx = X509_TRUST_get_by_id(trust); + if (idx == -1) + { + X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, + X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if (purpose && !ctx->purpose) ctx->purpose = purpose; + if (trust && !ctx->trust) ctx->trust = trust; + return 1; +} + +X509_STORE_CTX *X509_STORE_CTX_new(void) +{ + X509_STORE_CTX *ctx; + ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); + if (!ctx) + { + X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ctx, 0, sizeof(X509_STORE_CTX)); + return ctx; +} + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx) +{ + X509_STORE_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, + STACK_OF(X509) *chain) { - return(ctx->error_depth); + ctx->ctx=store; + ctx->current_method=0; + ctx->cert=x509; + ctx->untrusted=chain; + ctx->last_untrusted=0; + ctx->check_time=0; + ctx->other_ctx=NULL; + ctx->valid=0; + ctx->chain=NULL; + ctx->depth=9; + ctx->error=0; + ctx->error_depth=0; + ctx->current_cert=NULL; + ctx->current_issuer=NULL; + + /* Inherit callbacks and flags from X509_STORE if not set + * use defaults. + */ + + + if (store) + { + ctx->purpose=store->purpose; + ctx->trust=store->trust; + ctx->flags = store->flags; + ctx->cleanup = store->cleanup; + } + else + { + ctx->purpose = 0; + ctx->trust = 0; + ctx->flags = 0; + ctx->cleanup = 0; + } + + if (store && store->check_issued) + ctx->check_issued = store->check_issued; + else + ctx->check_issued = check_issued; + + if (store && store->get_issuer) + ctx->get_issuer = store->get_issuer; + else + ctx->get_issuer = X509_STORE_CTX_get1_issuer; + + if (store && store->verify_cb) + ctx->verify_cb = store->verify_cb; + else + ctx->verify_cb = null_callback; + + if (store && store->verify) + ctx->verify = store->verify; + else + ctx->verify = internal_verify; + + if (store && store->check_revocation) + ctx->check_revocation = store->check_revocation; + else + ctx->check_revocation = check_revocation; + + if (store && store->get_crl) + ctx->get_crl = store->get_crl; + else + ctx->get_crl = get_crl; + + if (store && store->check_crl) + ctx->check_crl = store->check_crl; + else + ctx->check_crl = check_crl; + + if (store && store->cert_crl) + ctx->cert_crl = store->cert_crl; + else + ctx->cert_crl = cert_crl; + + + /* This memset() can't make any sense anyway, so it's removed. As + * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a + * corresponding "new" here and remove this bogus initialisation. */ + /* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */ + if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, + &(ctx->ex_data))) + { + OPENSSL_free(ctx); + X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; } -X509 *X509_STORE_CTX_get_current_cert(ctx) -X509_STORE_CTX *ctx; +/* Set alternative lookup method: just a STACK of trusted certificates. + * This avoids X509_STORE nastiness where it isn't needed. + */ + +void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->other_ctx = sk; + ctx->get_issuer = get_issuer_sk; +} + +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) { - return(ctx->current_cert); + if (ctx->cleanup) ctx->cleanup(ctx); + if (ctx->chain != NULL) + { + sk_X509_pop_free(ctx->chain,X509_free); + ctx->chain=NULL; + } + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data)); + memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA)); } -STACK *X509_STORE_CTX_get_chain(ctx) -X509_STORE_CTX *ctx; +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags) { - return(ctx->chain); + ctx->flags |= flags; } -void X509_STORE_CTX_set_cert(ctx,x) -X509_STORE_CTX *ctx; -X509 *x; +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t) { - ctx->cert=x; + ctx->check_time = t; + ctx->flags |= X509_V_FLAG_USE_CHECK_TIME; } -void X509_STORE_CTX_set_chain(ctx,sk) -X509_STORE_CTX *ctx; -STACK *sk; +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)) { - ctx->untrusted=sk; + ctx->verify_cb=verify_cb; } +IMPLEMENT_STACK_OF(X509) +IMPLEMENT_ASN1_SET_OF(X509) + +IMPLEMENT_STACK_OF(X509_NAME) +IMPLEMENT_STACK_OF(X509_ATTRIBUTE) +IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE) diff --git a/src/lib/libcrypto/x509/x509_vfy.h b/src/lib/libcrypto/x509/x509_vfy.h index dfc060f899..f0be21f452 100644 --- a/src/lib/libcrypto/x509/x509_vfy.h +++ b/src/lib/libcrypto/x509/x509_vfy.h @@ -56,16 +56,26 @@ * [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 +#ifndef OPENSSL_NO_LHASH +#include +#endif +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include "bio.h" -#include "crypto.h" - /* Outer object */ typedef struct x509_hash_dir_st { @@ -119,43 +129,66 @@ typedef struct x509_object_st } data; } X509_OBJECT; +typedef struct x509_lookup_st X509_LOOKUP; + +DECLARE_STACK_OF(X509_LOOKUP) +DECLARE_STACK_OF(X509_OBJECT) + /* This is a static that defines the function interface */ typedef struct x509_lookup_method_st { - char *name; - int (*new_item)(); - void (*free)(); - int (*init)(/* meth, char ** */); - int (*shutdown)( /* meth, char ** */); - int (*ctrl)( /* meth, char **, int cmd, char *argp, int argi */); - int (*get_by_subject)(/* meth, char **, XNAME *, X509 **ret */); - int (*get_by_issuer_serial)(); - int (*get_by_fingerprint)(); - int (*get_by_alias)(); + 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; /* 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 +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 + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ /* These are external lookup methods */ - STACK *get_cert_methods;/* X509_LOOKUP */ - int (*verify)(); /* called to verify a certificate */ - int (*verify_cb)(); /* error callback */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + + /* The following fields are not used by X509_STORE but are + * inherited by X509_STORE_CTX when it is initialised. + */ + + unsigned long flags; /* Various verify flags */ + int purpose; + int trust; + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + int (*cleanup)(X509_STORE_CTX *ctx); CRYPTO_EX_DATA ex_data; int references; - int depth; /* how deep to look */ - } X509_STORE; + 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)) @@ -163,7 +196,7 @@ typedef struct x509_store_st #define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) /* This is the functions plus an instance of the local variables. */ -typedef struct x509_lookup_st +struct x509_lookup_st { int init; /* have we been started */ int skip; /* don't use us. */ @@ -171,33 +204,53 @@ typedef struct x509_lookup_st char *method_data; /* method data */ X509_STORE *store_ctx; /* who owns us */ - } X509_LOOKUP; + } /* X509_LOOKUP */; -/* This is a temporary used when processing cert chains. Since the +/* This is a used when verifying 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. */ -typedef struct x509_store_state_st +struct x509_store_ctx_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 *untrusted; /* chain of X509s - untrusted - passed in */ + STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + time_t check_time; /* time to make verify at */ + unsigned long flags; /* Various verify flags */ + void *other_ctx; /* Other info for use with get_issuer() */ + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + int (*cleanup)(X509_STORE_CTX *ctx); /* 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 *chain; /* chain of X509s - built up and trusted */ + 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; + X509 *current_issuer; /* cert currently being tested as valid issuer */ + X509_CRL *current_crl; /* current CRL */ CRYPTO_EX_DATA ex_data; - } X509_STORE_CTX; + } /* X509_STORE_CTX */; + +#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) @@ -207,15 +260,14 @@ typedef struct x509_store_state_st #define X509_L_FILE_LOAD 1 #define X509_L_ADD_DIR 2 -X509_LOOKUP_METHOD *X509_LOOKUP_file(); #define X509_LOOKUP_load_file(x,name,type) \ X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) -X509_LOOKUP_METHOD *X509_LOOKUP_dir(); #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 @@ -239,21 +291,52 @@ X509_LOOKUP_METHOD *X509_LOOKUP_dir(); #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 +/* These are 'informational' when looking for issuer cert */ +#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +#define X509_V_ERR_AKID_SKID_MISMATCH 30 +#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 + +#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 /* The application is not happy */ #define X509_V_ERR_APPLICATION_VERIFICATION 50 -#ifndef NOPROTO -#ifdef HEADER_LHASH_H -X509_OBJECT *X509_OBJECT_retrive_by_subject(LHASH *h,int type,X509_NAME *name); -#endif +/* Certificate verify flags */ + +#define X509_V_FLAG_CB_ISSUER_CHECK 0x1 /* Send issuer+subject checks to verify_cb */ +#define X509_V_FLAG_USE_CHECK_TIME 0x2 /* Use check time instead of current time */ +#define X509_V_FLAG_CRL_CHECK 0x4 /* Lookup CRLs */ +#define X509_V_FLAG_CRL_CHECK_ALL 0x8 /* Lookup CRLs for whole chain */ +#define X509_V_FLAG_IGNORE_CRITICAL 0x10 /* Ignore unhandled critical extensions */ + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x); 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); -void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, - X509 *x509, STACK *chain); +void X509_STORE_set_flags(X509_STORE *ctx, long flags); +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +int X509_STORE_set_trust(X509_STORE *ctx, int trust); + +X509_STORE_CTX *X509_STORE_CTX_new(void); + +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); @@ -267,17 +350,15 @@ 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,char *argc,long argl,char **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, char *file, int type); -int X509_load_crl_file(X509_LOOKUP *ctx, char *file, int type); +#ifndef OPENSSL_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 -void X509v3_cleanup_extensions(void ); -int X509v3_add_extension(X509_EXTENSION_METHOD *x); -int X509v3_add_netscape_extensions(void ); -int X509v3_add_standard_extensions(void ); X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); void X509_LOOKUP_free(X509_LOOKUP *ctx); @@ -292,84 +373,32 @@ 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 +#ifndef OPENSSL_NO_STDIO int X509_STORE_load_locations (X509_STORE *ctx, - char *file, char *dir); + 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, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); -int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,char *data); -char * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); +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 * X509_STORE_CTX_get_chain(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 /* X509 */ *sk); - -#else - -#ifdef HEADER_LHASH_H -X509_OBJECT *X509_OBJECT_retrive_by_subject(); -#endif -void X509_OBJECT_up_ref_count(); -void X509_OBJECT_free_contents(); -X509_STORE *X509_STORE_new(); -void X509_STORE_free(); - -void X509_STORE_CTX_init(); -void X509_STORE_CTX_cleanup(); - -X509_LOOKUP *X509_STORE_add_lookup(); - -X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(); -X509_LOOKUP_METHOD *X509_LOOKUP_file(); - -int X509_STORE_add_cert(); -int X509_STORE_add_crl(); - -int X509_STORE_get_by_subject(); - -int X509_LOOKUP_ctrl(); - -#ifndef NO_STDIO -int X509_load_cert_file(); -int X509_load_crl_file(); -#endif - -void X509v3_cleanup_extensions(); -int X509v3_add_extension(); -int X509v3_add_netscape_extensions(); -int X509v3_add_standard_extensions(); - -X509_LOOKUP *X509_LOOKUP_new(); -void X509_LOOKUP_free(); -int X509_LOOKUP_init(); -int X509_LOOKUP_by_subject(); -int X509_LOOKUP_by_issuer_serial(); -int X509_LOOKUP_by_fingerprint(); -int X509_LOOKUP_by_alias(); -int X509_LOOKUP_shutdown(); - -#ifndef NO_STDIO -int X509_STORE_load_locations (); -int X509_STORE_set_default_paths(); -#endif - -int X509_STORE_CTX_set_ex_data(); -char * X509_STORE_CTX_get_ex_data(); -int X509_STORE_CTX_get_error(); -void X509_STORE_CTX_set_error(); -int X509_STORE_CTX_get_error_depth(); -X509 * X509_STORE_CTX_get_current_cert(); -STACK * X509_STORE_CTX_get_chain(); -void X509_STORE_CTX_set_cert(); -void X509_STORE_CTX_set_chain(); - -#endif +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); +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, long flags); +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t); +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)); #ifdef __cplusplus } diff --git a/src/lib/libcrypto/x509/x509name.c b/src/lib/libcrypto/x509/x509name.c index 650e71b1b5..4c20e03ece 100644 --- a/src/lib/libcrypto/x509/x509name.c +++ b/src/lib/libcrypto/x509/x509name.c @@ -57,18 +57,14 @@ */ #include -#include "stack.h" +#include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" - -int X509_NAME_get_text_by_NID(name,nid,buf,len) -X509_NAME *name; -int nid; -char *buf; -int len; +#include +#include +#include +#include + +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) { ASN1_OBJECT *obj; @@ -77,11 +73,8 @@ int len; return(X509_NAME_get_text_by_OBJ(name,obj,buf,len)); } -int X509_NAME_get_text_by_OBJ(name,obj,buf,len) -X509_NAME *name; -ASN1_OBJECT *obj; -char *buf; -int len; +int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf, + int len) { int i; ASN1_STRING *data; @@ -96,17 +89,13 @@ int len; return(i); } -int X509_NAME_entry_count(name) -X509_NAME *name; +int X509_NAME_entry_count(X509_NAME *name) { if (name == NULL) return(0); - return(sk_num(name->entries)); + return(sk_X509_NAME_ENTRY_num(name->entries)); } -int X509_NAME_get_index_by_NID(name,nid,lastpos) -X509_NAME *name; -int nid; -int lastpos; +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) { ASN1_OBJECT *obj; @@ -116,61 +105,57 @@ int lastpos; } /* NOTE: you should be passsing -1, not 0 as lastpos */ -int X509_NAME_get_index_by_OBJ(name,obj,lastpos) -X509_NAME *name; -ASN1_OBJECT *obj; -int lastpos; +int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, + int lastpos) { int n; X509_NAME_ENTRY *ne; - STACK *sk; + STACK_OF(X509_NAME_ENTRY) *sk; if (name == NULL) return(-1); if (lastpos < 0) lastpos= -1; sk=name->entries; - n=sk_num(sk); + n=sk_X509_NAME_ENTRY_num(sk); for (lastpos++; lastpos < n; lastpos++) { - ne=(X509_NAME_ENTRY *)sk_value(sk,lastpos); + ne=sk_X509_NAME_ENTRY_value(sk,lastpos); if (OBJ_cmp(ne->object,obj) == 0) return(lastpos); } return(-1); } -X509_NAME_ENTRY *X509_NAME_get_entry(name,loc) -X509_NAME *name; -int loc; +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc) { - if ( (name == NULL) || (sk_num(name->entries) <= loc) || (loc < 0)) + if(name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc + || loc < 0) return(NULL); else - return((X509_NAME_ENTRY *)sk_value(name->entries,loc)); + return(sk_X509_NAME_ENTRY_value(name->entries,loc)); } -X509_NAME_ENTRY *X509_NAME_delete_entry(name,loc) -X509_NAME *name; -int loc; +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) { X509_NAME_ENTRY *ret; - int i,j,n,set_prev,set_next; - STACK *sk; + int i,n,set_prev,set_next; + STACK_OF(X509_NAME_ENTRY) *sk; - if ((name == NULL) || (sk_num(name->entries) <= loc) || (loc < 0)) + if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc + || loc < 0) return(NULL); sk=name->entries; - ret=(X509_NAME_ENTRY *)sk_delete(sk,loc); - n=sk_num(sk); + ret=sk_X509_NAME_ENTRY_delete(sk,loc); + n=sk_X509_NAME_ENTRY_num(sk); name->modified=1; if (loc == n) return(ret); /* else we need to fixup the set field */ if (loc != 0) - set_prev=((X509_NAME_ENTRY *)sk_value(sk,loc-1))->set; + set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set; else set_prev=ret->set-1; - set_next=((X509_NAME_ENTRY *)sk_value(sk,loc))->set; + set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set; /* set_prev is the previous set * set is the current set @@ -181,29 +166,59 @@ int loc; * so basically only if prev and next differ by 2, then * re-number down by 1 */ if (set_prev+1 < set_next) - { - j=set_next-set_prev-1; for (i=loc; iset-=j; - } + sk_X509_NAME_ENTRY_value(sk,i)->set--; return(ret); } +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len, int loc, int set) +{ + X509_NAME_ENTRY *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); + if(!ne) return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +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 *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); + if(!ne) return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + +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 *ne; + int ret; + ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); + if(!ne) return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} + /* if set is -1, append to previous set, 0 'a new one', and 1, * prepend to the guy we are about to stomp on. */ -int X509_NAME_add_entry(name,ne,loc,set) -X509_NAME *name; -X509_NAME_ENTRY *ne; -int loc; -int set; +int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, + int set) { X509_NAME_ENTRY *new_name=NULL; int n,i,inc; - STACK *sk; + STACK_OF(X509_NAME_ENTRY) *sk; if (name == NULL) return(0); sk=name->entries; - n=sk_num(sk); + n=sk_X509_NAME_ENTRY_num(sk); if (loc > n) loc=n; else if (loc < 0) loc=n; @@ -218,7 +233,7 @@ int set; } else { - set=((X509_NAME_ENTRY *)sk_value(sk,loc-1))->set; + set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set; inc=0; } } @@ -227,45 +242,60 @@ int set; if (loc >= n) { if (loc != 0) - set=((X509_NAME_ENTRY *) - sk_value(sk,loc-1))->set+1; + set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1; else set=0; } else - set=((X509_NAME_ENTRY *)sk_value(sk,loc))->set; + set=sk_X509_NAME_ENTRY_value(sk,loc)->set; inc=(set == 0)?1:0; } if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL) goto err; new_name->set=set; - if (!sk_insert(sk,(char *)new_name,loc)) + if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc)) { X509err(X509_F_X509_NAME_ADD_ENTRY,ERR_R_MALLOC_FAILURE); goto err; } if (inc) { - n=sk_num(sk); + n=sk_X509_NAME_ENTRY_num(sk); for (i=loc+1; iset+=1; + sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1; } return(1); err: if (new_name != NULL) - X509_NAME_ENTRY_free(ne); + X509_NAME_ENTRY_free(new_name); return(0); } -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(ne,nid,type,bytes,len) -X509_NAME_ENTRY **ne; -int nid; -int type; -unsigned char *bytes; -int len; +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + char *field, int type, unsigned char *bytes, int len) { ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj=OBJ_txt2obj(field, 0); + if (obj == NULL) + { + X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, + X509_R_INVALID_FIELD_NAME); + ERR_add_error_data(2, "name=", field); + return(NULL); + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len); + ASN1_OBJECT_free(obj); + return nentry; + } + +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, unsigned char *bytes, int len) + { + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; obj=OBJ_nid2obj(nid); if (obj == NULL) @@ -273,15 +303,13 @@ int len; X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID,X509_R_UNKNOWN_NID); return(NULL); } - return(X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len)); + nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len); + ASN1_OBJECT_free(obj); + return nentry; } -X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len) -X509_NAME_ENTRY **ne; -ASN1_OBJECT *obj; -int type; -unsigned char *bytes; -int len; +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + ASN1_OBJECT *obj, int type, unsigned char *bytes, int len) { X509_NAME_ENTRY *ret; @@ -297,7 +325,7 @@ int len; goto err; if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len)) goto err; - + if ((ne != NULL) && (*ne == NULL)) *ne=ret; return(ret); err: @@ -306,9 +334,7 @@ err: return(NULL); } -int X509_NAME_ENTRY_set_object(ne,obj) -X509_NAME_ENTRY *ne; -ASN1_OBJECT *obj; +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj) { if ((ne == NULL) || (obj == NULL)) { @@ -320,15 +346,16 @@ ASN1_OBJECT *obj; return((ne->object == NULL)?0:1); } -int X509_NAME_ENTRY_set_data(ne,type,bytes,len) -X509_NAME_ENTRY *ne; -int type; -unsigned char *bytes; -int len; +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + unsigned char *bytes, int len) { int i; if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0); + if((type > 0) && (type & MBSTRING_FLAG)) + return ASN1_STRING_set_by_NID(&ne->value, bytes, + len, type, + OBJ_obj2nid(ne->object)) ? 1 : 0; if (len < 0) len=strlen((char *)bytes); i=ASN1_STRING_set(ne->value,bytes,len); if (!i) return(0); @@ -342,15 +369,13 @@ int len; return(1); } -ASN1_OBJECT *X509_NAME_ENTRY_get_object(ne) -X509_NAME_ENTRY *ne; +ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne) { if (ne == NULL) return(NULL); return(ne->object); } -ASN1_STRING *X509_NAME_ENTRY_get_data(ne) -X509_NAME_ENTRY *ne; +ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) { if (ne == NULL) return(NULL); return(ne->value); diff --git a/src/lib/libcrypto/x509/x509rset.c b/src/lib/libcrypto/x509/x509rset.c index 323b25470a..d9f6b57372 100644 --- a/src/lib/libcrypto/x509/x509rset.c +++ b/src/lib/libcrypto/x509/x509rset.c @@ -58,30 +58,24 @@ #include #include "cryptlib.h" -#include "asn1.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include -int X509_REQ_set_version(x,version) -X509_REQ *x; -long version; +int X509_REQ_set_version(X509_REQ *x, long version) { if (x == NULL) return(0); return(ASN1_INTEGER_set(x->req_info->version,version)); } -int X509_REQ_set_subject_name(x,name) -X509_REQ *x; -X509_NAME *name; +int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) { if ((x == NULL) || (x->req_info == NULL)) return(0); return(X509_NAME_set(&x->req_info->subject,name)); } -int X509_REQ_set_pubkey(x,pkey) -X509_REQ *x; -EVP_PKEY *pkey; +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { if ((x == NULL) || (x->req_info == NULL)) return(0); return(X509_PUBKEY_set(&x->req_info->pubkey,pkey)); diff --git a/src/lib/libcrypto/x509/x509spki.c b/src/lib/libcrypto/x509/x509spki.c index b35c3f92e7..4c3af946ec 100644 --- a/src/lib/libcrypto/x509/x509spki.c +++ b/src/lib/libcrypto/x509/x509spki.c @@ -59,7 +59,6 @@ #include #include "cryptlib.h" #include -#include int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) { @@ -82,7 +81,7 @@ NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len) int spki_len; NETSCAPE_SPKI *spki; if(len <= 0) len = strlen(str); - if (!(spki_der = Malloc(len + 1))) { + if (!(spki_der = OPENSSL_malloc(len + 1))) { X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, ERR_R_MALLOC_FAILURE); return NULL; } @@ -90,12 +89,12 @@ NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len) if(spki_len < 0) { X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, X509_R_BASE64_DECODE_ERROR); - Free(spki_der); + OPENSSL_free(spki_der); return NULL; } p = spki_der; spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); - Free(spki_der); + OPENSSL_free(spki_der); return spki; } @@ -107,8 +106,8 @@ char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) char *b64_str; int der_len; der_len = i2d_NETSCAPE_SPKI(spki, NULL); - der_spki = Malloc(der_len); - b64_str = Malloc(der_len * 2); + der_spki = OPENSSL_malloc(der_len); + b64_str = OPENSSL_malloc(der_len * 2); if(!der_spki || !b64_str) { X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE); return NULL; @@ -116,6 +115,6 @@ char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) p = der_spki; i2d_NETSCAPE_SPKI(spki, &p); EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); - Free(der_spki); + OPENSSL_free(der_spki); return b64_str; } diff --git a/src/lib/libcrypto/x509/x509type.c b/src/lib/libcrypto/x509/x509type.c index 42c23bcfca..8e78b34458 100644 --- a/src/lib/libcrypto/x509/x509type.c +++ b/src/lib/libcrypto/x509/x509type.c @@ -58,13 +58,11 @@ #include #include "cryptlib.h" -#include "evp.h" -#include "objects.h" -#include "x509.h" +#include +#include +#include -int X509_certificate_type(x,pkey) -X509 *x; -EVP_PKEY *pkey; +int X509_certificate_type(X509 *x, EVP_PKEY *pkey) { EVP_PKEY *pk; int ret=0,i; @@ -108,8 +106,9 @@ EVP_PKEY *pkey; break; } - if (EVP_PKEY_size(pkey) <= 512) + if (EVP_PKEY_size(pk) <= 512) ret|=EVP_PKT_EXP; + if(pkey==NULL) EVP_PKEY_free(pk); return(ret); } diff --git a/src/lib/libcrypto/x509/x_all.c b/src/lib/libcrypto/x509/x_all.c index b7dde23e9a..fb5015cd4d 100644 --- a/src/lib/libcrypto/x509/x_all.c +++ b/src/lib/libcrypto/x509/x_all.c @@ -58,408 +58,431 @@ #include #undef SSLEAY_MACROS -#include "stack.h" +#include #include "cryptlib.h" -#include "buffer.h" -#include "asn1.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include -int X509_verify(a,r) -X509 *a; -EVP_PKEY *r; +int X509_verify(X509 *a, EVP_PKEY *r) { - return(ASN1_verify((int (*)())i2d_X509_CINF,a->sig_alg, - a->signature,(char *)a->cert_info,r)); + return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg, + a->signature,a->cert_info,r)); } -int X509_REQ_verify(a,r) -X509_REQ *a; -EVP_PKEY *r; +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) { - return( ASN1_verify((int (*)())i2d_X509_REQ_INFO, - a->sig_alg,a->signature,(char *)a->req_info,r)); + return( ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), + a->sig_alg,a->signature,a->req_info,r)); } -int X509_CRL_verify(a,r) -X509_CRL *a; -EVP_PKEY *r; +int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r) { - return(ASN1_verify((int (*)())i2d_X509_CRL_INFO, - a->sig_alg, a->signature,(char *)a->crl,r)); + return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), + a->sig_alg, a->signature,a->crl,r)); } -int NETSCAPE_SPKI_verify(a,r) -NETSCAPE_SPKI *a; -EVP_PKEY *r; +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) { - return(ASN1_verify((int (*)())i2d_NETSCAPE_SPKAC, - a->sig_algor,a->signature, (char *)a->spkac,r)); + return(ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), + a->sig_algor,a->signature,a->spkac,r)); } -int X509_sign(x,pkey,md) -X509 *x; -EVP_PKEY *pkey; -EVP_MD *md; +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { - return(ASN1_sign((int (*)())i2d_X509_CINF, x->cert_info->signature, - x->sig_alg, x->signature, (char *)x->cert_info,pkey,md)); + return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature, + x->sig_alg, x->signature, x->cert_info,pkey,md)); } -int X509_REQ_sign(x,pkey,md) -X509_REQ *x; -EVP_PKEY *pkey; -EVP_MD *md; +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { - return(ASN1_sign((int (*)())i2d_X509_REQ_INFO,x->sig_alg, NULL, - x->signature, (char *)x->req_info,pkey,md)); + return(ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO),x->sig_alg, NULL, + x->signature, x->req_info,pkey,md)); } -int X509_CRL_sign(x,pkey,md) -X509_CRL *x; -EVP_PKEY *pkey; -EVP_MD *md; +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) { - return(ASN1_sign((int (*)())i2d_X509_CRL_INFO,x->crl->sig_alg, - x->sig_alg, x->signature, (char *)x->crl,pkey,md)); + return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO),x->crl->sig_alg, + x->sig_alg, x->signature, x->crl,pkey,md)); } -int NETSCAPE_SPKI_sign(x,pkey,md) -NETSCAPE_SPKI *x; -EVP_PKEY *pkey; -EVP_MD *md; +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { - return(ASN1_sign((int (*)())i2d_NETSCAPE_SPKAC, x->sig_algor,NULL, - x->signature, (char *)x->spkac,pkey,md)); + return(ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,NULL, + x->signature, x->spkac,pkey,md)); } -X509 *X509_dup(x509) -X509 *x509; +#ifndef OPENSSL_NO_FP_API +X509 *d2i_X509_fp(FILE *fp, X509 **x509) { - return((X509 *)ASN1_dup((int (*)())i2d_X509, - (char *(*)())d2i_X509,(char *)x509)); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509); } -X509_EXTENSION *X509_EXTENSION_dup(ex) -X509_EXTENSION *ex; +int i2d_X509_fp(FILE *fp, X509 *x509) { - return((X509_EXTENSION *)ASN1_dup( - (int (*)())i2d_X509_EXTENSION, - (char *(*)())d2i_X509_EXTENSION,(char *)ex)); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509); } +#endif -#ifndef NO_FP_API -X509 *d2i_X509_fp(fp,x509) -FILE *fp; -X509 *x509; +X509 *d2i_X509_bio(BIO *bp, X509 **x509) { - return((X509 *)ASN1_d2i_fp((char *(*)())X509_new, - (char *(*)())d2i_X509, (fp),(unsigned char **)(x509))); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509); } -int i2d_X509_fp(fp,x509) -FILE *fp; -X509 *x509; +int i2d_X509_bio(BIO *bp, X509 *x509) { - return(ASN1_i2d_fp(i2d_X509,fp,(unsigned char *)x509)); + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509); } -#endif -X509 *d2i_X509_bio(bp,x509) -BIO *bp; -X509 *x509; +#ifndef OPENSSL_NO_FP_API +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) { - return((X509 *)ASN1_d2i_bio((char *(*)())X509_new, - (char *(*)())d2i_X509, (bp),(unsigned char **)(x509))); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); } -int i2d_X509_bio(bp,x509) -BIO *bp; -X509 *x509; +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl) { - return(ASN1_i2d_bio(i2d_X509,bp,(unsigned char *)x509)); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl); } +#endif -X509_CRL *X509_CRL_dup(crl) -X509_CRL *crl; +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl) { - return((X509_CRL *)ASN1_dup((int (*)())i2d_X509_CRL, - (char *(*)())d2i_X509_CRL,(char *)crl)); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); } -#ifndef NO_FP_API -X509_CRL *d2i_X509_CRL_fp(fp,crl) -FILE *fp; -X509_CRL *crl; +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) { - return((X509_CRL *)ASN1_d2i_fp((char *(*)()) - X509_CRL_new,(char *(*)())d2i_X509_CRL, (fp), - (unsigned char **)(crl))); + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl); } -int i2d_X509_CRL_fp(fp,crl) -FILE *fp; -X509_CRL *crl; +#ifndef OPENSSL_NO_FP_API +PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7) { - return(ASN1_i2d_fp(i2d_X509_CRL,fp,(unsigned char *)crl)); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7); } -#endif -X509_CRL *d2i_X509_CRL_bio(bp,crl) -BIO *bp; -X509_CRL *crl; +int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7) { - return((X509_CRL *)ASN1_d2i_bio((char *(*)()) - X509_CRL_new,(char *(*)())d2i_X509_CRL, (bp), - (unsigned char **)(crl))); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7); } +#endif -int i2d_X509_CRL_bio(bp,crl) -BIO *bp; -X509_CRL *crl; +PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7) { - return(ASN1_i2d_bio(i2d_X509_CRL,bp,(unsigned char *)crl)); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7); } -PKCS7 *PKCS7_dup(p7) -PKCS7 *p7; +int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7) { - return((PKCS7 *)ASN1_dup((int (*)())i2d_PKCS7, - (char *(*)())d2i_PKCS7,(char *)p7)); + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7); } -#ifndef NO_FP_API -PKCS7 *d2i_PKCS7_fp(fp,p7) -FILE *fp; -PKCS7 *p7; +#ifndef OPENSSL_NO_FP_API +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) { - return((PKCS7 *)ASN1_d2i_fp((char *(*)()) - PKCS7_new,(char *(*)())d2i_PKCS7, (fp), - (unsigned char **)(p7))); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); } -int i2d_PKCS7_fp(fp,p7) -FILE *fp; -PKCS7 *p7; +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req) { - return(ASN1_i2d_fp(i2d_PKCS7,fp,(unsigned char *)p7)); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req); } #endif -PKCS7 *d2i_PKCS7_bio(bp,p7) -BIO *bp; -PKCS7 *p7; +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) { - return((PKCS7 *)ASN1_d2i_bio((char *(*)()) - PKCS7_new,(char *(*)())d2i_PKCS7, (bp), - (unsigned char **)(p7))); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); } -int i2d_PKCS7_bio(bp,p7) -BIO *bp; -PKCS7 *p7; +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) { - return(ASN1_i2d_bio(i2d_PKCS7,bp,(unsigned char *)p7)); + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req); } -X509_REQ *X509_REQ_dup(req) -X509_REQ *req; +#ifndef OPENSSL_NO_RSA + +#ifndef OPENSSL_NO_FP_API +RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa) { - return((X509_REQ *)ASN1_dup((int (*)())i2d_X509_REQ, - (char *(*)())d2i_X509_REQ,(char *)req)); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa); } -#ifndef NO_FP_API -X509_REQ *d2i_X509_REQ_fp(fp,req) -FILE *fp; -X509_REQ *req; +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) { - return((X509_REQ *)ASN1_d2i_fp((char *(*)()) - X509_REQ_new, (char *(*)())d2i_X509_REQ, (fp), - (unsigned char **)(req))); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa); } -int i2d_X509_REQ_fp(fp,req) -FILE *fp; -X509_REQ *req; +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) { - return(ASN1_i2d_fp(i2d_X509_REQ,fp,(unsigned char *)req)); + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa); } -#endif -X509_REQ *d2i_X509_REQ_bio(bp,req) -BIO *bp; -X509_REQ *req; + +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) { - return((X509_REQ *)ASN1_d2i_bio((char *(*)()) - X509_REQ_new, (char *(*)())d2i_X509_REQ, (bp), - (unsigned char **)(req))); + return((RSA *)ASN1_d2i_fp((char *(*)()) + RSA_new,(char *(*)())d2i_RSA_PUBKEY, (fp), + (unsigned char **)(rsa))); } -int i2d_X509_REQ_bio(bp,req) -BIO *bp; -X509_REQ *req; +int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) { - return(ASN1_i2d_bio(i2d_X509_REQ,bp,(unsigned char *)req)); + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa); } -#ifndef NO_RSA -RSA *RSAPublicKey_dup(rsa) -RSA *rsa; +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) { - return((RSA *)ASN1_dup((int (*)())i2d_RSAPublicKey, - (char *(*)())d2i_RSAPublicKey,(char *)rsa)); + return(ASN1_i2d_fp(i2d_RSA_PUBKEY,fp,(unsigned char *)rsa)); } +#endif -RSA *RSAPrivateKey_dup(rsa) -RSA *rsa; +RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa) { - return((RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey, - (char *(*)())d2i_RSAPrivateKey,(char *)rsa)); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa); } -#ifndef NO_FP_API -RSA *d2i_RSAPrivateKey_fp(fp,rsa) -FILE *fp; -RSA *rsa; +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) { - return((RSA *)ASN1_d2i_fp((char *(*)()) - RSA_new,(char *(*)())d2i_RSAPrivateKey, (fp), - (unsigned char **)(rsa))); + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa); } -int i2d_RSAPrivateKey_fp(fp,rsa) -FILE *fp; -RSA *rsa; +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) { - return(ASN1_i2d_fp(i2d_RSAPrivateKey,fp,(unsigned char *)rsa)); + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa); } -RSA *d2i_RSAPublicKey_fp(fp,rsa) -FILE *fp; -RSA *rsa; + +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) { - return((RSA *)ASN1_d2i_fp((char *(*)()) - RSA_new,(char *(*)())d2i_RSAPublicKey, (fp), + return((RSA *)ASN1_d2i_bio((char *(*)()) + RSA_new,(char *(*)())d2i_RSA_PUBKEY, (bp), (unsigned char **)(rsa))); } -int i2d_RSAPublicKey_fp(fp,rsa) -FILE *fp; -RSA *rsa; +int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) + { + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa); + } + +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) { - return(ASN1_i2d_fp(i2d_RSAPublicKey,fp,(unsigned char *)rsa)); + return(ASN1_i2d_bio(i2d_RSA_PUBKEY,bp,(unsigned char *)rsa)); } #endif -RSA *d2i_RSAPrivateKey_bio(bp,rsa) -BIO *bp; -RSA *rsa; +#ifndef OPENSSL_NO_DSA +#ifndef OPENSSL_NO_FP_API +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) { - return((RSA *)ASN1_d2i_bio((char *(*)()) - RSA_new,(char *(*)())d2i_RSAPrivateKey, (bp), - (unsigned char **)(rsa))); + return((DSA *)ASN1_d2i_fp((char *(*)()) + DSA_new,(char *(*)())d2i_DSAPrivateKey, (fp), + (unsigned char **)(dsa))); } -int i2d_RSAPrivateKey_bio(bp,rsa) -BIO *bp; -RSA *rsa; +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) { - return(ASN1_i2d_bio(i2d_RSAPrivateKey,bp,(unsigned char *)rsa)); + return(ASN1_i2d_fp(i2d_DSAPrivateKey,fp,(unsigned char *)dsa)); } -RSA *d2i_RSAPublicKey_bio(bp,rsa) -BIO *bp; -RSA *rsa; +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) { - return((RSA *)ASN1_d2i_bio((char *(*)()) - RSA_new,(char *(*)())d2i_RSAPublicKey, (bp), - (unsigned char **)(rsa))); + return((DSA *)ASN1_d2i_fp((char *(*)()) + DSA_new,(char *(*)())d2i_DSA_PUBKEY, (fp), + (unsigned char **)(dsa))); } -int i2d_RSAPublicKey_bio(bp,rsa) -BIO *bp; -RSA *rsa; +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) { - return(ASN1_i2d_bio(i2d_RSAPublicKey,bp,(unsigned char *)rsa)); + return(ASN1_i2d_fp(i2d_DSA_PUBKEY,fp,(unsigned char *)dsa)); } #endif -#ifndef NO_DSA -#ifndef NO_FP_API -DSA *d2i_DSAPrivateKey_fp(fp,dsa) -FILE *fp; -DSA *dsa; +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa) { - return((DSA *)ASN1_d2i_fp((char *(*)()) - DSA_new,(char *(*)())d2i_DSAPrivateKey, (fp), + return((DSA *)ASN1_d2i_bio((char *(*)()) + DSA_new,(char *(*)())d2i_DSAPrivateKey, (bp), (unsigned char **)(dsa))); } -int i2d_DSAPrivateKey_fp(fp,dsa) -FILE *fp; -DSA *dsa; +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa) { - return(ASN1_i2d_fp(i2d_DSAPrivateKey,fp,(unsigned char *)dsa)); + return(ASN1_i2d_bio(i2d_DSAPrivateKey,bp,(unsigned char *)dsa)); } -#endif -DSA *d2i_DSAPrivateKey_bio(bp,dsa) -BIO *bp; -DSA *dsa; +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) { return((DSA *)ASN1_d2i_bio((char *(*)()) - DSA_new,(char *(*)())d2i_DSAPrivateKey, (bp), + DSA_new,(char *(*)())d2i_DSA_PUBKEY, (bp), (unsigned char **)(dsa))); } -int i2d_DSAPrivateKey_bio(bp,dsa) -BIO *bp; -DSA *dsa; +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) { - return(ASN1_i2d_bio(i2d_DSAPrivateKey,bp,(unsigned char *)dsa)); + return(ASN1_i2d_bio(i2d_DSA_PUBKEY,bp,(unsigned char *)dsa)); } + #endif -X509_NAME *X509_NAME_dup(xn) -X509_NAME *xn; +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) + { + ASN1_BIT_STRING *key; + key = X509_get0_pubkey_bitstr(data); + if(!key) return 0; + return EVP_Digest(key->data, key->length, md, len, type, NULL); + } + +int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { - return((X509_NAME *)ASN1_dup((int (*)())i2d_X509_NAME, - (char *(*)())d2i_X509_NAME,(char *)xn)); + return(ASN1_item_digest(ASN1_ITEM_rptr(X509),type,(char *)data,md,len)); } -X509_NAME_ENTRY *X509_NAME_ENTRY_dup(ne) -X509_NAME_ENTRY *ne; +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { - return((X509_NAME_ENTRY *)ASN1_dup((int (*)())i2d_X509_NAME_ENTRY, - (char *(*)())d2i_X509_NAME_ENTRY,(char *)ne)); + return(ASN1_item_digest(ASN1_ITEM_rptr(X509_CRL),type,(char *)data,md,len)); } -int X509_digest(data,type,md,len) -X509 *data; -EVP_MD *type; -unsigned char *md; -unsigned int *len; +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { - return(ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len)); + return(ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ),type,(char *)data,md,len)); } -int X509_NAME_digest(data,type,md,len) -X509_NAME *data; -EVP_MD *type; -unsigned char *md; -unsigned int *len; +int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) { - return(ASN1_digest((int (*)())i2d_X509_NAME,type,(char *)data,md,len)); + return(ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME),type,(char *)data,md,len)); } -int PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) -PKCS7_ISSUER_AND_SERIAL *data; -EVP_MD *type; -unsigned char *md; -unsigned int *len; +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, const EVP_MD *type, + unsigned char *md, unsigned int *len) { - return(ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type, + return(ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL),type, (char *)data,md,len)); } + +#ifndef OPENSSL_NO_FP_API +X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) + { + return((X509_SIG *)ASN1_d2i_fp((char *(*)())X509_SIG_new, + (char *(*)())d2i_X509_SIG, (fp),(unsigned char **)(p8))); + } + +int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8) + { + return(ASN1_i2d_fp(i2d_X509_SIG,fp,(unsigned char *)p8)); + } +#endif + +X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8) + { + return((X509_SIG *)ASN1_d2i_bio((char *(*)())X509_SIG_new, + (char *(*)())d2i_X509_SIG, (bp),(unsigned char **)(p8))); + } + +int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8) + { + return(ASN1_i2d_bio(i2d_X509_SIG,bp,(unsigned char *)p8)); + } + +#ifndef OPENSSL_NO_FP_API +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf) + { + return((PKCS8_PRIV_KEY_INFO *)ASN1_d2i_fp( + (char *(*)())PKCS8_PRIV_KEY_INFO_new, + (char *(*)())d2i_PKCS8_PRIV_KEY_INFO, (fp), + (unsigned char **)(p8inf))); + } + +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf) + { + return(ASN1_i2d_fp(i2d_PKCS8_PRIV_KEY_INFO,fp,(unsigned char *)p8inf)); + } + +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) + { + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if(!p8inf) return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; + } + +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey) + { + return(ASN1_i2d_fp(i2d_PrivateKey,fp,(unsigned char *)pkey)); + } + +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a) +{ + return((EVP_PKEY *)ASN1_d2i_fp((char *(*)())EVP_PKEY_new, + (char *(*)())d2i_AutoPrivateKey, (fp),(unsigned char **)(a))); +} + +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey) + { + return(ASN1_i2d_fp(i2d_PUBKEY,fp,(unsigned char *)pkey)); + } + +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) +{ + return((EVP_PKEY *)ASN1_d2i_fp((char *(*)())EVP_PKEY_new, + (char *(*)())d2i_PUBKEY, (fp),(unsigned char **)(a))); +} + +#endif + +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf) + { + return((PKCS8_PRIV_KEY_INFO *)ASN1_d2i_bio( + (char *(*)())PKCS8_PRIV_KEY_INFO_new, + (char *(*)())d2i_PKCS8_PRIV_KEY_INFO, (bp), + (unsigned char **)(p8inf))); + } + +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf) + { + return(ASN1_i2d_bio(i2d_PKCS8_PRIV_KEY_INFO,bp,(unsigned char *)p8inf)); + } + +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) + { + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if(!p8inf) return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; + } + +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey) + { + return(ASN1_i2d_bio(i2d_PrivateKey,bp,(unsigned char *)pkey)); + } + +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a) + { + return((EVP_PKEY *)ASN1_d2i_bio((char *(*)())EVP_PKEY_new, + (char *(*)())d2i_AutoPrivateKey, (bp),(unsigned char **)(a))); + } + +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey) + { + return(ASN1_i2d_bio(i2d_PUBKEY,bp,(unsigned char *)pkey)); + } + +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) + { + return((EVP_PKEY *)ASN1_d2i_bio((char *(*)())EVP_PKEY_new, + (char *(*)())d2i_PUBKEY, (bp),(unsigned char **)(a))); + } diff --git a/src/lib/libcrypto/x509v3/ext_dat.h b/src/lib/libcrypto/x509v3/ext_dat.h index 801a585a52..586f116db5 100644 --- a/src/lib/libcrypto/x509v3/ext_dat.h +++ b/src/lib/libcrypto/x509v3/ext_dat.h @@ -58,9 +58,12 @@ /* This file contains a table of "standard" extensions */ extern X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; -extern X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info; +extern X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo; extern X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id; -extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_cpols, v3_crld; +extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate, v3_cpols, v3_crld; +extern X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff; +extern X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc; +extern X509V3_EXT_METHOD v3_crl_hold; /* This table will be searched using OBJ_bsearch so it *must* kept in * order of the ext_nid values. @@ -87,8 +90,17 @@ static X509V3_EXT_METHOD *standard_exts[] = { &v3_crld, &v3_ext_ku, &v3_crl_reason, +&v3_crl_invdate, &v3_sxnet, &v3_info, +&v3_ocsp_nonce, +&v3_ocsp_crlid, +&v3_ocsp_accresp, +&v3_ocsp_nocheck, +&v3_ocsp_acutoff, +&v3_ocsp_serviceloc, +&v3_crl_hold, +&v3_sinfo }; /* Number of standard extensions */ diff --git a/src/lib/libcrypto/x509v3/v3_akey.c b/src/lib/libcrypto/x509v3/v3_akey.c index 4099e6019e..97e686f97a 100644 --- a/src/lib/libcrypto/x509v3/v3_akey.c +++ b/src/lib/libcrypto/x509v3/v3_akey.c @@ -60,7 +60,7 @@ #include "cryptlib.h" #include #include -#include +#include #include static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, @@ -69,72 +69,15 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); X509V3_EXT_METHOD v3_akey_id = { -NID_authority_key_identifier, X509V3_EXT_MULTILINE, -(X509V3_EXT_NEW)AUTHORITY_KEYID_new, -(X509V3_EXT_FREE)AUTHORITY_KEYID_free, -(X509V3_EXT_D2I)d2i_AUTHORITY_KEYID, -(X509V3_EXT_I2D)i2d_AUTHORITY_KEYID, -NULL, NULL, +NID_authority_key_identifier, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID), +0,0,0,0, +0,0, (X509V3_EXT_I2V)i2v_AUTHORITY_KEYID, (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID, -NULL,NULL, +0,0, NULL }; - -int i2d_AUTHORITY_KEYID(AUTHORITY_KEYID *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len_IMP_opt (a->keyid, i2d_ASN1_OCTET_STRING); - M_ASN1_I2D_len_IMP_opt (a->issuer, i2d_GENERAL_NAMES); - M_ASN1_I2D_len_IMP_opt (a->serial, i2d_ASN1_INTEGER); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put_IMP_opt (a->keyid, i2d_ASN1_OCTET_STRING, 0); - M_ASN1_I2D_put_IMP_opt (a->issuer, i2d_GENERAL_NAMES, 1); - M_ASN1_I2D_put_IMP_opt (a->serial, i2d_ASN1_INTEGER, 2); - - M_ASN1_I2D_finish(); -} - -AUTHORITY_KEYID *AUTHORITY_KEYID_new(void) -{ - AUTHORITY_KEYID *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, AUTHORITY_KEYID); - ret->keyid = NULL; - ret->issuer = NULL; - ret->serial = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_AUTHORITY_KEYID_NEW); -} - -AUTHORITY_KEYID *d2i_AUTHORITY_KEYID(AUTHORITY_KEYID **a, unsigned char **pp, - long length) -{ - M_ASN1_D2I_vars(a,AUTHORITY_KEYID *,AUTHORITY_KEYID_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get_IMP_opt (ret->keyid, d2i_ASN1_OCTET_STRING, 0, - V_ASN1_OCTET_STRING); - M_ASN1_D2I_get_IMP_opt (ret->issuer, d2i_GENERAL_NAMES, 1, - V_ASN1_SEQUENCE); - M_ASN1_D2I_get_IMP_opt (ret->serial, d2i_ASN1_INTEGER, 2, - V_ASN1_INTEGER); - M_ASN1_D2I_Finish(a, AUTHORITY_KEYID_free, ASN1_F_D2I_AUTHORITY_KEYID); -} - -void AUTHORITY_KEYID_free(AUTHORITY_KEYID *a) -{ - if (a == NULL) return; - ASN1_OCTET_STRING_free(a->keyid); - sk_GENERAL_NAME_pop_free(a->issuer, GENERAL_NAME_free); - ASN1_INTEGER_free (a->serial); - Free ((char *)a); -} - static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist) { @@ -142,7 +85,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, if(akeyid->keyid) { tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length); X509V3_add_value("keyid", tmp, &extlist); - Free(tmp); + OPENSSL_free(tmp); } if(akeyid->issuer) extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist); @@ -150,7 +93,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, tmp = hex_to_string(akeyid->serial->data, akeyid->serial->length); X509V3_add_value("serial", tmp, &extlist); - Free(tmp); + OPENSSL_free(tmp); } return extlist; } @@ -171,7 +114,7 @@ int i; CONF_VALUE *cnf; ASN1_OCTET_STRING *ikeyid = NULL; X509_NAME *isname = NULL; -STACK_OF(GENERAL_NAME) * gens = NULL; +GENERAL_NAMES * gens = NULL; GENERAL_NAME *gen = NULL; ASN1_INTEGER *serial = NULL; X509_EXTENSION *ext; @@ -192,8 +135,6 @@ for(i = 0; i < sk_CONF_VALUE_num(values); i++) { } } - - if(!ctx || !ctx->issuer_cert) { if(ctx && (ctx->flags==CTX_TEST)) return AUTHORITY_KEYID_new(); X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,X509V3_R_NO_ISSUER_CERTIFICATE); @@ -214,7 +155,7 @@ if(keyid) { if((issuer && !ikeyid) || (issuer == 2)) { isname = X509_NAME_dup(X509_get_issuer_name(cert)); - serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert)); if(!isname || !serial) { X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); goto err; @@ -224,7 +165,7 @@ if((issuer && !ikeyid) || (issuer == 2)) { if(!(akeyid = AUTHORITY_KEYID_new())) goto err; if(isname) { - if(!(gens = sk_GENERAL_NAME_new(NULL)) || !(gen = GENERAL_NAME_new()) + if(!(gens = sk_GENERAL_NAME_new_null()) || !(gen = GENERAL_NAME_new()) || !sk_GENERAL_NAME_push(gens, gen)) { X509V3err(X509V3_F_V2I_AUTHORITY_KEYID,ERR_R_MALLOC_FAILURE); goto err; @@ -241,8 +182,8 @@ return akeyid; err: X509_NAME_free(isname); -ASN1_INTEGER_free(serial); -ASN1_OCTET_STRING_free(ikeyid); +M_ASN1_INTEGER_free(serial); +M_ASN1_OCTET_STRING_free(ikeyid); return NULL; } diff --git a/src/lib/libcrypto/x509v3/v3_alt.c b/src/lib/libcrypto/x509v3/v3_alt.c index b5e1f8af96..0e9e7dcb4f 100644 --- a/src/lib/libcrypto/x509v3/v3_alt.c +++ b/src/lib/libcrypto/x509v3/v3_alt.c @@ -61,34 +61,28 @@ #include #include -static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens); -static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens); +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); X509V3_EXT_METHOD v3_alt[] = { -{ NID_subject_alt_name, 0, -(X509V3_EXT_NEW)GENERAL_NAMES_new, -(X509V3_EXT_FREE)GENERAL_NAMES_free, -(X509V3_EXT_D2I)d2i_GENERAL_NAMES, -(X509V3_EXT_I2D)i2d_GENERAL_NAMES, -NULL, NULL, +{ NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), +0,0,0,0, +0,0, (X509V3_EXT_I2V)i2v_GENERAL_NAMES, (X509V3_EXT_V2I)v2i_subject_alt, NULL, NULL, NULL}, -{ NID_issuer_alt_name, 0, -(X509V3_EXT_NEW)GENERAL_NAMES_new, -(X509V3_EXT_FREE)GENERAL_NAMES_free, -(X509V3_EXT_D2I)d2i_GENERAL_NAMES, -(X509V3_EXT_I2D)i2d_GENERAL_NAMES, -NULL, NULL, + +{ NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), +0,0,0,0, +0,0, (X509V3_EXT_I2V)i2v_GENERAL_NAMES, (X509V3_EXT_V2I)v2i_issuer_alt, NULL, NULL, NULL}, -EXT_END }; STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, - STACK_OF(GENERAL_NAME) *gens, STACK_OF(CONF_VALUE) *ret) + GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret) { int i; GENERAL_NAME *gen; @@ -103,8 +97,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) { - char oline[256]; unsigned char *p; + char oline[256]; switch (gen->type) { case GEN_OTHERNAME: @@ -155,13 +149,66 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, return ret; } -static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) +{ + unsigned char *p; + switch (gen->type) + { + case GEN_OTHERNAME: + BIO_printf(out, "othername:"); + break; + + case GEN_X400: + BIO_printf(out, "X400Name:"); + break; + + case GEN_EDIPARTY: + /* Maybe fix this: it is supported now */ + BIO_printf(out, "EdiPartyName:"); + break; + + case GEN_EMAIL: + BIO_printf(out, "email:%s",gen->d.ia5->data); + break; + + case GEN_DNS: + BIO_printf(out, "DNS:%s",gen->d.ia5->data); + break; + + case GEN_URI: + BIO_printf(out, "URI:%s",gen->d.ia5->data); + break; + + case GEN_DIRNAME: + BIO_printf(out, "DirName: "); + X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); + break; + + case GEN_IPADD: + p = gen->d.ip->data; + /* BUG: doesn't support IPV6 */ + if(gen->d.ip->length != 4) { + BIO_printf(out,"IP Address:"); + break; + } + BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + break; + + case GEN_RID: + BIO_printf(out, "Registered ID"); + i2a_ASN1_OBJECT(out, gen->d.rid); + break; + } + return 1; +} + +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { - STACK_OF(GENERAL_NAME) *gens = NULL; + GENERAL_NAMES *gens = NULL; CONF_VALUE *cnf; int i; - if(!(gens = sk_GENERAL_NAME_new(NULL))) { + if(!(gens = sk_GENERAL_NAME_new_null())) { X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); return NULL; } @@ -185,9 +232,9 @@ static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, /* Append subject altname of issuer to issuer alt name of subject */ -static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) { - STACK_OF(GENERAL_NAME) *ialt; + GENERAL_NAMES *ialt; GENERAL_NAME *gen; X509_EXTENSION *ext; int i; @@ -220,13 +267,13 @@ static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) } -static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { - STACK_OF(GENERAL_NAME) *gens = NULL; + GENERAL_NAMES *gens = NULL; CONF_VALUE *cnf; int i; - if(!(gens = sk_GENERAL_NAME_new(NULL))) { + if(!(gens = sk_GENERAL_NAME_new_null())) { X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); return NULL; } @@ -234,7 +281,10 @@ static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, cnf = sk_CONF_VALUE_value(nval, i); if(!name_cmp(cnf->name, "email") && cnf->value && !strcmp(cnf->value, "copy")) { - if(!copy_email(ctx, gens)) goto err; + if(!copy_email(ctx, gens, 0)) goto err; + } else if(!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "move")) { + if(!copy_email(ctx, gens, 1)) goto err; } else { GENERAL_NAME *gen; if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) @@ -252,7 +302,7 @@ static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, * GENERAL_NAMES */ -static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) { X509_NAME *nm; ASN1_IA5STRING *email = NULL; @@ -271,9 +321,14 @@ static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) /* Now add any email address(es) to STACK */ i = -1; while((i = X509_NAME_get_index_by_NID(nm, - NID_pkcs9_emailAddress, i)) > 0) { + NID_pkcs9_emailAddress, i)) >= 0) { ne = X509_NAME_get_entry(nm, i); - email = ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); + email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if (move_p) + { + X509_NAME_delete_entry(nm, i); + i--; + } if(!email || !(gen = GENERAL_NAME_new())) { X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); goto err; @@ -293,19 +348,19 @@ static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) err: GENERAL_NAME_free(gen); - ASN1_IA5STRING_free(email); + M_ASN1_IA5STRING_free(email); return 0; } -STACK_OF(GENERAL_NAME) *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, +GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { GENERAL_NAME *gen; - STACK_OF(GENERAL_NAME) *gens = NULL; + GENERAL_NAMES *gens = NULL; CONF_VALUE *cnf; int i; - if(!(gens = sk_GENERAL_NAME_new(NULL))) { + if(!(gens = sk_GENERAL_NAME_new_null())) { X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); return NULL; } @@ -371,7 +426,7 @@ if(!name_cmp(name, "email")) { goto err; } ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4; - if(!(gen->d.ip = ASN1_OCTET_STRING_new()) || + if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) || !ASN1_STRING_set(gen->d.ip, ip, 4)) { X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); goto err; @@ -384,7 +439,7 @@ if(!name_cmp(name, "email")) { } if(is_string) { - if(!(gen->d.ia5 = ASN1_IA5STRING_new()) || + if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value, strlen(value))) { X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); diff --git a/src/lib/libcrypto/x509v3/v3_bcons.c b/src/lib/libcrypto/x509v3/v3_bcons.c index de2f855c35..cbb012715e 100644 --- a/src/lib/libcrypto/x509v3/v3_bcons.c +++ b/src/lib/libcrypto/x509v3/v3_bcons.c @@ -60,7 +60,7 @@ #include #include "cryptlib.h" #include -#include +#include #include #include @@ -69,62 +69,22 @@ static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, X509V X509V3_EXT_METHOD v3_bcons = { NID_basic_constraints, 0, -(X509V3_EXT_NEW)BASIC_CONSTRAINTS_new, -(X509V3_EXT_FREE)BASIC_CONSTRAINTS_free, -(X509V3_EXT_D2I)d2i_BASIC_CONSTRAINTS, -(X509V3_EXT_I2D)i2d_BASIC_CONSTRAINTS, -NULL, NULL, +ASN1_ITEM_ref(BASIC_CONSTRAINTS), +0,0,0,0, +0,0, (X509V3_EXT_I2V)i2v_BASIC_CONSTRAINTS, (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS, NULL,NULL, NULL }; +ASN1_SEQUENCE(BASIC_CONSTRAINTS) = { + ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN), + ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER) +} ASN1_SEQUENCE_END(BASIC_CONSTRAINTS) -int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - if(a->ca) M_ASN1_I2D_len (a->ca, i2d_ASN1_BOOLEAN); - M_ASN1_I2D_len (a->pathlen, i2d_ASN1_INTEGER); - - M_ASN1_I2D_seq_total(); - - if (a->ca) M_ASN1_I2D_put (a->ca, i2d_ASN1_BOOLEAN); - M_ASN1_I2D_put (a->pathlen, i2d_ASN1_INTEGER); - M_ASN1_I2D_finish(); -} - -BASIC_CONSTRAINTS *BASIC_CONSTRAINTS_new(void) -{ - BASIC_CONSTRAINTS *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, BASIC_CONSTRAINTS); - ret->ca = 0; - ret->pathlen = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_BASIC_CONSTRAINTS_NEW); -} +IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) -BASIC_CONSTRAINTS *d2i_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS **a, - unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,BASIC_CONSTRAINTS *,BASIC_CONSTRAINTS_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - if((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == - (V_ASN1_UNIVERSAL|V_ASN1_BOOLEAN) ) { - M_ASN1_D2I_get_int (ret->ca, d2i_ASN1_BOOLEAN); - } - M_ASN1_D2I_get_opt (ret->pathlen, d2i_ASN1_INTEGER, V_ASN1_INTEGER); - M_ASN1_D2I_Finish(a, BASIC_CONSTRAINTS_free, ASN1_F_D2I_BASIC_CONSTRAINTS); -} - -void BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a) -{ - if (a == NULL) return; - ASN1_INTEGER_free (a->pathlen); - Free ((char *)a); -} static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist) diff --git a/src/lib/libcrypto/x509v3/v3_bitst.c b/src/lib/libcrypto/x509v3/v3_bitst.c index 9828ba15b3..16cf125562 100644 --- a/src/lib/libcrypto/x509v3/v3_bitst.c +++ b/src/lib/libcrypto/x509v3/v3_bitst.c @@ -61,12 +61,12 @@ #include #include -static ASN1_BIT_STRING *asn1_bit_string_new(void); static ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); static STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, ASN1_BIT_STRING *bits, STACK_OF(CONF_VALUE) *extlist); + static BIT_STRING_BITNAME ns_cert_type_table[] = { {0, "SSL Client", "client"}, {1, "SSL Server", "server"}, @@ -97,11 +97,6 @@ static BIT_STRING_BITNAME key_usage_type_table[] = { X509V3_EXT_METHOD v3_nscert = EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table); X509V3_EXT_METHOD v3_key_usage = EXT_BITSTRING(NID_key_usage, key_usage_type_table); -static ASN1_BIT_STRING *asn1_bit_string_new(void) -{ - return ASN1_BIT_STRING_new(); -} - static STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, ASN1_BIT_STRING *bits, STACK_OF(CONF_VALUE) *ret) { @@ -120,7 +115,7 @@ static ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, ASN1_BIT_STRING *bs; int i; BIT_STRING_BITNAME *bnam; - if(!(bs = ASN1_BIT_STRING_new())) { + if(!(bs = M_ASN1_BIT_STRING_new())) { X509V3err(X509V3_F_V2I_ASN1_BIT_STRING,ERR_R_MALLOC_FAILURE); return NULL; } @@ -137,7 +132,7 @@ static ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, X509V3err(X509V3_F_V2I_ASN1_BIT_STRING, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); X509V3_conf_err(val); - ASN1_BIT_STRING_free(bs); + M_ASN1_BIT_STRING_free(bs); return NULL; } } diff --git a/src/lib/libcrypto/x509v3/v3_conf.c b/src/lib/libcrypto/x509v3/v3_conf.c index f19bb3ad84..1a3448e121 100644 --- a/src/lib/libcrypto/x509v3/v3_conf.c +++ b/src/lib/libcrypto/x509v3/v3_conf.c @@ -68,115 +68,138 @@ static int v3_check_critical(char **value); static int v3_check_generic(char **value); -static X509_EXTENSION *do_ext_conf(LHASH *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value); +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value); static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type); static char *conf_lhash_get_string(void *db, char *section, char *value); static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section); static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, int crit, void *ext_struc); -/* LHASH *conf: Config file */ +/* CONF *conf: Config file */ /* char *name: Name */ /* char *value: Value */ -X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value) -{ + { int crit; int ext_type; X509_EXTENSION *ret; crit = v3_check_critical(&value); - if((ext_type = v3_check_generic(&value))) + if ((ext_type = v3_check_generic(&value))) return v3_generic_extension(name, value, crit, ext_type); - ret = do_ext_conf(conf, ctx, OBJ_sn2nid(name), crit, value); - if(!ret) { + ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); + if (!ret) + { X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_ERROR_IN_EXTENSION); ERR_add_error_data(4,"name=", name, ", value=", value); - } + } return ret; -} + } -/* LHASH *conf: Config file */ +/* CONF *conf: Config file */ /* char *value: Value */ -X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value) -{ + { int crit; int ext_type; crit = v3_check_critical(&value); - if((ext_type = v3_check_generic(&value))) + if ((ext_type = v3_check_generic(&value))) return v3_generic_extension(OBJ_nid2sn(ext_nid), value, crit, ext_type); - return do_ext_conf(conf, ctx, ext_nid, crit, value); -} + return do_ext_nconf(conf, ctx, ext_nid, crit, value); + } -/* LHASH *conf: Config file */ +/* CONF *conf: Config file */ /* char *value: Value */ -static X509_EXTENSION *do_ext_conf(LHASH *conf, X509V3_CTX *ctx, int ext_nid, +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value) -{ + { X509V3_EXT_METHOD *method; X509_EXTENSION *ext; STACK_OF(CONF_VALUE) *nval; void *ext_struc; - if(ext_nid == NID_undef) { + if (ext_nid == NID_undef) + { X509V3err(X509V3_F_DO_EXT_CONF,X509V3_R_UNKNOWN_EXTENSION_NAME); return NULL; - } - if(!(method = X509V3_EXT_get_nid(ext_nid))) { + } + if (!(method = X509V3_EXT_get_nid(ext_nid))) + { X509V3err(X509V3_F_DO_EXT_CONF,X509V3_R_UNKNOWN_EXTENSION); return NULL; - } + } /* Now get internal extension representation based on type */ - if(method->v2i) { - if(*value == '@') nval = CONF_get_section(conf, value + 1); + if (method->v2i) + { + if(*value == '@') nval = NCONF_get_section(conf, value + 1); else nval = X509V3_parse_list(value); - if(!nval) { + if(!nval) + { X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_INVALID_EXTENSION_STRING); ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value); return NULL; - } + } ext_struc = method->v2i(method, ctx, nval); if(*value != '@') sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); if(!ext_struc) return NULL; - } else if(method->s2i) { + } + else if(method->s2i) + { if(!(ext_struc = method->s2i(method, ctx, value))) return NULL; - } else if(method->r2i) { - if(!ctx->db) { + } + else if(method->r2i) + { + if(!ctx->db) + { X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_NO_CONFIG_DATABASE); return NULL; - } + } if(!(ext_struc = method->r2i(method, ctx, value))) return NULL; - } else { + } + else + { X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); return NULL; - } + } ext = do_ext_i2d(method, ext_nid, crit, ext_struc); - method->ext_free(ext_struc); + if(method->it) ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); + else method->ext_free(ext_struc); return ext; -} + } static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, int crit, void *ext_struc) -{ - unsigned char *ext_der, *p; + { + unsigned char *ext_der; int ext_len; ASN1_OCTET_STRING *ext_oct; X509_EXTENSION *ext; /* Convert internal representation to DER */ - ext_len = method->i2d(ext_struc, NULL); - if(!(ext_der = Malloc(ext_len))) goto merr; - p = ext_der; - method->i2d(ext_struc, &p); - if(!(ext_oct = ASN1_OCTET_STRING_new())) goto merr; + if (method->it) + { + ext_der = NULL; + ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); + if (ext_len < 0) goto merr; + } + else + { + unsigned char *p; + ext_len = method->i2d(ext_struc, NULL); + if(!(ext_der = OPENSSL_malloc(ext_len))) goto merr; + p = ext_der; + method->i2d(ext_struc, &p); + } + if (!(ext_oct = M_ASN1_OCTET_STRING_new())) goto merr; ext_oct->data = ext_der; ext_oct->length = ext_len; - + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); - if(!ext) goto merr; - ASN1_OCTET_STRING_free(ext_oct); + if (!ext) goto merr; + M_ASN1_OCTET_STRING_free(ext_oct); return ext; @@ -184,14 +207,14 @@ static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, X509V3err(X509V3_F_DO_EXT_I2D,ERR_R_MALLOC_FAILURE); return NULL; -} + } /* Given an internal structure, nid and critical flag create an extension */ X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) -{ + { X509V3_EXT_METHOD *method; - if(!(method = X509V3_EXT_get_nid(ext_nid))) { + if (!(method = X509V3_EXT_get_nid(ext_nid))) { X509V3err(X509V3_F_X509V3_EXT_I2D,X509V3_R_UNKNOWN_EXTENSION); return NULL; } @@ -202,7 +225,7 @@ X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) static int v3_check_critical(char **value) { char *p = *value; - if((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0; + if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0; p+=9; while(isspace((unsigned char)*p)) p++; *value = p; @@ -213,134 +236,212 @@ static int v3_check_critical(char **value) static int v3_check_generic(char **value) { char *p = *value; - if((strlen(p) < 4) || strncmp(p, "DER:,", 4)) return 0; + if ((strlen(p) < 4) || strncmp(p, "DER:,", 4)) return 0; p+=4; - while(isspace((unsigned char)*p)) p++; + while (isspace((unsigned char)*p)) p++; *value = p; return 1; } -/* Create a generic extension: for now just handle RAW type */ +/* Create a generic extension: for now just handle DER type */ static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type) -{ -unsigned char *ext_der=NULL; -long ext_len; -ASN1_OBJECT *obj=NULL; -ASN1_OCTET_STRING *oct=NULL; -X509_EXTENSION *extension=NULL; -if(!(obj = OBJ_txt2obj(ext, 0))) { - X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_NAME_ERROR); - ERR_add_error_data(2, "name=", ext); - goto err; -} + { + unsigned char *ext_der=NULL; + long ext_len; + ASN1_OBJECT *obj=NULL; + ASN1_OCTET_STRING *oct=NULL; + X509_EXTENSION *extension=NULL; + if (!(obj = OBJ_txt2obj(ext, 0))) + { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_NAME_ERROR); + ERR_add_error_data(2, "name=", ext); + goto err; + } -if(!(ext_der = string_to_hex(value, &ext_len))) { - X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR); - ERR_add_error_data(2, "value=", value); - goto err; -} + if (!(ext_der = string_to_hex(value, &ext_len))) + { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR); + ERR_add_error_data(2, "value=", value); + goto err; + } -if(!(oct = ASN1_OCTET_STRING_new())) { - X509V3err(X509V3_F_V3_GENERIC_EXTENSION,ERR_R_MALLOC_FAILURE); - goto err; -} + if (!(oct = M_ASN1_OCTET_STRING_new())) + { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,ERR_R_MALLOC_FAILURE); + goto err; + } -oct->data = ext_der; -oct->length = ext_len; -ext_der = NULL; + oct->data = ext_der; + oct->length = ext_len; + ext_der = NULL; -extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); -err: -ASN1_OBJECT_free(obj); -ASN1_OCTET_STRING_free(oct); -if(ext_der) Free(ext_der); -return extension; -} + err: + ASN1_OBJECT_free(obj); + M_ASN1_OCTET_STRING_free(oct); + if(ext_der) OPENSSL_free(ext_der); + return extension; + + } /* This is the main function: add a bunch of extensions based on a config file - * section + * section to an extension STACK. */ -int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, - X509 *cert) -{ + +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, + STACK_OF(X509_EXTENSION) **sk) + { X509_EXTENSION *ext; STACK_OF(CONF_VALUE) *nval; CONF_VALUE *val; int i; - if(!(nval = CONF_get_section(conf, section))) return 0; - for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + if (!(nval = NCONF_get_section(conf, section))) return 0; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) + { val = sk_CONF_VALUE_value(nval, i); - if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value))) + if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value))) return 0; - if(cert) X509_add_ext(cert, ext, -1); + if (sk) X509v3_add_ext(sk, ext, -1); X509_EXTENSION_free(ext); - } + } return 1; -} + } + +/* Convenience functions to add extensions to a certificate, CRL and request */ + +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509 *cert) + { + STACK_OF(X509_EXTENSION) **sk = NULL; + if (cert) + sk = &cert->cert_info->extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + } /* Same as above but for a CRL */ -int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl) -{ - X509_EXTENSION *ext; - STACK_OF(CONF_VALUE) *nval; - CONF_VALUE *val; + { + STACK_OF(X509_EXTENSION) **sk = NULL; + if (crl) + sk = &crl->crl->extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + } + +/* Add extensions to certificate request */ + +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509_REQ *req) + { + STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; int i; - if(!(nval = CONF_get_section(conf, section))) return 0; - for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value))) - return 0; - if(crl) X509_CRL_add_ext(crl, ext, -1); - X509_EXTENSION_free(ext); + if (req) + sk = &extlist; + i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + if (!i || !sk) + return i; + i = X509_REQ_add_extensions(req, extlist); + sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); + return i; } - return 1; -} /* Config database functions */ char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section) -{ - if(ctx->db_meth->get_string) + { + if (ctx->db_meth->get_string) return ctx->db_meth->get_string(ctx->db, name, section); return NULL; -} + } STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section) -{ - if(ctx->db_meth->get_section) + { + if (ctx->db_meth->get_section) return ctx->db_meth->get_section(ctx->db, section); return NULL; -} + } void X509V3_string_free(X509V3_CTX *ctx, char *str) -{ - if(!str) return; - if(ctx->db_meth->free_string) + { + if (!str) return; + if (ctx->db_meth->free_string) ctx->db_meth->free_string(ctx->db, str); -} + } void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) -{ - if(!section) return; - if(ctx->db_meth->free_section) + { + if (!section) return; + if (ctx->db_meth->free_section) ctx->db_meth->free_section(ctx->db, section); -} + } + +static char *nconf_get_string(void *db, char *section, char *value) + { + return NCONF_get_string(db, section, value); + } + +static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section) + { + return NCONF_get_section(db, section); + } + +static X509V3_CONF_METHOD nconf_method = { +nconf_get_string, +nconf_get_section, +NULL, +NULL +}; + +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) + { + ctx->db_meth = &nconf_method; + ctx->db = conf; + } + +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, + X509_CRL *crl, int flags) + { + ctx->issuer_cert = issuer; + ctx->subject_cert = subj; + ctx->crl = crl; + ctx->subject_req = req; + ctx->flags = flags; + } + +/* Old conf compatibility functions */ + +X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, + char *value) + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_nconf(&ctmp, ctx, name, value); + } + +/* LHASH *conf: Config file */ +/* char *value: Value */ +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, + char *value) + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value); + } static char *conf_lhash_get_string(void *db, char *section, char *value) -{ + { return CONF_get_string(db, section, value); -} + } static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section) -{ + { return CONF_get_section(db, section); -} + } static X509V3_CONF_METHOD conf_lhash_method = { conf_lhash_get_string, @@ -350,17 +451,35 @@ NULL }; void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash) -{ + { ctx->db_meth = &conf_lhash_method; ctx->db = lhash; -} + } -void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, - X509_CRL *crl, int flags) -{ - ctx->issuer_cert = issuer; - ctx->subject_cert = subj; - ctx->crl = crl; - ctx->subject_req = req; - ctx->flags = flags; -} +int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509 *cert) + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert); + } + +/* Same as above but for a CRL */ + +int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509_CRL *crl) + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl); + } + +/* Add extensions to certificate request */ + +int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, + X509_REQ *req) + { + CONF ctmp; + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req); + } diff --git a/src/lib/libcrypto/x509v3/v3_cpols.c b/src/lib/libcrypto/x509v3/v3_cpols.c index b4d4883545..0d4ab1f680 100644 --- a/src/lib/libcrypto/x509v3/v3_cpols.c +++ b/src/lib/libcrypto/x509v3/v3_cpols.c @@ -60,7 +60,7 @@ #include "cryptlib.h" #include #include -#include +#include #include /* Certificate policies extension support: this one is a bit complex... */ @@ -73,21 +73,58 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *polstrs, int ia5org); static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *unot, int ia5org); -static STACK *nref_nos(STACK_OF(CONF_VALUE) *nos); +static STACK_OF(ASN1_INTEGER) *nref_nos(STACK_OF(CONF_VALUE) *nos); X509V3_EXT_METHOD v3_cpols = { -NID_certificate_policies, 0, -(X509V3_EXT_NEW)CERTIFICATEPOLICIES_new, -(X509V3_EXT_FREE)CERTIFICATEPOLICIES_free, -(X509V3_EXT_D2I)d2i_CERTIFICATEPOLICIES, -(X509V3_EXT_I2D)i2d_CERTIFICATEPOLICIES, -NULL, NULL, -NULL, NULL, +NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES), +0,0,0,0, +0,0, +0,0, (X509V3_EXT_I2R)i2r_certpol, (X509V3_EXT_R2I)r2i_certpol, NULL }; +ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) +ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES) + +IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) + +ASN1_SEQUENCE(POLICYINFO) = { + ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), + ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO) +} ASN1_SEQUENCE_END(POLICYINFO) + +IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO) + +ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY); + +ASN1_ADB(POLICYQUALINFO) = { + ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), + ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)) +} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL); + +ASN1_SEQUENCE(POLICYQUALINFO) = { + ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), + ASN1_ADB_OBJECT(POLICYQUALINFO) +} ASN1_SEQUENCE_END(POLICYQUALINFO) + +IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO) + +ASN1_SEQUENCE(USERNOTICE) = { + ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), + ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT) +} ASN1_SEQUENCE_END(USERNOTICE) + +IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE) + +ASN1_SEQUENCE(NOTICEREF) = { + ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), + ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER) +} ASN1_SEQUENCE_END(NOTICEREF) + +IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF) static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value) @@ -169,7 +206,7 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) goto merr; qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); - qual->d.cpsuri = ASN1_IA5STRING_new(); + qual->d.cpsuri = M_ASN1_IA5STRING_new(); if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value, strlen(cnf->value))) goto merr; } else if(!name_cmp(cnf->name, "userNotice")) { @@ -229,7 +266,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, for(i = 0; i < sk_CONF_VALUE_num(unot); i++) { cnf = sk_CONF_VALUE_value(unot, i); if(!strcmp(cnf->name, "explicitText")) { - not->exptext = ASN1_VISIBLESTRING_new(); + not->exptext = M_ASN1_VISIBLESTRING_new(); if(!ASN1_STRING_set(not->exptext, cnf->value, strlen(cnf->value))) goto merr; } else if(!strcmp(cnf->name, "organization")) { @@ -238,8 +275,8 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, if(!(nref = NOTICEREF_new())) goto merr; not->noticeref = nref; } else nref = not->noticeref; - if(ia5org) nref->organization = ASN1_IA5STRING_new(); - else nref->organization = ASN1_VISIBLESTRING_new(); + if(ia5org) nref->organization = M_ASN1_IA5STRING_new(); + else nref->organization = M_ASN1_VISIBLESTRING_new(); if(!ASN1_STRING_set(nref->organization, cnf->value, strlen(cnf->value))) goto merr; } else if(!strcmp(cnf->name, "noticeNumbers")) { @@ -282,20 +319,22 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, return NULL; } -static STACK *nref_nos(STACK_OF(CONF_VALUE) *nos) +static STACK_OF(ASN1_INTEGER) *nref_nos(STACK_OF(CONF_VALUE) *nos) { - STACK *nnums; + STACK_OF(ASN1_INTEGER) *nnums; CONF_VALUE *cnf; ASN1_INTEGER *aint; + int i; - if(!(nnums = sk_new_null())) goto merr; + + if(!(nnums = sk_ASN1_INTEGER_new_null())) goto merr; for(i = 0; i < sk_CONF_VALUE_num(nos); i++) { cnf = sk_CONF_VALUE_value(nos, i); if(!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { X509V3err(X509V3_F_NREF_NOS,X509V3_R_INVALID_NUMBER); goto err; } - if(!sk_push(nnums, (char *)aint)) goto merr; + if(!sk_ASN1_INTEGER_push(nnums, aint)) goto merr; } return nnums; @@ -303,7 +342,7 @@ static STACK *nref_nos(STACK_OF(CONF_VALUE) *nos) X509V3err(X509V3_F_NOTICE_SECTION,ERR_R_MALLOC_FAILURE); err: - sk_pop_free(nnums, ASN1_STRING_free); + sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); return NULL; } @@ -325,83 +364,6 @@ static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, return 1; } - -int i2d_CERTIFICATEPOLICIES(STACK_OF(POLICYINFO) *a, unsigned char **pp) -{ - -return i2d_ASN1_SET_OF_POLICYINFO(a, pp, i2d_POLICYINFO, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE);} - -STACK_OF(POLICYINFO) *CERTIFICATEPOLICIES_new(void) -{ - return sk_POLICYINFO_new_null(); -} - -void CERTIFICATEPOLICIES_free(STACK_OF(POLICYINFO) *a) -{ - sk_POLICYINFO_pop_free(a, POLICYINFO_free); -} - -STACK_OF(POLICYINFO) *d2i_CERTIFICATEPOLICIES(STACK_OF(POLICYINFO) **a, - unsigned char **pp,long length) -{ -return d2i_ASN1_SET_OF_POLICYINFO(a, pp, length, d2i_POLICYINFO, - POLICYINFO_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); - -} - -IMPLEMENT_STACK_OF(POLICYINFO) -IMPLEMENT_ASN1_SET_OF(POLICYINFO) - -int i2d_POLICYINFO(POLICYINFO *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->policyid, i2d_ASN1_OBJECT); - M_ASN1_I2D_len_SEQUENCE_type(POLICYQUALINFO, a->qualifiers, - i2d_POLICYQUALINFO); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->policyid, i2d_ASN1_OBJECT); - M_ASN1_I2D_put_SEQUENCE_type(POLICYQUALINFO, a->qualifiers, - i2d_POLICYQUALINFO); - - M_ASN1_I2D_finish(); -} - -POLICYINFO *POLICYINFO_new(void) -{ - POLICYINFO *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, POLICYINFO); - ret->policyid = NULL; - ret->qualifiers = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_POLICYINFO_NEW); -} - -POLICYINFO *d2i_POLICYINFO(POLICYINFO **a, unsigned char **pp,long length) -{ - M_ASN1_D2I_vars(a,POLICYINFO *,POLICYINFO_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->policyid, d2i_ASN1_OBJECT); - if(!M_ASN1_D2I_end_sequence()) { - M_ASN1_D2I_get_seq_type (POLICYQUALINFO, ret->qualifiers, - d2i_POLICYQUALINFO, POLICYQUALINFO_free); - } - M_ASN1_D2I_Finish(a, POLICYINFO_free, ASN1_F_D2I_POLICYINFO); -} - -void POLICYINFO_free(POLICYINFO *a) -{ - if (a == NULL) return; - ASN1_OBJECT_free(a->policyid); - sk_POLICYQUALINFO_pop_free(a->qualifiers, POLICYQUALINFO_free); - Free (a); -} - static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent) { @@ -441,15 +403,15 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent) BIO_printf(out, "%*sOrganization: %s\n", indent, "", ref->organization->data); BIO_printf(out, "%*sNumber%s: ", indent, "", - (sk_num(ref->noticenos) > 1) ? "s" : ""); - for(i = 0; i < sk_num(ref->noticenos); i++) { + sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); + for(i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { ASN1_INTEGER *num; char *tmp; - num = (ASN1_INTEGER *)sk_value(ref->noticenos, i); + num = sk_ASN1_INTEGER_value(ref->noticenos, i); if(i) BIO_puts(out, ", "); tmp = i2s_ASN1_INTEGER(NULL, num); BIO_puts(out, tmp); - Free(tmp); + OPENSSL_free(tmp); } BIO_puts(out, "\n"); } @@ -457,199 +419,4 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent) BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", notice->exptext->data); } - - - -int i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->pqualid, i2d_ASN1_OBJECT); - switch(OBJ_obj2nid(a->pqualid)) { - case NID_id_qt_cps: - M_ASN1_I2D_len(a->d.cpsuri, i2d_ASN1_IA5STRING); - break; - - case NID_id_qt_unotice: - M_ASN1_I2D_len(a->d.usernotice, i2d_USERNOTICE); - break; - - default: - M_ASN1_I2D_len(a->d.other, i2d_ASN1_TYPE); - break; - } - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->pqualid, i2d_ASN1_OBJECT); - switch(OBJ_obj2nid(a->pqualid)) { - case NID_id_qt_cps: - M_ASN1_I2D_put(a->d.cpsuri, i2d_ASN1_IA5STRING); - break; - - case NID_id_qt_unotice: - M_ASN1_I2D_put(a->d.usernotice, i2d_USERNOTICE); - break; - - default: - M_ASN1_I2D_put(a->d.other, i2d_ASN1_TYPE); - break; - } - - M_ASN1_I2D_finish(); -} - -POLICYQUALINFO *POLICYQUALINFO_new(void) -{ - POLICYQUALINFO *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, POLICYQUALINFO); - ret->pqualid = NULL; - ret->d.other = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_POLICYQUALINFO_NEW); -} - -POLICYQUALINFO *d2i_POLICYQUALINFO(POLICYQUALINFO **a, unsigned char **pp, - long length) -{ - M_ASN1_D2I_vars(a,POLICYQUALINFO *,POLICYQUALINFO_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->pqualid, d2i_ASN1_OBJECT); - switch(OBJ_obj2nid(ret->pqualid)) { - case NID_id_qt_cps: - M_ASN1_D2I_get(ret->d.cpsuri, d2i_ASN1_IA5STRING); - break; - - case NID_id_qt_unotice: - M_ASN1_D2I_get(ret->d.usernotice, d2i_USERNOTICE); - break; - - default: - M_ASN1_D2I_get(ret->d.other, d2i_ASN1_TYPE); - break; - } - M_ASN1_D2I_Finish(a, POLICYQUALINFO_free, ASN1_F_D2I_POLICYQUALINFO); -} - -void POLICYQUALINFO_free(POLICYQUALINFO *a) -{ - if (a == NULL) return; - switch(OBJ_obj2nid(a->pqualid)) { - case NID_id_qt_cps: - ASN1_IA5STRING_free(a->d.cpsuri); - break; - - case NID_id_qt_unotice: - USERNOTICE_free(a->d.usernotice); - break; - - default: - ASN1_TYPE_free(a->d.other); - break; - } - - ASN1_OBJECT_free(a->pqualid); - Free (a); -} - -int i2d_USERNOTICE(USERNOTICE *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->noticeref, i2d_NOTICEREF); - M_ASN1_I2D_len (a->exptext, i2d_DISPLAYTEXT); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->noticeref, i2d_NOTICEREF); - M_ASN1_I2D_put (a->exptext, i2d_DISPLAYTEXT); - - M_ASN1_I2D_finish(); -} - -USERNOTICE *USERNOTICE_new(void) -{ - USERNOTICE *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, USERNOTICE); - ret->noticeref = NULL; - ret->exptext = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_USERNOTICE_NEW); -} - -USERNOTICE *d2i_USERNOTICE(USERNOTICE **a, unsigned char **pp,long length) -{ - M_ASN1_D2I_vars(a,USERNOTICE *,USERNOTICE_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get_opt(ret->noticeref, d2i_NOTICEREF, V_ASN1_SEQUENCE); - if (!M_ASN1_D2I_end_sequence()) { - M_ASN1_D2I_get(ret->exptext, d2i_DISPLAYTEXT); - } - M_ASN1_D2I_Finish(a, USERNOTICE_free, ASN1_F_D2I_USERNOTICE); -} - -void USERNOTICE_free(USERNOTICE *a) -{ - if (a == NULL) return; - NOTICEREF_free(a->noticeref); - DISPLAYTEXT_free(a->exptext); - Free (a); -} - -int i2d_NOTICEREF(NOTICEREF *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->organization, i2d_DISPLAYTEXT); - M_ASN1_I2D_len_SEQUENCE(a->noticenos, i2d_ASN1_INTEGER); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->organization, i2d_DISPLAYTEXT); - M_ASN1_I2D_put_SEQUENCE(a->noticenos, i2d_ASN1_INTEGER); - - M_ASN1_I2D_finish(); -} - -NOTICEREF *NOTICEREF_new(void) -{ - NOTICEREF *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, NOTICEREF); - ret->organization = NULL; - ret->noticenos = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_NOTICEREF_NEW); -} - -NOTICEREF *d2i_NOTICEREF(NOTICEREF **a, unsigned char **pp,long length) -{ - M_ASN1_D2I_vars(a,NOTICEREF *,NOTICEREF_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - /* This is to cope with some broken encodings that use IA5STRING for - * the organization field - */ - M_ASN1_D2I_get_opt(ret->organization, d2i_ASN1_IA5STRING, - V_ASN1_IA5STRING); - if(!ret->organization) { - M_ASN1_D2I_get(ret->organization, d2i_DISPLAYTEXT); - } - M_ASN1_D2I_get_seq(ret->noticenos, d2i_ASN1_INTEGER, ASN1_STRING_free); - M_ASN1_D2I_Finish(a, NOTICEREF_free, ASN1_F_D2I_NOTICEREF); -} - -void NOTICEREF_free(NOTICEREF *a) -{ - if (a == NULL) return; - DISPLAYTEXT_free(a->organization); - sk_pop_free(a->noticenos, ASN1_STRING_free); - Free (a); -} -IMPLEMENT_STACK_OF(POLICYQUALINFO) -IMPLEMENT_ASN1_SET_OF(POLICYQUALINFO) diff --git a/src/lib/libcrypto/x509v3/v3_crld.c b/src/lib/libcrypto/x509v3/v3_crld.c index 897ffb63e4..894a8b94d8 100644 --- a/src/lib/libcrypto/x509v3/v3_crld.c +++ b/src/lib/libcrypto/x509v3/v3_crld.c @@ -60,7 +60,7 @@ #include "cryptlib.h" #include #include -#include +#include #include static STACK_OF(CONF_VALUE) *i2v_crld(X509V3_EXT_METHOD *method, @@ -69,15 +69,13 @@ static STACK_OF(DIST_POINT) *v2i_crld(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); X509V3_EXT_METHOD v3_crld = { -NID_crl_distribution_points, X509V3_EXT_MULTILINE, -(X509V3_EXT_NEW)CRL_DIST_POINTS_new, -(X509V3_EXT_FREE)CRL_DIST_POINTS_free, -(X509V3_EXT_D2I)d2i_CRL_DIST_POINTS, -(X509V3_EXT_I2D)i2d_CRL_DIST_POINTS, -NULL, NULL, +NID_crl_distribution_points, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(CRL_DIST_POINTS), +0,0,0,0, +0,0, (X509V3_EXT_I2V)i2v_crld, (X509V3_EXT_V2I)v2i_crld, -NULL, NULL, NULL +0,0, +NULL }; static STACK_OF(CONF_VALUE) *i2v_crld(X509V3_EXT_METHOD *method, @@ -87,16 +85,16 @@ static STACK_OF(CONF_VALUE) *i2v_crld(X509V3_EXT_METHOD *method, int i; for(i = 0; i < sk_DIST_POINT_num(crld); i++) { point = sk_DIST_POINT_value(crld, i); - if(point->distpoint->fullname) { - exts = i2v_GENERAL_NAMES(NULL, - point->distpoint->fullname, exts); + if(point->distpoint) { + if(point->distpoint->type == 0) + exts = i2v_GENERAL_NAMES(NULL, + point->distpoint->name.fullname, exts); + else X509V3_add_value("RelativeName","", &exts); } if(point->reasons) X509V3_add_value("reasons","", &exts); if(point->CRLissuer) X509V3_add_value("CRLissuer","", &exts); - if(point->distpoint->relativename) - X509V3_add_value("RelativeName","", &exts); } return exts; } @@ -105,11 +103,11 @@ static STACK_OF(DIST_POINT) *v2i_crld(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { STACK_OF(DIST_POINT) *crld = NULL; - STACK_OF(GENERAL_NAME) *gens = NULL; + GENERAL_NAMES *gens = NULL; GENERAL_NAME *gen = NULL; CONF_VALUE *cnf; int i; - if(!(crld = sk_DIST_POINT_new(NULL))) goto merr; + if(!(crld = sk_DIST_POINT_new_null())) goto merr; for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { DIST_POINT *point; cnf = sk_CONF_VALUE_value(nval, i); @@ -123,7 +121,8 @@ static STACK_OF(DIST_POINT) *v2i_crld(X509V3_EXT_METHOD *method, goto merr; } if(!(point->distpoint = DIST_POINT_NAME_new())) goto merr; - point->distpoint->fullname = gens; + point->distpoint->name.fullname = gens; + point->distpoint->type = 0; gens = NULL; } return crld; @@ -137,147 +136,27 @@ static STACK_OF(DIST_POINT) *v2i_crld(X509V3_EXT_METHOD *method, return NULL; } -int i2d_CRL_DIST_POINTS(STACK_OF(DIST_POINT) *a, unsigned char **pp) -{ - -return i2d_ASN1_SET_OF_DIST_POINT(a, pp, i2d_DIST_POINT, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE);} - -STACK_OF(DIST_POINT) *CRL_DIST_POINTS_new(void) -{ - return sk_DIST_POINT_new_null(); -} - -void CRL_DIST_POINTS_free(STACK_OF(DIST_POINT) *a) -{ - sk_DIST_POINT_pop_free(a, DIST_POINT_free); -} - -STACK_OF(DIST_POINT) *d2i_CRL_DIST_POINTS(STACK_OF(DIST_POINT) **a, - unsigned char **pp,long length) -{ -return d2i_ASN1_SET_OF_DIST_POINT(a, pp, length, d2i_DIST_POINT, - DIST_POINT_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); - -} - IMPLEMENT_STACK_OF(DIST_POINT) IMPLEMENT_ASN1_SET_OF(DIST_POINT) -int i2d_DIST_POINT(DIST_POINT *a, unsigned char **pp) -{ - int v = 0; - M_ASN1_I2D_vars(a); - /* NB: underlying type is a CHOICE so need EXPLICIT tagging */ - M_ASN1_I2D_len_EXP_opt (a->distpoint, i2d_DIST_POINT_NAME, 0, v); - M_ASN1_I2D_len_IMP_opt (a->reasons, i2d_ASN1_BIT_STRING); - M_ASN1_I2D_len_IMP_opt (a->CRLissuer, i2d_GENERAL_NAMES); - M_ASN1_I2D_seq_total(); +ASN1_CHOICE(DIST_POINT_NAME) = { + ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0), + ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1) +} ASN1_CHOICE_END(DIST_POINT_NAME) - M_ASN1_I2D_put_EXP_opt (a->distpoint, i2d_DIST_POINT_NAME, 0, v); - M_ASN1_I2D_put_IMP_opt (a->reasons, i2d_ASN1_BIT_STRING, 1); - M_ASN1_I2D_put_IMP_opt (a->CRLissuer, i2d_GENERAL_NAMES, 2); +IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) - M_ASN1_I2D_finish(); -} +ASN1_SEQUENCE(DIST_POINT) = { + ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1), + ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2) +} ASN1_SEQUENCE_END(DIST_POINT) -DIST_POINT *DIST_POINT_new(void) -{ - DIST_POINT *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, DIST_POINT); - ret->distpoint = NULL; - ret->reasons = NULL; - ret->CRLissuer = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_DIST_POINT_NEW); -} +IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT) -DIST_POINT *d2i_DIST_POINT(DIST_POINT **a, unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,DIST_POINT *,DIST_POINT_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get_EXP_opt (ret->distpoint, d2i_DIST_POINT_NAME, 0); - M_ASN1_D2I_get_IMP_opt (ret->reasons, d2i_ASN1_BIT_STRING, 1, - V_ASN1_BIT_STRING); - M_ASN1_D2I_get_IMP_opt (ret->CRLissuer, d2i_GENERAL_NAMES, 2, - V_ASN1_SEQUENCE); - M_ASN1_D2I_Finish(a, DIST_POINT_free, ASN1_F_D2I_DIST_POINT); -} +ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, DIST_POINT, DIST_POINT) +ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS) -void DIST_POINT_free(DIST_POINT *a) -{ - if (a == NULL) return; - DIST_POINT_NAME_free(a->distpoint); - ASN1_BIT_STRING_free(a->reasons); - sk_GENERAL_NAME_pop_free(a->CRLissuer, GENERAL_NAME_free); - Free ((char *)a); -} - -int i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **pp) -{ - int v = 0; - M_ASN1_I2D_vars(a); - - if(a->fullname) { - M_ASN1_I2D_len_IMP_opt (a->fullname, i2d_GENERAL_NAMES); - } else { - M_ASN1_I2D_len_EXP_opt (a->relativename, i2d_X509_NAME, 1, v); - } - - /* Don't want a SEQUENCE so... */ - if(pp == NULL) return ret; - p = *pp; - - if(a->fullname) { - M_ASN1_I2D_put_IMP_opt (a->fullname, i2d_GENERAL_NAMES, 0); - } else { - M_ASN1_I2D_put_EXP_opt (a->relativename, i2d_X509_NAME, 1, v); - } - M_ASN1_I2D_finish(); -} - -DIST_POINT_NAME *DIST_POINT_NAME_new(void) -{ - DIST_POINT_NAME *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, DIST_POINT_NAME); - ret->fullname = NULL; - ret->relativename = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_DIST_POINT_NAME_NEW); -} - -void DIST_POINT_NAME_free(DIST_POINT_NAME *a) -{ - if (a == NULL) return; - X509_NAME_free(a->relativename); - sk_GENERAL_NAME_pop_free(a->fullname, GENERAL_NAME_free); - Free ((char *)a); -} - -DIST_POINT_NAME *d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, unsigned char **pp, - long length) -{ - unsigned char _tmp, tag; - M_ASN1_D2I_vars(a,DIST_POINT_NAME *,DIST_POINT_NAME_new); - M_ASN1_D2I_Init(); - c.slen = length; - - _tmp = M_ASN1_next; - tag = _tmp & ~V_ASN1_CONSTRUCTED; - - if(tag == (0|V_ASN1_CONTEXT_SPECIFIC)) { - M_ASN1_D2I_get_imp(ret->fullname, d2i_GENERAL_NAMES, - V_ASN1_SEQUENCE); - } else if (tag == (1|V_ASN1_CONTEXT_SPECIFIC)) { - M_ASN1_D2I_get_EXP_opt (ret->relativename, d2i_X509_NAME, 1); - } else { - c.error = ASN1_R_BAD_TAG; - goto err; - } - - M_ASN1_D2I_Finish(a, DIST_POINT_NAME_free, ASN1_F_D2I_DIST_POINT_NAME); -} +IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS) diff --git a/src/lib/libcrypto/x509v3/v3_enum.c b/src/lib/libcrypto/x509v3/v3_enum.c index db423548ff..010c9d6260 100644 --- a/src/lib/libcrypto/x509v3/v3_enum.c +++ b/src/lib/libcrypto/x509v3/v3_enum.c @@ -60,8 +60,6 @@ #include "cryptlib.h" #include -static ASN1_ENUMERATED *asn1_enumerated_new(void); - static ENUMERATED_NAMES crl_reasons[] = { {0, "Unspecified", "unspecified"}, {1, "Key Compromise", "keyCompromise"}, @@ -75,20 +73,13 @@ static ENUMERATED_NAMES crl_reasons[] = { }; X509V3_EXT_METHOD v3_crl_reason = { -NID_crl_reason, 0, -(X509V3_EXT_NEW)asn1_enumerated_new, -(X509V3_EXT_FREE)ASN1_STRING_free, -(X509V3_EXT_D2I)d2i_ASN1_ENUMERATED, -(X509V3_EXT_I2D)i2d_ASN1_ENUMERATED, +NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED), +0,0,0,0, (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE, -(X509V3_EXT_S2I)NULL, -NULL, NULL, NULL, NULL, crl_reasons}; - +0, +0,0,0,0, +crl_reasons}; -static ASN1_ENUMERATED *asn1_enumerated_new(void) -{ - return ASN1_ENUMERATED_new(); -} char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *e) diff --git a/src/lib/libcrypto/x509v3/v3_extku.c b/src/lib/libcrypto/x509v3/v3_extku.c index e039d21cbf..b1cfaba1aa 100644 --- a/src/lib/libcrypto/x509v3/v3_extku.c +++ b/src/lib/libcrypto/x509v3/v3_extku.c @@ -59,92 +59,84 @@ #include #include "cryptlib.h" -#include +#include #include #include -static STACK_OF(ASN1_OBJECT) *v2i_ext_ku(X509V3_EXT_METHOD *method, +static void *v2i_EXTENDED_KEY_USAGE(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -static STACK_OF(CONF_VALUE) *i2v_ext_ku(X509V3_EXT_METHOD *method, - STACK_OF(ASN1_OBJECT) *eku, STACK_OF(CONF_VALUE) *extlist); +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(X509V3_EXT_METHOD *method, + void *eku, STACK_OF(CONF_VALUE) *extlist); + X509V3_EXT_METHOD v3_ext_ku = { -NID_ext_key_usage, 0, -(X509V3_EXT_NEW)ext_ku_new, -(X509V3_EXT_FREE)ext_ku_free, -(X509V3_EXT_D2I)d2i_ext_ku, -(X509V3_EXT_I2D)i2d_ext_ku, -NULL, NULL, -(X509V3_EXT_I2V)i2v_ext_ku, -(X509V3_EXT_V2I)v2i_ext_ku, -NULL,NULL, -NULL + NID_ext_key_usage, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0,0,0,0, + 0,0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0,0, + NULL }; -STACK_OF(ASN1_OBJECT) *ext_ku_new(void) -{ - return sk_ASN1_OBJECT_new_null(); -} - -void ext_ku_free(STACK_OF(ASN1_OBJECT) *eku) -{ - sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free); - return; -} - -int i2d_ext_ku(STACK_OF(ASN1_OBJECT) *a, unsigned char **pp) -{ - return i2d_ASN1_SET_OF_ASN1_OBJECT(a, pp, i2d_ASN1_OBJECT, - V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, IS_SEQUENCE); -} - -STACK_OF(ASN1_OBJECT) *d2i_ext_ku(STACK_OF(ASN1_OBJECT) **a, - unsigned char **pp, long length) -{ - return d2i_ASN1_SET_OF_ASN1_OBJECT(a, pp, length, d2i_ASN1_OBJECT, - ASN1_OBJECT_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); -} +/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */ +X509V3_EXT_METHOD v3_ocsp_accresp = { + NID_id_pkix_OCSP_acceptableResponses, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0,0,0,0, + 0,0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0,0, + NULL +}; +ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT) +ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE) +IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) -static STACK_OF(CONF_VALUE) *i2v_ext_ku(X509V3_EXT_METHOD *method, - STACK_OF(ASN1_OBJECT) *eku, STACK_OF(CONF_VALUE) *ext_list) +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(X509V3_EXT_METHOD *method, + void *a, STACK_OF(CONF_VALUE) *ext_list) { -int i; -ASN1_OBJECT *obj; -char obj_tmp[80]; -for(i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { - obj = sk_ASN1_OBJECT_value(eku, i); - i2t_ASN1_OBJECT(obj_tmp, 80, obj); - X509V3_add_value(NULL, obj_tmp, &ext_list); -} -return ext_list; + EXTENDED_KEY_USAGE *eku = a; + int i; + ASN1_OBJECT *obj; + char obj_tmp[80]; + for(i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + obj = sk_ASN1_OBJECT_value(eku, i); + i2t_ASN1_OBJECT(obj_tmp, 80, obj); + X509V3_add_value(NULL, obj_tmp, &ext_list); + } + return ext_list; } -static STACK_OF(ASN1_OBJECT) *v2i_ext_ku(X509V3_EXT_METHOD *method, +static void *v2i_EXTENDED_KEY_USAGE(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { -STACK_OF(ASN1_OBJECT) *extku; -char *extval; -ASN1_OBJECT *objtmp; -CONF_VALUE *val; -int i; + EXTENDED_KEY_USAGE *extku; + char *extval; + ASN1_OBJECT *objtmp; + CONF_VALUE *val; + int i; -if(!(extku = sk_ASN1_OBJECT_new(NULL))) { - X509V3err(X509V3_F_V2I_EXT_KU,ERR_R_MALLOC_FAILURE); - return NULL; -} - -for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { - val = sk_CONF_VALUE_value(nval, i); - if(val->value) extval = val->value; - else extval = val->name; - if(!(objtmp = OBJ_txt2obj(extval, 0))) { - sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); - X509V3err(X509V3_F_V2I_EXT_KU,X509V3_R_INVALID_OBJECT_IDENTIFIER); - X509V3_conf_err(val); + if(!(extku = sk_ASN1_OBJECT_new_null())) { + X509V3err(X509V3_F_V2I_EXT_KU,ERR_R_MALLOC_FAILURE); return NULL; } - sk_ASN1_OBJECT_push(extku, objtmp); -} -return extku; + + for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if(val->value) extval = val->value; + else extval = val->name; + if(!(objtmp = OBJ_txt2obj(extval, 0))) { + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + X509V3err(X509V3_F_V2I_EXT_KU,X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + sk_ASN1_OBJECT_push(extku, objtmp); + } + return extku; } diff --git a/src/lib/libcrypto/x509v3/v3_genn.c b/src/lib/libcrypto/x509v3/v3_genn.c index af716232f8..650b510980 100644 --- a/src/lib/libcrypto/x509v3/v3_genn.c +++ b/src/lib/libcrypto/x509v3/v3_genn.c @@ -59,179 +59,43 @@ #include #include "cryptlib.h" -#include -#include +#include #include #include -int i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **pp) -{ - unsigned char *p; - int ret; - - ret = 0; - - /* Save the location of initial TAG */ - if(pp) p = *pp; - else p = NULL; - - /* GEN_DNAME needs special treatment because of EXPLICIT tag */ - - if(a->type == GEN_DIRNAME) { - int v = 0; - M_ASN1_I2D_len_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v); - if(!p) return ret; - M_ASN1_I2D_put_EXP_opt(a->d.dirn, i2d_X509_NAME, 4, v); - *pp = p; - return ret; - } - - switch(a->type) { - - case GEN_OTHERNAME: - case GEN_X400: - case GEN_EDIPARTY: - ret = i2d_ASN1_TYPE(a->d.other, pp); - break; - - case GEN_EMAIL: - case GEN_DNS: - case GEN_URI: - ret = i2d_ASN1_IA5STRING(a->d.ia5, pp); - break; - - case GEN_IPADD: - ret = i2d_ASN1_OCTET_STRING(a->d.ip, pp); - break; - - case GEN_RID: - ret = i2d_ASN1_OBJECT(a->d.rid, pp); - break; - } - /* Replace TAG with IMPLICIT value */ - if(p) *p = (*p & V_ASN1_CONSTRUCTED) | a->type; - return ret; -} - -GENERAL_NAME *GENERAL_NAME_new() -{ - GENERAL_NAME *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, GENERAL_NAME); - ret->type = -1; - ret->d.ptr = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_GENERAL_NAME_NEW); -} - -GENERAL_NAME *d2i_GENERAL_NAME(GENERAL_NAME **a, unsigned char **pp, - long length) -{ - unsigned char _tmp; - M_ASN1_D2I_vars(a,GENERAL_NAME *,GENERAL_NAME_new); - M_ASN1_D2I_Init(); - c.slen = length; - - _tmp = M_ASN1_next; - ret->type = _tmp & ~V_ASN1_CONSTRUCTED; - - switch(ret->type) { - /* Just put these in a "blob" for now */ - case GEN_OTHERNAME: - case GEN_X400: - case GEN_EDIPARTY: - M_ASN1_D2I_get_imp(ret->d.other, d2i_ASN1_TYPE,V_ASN1_SEQUENCE); - break; - - case GEN_EMAIL: - case GEN_DNS: - case GEN_URI: - M_ASN1_D2I_get_imp(ret->d.ia5, d2i_ASN1_IA5STRING, - V_ASN1_IA5STRING); - break; - - case GEN_DIRNAME: - M_ASN1_D2I_get_EXP_opt(ret->d.dirn, d2i_X509_NAME, 4); - break; - - case GEN_IPADD: - M_ASN1_D2I_get_imp(ret->d.ip, d2i_ASN1_OCTET_STRING, - V_ASN1_OCTET_STRING); - break; - - case GEN_RID: - M_ASN1_D2I_get_imp(ret->d.rid, d2i_ASN1_OBJECT,V_ASN1_OBJECT); - break; - - default: - c.error = ASN1_R_BAD_TAG; - goto err; - } - - c.slen = 0; - M_ASN1_D2I_Finish(a, GENERAL_NAME_free, ASN1_F_D2I_GENERAL_NAME); -} - -void GENERAL_NAME_free(GENERAL_NAME *a) -{ - if (a == NULL) return; - switch(a->type) { - case GEN_OTHERNAME: - case GEN_X400: - case GEN_EDIPARTY: - ASN1_TYPE_free(a->d.other); - break; - - case GEN_EMAIL: - case GEN_DNS: - case GEN_URI: - - ASN1_IA5STRING_free(a->d.ia5); - break; - - case GEN_DIRNAME: - X509_NAME_free(a->d.dirn); - break; - - case GEN_IPADD: - ASN1_OCTET_STRING_free(a->d.ip); - break; - - case GEN_RID: - ASN1_OBJECT_free(a->d.rid); - break; - - } - Free ((char *)a); -} - -/* Now the GeneralNames versions: a SEQUENCE OF GeneralName These are needed as - * an explicit functions. - */ - -STACK_OF(GENERAL_NAME) *GENERAL_NAMES_new() -{ - return sk_GENERAL_NAME_new(NULL); -} - -void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *a) -{ - sk_GENERAL_NAME_pop_free(a, GENERAL_NAME_free); -} - -STACK_OF(GENERAL_NAME) *d2i_GENERAL_NAMES(STACK_OF(GENERAL_NAME) **a, - unsigned char **pp, long length) -{ -return d2i_ASN1_SET_OF_GENERAL_NAME(a, pp, length, d2i_GENERAL_NAME, - GENERAL_NAME_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); -} - -int i2d_GENERAL_NAMES(STACK_OF(GENERAL_NAME) *a, unsigned char **pp) -{ -return i2d_ASN1_SET_OF_GENERAL_NAME(a, pp, i2d_GENERAL_NAME, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE); -} - -IMPLEMENT_STACK_OF(GENERAL_NAME) -IMPLEMENT_ASN1_SET_OF(GENERAL_NAME) - +ASN1_SEQUENCE(OTHERNAME) = { + ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT), + /* Maybe have a true ANY DEFINED BY later */ + ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0) +} ASN1_SEQUENCE_END(OTHERNAME) + +IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME) + +ASN1_SEQUENCE(EDIPARTYNAME) = { + ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0), + ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1) +} ASN1_SEQUENCE_END(EDIPARTYNAME) + +IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME) + +ASN1_CHOICE(GENERAL_NAME) = { + ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME), + ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL), + ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS), + /* Don't decode this */ + ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400), + /* X509_NAME is a CHOICE type so use EXPLICIT */ + ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME), + ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY), + ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI), + ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD), + ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID) +} ASN1_CHOICE_END(GENERAL_NAME) + +IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME) + +ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME) +ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES) + +IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES) diff --git a/src/lib/libcrypto/x509v3/v3_ia5.c b/src/lib/libcrypto/x509v3/v3_ia5.c index 3446c5cd6a..f9414456de 100644 --- a/src/lib/libcrypto/x509v3/v3_ia5.c +++ b/src/lib/libcrypto/x509v3/v3_ia5.c @@ -63,7 +63,6 @@ #include #include -static ASN1_IA5STRING *ia5string_new(void); static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5); static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); X509V3_EXT_METHOD v3_ns_ia5_list[] = { @@ -78,17 +77,12 @@ EXT_END }; -static ASN1_IA5STRING *ia5string_new(void) -{ - return ASN1_IA5STRING_new(); -} - static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5) { char *tmp; if(!ia5 || !ia5->length) return NULL; - tmp = Malloc(ia5->length + 1); + if (!(tmp = OPENSSL_malloc(ia5->length + 1))) return NULL; memcpy(tmp, ia5->data, ia5->length); tmp[ia5->length] = 0; return tmp; @@ -102,12 +96,15 @@ static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3err(X509V3_F_S2I_ASN1_IA5STRING,X509V3_R_INVALID_NULL_ARGUMENT); return NULL; } - if(!(ia5 = ASN1_IA5STRING_new())) goto err; + if(!(ia5 = M_ASN1_IA5STRING_new())) goto err; if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str, strlen(str))) { - ASN1_IA5STRING_free(ia5); + M_ASN1_IA5STRING_free(ia5); goto err; } +#ifdef CHARSET_EBCDIC + ebcdic2ascii(ia5->data, ia5->data, ia5->length); +#endif /*CHARSET_EBCDIC*/ return ia5; err: X509V3err(X509V3_F_S2I_ASN1_IA5STRING,ERR_R_MALLOC_FAILURE); diff --git a/src/lib/libcrypto/x509v3/v3_info.c b/src/lib/libcrypto/x509v3/v3_info.c index 78d2135046..7f17f3231d 100644 --- a/src/lib/libcrypto/x509v3/v3_info.c +++ b/src/lib/libcrypto/x509v3/v3_info.c @@ -60,28 +60,48 @@ #include "cryptlib.h" #include #include -#include +#include #include static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, - STACK_OF(ACCESS_DESCRIPTION) *ainfo, + AUTHORITY_INFO_ACCESS *ainfo, STACK_OF(CONF_VALUE) *ret); -static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); X509V3_EXT_METHOD v3_info = -{ NID_info_access, X509V3_EXT_MULTILINE, -(X509V3_EXT_NEW)AUTHORITY_INFO_ACCESS_new, -(X509V3_EXT_FREE)AUTHORITY_INFO_ACCESS_free, -(X509V3_EXT_D2I)d2i_AUTHORITY_INFO_ACCESS, -(X509V3_EXT_I2D)i2d_AUTHORITY_INFO_ACCESS, -NULL, NULL, +{ NID_info_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), +0,0,0,0, +0,0, (X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS, (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, -NULL, NULL, NULL}; +0,0, +NULL}; + +X509V3_EXT_METHOD v3_sinfo = +{ NID_sinfo_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS), +0,0,0,0, +0,0, +(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS, +(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, +0,0, +NULL}; + +ASN1_SEQUENCE(ACCESS_DESCRIPTION) = { + ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT), + ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME) +} ASN1_SEQUENCE_END(ACCESS_DESCRIPTION) + +IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) + +ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION) +ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS) + +IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, - STACK_OF(ACCESS_DESCRIPTION) *ainfo, + AUTHORITY_INFO_ACCESS *ainfo, STACK_OF(CONF_VALUE) *ret) { ACCESS_DESCRIPTION *desc; @@ -94,7 +114,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method if(!ret) break; vtmp = sk_CONF_VALUE_value(ret, i); i2t_ASN1_OBJECT(objtmp, 80, desc->method); - ntmp = Malloc(strlen(objtmp) + strlen(vtmp->name) + 5); + ntmp = OPENSSL_malloc(strlen(objtmp) + strlen(vtmp->name) + 5); if(!ntmp) { X509V3err(X509V3_F_I2V_AUTHORITY_INFO_ACCESS, ERR_R_MALLOC_FAILURE); @@ -103,7 +123,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method strcpy(ntmp, objtmp); strcat(ntmp, " - "); strcat(ntmp, vtmp->name); - Free(vtmp->name); + OPENSSL_free(vtmp->name); vtmp->name = ntmp; } @@ -111,15 +131,15 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method return ret; } -static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { - STACK_OF(ACCESS_DESCRIPTION) *ainfo = NULL; + AUTHORITY_INFO_ACCESS *ainfo = NULL; CONF_VALUE *cnf, ctmp; ACCESS_DESCRIPTION *acc; int i, objlen; char *objtmp, *ptmp; - if(!(ainfo = sk_ACCESS_DESCRIPTION_new(NULL))) { + if(!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) { X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,ERR_R_MALLOC_FAILURE); return NULL; } @@ -140,7 +160,7 @@ static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD ctmp.value = cnf->value; if(!(acc->location = v2i_GENERAL_NAME(method, ctx, &ctmp))) goto err; - if(!(objtmp = Malloc(objlen + 1))) { + if(!(objtmp = OPENSSL_malloc(objlen + 1))) { X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,ERR_R_MALLOC_FAILURE); goto err; } @@ -150,10 +170,10 @@ static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD if(!acc->method) { X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,X509V3_R_BAD_OBJECT); ERR_add_error_data(2, "value=", objtmp); - Free(objtmp); + OPENSSL_free(objtmp); goto err; } - Free(objtmp); + OPENSSL_free(objtmp); } return ainfo; @@ -162,75 +182,11 @@ static STACK_OF(ACCESS_DESCRIPTION) *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD return NULL; } -int i2d_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len(a->method, i2d_ASN1_OBJECT); - M_ASN1_I2D_len(a->location, i2d_GENERAL_NAME); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put(a->method, i2d_ASN1_OBJECT); - M_ASN1_I2D_put(a->location, i2d_GENERAL_NAME); - - M_ASN1_I2D_finish(); -} - -ACCESS_DESCRIPTION *ACCESS_DESCRIPTION_new(void) -{ - ACCESS_DESCRIPTION *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, ACCESS_DESCRIPTION); - ret->method = OBJ_nid2obj(NID_undef); - ret->location = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_ACCESS_DESCRIPTION_NEW); -} - -ACCESS_DESCRIPTION *d2i_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION **a, unsigned char **pp, - long length) -{ - M_ASN1_D2I_vars(a,ACCESS_DESCRIPTION *,ACCESS_DESCRIPTION_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->method, d2i_ASN1_OBJECT); - M_ASN1_D2I_get(ret->location, d2i_GENERAL_NAME); - M_ASN1_D2I_Finish(a, ACCESS_DESCRIPTION_free, ASN1_F_D2I_ACCESS_DESCRIPTION); -} - -void ACCESS_DESCRIPTION_free(ACCESS_DESCRIPTION *a) -{ - if (a == NULL) return; - ASN1_OBJECT_free(a->method); - GENERAL_NAME_free(a->location); - Free (a); -} - -STACK_OF(ACCESS_DESCRIPTION) *AUTHORITY_INFO_ACCESS_new(void) -{ - return sk_ACCESS_DESCRIPTION_new(NULL); -} - -void AUTHORITY_INFO_ACCESS_free(STACK_OF(ACCESS_DESCRIPTION) *a) -{ - sk_ACCESS_DESCRIPTION_pop_free(a, ACCESS_DESCRIPTION_free); -} - -STACK_OF(ACCESS_DESCRIPTION) *d2i_AUTHORITY_INFO_ACCESS(STACK_OF(ACCESS_DESCRIPTION) **a, - unsigned char **pp, long length) -{ -return d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(a, pp, length, d2i_ACCESS_DESCRIPTION, - ACCESS_DESCRIPTION_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); -} - -int i2d_AUTHORITY_INFO_ACCESS(STACK_OF(ACCESS_DESCRIPTION) *a, unsigned char **pp) -{ -return i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(a, pp, i2d_ACCESS_DESCRIPTION, V_ASN1_SEQUENCE, - V_ASN1_UNIVERSAL, IS_SEQUENCE); -} - -IMPLEMENT_STACK_OF(ACCESS_DESCRIPTION) -IMPLEMENT_ASN1_SET_OF(ACCESS_DESCRIPTION) - - +int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a) + { + i2a_ASN1_OBJECT(bp, a->method); +#ifdef UNDEF + i2a_GENERAL_NAME(bp, a->location); +#endif + return 2; + } diff --git a/src/lib/libcrypto/x509v3/v3_int.c b/src/lib/libcrypto/x509v3/v3_int.c index 637dd5e128..f34cbfb731 100644 --- a/src/lib/libcrypto/x509v3/v3_int.c +++ b/src/lib/libcrypto/x509v3/v3_int.c @@ -60,20 +60,10 @@ #include "cryptlib.h" #include -static ASN1_INTEGER *asn1_integer_new(void); - X509V3_EXT_METHOD v3_crl_num = { -NID_crl_number, 0, -(X509V3_EXT_NEW)asn1_integer_new, -(X509V3_EXT_FREE)ASN1_STRING_free, -(X509V3_EXT_D2I)d2i_ASN1_INTEGER, -(X509V3_EXT_I2D)i2d_ASN1_INTEGER, +NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER), +0,0,0,0, (X509V3_EXT_I2S)i2s_ASN1_INTEGER, -(X509V3_EXT_S2I)NULL, -NULL, NULL, NULL, NULL, NULL}; - +0, +0,0,0,0, NULL}; -static ASN1_INTEGER *asn1_integer_new(void) -{ - return ASN1_INTEGER_new(); -} diff --git a/src/lib/libcrypto/x509v3/v3_lib.c b/src/lib/libcrypto/x509v3/v3_lib.c index a0aa5de794..482ca8ccf5 100644 --- a/src/lib/libcrypto/x509v3/v3_lib.c +++ b/src/lib/libcrypto/x509v3/v3_lib.c @@ -62,38 +62,47 @@ #include #include -static STACK *ext_list = NULL; +#include "ext_dat.h" -static int ext_cmp(X509V3_EXT_METHOD **a, X509V3_EXT_METHOD **b); +static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL; + +static int ext_cmp(const X509V3_EXT_METHOD * const *a, + const X509V3_EXT_METHOD * const *b); static void ext_list_free(X509V3_EXT_METHOD *ext); int X509V3_EXT_add(X509V3_EXT_METHOD *ext) { - if(!ext_list && !(ext_list = sk_new(ext_cmp))) { + if(!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp))) { X509V3err(X509V3_F_X509V3_EXT_ADD,ERR_R_MALLOC_FAILURE); return 0; } - if(!sk_push(ext_list, (char *)ext)) { + if(!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { X509V3err(X509V3_F_X509V3_EXT_ADD,ERR_R_MALLOC_FAILURE); return 0; } return 1; } -static int ext_cmp(X509V3_EXT_METHOD **a, X509V3_EXT_METHOD **b) +static int ext_cmp(const X509V3_EXT_METHOD * const *a, + const X509V3_EXT_METHOD * const *b) { return ((*a)->ext_nid - (*b)->ext_nid); } X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) { - X509V3_EXT_METHOD tmp; + X509V3_EXT_METHOD tmp, *t = &tmp, **ret; int idx; + if(nid < 0) return NULL; tmp.ext_nid = nid; - if(!ext_list || (tmp.ext_nid < 0) ) return NULL; - idx = sk_find(ext_list, (char *)&tmp); + ret = (X509V3_EXT_METHOD **) OBJ_bsearch((char *)&t, + (char *)standard_exts, STANDARD_EXTENSION_COUNT, + sizeof(X509V3_EXT_METHOD *), (int (*)(const void *, const void *))ext_cmp); + if(ret) return *ret; + if(!ext_list) return NULL; + idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp); if(idx == -1) return NULL; - return (X509V3_EXT_METHOD *)sk_value(ext_list, idx); + return sk_X509V3_EXT_METHOD_value(ext_list, idx); } X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext) @@ -118,49 +127,33 @@ int X509V3_EXT_add_alias(int nid_to, int nid_from) X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,X509V3_R_EXTENSION_NOT_FOUND); return 0; } - if(!(tmpext = (X509V3_EXT_METHOD *)Malloc(sizeof(X509V3_EXT_METHOD)))) { + if(!(tmpext = (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) { X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,ERR_R_MALLOC_FAILURE); return 0; } *tmpext = *ext; tmpext->ext_nid = nid_to; tmpext->ext_flags |= X509V3_EXT_DYNAMIC; - return 1; + return X509V3_EXT_add(tmpext); } void X509V3_EXT_cleanup(void) { - sk_pop_free(ext_list, ext_list_free); + sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); ext_list = NULL; } static void ext_list_free(X509V3_EXT_METHOD *ext) { - if(ext->ext_flags & X509V3_EXT_DYNAMIC) Free(ext); + if(ext->ext_flags & X509V3_EXT_DYNAMIC) OPENSSL_free(ext); } -extern X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku; -extern X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet; -extern X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id; - -extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_cpols, v3_crld; +/* Legacy function: we don't need to add standard extensions + * any more because they are now kept in ext_dat.h. + */ int X509V3_add_standard_extensions(void) { - X509V3_EXT_add_list(v3_ns_ia5_list); - X509V3_EXT_add_list(v3_alt); - X509V3_EXT_add(&v3_bcons); - X509V3_EXT_add(&v3_nscert); - X509V3_EXT_add(&v3_key_usage); - X509V3_EXT_add(&v3_ext_ku); - X509V3_EXT_add(&v3_skey_id); - X509V3_EXT_add(&v3_akey_id); - X509V3_EXT_add(&v3_pkey_usage_period); - X509V3_EXT_add(&v3_crl_num); - X509V3_EXT_add(&v3_sxnet); - X509V3_EXT_add(&v3_crl_reason); - X509V3_EXT_add(&v3_cpols); - X509V3_EXT_add(&v3_crld); return 1; } @@ -170,8 +163,139 @@ void *X509V3_EXT_d2i(X509_EXTENSION *ext) { X509V3_EXT_METHOD *method; unsigned char *p; - if(!(method = X509V3_EXT_get(ext)) || !method->d2i) return NULL; + if(!(method = X509V3_EXT_get(ext))) return NULL; p = ext->value->data; + if(method->it) return ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it)); return method->d2i(NULL, &p, ext->value->length); } +/* Get critical flag and decoded version of extension from a NID. + * The "idx" variable returns the last found extension and can + * be used to retrieve multiple extensions of the same NID. + * However multiple extensions with the same NID is usually + * due to a badly encoded certificate so if idx is NULL we + * choke if multiple extensions exist. + * The "crit" variable is set to the critical value. + * The return value is the decoded extension or NULL on + * error. The actual error can have several different causes, + * the value of *crit reflects the cause: + * >= 0, extension found but not decoded (reflects critical value). + * -1 extension not found. + * -2 extension occurs more than once. + */ + +void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx) +{ + int lastpos, i; + X509_EXTENSION *ex, *found_ex = NULL; + if(!x) { + if(idx) *idx = -1; + if(crit) *crit = -1; + return NULL; + } + if(idx) lastpos = *idx + 1; + else lastpos = 0; + if(lastpos < 0) lastpos = 0; + for(i = lastpos; i < sk_X509_EXTENSION_num(x); i++) + { + ex = sk_X509_EXTENSION_value(x, i); + if(OBJ_obj2nid(ex->object) == nid) { + if(idx) { + *idx = i; + break; + } else if(found_ex) { + /* Found more than one */ + if(crit) *crit = -2; + return NULL; + } + found_ex = ex; + } + } + if(found_ex) { + /* Found it */ + if(crit) *crit = X509_EXTENSION_get_critical(found_ex); + return X509V3_EXT_d2i(found_ex); + } + + /* Extension not found */ + if(idx) *idx = -1; + if(crit) *crit = -1; + return NULL; +} + +/* This function is a general extension append, replace and delete utility. + * The precise operation is governed by the 'flags' value. The 'crit' and + * 'value' arguments (if relevant) are the extensions internal structure. + */ + +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags) +{ + int extidx = -1; + int errcode; + X509_EXTENSION *ext, *extmp; + unsigned long ext_op = flags & X509V3_ADD_OP_MASK; + + /* If appending we don't care if it exists, otherwise + * look for existing extension. + */ + if(ext_op != X509V3_ADD_APPEND) + extidx = X509v3_get_ext_by_NID(*x, nid, -1); + + /* See if extension exists */ + if(extidx >= 0) { + /* If keep existing, nothing to do */ + if(ext_op == X509V3_ADD_KEEP_EXISTING) + return 1; + /* If default then its an error */ + if(ext_op == X509V3_ADD_DEFAULT) { + errcode = X509V3_R_EXTENSION_EXISTS; + goto err; + } + /* If delete, just delete it */ + if(ext_op == X509V3_ADD_DELETE) { + if(!sk_X509_EXTENSION_delete(*x, extidx)) return -1; + return 1; + } + } else { + /* If replace existing or delete, error since + * extension must exist + */ + if((ext_op == X509V3_ADD_REPLACE_EXISTING) || + (ext_op == X509V3_ADD_DELETE)) { + errcode = X509V3_R_EXTENSION_NOT_FOUND; + goto err; + } + } + + /* If we get this far then we have to create an extension: + * could have some flags for alternative encoding schemes... + */ + + ext = X509V3_EXT_i2d(nid, crit, value); + + if(!ext) { + X509V3err(X509V3_F_X509V3_ADD_I2D, X509V3_R_ERROR_CREATING_EXTENSION); + return 0; + } + + /* If extension exists replace it.. */ + if(extidx >= 0) { + extmp = sk_X509_EXTENSION_value(*x, extidx); + X509_EXTENSION_free(extmp); + if(!sk_X509_EXTENSION_set(*x, extidx, ext)) return -1; + return 1; + } + + if(!*x && !(*x = sk_X509_EXTENSION_new_null())) return -1; + if(!sk_X509_EXTENSION_push(*x, ext)) return -1; + + return 1; + + err: + if(!(flags & X509V3_ADD_SILENT)) + X509V3err(X509V3_F_X509V3_ADD_I2D, errcode); + return 0; +} + +IMPLEMENT_STACK_OF(X509V3_EXT_METHOD) diff --git a/src/lib/libcrypto/x509v3/v3_pku.c b/src/lib/libcrypto/x509v3/v3_pku.c index c13e7d8f45..49a2e4697a 100644 --- a/src/lib/libcrypto/x509v3/v3_pku.c +++ b/src/lib/libcrypto/x509v3/v3_pku.c @@ -59,7 +59,7 @@ #include #include "cryptlib.h" #include -#include +#include #include static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, BIO *out, int indent); @@ -67,62 +67,19 @@ static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *u static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); */ X509V3_EXT_METHOD v3_pkey_usage_period = { -NID_private_key_usage_period, 0, -(X509V3_EXT_NEW)PKEY_USAGE_PERIOD_new, -(X509V3_EXT_FREE)PKEY_USAGE_PERIOD_free, -(X509V3_EXT_D2I)d2i_PKEY_USAGE_PERIOD, -(X509V3_EXT_I2D)i2d_PKEY_USAGE_PERIOD, -NULL, NULL, NULL, NULL, +NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD), +0,0,0,0, +0,0,0,0, (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL, NULL }; -int i2d_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len_IMP_opt (a->notBefore, i2d_ASN1_GENERALIZEDTIME); - M_ASN1_I2D_len_IMP_opt (a->notAfter, i2d_ASN1_GENERALIZEDTIME); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put_IMP_opt (a->notBefore, i2d_ASN1_GENERALIZEDTIME, 0); - M_ASN1_I2D_put_IMP_opt (a->notAfter, i2d_ASN1_GENERALIZEDTIME, 1); - - M_ASN1_I2D_finish(); -} - -PKEY_USAGE_PERIOD *PKEY_USAGE_PERIOD_new(void) -{ - PKEY_USAGE_PERIOD *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, PKEY_USAGE_PERIOD); - ret->notBefore = NULL; - ret->notAfter = NULL; - return (ret); - M_ASN1_New_Error(ASN1_F_PKEY_USAGE_PERIOD_NEW); -} +ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = { + ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0), + ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1) +} ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD) -PKEY_USAGE_PERIOD *d2i_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD **a, - unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,PKEY_USAGE_PERIOD *,PKEY_USAGE_PERIOD_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get_IMP_opt (ret->notBefore, d2i_ASN1_GENERALIZEDTIME, 0, - V_ASN1_GENERALIZEDTIME); - M_ASN1_D2I_get_IMP_opt (ret->notAfter, d2i_ASN1_GENERALIZEDTIME, 1, - V_ASN1_GENERALIZEDTIME); - M_ASN1_D2I_Finish(a, PKEY_USAGE_PERIOD_free, ASN1_F_D2I_PKEY_USAGE_PERIOD); -} - -void PKEY_USAGE_PERIOD_free(PKEY_USAGE_PERIOD *a) -{ - if (a == NULL) return; - ASN1_GENERALIZEDTIME_free(a->notBefore); - ASN1_GENERALIZEDTIME_free(a->notAfter); - Free ((char *)a); -} +IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, BIO *out, int indent) diff --git a/src/lib/libcrypto/x509v3/v3_prn.c b/src/lib/libcrypto/x509v3/v3_prn.c index dc20c6bdba..aeaf6170fe 100644 --- a/src/lib/libcrypto/x509v3/v3_prn.c +++ b/src/lib/libcrypto/x509v3/v3_prn.c @@ -64,6 +64,8 @@ /* Extension printing routines */ +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent, int supported); + /* Print out a name+value stack */ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml) @@ -81,29 +83,65 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml) nval = sk_CONF_VALUE_value(val, i); if(!nval->name) BIO_puts(out, nval->value); else if(!nval->value) BIO_puts(out, nval->name); +#ifndef CHARSET_EBCDIC else BIO_printf(out, "%s:%s", nval->name, nval->value); +#else + else { + int len; + char *tmp; + len = strlen(nval->value)+1; + tmp = OPENSSL_malloc(len); + if (tmp) + { + ascii2ebcdic(tmp, nval->value, len); + BIO_printf(out, "%s:%s", nval->name, tmp); + OPENSSL_free(tmp); + } + } +#endif if(ml) BIO_puts(out, "\n"); } } /* Main routine: print out a general extension */ -int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, int flag, int indent) +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent) { - char *ext_str = NULL, *value = NULL; + void *ext_str = NULL; + char *value = NULL; unsigned char *p; X509V3_EXT_METHOD *method; STACK_OF(CONF_VALUE) *nval = NULL; int ok = 1; - if(!(method = X509V3_EXT_get(ext))) return 0; + if(!(method = X509V3_EXT_get(ext))) + return unknown_ext_print(out, ext, flag, indent, 0); p = ext->value->data; - if(!(ext_str = method->d2i(NULL, &p, ext->value->length))) return 0; + if(method->it) ext_str = ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it)); + else ext_str = method->d2i(NULL, &p, ext->value->length); + + if(!ext_str) return unknown_ext_print(out, ext, flag, indent, 1); + if(method->i2s) { if(!(value = method->i2s(method, ext_str))) { ok = 0; goto err; } +#ifndef CHARSET_EBCDIC BIO_printf(out, "%*s%s", indent, "", value); +#else + { + int len; + char *tmp; + len = strlen(value)+1; + tmp = OPENSSL_malloc(len); + if (tmp) + { + ascii2ebcdic(tmp, value, len); + BIO_printf(out, "%*s%s", indent, "", tmp); + OPENSSL_free(tmp); + } + } +#endif } else if(method->i2v) { if(!(nval = method->i2v(method, ext_str, NULL))) { ok = 0; @@ -117,12 +155,72 @@ int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, int flag, int indent) err: sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); - if(value) Free(value); - method->ext_free(ext_str); + if(value) OPENSSL_free(value); + if(method->it) ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it)); + else method->ext_free(ext_str); return ok; } -#ifndef NO_FP_API +int X509V3_extensions_print(BIO *bp, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent) +{ + int i, j; + + if(sk_X509_EXTENSION_num(exts) <= 0) return 1; + + if(title) + { + BIO_printf(bp,"%*s%s:\n",indent, "", title); + indent += 4; + } + + for (i=0; ivalue); + } + if (BIO_write(bp,"\n",1) <= 0) return 0; + } + return 1; +} + +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent, int supported) +{ + switch(flag & X509V3_EXT_UNKNOWN_MASK) { + + case X509V3_EXT_DEFAULT: + return 0; + + case X509V3_EXT_ERROR_UNKNOWN: + if(supported) + BIO_printf(out, "%*s", indent, ""); + else + BIO_printf(out, "%*s", indent, ""); + return 1; + + case X509V3_EXT_PARSE_UNKNOWN: + return ASN1_parse_dump(out, + ext->value->data, ext->value->length, indent, -1); + case X509V3_EXT_DUMP_UNKNOWN: + return BIO_dump_indent(out, (char *)ext->value->data, ext->value->length, indent); + + default: + return 1; + } +} + + +#ifndef OPENSSL_NO_FP_API int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) { BIO *bio_tmp; diff --git a/src/lib/libcrypto/x509v3/v3_purp.c b/src/lib/libcrypto/x509v3/v3_purp.c index b7494ebcd5..b739e4fd83 100644 --- a/src/lib/libcrypto/x509v3/v3_purp.c +++ b/src/lib/libcrypto/x509v3/v3_purp.c @@ -1,9 +1,9 @@ /* v3_purp.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL - * project 1999. + * project 2001. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2001 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 @@ -59,20 +59,24 @@ #include #include "cryptlib.h" #include - +#include static void x509v3_cache_extensions(X509 *x); -static int ca_check(X509 *x); -static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca); -static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); -static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca); -static int purpose_smime(X509 *x, int ca); -static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca); -static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca); -static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca); - -static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b); +static int ca_check(const X509 *x); +static int check_ssl_ca(const X509 *x); +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca); +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca); +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca); +static int purpose_smime(const X509 *x, int ca); +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca); +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca); +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca); +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); + +static int xp_cmp(const X509_PURPOSE * const *a, + const X509_PURPOSE * const *b); static void xptable_free(X509_PURPOSE *p); static X509_PURPOSE xstandard[] = { @@ -81,7 +85,9 @@ static X509_PURPOSE xstandard[] = { {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL}, {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, - {X509_PURPOSE_CRL_SIGN, X509_TRUST_ANY, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL}, + {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL}, + {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL}, + {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL}, }; #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE)) @@ -90,15 +96,19 @@ IMPLEMENT_STACK_OF(X509_PURPOSE) static STACK_OF(X509_PURPOSE) *xptable = NULL; -static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b) +static int xp_cmp(const X509_PURPOSE * const *a, + const X509_PURPOSE * const *b) { return (*a)->purpose - (*b)->purpose; } +/* As much as I'd like to make X509_check_purpose use a "const" X509* + * I really can't because it does recalculate hashes and do other non-const + * things. */ int X509_check_purpose(X509 *x, int id, int ca) { int idx; - X509_PURPOSE *pt; + const X509_PURPOSE *pt; if(!(x->ex_flags & EXFLAG_SET)) { CRYPTO_w_lock(CRYPTO_LOCK_X509); x509v3_cache_extensions(x); @@ -111,6 +121,16 @@ int X509_check_purpose(X509 *x, int id, int ca) return pt->check_purpose(pt, x, ca); } +int X509_PURPOSE_set(int *p, int purpose) +{ + if(X509_PURPOSE_get_by_id(purpose) == -1) { + X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE); + return 0; + } + *p = purpose; + return 1; +} + int X509_PURPOSE_get_count(void) { if(!xptable) return X509_PURPOSE_COUNT; @@ -135,7 +155,6 @@ int X509_PURPOSE_get_by_sname(char *sname) return -1; } - int X509_PURPOSE_get_by_id(int purpose) { X509_PURPOSE tmp; @@ -150,7 +169,7 @@ int X509_PURPOSE_get_by_id(int purpose) } int X509_PURPOSE_add(int id, int trust, int flags, - int (*ck)(X509_PURPOSE *, X509 *, int), + int (*ck)(const X509_PURPOSE *, const X509 *, int), char *name, char *sname, void *arg) { int idx; @@ -163,17 +182,17 @@ int X509_PURPOSE_add(int id, int trust, int flags, idx = X509_PURPOSE_get_by_id(id); /* Need a new entry */ if(idx == -1) { - if(!(ptmp = Malloc(sizeof(X509_PURPOSE)))) { + if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) { X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); return 0; } ptmp->flags = X509_PURPOSE_DYNAMIC; } else ptmp = X509_PURPOSE_get0(idx); - /* Free existing name if dynamic */ + /* OPENSSL_free existing name if dynamic */ if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { - Free(ptmp->name); - Free(ptmp->sname); + OPENSSL_free(ptmp->name); + OPENSSL_free(ptmp->sname); } /* dup supplied name */ ptmp->name = BUF_strdup(name); @@ -212,10 +231,10 @@ static void xptable_free(X509_PURPOSE *p) if (p->flags & X509_PURPOSE_DYNAMIC) { if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { - Free(p->name); - Free(p->sname); + OPENSSL_free(p->name); + OPENSSL_free(p->sname); } - Free(p); + OPENSSL_free(p); } } @@ -247,16 +266,57 @@ int X509_PURPOSE_get_trust(X509_PURPOSE *xp) return xp->trust; } -#ifndef NO_SHA +static int nid_cmp(int *a, int *b) + { + return *a - *b; + } + +int X509_supported_extension(X509_EXTENSION *ex) + { + /* This table is a list of the NIDs of supported extensions: + * that is those which are used by the verify process. If + * an extension is critical and doesn't appear in this list + * then the verify process will normally reject the certificate. + * The list must be kept in numerical order because it will be + * searched using bsearch. + */ + + static int supported_nids[] = { + NID_netscape_cert_type, /* 71 */ + NID_key_usage, /* 83 */ + NID_subject_alt_name, /* 85 */ + NID_basic_constraints, /* 87 */ + NID_ext_key_usage /* 126 */ + }; + + int ex_nid; + + ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); + + if (ex_nid == NID_undef) + return 0; + + if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids, + sizeof(supported_nids)/sizeof(int), sizeof(int), + (int (*)(const void *, const void *))nid_cmp)) + return 1; + return 0; + } + + static void x509v3_cache_extensions(X509 *x) { BASIC_CONSTRAINTS *bs; ASN1_BIT_STRING *usage; ASN1_BIT_STRING *ns; - STACK_OF(ASN1_OBJECT) *extusage; + EXTENDED_KEY_USAGE *extusage; + X509_EXTENSION *ex; + int i; if(x->ex_flags & EXFLAG_SET) return; +#ifndef OPENSSL_NO_SHA X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); +#endif /* Does subject name match issuer ? */ if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) x->ex_flags |= EXFLAG_SS; @@ -309,6 +369,15 @@ static void x509v3_cache_extensions(X509 *x) case NID_ms_sgc: case NID_ns_sgc: x->ex_xkusage |= XKU_SGC; + break; + + case NID_OCSP_sign: + x->ex_xkusage |= XKU_OCSP_SIGN; + break; + + case NID_time_stamp: + x->ex_xkusage |= XKU_TIMESTAMP; + break; } } sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); @@ -320,9 +389,21 @@ static void x509v3_cache_extensions(X509 *x) x->ex_flags |= EXFLAG_NSCERT; ASN1_BIT_STRING_free(ns); } + x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); + x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); + for (i = 0; i < X509_get_ext_count(x); i++) + { + ex = X509_get_ext(x, i); + if (!X509_EXTENSION_get_critical(ex)) + continue; + if (!X509_supported_extension(ex)) + { + x->ex_flags |= EXFLAG_CRITICAL; + break; + } + } x->ex_flags |= EXFLAG_SET; } -#endif /* CA checks common to all purposes * return codes: @@ -340,7 +421,7 @@ static void x509v3_cache_extensions(X509 *x) #define ns_reject(x, usage) \ (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) -static int ca_check(X509 *x) +static int ca_check(const X509 *x) { /* keyUsage if present should allow cert signing */ if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0; @@ -350,26 +431,32 @@ static int ca_check(X509 *x) else return 0; } else { if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3; + /* If key usage present it must have certSign so tolerate it */ + else if (x->ex_flags & EXFLAG_KUSAGE) return 3; else return 2; } } +/* Check SSL CA: common checks for SSL client and server */ +static int check_ssl_ca(const X509 *x) +{ + int ca_ret; + ca_ret = ca_check(x); + if(!ca_ret) return 0; + /* check nsCertType if present */ + if(x->ex_flags & EXFLAG_NSCERT) { + if(x->ex_nscert & NS_SSL_CA) return ca_ret; + return 0; + } + if(ca_ret != 2) return ca_ret; + else return 0; +} -static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca) + +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca) { if(xku_reject(x,XKU_SSL_CLIENT)) return 0; - if(ca) { - int ca_ret; - ca_ret = ca_check(x); - if(!ca_ret) return 0; - /* check nsCertType if present */ - if(x->ex_flags & EXFLAG_NSCERT) { - if(x->ex_nscert & NS_SSL_CA) return ca_ret; - return 0; - } - if(ca_ret != 2) return ca_ret; - else return 0; - } + if(ca) return check_ssl_ca(x); /* We need to do digital signatures with it */ if(ku_reject(x,KU_DIGITAL_SIGNATURE)) return 0; /* nsCertType if present should allow SSL client use */ @@ -377,11 +464,10 @@ static int check_purpose_ssl_client(X509_PURPOSE *xp, X509 *x, int ca) return 1; } -static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) { if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0; - /* Otherwise same as SSL client for a CA */ - if(ca) return check_purpose_ssl_client(xp, x, 1); + if(ca) return check_ssl_ca(x); if(ns_reject(x, NS_SSL_SERVER)) return 0; /* Now as for keyUsage: we'll at least need to sign OR encipher */ @@ -391,7 +477,7 @@ static int check_purpose_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) } -static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) { int ret; ret = check_purpose_ssl_server(xp, x, ca); @@ -402,7 +488,7 @@ static int check_purpose_ns_ssl_server(X509_PURPOSE *xp, X509 *x, int ca) } /* common S/MIME checks */ -static int purpose_smime(X509 *x, int ca) +static int purpose_smime(const X509 *x, int ca) { if(xku_reject(x,XKU_SMIME)) return 0; if(ca) { @@ -426,16 +512,16 @@ static int purpose_smime(X509 *x, int ca) return 1; } -static int check_purpose_smime_sign(X509_PURPOSE *xp, X509 *x, int ca) +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca) { int ret; ret = purpose_smime(x, ca); if(!ret || ca) return ret; - if(ku_reject(x, KU_DIGITAL_SIGNATURE)) return 0; + if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) return 0; return ret; } -static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca) +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca) { int ret; ret = purpose_smime(x, ca); @@ -444,7 +530,7 @@ static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca) return ret; } -static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca) +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca) { if(ca) { int ca_ret; @@ -454,3 +540,86 @@ static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca) if(ku_reject(x, KU_CRL_SIGN)) return 0; return 1; } + +/* OCSP helper: this is *not* a full OCSP check. It just checks that + * each CA is valid. Additional checks must be made on the chain. + */ + +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + /* Must be a valid CA */ + if(ca) { + int ca_ret; + ca_ret = ca_check(x); + if(ca_ret != 2) return ca_ret; + if(x->ex_flags & EXFLAG_NSCERT) { + if(x->ex_nscert & NS_ANY_CA) return ca_ret; + return 0; + } + return 0; + } + /* leaf certificate is checked in OCSP_verify() */ + return 1; +} + +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + return 1; +} + +/* Various checks to see if one certificate issued the second. + * This can be used to prune a set of possible issuer certificates + * which have been looked up using some simple method such as by + * subject name. + * These are: + * 1. Check issuer_name(subject) == subject_name(issuer) + * 2. If akid(subject) exists check it matches issuer + * 3. If key_usage(issuer) exists check it supports certificate signing + * returns 0 for OK, positive for reason for mismatch, reasons match + * codes for X509_verify_cert() + */ + +int X509_check_issued(X509 *issuer, X509 *subject) +{ + if(X509_NAME_cmp(X509_get_subject_name(issuer), + X509_get_issuer_name(subject))) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + x509v3_cache_extensions(issuer); + x509v3_cache_extensions(subject); + if(subject->akid) { + /* Check key ids (if present) */ + if(subject->akid->keyid && issuer->skid && + ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid) ) + return X509_V_ERR_AKID_SKID_MISMATCH; + /* Check serial number */ + if(subject->akid->serial && + ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), + subject->akid->serial)) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + /* Check issuer name */ + if(subject->akid->issuer) { + /* Ugh, for some peculiar reason AKID includes + * SEQUENCE OF GeneralName. So look for a DirName. + * There may be more than one but we only take any + * notice of the first. + */ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + X509_NAME *nm = NULL; + int i; + gens = subject->akid->issuer; + for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if(gen->type == GEN_DIRNAME) { + nm = gen->d.dirn; + break; + } + } + if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + } + if(ku_reject(issuer, KU_KEY_CERT_SIGN)) return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; + return X509_V_OK; +} + diff --git a/src/lib/libcrypto/x509v3/v3_skey.c b/src/lib/libcrypto/x509v3/v3_skey.c index fb3e36014d..c0f044ac1b 100644 --- a/src/lib/libcrypto/x509v3/v3_skey.c +++ b/src/lib/libcrypto/x509v3/v3_skey.c @@ -61,23 +61,14 @@ #include "cryptlib.h" #include -static ASN1_OCTET_STRING *octet_string_new(void); static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); X509V3_EXT_METHOD v3_skey_id = { -NID_subject_key_identifier, 0, -(X509V3_EXT_NEW)octet_string_new, -(X509V3_EXT_FREE)ASN1_STRING_free, -(X509V3_EXT_D2I)d2i_ASN1_OCTET_STRING, -(X509V3_EXT_I2D)i2d_ASN1_OCTET_STRING, +NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING), +0,0,0,0, (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING, (X509V3_EXT_S2I)s2i_skey_id, -NULL, NULL, NULL, NULL, NULL}; - - -static ASN1_OCTET_STRING *octet_string_new(void) -{ - return ASN1_OCTET_STRING_new(); -} +0,0,0,0, +NULL}; char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct) @@ -91,13 +82,13 @@ ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct; long length; - if(!(oct = ASN1_OCTET_STRING_new())) { + if(!(oct = M_ASN1_OCTET_STRING_new())) { X509V3err(X509V3_F_S2I_ASN1_OCTET_STRING,ERR_R_MALLOC_FAILURE); return NULL; } if(!(oct->data = string_to_hex(str, &length))) { - ASN1_OCTET_STRING_free(oct); + M_ASN1_OCTET_STRING_free(oct); return NULL; } @@ -113,12 +104,11 @@ static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct; ASN1_BIT_STRING *pk; unsigned char pkey_dig[EVP_MAX_MD_SIZE]; - EVP_MD_CTX md; unsigned int diglen; if(strcmp(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str); - if(!(oct = ASN1_OCTET_STRING_new())) { + if(!(oct = M_ASN1_OCTET_STRING_new())) { X509V3err(X509V3_F_S2I_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE); return NULL; } @@ -139,11 +129,9 @@ static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, goto err; } - EVP_DigestInit(&md, EVP_sha1()); - EVP_DigestUpdate(&md, pk->data, pk->length); - EVP_DigestFinal(&md, pkey_dig, &diglen); + EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL); - if(!ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { + if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { X509V3err(X509V3_F_S2I_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE); goto err; } @@ -151,6 +139,6 @@ static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, return oct; err: - ASN1_OCTET_STRING_free(oct); + M_ASN1_OCTET_STRING_free(oct); return NULL; } diff --git a/src/lib/libcrypto/x509v3/v3_sxnet.c b/src/lib/libcrypto/x509v3/v3_sxnet.c index 0687bb4e3d..d3f4ba3a72 100644 --- a/src/lib/libcrypto/x509v3/v3_sxnet.c +++ b/src/lib/libcrypto/x509v3/v3_sxnet.c @@ -60,7 +60,7 @@ #include "cryptlib.h" #include #include -#include +#include #include /* Support for Thawte strong extranet extension */ @@ -73,111 +73,33 @@ static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); #endif X509V3_EXT_METHOD v3_sxnet = { -NID_sxnet, X509V3_EXT_MULTILINE, -(X509V3_EXT_NEW)SXNET_new, -(X509V3_EXT_FREE)SXNET_free, -(X509V3_EXT_D2I)d2i_SXNET, -(X509V3_EXT_I2D)i2d_SXNET, -NULL, NULL, -NULL, +NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET), +0,0,0,0, +0,0, +0, #ifdef SXNET_TEST (X509V3_EXT_V2I)sxnet_v2i, #else -NULL, +0, #endif (X509V3_EXT_I2R)sxnet_i2r, -NULL, +0, NULL }; +ASN1_SEQUENCE(SXNETID) = { + ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER), + ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SXNETID) -int i2d_SXNET(SXNET *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_len_SEQUENCE_type (SXNETID, a->ids, i2d_SXNETID); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->version, i2d_ASN1_INTEGER); - M_ASN1_I2D_put_SEQUENCE_type (SXNETID, a->ids, i2d_SXNETID); +IMPLEMENT_ASN1_FUNCTIONS(SXNETID) - M_ASN1_I2D_finish(); -} - -SXNET *SXNET_new(void) -{ - SXNET *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, SXNET); - M_ASN1_New(ret->version,ASN1_INTEGER_new); - M_ASN1_New(ret->ids,sk_SXNETID_new_null); - return (ret); - M_ASN1_New_Error(ASN1_F_SXNET_NEW); -} +ASN1_SEQUENCE(SXNET) = { + ASN1_SIMPLE(SXNET, version, ASN1_INTEGER), + ASN1_SEQUENCE_OF(SXNET, ids, SXNETID) +} ASN1_SEQUENCE_END(SXNET) -SXNET *d2i_SXNET(SXNET **a, unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,SXNET *,SXNET_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get (ret->version, d2i_ASN1_INTEGER); - M_ASN1_D2I_get_seq_type (SXNETID, ret->ids, d2i_SXNETID, SXNETID_free); - M_ASN1_D2I_Finish(a, SXNET_free, ASN1_F_D2I_SXNET); -} - -void SXNET_free(SXNET *a) -{ - if (a == NULL) return; - ASN1_INTEGER_free(a->version); - sk_SXNETID_pop_free(a->ids, SXNETID_free); - Free (a); -} - -int i2d_SXNETID(SXNETID *a, unsigned char **pp) -{ - M_ASN1_I2D_vars(a); - - M_ASN1_I2D_len (a->zone, i2d_ASN1_INTEGER); - M_ASN1_I2D_len (a->user, i2d_ASN1_OCTET_STRING); - - M_ASN1_I2D_seq_total(); - - M_ASN1_I2D_put (a->zone, i2d_ASN1_INTEGER); - M_ASN1_I2D_put (a->user, i2d_ASN1_OCTET_STRING); - - M_ASN1_I2D_finish(); -} - -SXNETID *SXNETID_new(void) -{ - SXNETID *ret=NULL; - ASN1_CTX c; - M_ASN1_New_Malloc(ret, SXNETID); - ret->zone = NULL; - M_ASN1_New(ret->user,ASN1_OCTET_STRING_new); - return (ret); - M_ASN1_New_Error(ASN1_F_SXNETID_NEW); -} - -SXNETID *d2i_SXNETID(SXNETID **a, unsigned char **pp, long length) -{ - M_ASN1_D2I_vars(a,SXNETID *,SXNETID_new); - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->zone, d2i_ASN1_INTEGER); - M_ASN1_D2I_get(ret->user, d2i_ASN1_OCTET_STRING); - M_ASN1_D2I_Finish(a, SXNETID_free, ASN1_F_D2I_SXNETID); -} - -void SXNETID_free(SXNETID *a) -{ - if (a == NULL) return; - ASN1_INTEGER_free(a->zone); - ASN1_OCTET_STRING_free(a->user); - Free (a); -} +IMPLEMENT_ASN1_FUNCTIONS(SXNET) static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, int indent) @@ -192,8 +114,8 @@ static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, id = sk_SXNETID_value(sx->ids, i); tmp = i2s_ASN1_INTEGER(NULL, id->zone); BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp); - Free(tmp); - ASN1_OCTET_STRING_print(out, id->user); + OPENSSL_free(tmp); + M_ASN1_OCTET_STRING_print(out, id->user); } return 1; } @@ -244,9 +166,9 @@ int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen) { ASN1_INTEGER *izone = NULL; - if(!(izone = ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { + if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { X509V3err(X509V3_F_SXNET_ADD_ID_ULONG,ERR_R_MALLOC_FAILURE); - ASN1_INTEGER_free(izone); + M_ASN1_INTEGER_free(izone); return 0; } return SXNET_add_id_INTEGER(psx, izone, user, userlen); @@ -285,7 +207,7 @@ int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, char *user, if(!(id = SXNETID_new())) goto err; if(userlen == -1) userlen = strlen(user); - if(!ASN1_OCTET_STRING_set(id->user, user, userlen)) goto err; + if(!M_ASN1_OCTET_STRING_set(id->user, user, userlen)) goto err; if(!sk_SXNETID_push(sx->ids, id)) goto err; id->zone = zone; return 1; @@ -307,7 +229,7 @@ ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone) return NULL; } oct = SXNET_get_id_INTEGER(sx, izone); - ASN1_INTEGER_free(izone); + M_ASN1_INTEGER_free(izone); return oct; } @@ -315,13 +237,13 @@ ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone) { ASN1_INTEGER *izone = NULL; ASN1_OCTET_STRING *oct; - if(!(izone = ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { + if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) { X509V3err(X509V3_F_SXNET_GET_ID_ULONG,ERR_R_MALLOC_FAILURE); - ASN1_INTEGER_free(izone); + M_ASN1_INTEGER_free(izone); return NULL; } oct = SXNET_get_id_INTEGER(sx, izone); - ASN1_INTEGER_free(izone); + M_ASN1_INTEGER_free(izone); return oct; } @@ -331,7 +253,7 @@ ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone) int i; for(i = 0; i < sk_SXNETID_num(sx->ids); i++) { id = sk_SXNETID_value(sx->ids, i); - if(!ASN1_INTEGER_cmp(id->zone, zone)) return id->user; + if(!M_ASN1_INTEGER_cmp(id->zone, zone)) return id->user; } return NULL; } diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c index 40f71c71b4..283e943e46 100644 --- a/src/lib/libcrypto/x509v3/v3_utl.c +++ b/src/lib/libcrypto/x509v3/v3_utl.c @@ -65,6 +65,10 @@ #include static char *strip_spaces(char *name); +static int sk_strcmp(const char * const *a, const char * const *b); +static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); +static void str_free(void *str); +static int append_ia5(STACK **sk, ASN1_IA5STRING *email); /* Add a CONF_VALUE name value pair to stack */ @@ -75,8 +79,8 @@ int X509V3_add_value(const char *name, const char *value, char *tname = NULL, *tvalue = NULL; if(name && !(tname = BUF_strdup(name))) goto err; if(value && !(tvalue = BUF_strdup(value))) goto err;; - if(!(vtmp = (CONF_VALUE *)Malloc(sizeof(CONF_VALUE)))) goto err; - if(!*extlist && !(*extlist = sk_CONF_VALUE_new(NULL))) goto err; + if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err; + if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err; vtmp->section = NULL; vtmp->name = tname; vtmp->value = tvalue; @@ -84,9 +88,9 @@ int X509V3_add_value(const char *name, const char *value, return 1; err: X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE); - if(vtmp) Free(vtmp); - if(tname) Free(tname); - if(tvalue) Free(tvalue); + if(vtmp) OPENSSL_free(vtmp); + if(tname) OPENSSL_free(tname); + if(tvalue) OPENSSL_free(tvalue); return 0; } @@ -101,10 +105,10 @@ int X509V3_add_value_uchar(const char *name, const unsigned char *value, void X509V3_conf_free(CONF_VALUE *conf) { if(!conf) return; - if(conf->name) Free(conf->name); - if(conf->value) Free(conf->value); - if(conf->section) Free(conf->section); - Free((char *)conf); + if(conf->name) OPENSSL_free(conf->name); + if(conf->value) OPENSSL_free(conf->value); + if(conf->section) OPENSSL_free(conf->section); + OPENSSL_free(conf); } int X509V3_add_value_bool(const char *name, int asn1_bool, @@ -150,21 +154,40 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) { BIGNUM *bn = NULL; ASN1_INTEGER *aint; + int isneg, ishex; + int ret; bn = BN_new(); - if(!value) { + if (!value) { X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); return 0; } - if(!BN_dec2bn(&bn, value)) { + if (value[0] == '-') { + value++; + isneg = 1; + } else isneg = 0; + + if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { + value += 2; + ishex = 1; + } else ishex = 0; + + if (ishex) ret = BN_hex2bn(&bn, value); + else ret = BN_dec2bn(&bn, value); + + if (!ret) { X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); return 0; } - if(!(aint = BN_to_ASN1_INTEGER(bn, NULL))) { + if (isneg && BN_is_zero(bn)) isneg = 0; + + aint = BN_to_ASN1_INTEGER(bn, NULL); + BN_free(bn); + if (!aint) { X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR); return 0; } - BN_free(bn); + if (isneg) aint->type |= V_ASN1_NEG; return aint; } @@ -176,7 +199,7 @@ int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, if(!aint) return 1; if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0; ret = X509V3_add_value(name, strtmp, extlist); - Free(strtmp); + OPENSSL_free(strtmp); return ret; } @@ -217,7 +240,7 @@ int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) /*#define DEBUG*/ -STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) { char *p, *q, c; char *ntmp, *vtmp; @@ -246,7 +269,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) *p = 0; ntmp = strip_spaces(q); q = p + 1; -#ifdef DEBUG +#if 0 printf("%s\n", ntmp); #endif if(!ntmp) { @@ -262,7 +285,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) state = HDR_NAME; *p = 0; vtmp = strip_spaces(q); -#ifdef DEBUG +#if 0 printf("%s\n", ntmp); #endif if(!vtmp) { @@ -279,7 +302,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) if(state == HDR_VALUE) { vtmp = strip_spaces(q); -#ifdef DEBUG +#if 0 printf("%s=%s\n", ntmp, vtmp); #endif if(!vtmp) { @@ -289,7 +312,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) X509V3_add_value(ntmp, vtmp, &values); } else { ntmp = strip_spaces(q); -#ifdef DEBUG +#if 0 printf("%s\n", ntmp); #endif if(!ntmp) { @@ -298,11 +321,11 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) } X509V3_add_value(ntmp, NULL, &values); } -Free(linebuf); +OPENSSL_free(linebuf); return values; err: -Free(linebuf); +OPENSSL_free(linebuf); sk_CONF_VALUE_pop_free(values, X509V3_conf_free); return NULL; @@ -325,8 +348,9 @@ static char *strip_spaces(char *name) /* hex string utilities */ -/* Given a buffer of length 'len' return a Malloc'ed string with its +/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its * hex representation + * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines) */ char *hex_to_string(unsigned char *buffer, long len) @@ -336,7 +360,7 @@ char *hex_to_string(unsigned char *buffer, long len) int i; static char hexdig[] = "0123456789ABCDEF"; if(!buffer || !len) return NULL; - if(!(tmp = Malloc(len * 3 + 1))) { + if(!(tmp = OPENSSL_malloc(len * 3 + 1))) { X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); return NULL; } @@ -347,6 +371,10 @@ char *hex_to_string(unsigned char *buffer, long len) *q++ = ':'; } q[-1] = 0; +#ifdef CHARSET_EBCDIC + ebcdic2ascii(tmp, tmp, q - tmp - 1); +#endif + return tmp; } @@ -362,14 +390,20 @@ unsigned char *string_to_hex(char *str, long *len) X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT); return NULL; } - if(!(hexbuf = Malloc(strlen(str) >> 1))) goto err; + if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err; for(p = (unsigned char *)str, q = hexbuf; *p;) { ch = *p++; +#ifdef CHARSET_EBCDIC + ch = os_toebcdic[ch]; +#endif if(ch == ':') continue; cl = *p++; +#ifdef CHARSET_EBCDIC + cl = os_toebcdic[cl]; +#endif if(!cl) { X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS); - Free(hexbuf); + OPENSSL_free(hexbuf); return NULL; } if(isupper(ch)) ch = tolower(ch); @@ -391,12 +425,12 @@ unsigned char *string_to_hex(char *str, long *len) return hexbuf; err: - if(hexbuf) Free(hexbuf); + if(hexbuf) OPENSSL_free(hexbuf); X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE); return NULL; badhex: - Free(hexbuf); + OPENSSL_free(hexbuf); X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT); return NULL; @@ -416,3 +450,86 @@ int name_cmp(const char *name, const char *cmp) if(!c || (c=='.')) return 0; return 1; } + +static int sk_strcmp(const char * const *a, const char * const *b) +{ + return strcmp(*a, *b); +} + +STACK *X509_get1_email(X509 *x) +{ + GENERAL_NAMES *gens; + STACK *ret; + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return ret; +} + +STACK *X509_REQ_get1_email(X509_REQ *x) +{ + GENERAL_NAMES *gens; + STACK_OF(X509_EXTENSION) *exts; + STACK *ret; + exts = X509_REQ_get_extensions(x); + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_REQ_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + return ret; +} + + +static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens) +{ + STACK *ret = NULL; + X509_NAME_ENTRY *ne; + ASN1_IA5STRING *email; + GENERAL_NAME *gen; + int i; + /* Now add any email address(es) to STACK */ + i = -1; + /* First supplied X509_NAME */ + while((i = X509_NAME_get_index_by_NID(name, + NID_pkcs9_emailAddress, i)) > 0) { + ne = X509_NAME_get_entry(name, i); + email = X509_NAME_ENTRY_get_data(ne); + if(!append_ia5(&ret, email)) return NULL; + } + for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) + { + gen = sk_GENERAL_NAME_value(gens, i); + if(gen->type != GEN_EMAIL) continue; + if(!append_ia5(&ret, gen->d.ia5)) return NULL; + } + return ret; +} + +static void str_free(void *str) +{ + OPENSSL_free(str); +} + +static int append_ia5(STACK **sk, ASN1_IA5STRING *email) +{ + char *emtmp; + /* First some sanity checks */ + if(email->type != V_ASN1_IA5STRING) return 1; + if(!email->data || !email->length) return 1; + if(!*sk) *sk = sk_new(sk_strcmp); + if(!*sk) return 0; + /* Don't add duplicates */ + if(sk_find(*sk, (char *)email->data) != -1) return 1; + emtmp = BUF_strdup((char *)email->data); + if(!emtmp || !sk_push(*sk, emtmp)) { + X509_email_free(*sk); + *sk = NULL; + return 0; + } + return 1; +} + +void X509_email_free(STACK *sk) +{ + sk_pop_free(sk, str_free); +} diff --git a/src/lib/libcrypto/x509v3/v3err.c b/src/lib/libcrypto/x509v3/v3err.c index 50efa8d99d..6458e95bb9 100644 --- a/src/lib/libcrypto/x509v3/v3err.c +++ b/src/lib/libcrypto/x509v3/v3err.c @@ -54,7 +54,8 @@ */ /* 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. + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. */ #include @@ -62,7 +63,7 @@ #include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA X509V3_str_functs[]= { {ERR_PACK(0,X509V3_F_COPY_EMAIL,0), "COPY_EMAIL"}, @@ -72,6 +73,7 @@ static ERR_STRING_DATA X509V3_str_functs[]= {ERR_PACK(0,X509V3_F_HEX_TO_STRING,0), "hex_to_string"}, {ERR_PACK(0,X509V3_F_I2S_ASN1_ENUMERATED,0), "i2s_ASN1_ENUMERATED"}, {ERR_PACK(0,X509V3_F_I2S_ASN1_INTEGER,0), "i2s_ASN1_INTEGER"}, +{ERR_PACK(0,X509V3_F_I2V_AUTHORITY_INFO_ACCESS,0), "I2V_AUTHORITY_INFO_ACCESS"}, {ERR_PACK(0,X509V3_F_NOTICE_SECTION,0), "NOTICE_SECTION"}, {ERR_PACK(0,X509V3_F_NREF_NOS,0), "NREF_NOS"}, {ERR_PACK(0,X509V3_F_POLICY_SECTION,0), "POLICY_SECTION"}, @@ -87,6 +89,7 @@ static ERR_STRING_DATA X509V3_str_functs[]= {ERR_PACK(0,X509V3_F_SXNET_ADD_ID_ULONG,0), "SXNET_add_id_ulong"}, {ERR_PACK(0,X509V3_F_SXNET_GET_ID_ASC,0), "SXNET_get_id_asc"}, {ERR_PACK(0,X509V3_F_SXNET_GET_ID_ULONG,0), "SXNET_get_id_ulong"}, +{ERR_PACK(0,X509V3_F_V2I_ACCESS_DESCRIPTION,0), "V2I_ACCESS_DESCRIPTION"}, {ERR_PACK(0,X509V3_F_V2I_ASN1_BIT_STRING,0), "V2I_ASN1_BIT_STRING"}, {ERR_PACK(0,X509V3_F_V2I_AUTHORITY_KEYID,0), "V2I_AUTHORITY_KEYID"}, {ERR_PACK(0,X509V3_F_V2I_BASIC_CONSTRAINTS,0), "V2I_BASIC_CONSTRAINTS"}, @@ -95,6 +98,7 @@ static ERR_STRING_DATA X509V3_str_functs[]= {ERR_PACK(0,X509V3_F_V2I_GENERAL_NAME,0), "v2i_GENERAL_NAME"}, {ERR_PACK(0,X509V3_F_V2I_GENERAL_NAMES,0), "v2i_GENERAL_NAMES"}, {ERR_PACK(0,X509V3_F_V3_GENERIC_EXTENSION,0), "V3_GENERIC_EXTENSION"}, +{ERR_PACK(0,X509V3_F_X509V3_ADD_I2D,0), "X509V3_ADD_I2D"}, {ERR_PACK(0,X509V3_F_X509V3_ADD_VALUE,0), "X509V3_add_value"}, {ERR_PACK(0,X509V3_F_X509V3_EXT_ADD,0), "X509V3_EXT_add"}, {ERR_PACK(0,X509V3_F_X509V3_EXT_ADD_ALIAS,0), "X509V3_EXT_add_alias"}, @@ -102,6 +106,8 @@ static ERR_STRING_DATA X509V3_str_functs[]= {ERR_PACK(0,X509V3_F_X509V3_EXT_I2D,0), "X509V3_EXT_i2d"}, {ERR_PACK(0,X509V3_F_X509V3_GET_VALUE_BOOL,0), "X509V3_get_value_bool"}, {ERR_PACK(0,X509V3_F_X509V3_PARSE_LIST,0), "X509V3_parse_list"}, +{ERR_PACK(0,X509V3_F_X509_PURPOSE_ADD,0), "X509_PURPOSE_add"}, +{ERR_PACK(0,X509V3_F_X509_PURPOSE_SET,0), "X509_PURPOSE_set"}, {0,NULL} }; @@ -113,8 +119,10 @@ static ERR_STRING_DATA X509V3_str_reasons[]= {X509V3_R_BN_TO_ASN1_INTEGER_ERROR ,"bn to asn1 integer error"}, {X509V3_R_DUPLICATE_ZONE_ID ,"duplicate zone id"}, {X509V3_R_ERROR_CONVERTING_ZONE ,"error converting zone"}, +{X509V3_R_ERROR_CREATING_EXTENSION ,"error creating extension"}, {X509V3_R_ERROR_IN_EXTENSION ,"error in extension"}, {X509V3_R_EXPECTED_A_SECTION_NAME ,"expected a section name"}, +{X509V3_R_EXTENSION_EXISTS ,"extension exists"}, {X509V3_R_EXTENSION_NAME_ERROR ,"extension name error"}, {X509V3_R_EXTENSION_NOT_FOUND ,"extension not found"}, {X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED,"extension setting not supported"}, @@ -131,7 +139,9 @@ static ERR_STRING_DATA X509V3_str_reasons[]= {X509V3_R_INVALID_OBJECT_IDENTIFIER ,"invalid object identifier"}, {X509V3_R_INVALID_OPTION ,"invalid option"}, {X509V3_R_INVALID_POLICY_IDENTIFIER ,"invalid policy identifier"}, +{X509V3_R_INVALID_PURPOSE ,"invalid purpose"}, {X509V3_R_INVALID_SECTION ,"invalid section"}, +{X509V3_R_INVALID_SYNTAX ,"invalid syntax"}, {X509V3_R_ISSUER_DECODE_ERROR ,"issuer decode error"}, {X509V3_R_MISSING_VALUE ,"missing value"}, {X509V3_R_NEED_ORGANIZATION_AND_NUMBERS ,"need organization and numbers"}, @@ -162,7 +172,7 @@ void ERR_load_X509V3_strings(void) if (init) { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_X509V3,X509V3_str_functs); ERR_load_strings(ERR_LIB_X509V3,X509V3_str_reasons); #endif diff --git a/src/lib/libcrypto/x509v3/x509v3.h b/src/lib/libcrypto/x509v3/x509v3.h index d7945bc9cd..daecc55271 100644 --- a/src/lib/libcrypto/x509v3/x509v3.h +++ b/src/lib/libcrypto/x509v3/x509v3.h @@ -1,87 +1,655 @@ -/* crypto/x509v3/x509v3.h */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* x509v3.h */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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). + * + */ +#ifndef HEADER_X509V3_H +#define HEADER_X509V3_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward reference */ +struct v3_ext_method; +struct v3_ext_ctx; + +/* Useful typedefs */ + +typedef void * (*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE)(void *); +typedef void * (*X509V3_EXT_D2I)(void *, unsigned char ** , long); +typedef int (*X509V3_EXT_I2D)(void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) * (*X509V3_EXT_I2V)(struct v3_ext_method *method, void *ext, STACK_OF(CONF_VALUE) *extlist); +typedef void * (*X509V3_EXT_V2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, STACK_OF(CONF_VALUE) *values); +typedef char * (*X509V3_EXT_I2S)(struct v3_ext_method *method, void *ext); +typedef void * (*X509V3_EXT_S2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, char *str); +typedef int (*X509V3_EXT_I2R)(struct v3_ext_method *method, void *ext, BIO *out, int indent); +typedef void * (*X509V3_EXT_R2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, char *str); + +/* V3 extension structure */ + +struct v3_ext_method { +int ext_nid; +int ext_flags; +/* If this is set the following four fields are ignored */ +ASN1_ITEM_EXP *it; +/* Old style ASN1 calls */ +X509V3_EXT_NEW ext_new; +X509V3_EXT_FREE ext_free; +X509V3_EXT_D2I d2i; +X509V3_EXT_I2D i2d; + +/* The following pair is used for string extensions */ +X509V3_EXT_I2S i2s; +X509V3_EXT_S2I s2i; + +/* The following pair is used for multi-valued extensions */ +X509V3_EXT_I2V i2v; +X509V3_EXT_V2I v2i; + +/* The following are used for raw extensions */ +X509V3_EXT_I2R i2r; +X509V3_EXT_R2I r2i; + +void *usr_data; /* Any extension specific data */ +}; + +typedef struct X509V3_CONF_METHOD_st { +char * (*get_string)(void *db, char *section, char *value); +STACK_OF(CONF_VALUE) * (*get_section)(void *db, char *section); +void (*free_string)(void *db, char * string); +void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section); +} X509V3_CONF_METHOD; + +/* Context specific info */ +struct v3_ext_ctx { +#define CTX_TEST 0x1 +int flags; +X509 *issuer_cert; +X509 *subject_cert; +X509_REQ *subject_req; +X509_CRL *crl; +X509V3_CONF_METHOD *db_meth; +void *db; +/* Maybe more here */ +}; + +typedef struct v3_ext_method X509V3_EXT_METHOD; +typedef struct v3_ext_ctx X509V3_CTX; + +DECLARE_STACK_OF(X509V3_EXT_METHOD) + +/* ext_flags values */ +#define X509V3_EXT_DYNAMIC 0x1 +#define X509V3_EXT_CTX_DEP 0x2 +#define X509V3_EXT_MULTILINE 0x4 + +typedef BIT_STRING_BITNAME ENUMERATED_NAMES; + +typedef struct BASIC_CONSTRAINTS_st { +int ca; +ASN1_INTEGER *pathlen; +} BASIC_CONSTRAINTS; + + +typedef struct PKEY_USAGE_PERIOD_st { +ASN1_GENERALIZEDTIME *notBefore; +ASN1_GENERALIZEDTIME *notAfter; +} PKEY_USAGE_PERIOD; + +typedef struct otherName_st { +ASN1_OBJECT *type_id; +ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { + +#define GEN_OTHERNAME 0 +#define GEN_EMAIL 1 +#define GEN_DNS 2 +#define GEN_X400 3 +#define GEN_DIRNAME 4 +#define GEN_EDIPARTY 5 +#define GEN_URI 6 +#define GEN_IPADD 7 +#define GEN_RID 8 + +int type; +union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_TYPE *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + ASN1_TYPE *other; /* x400Address */ +} d; +} GENERAL_NAME; + +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +DECLARE_STACK_OF(GENERAL_NAME) +DECLARE_ASN1_SET_OF(GENERAL_NAME) + +DECLARE_STACK_OF(ACCESS_DESCRIPTION) +DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) + +typedef struct DIST_POINT_NAME_st { +int type; +union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; +} name; +} DIST_POINT_NAME; + +typedef struct DIST_POINT_st { +DIST_POINT_NAME *distpoint; +ASN1_BIT_STRING *reasons; +GENERAL_NAMES *CRLissuer; +} DIST_POINT; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DECLARE_STACK_OF(DIST_POINT) +DECLARE_ASN1_SET_OF(DIST_POINT) + +typedef struct AUTHORITY_KEYID_st { +ASN1_OCTET_STRING *keyid; +GENERAL_NAMES *issuer; +ASN1_INTEGER *serial; +} AUTHORITY_KEYID; + +/* Strong extranet structures */ + +typedef struct SXNET_ID_st { + ASN1_INTEGER *zone; + ASN1_OCTET_STRING *user; +} SXNETID; + +DECLARE_STACK_OF(SXNETID) +DECLARE_ASN1_SET_OF(SXNETID) + +typedef struct SXNET_st { + ASN1_INTEGER *version; + STACK_OF(SXNETID) *ids; +} SXNET; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DECLARE_STACK_OF(POLICYQUALINFO) +DECLARE_ASN1_SET_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DECLARE_STACK_OF(POLICYINFO) +DECLARE_ASN1_SET_OF(POLICYINFO) + +#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \ +",name:", val->name, ",value:", val->value); + +#define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL; + +#define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \ + 0,0,0,0, \ + 0,0, \ + (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \ + (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \ + NULL, NULL, \ + table} + +#define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \ + 0,0,0,0, \ + (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \ + (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \ + 0,0,0,0, \ + NULL} + +#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + +/* X509_PURPOSE stuff */ + +#define EXFLAG_BCONS 0x1 +#define EXFLAG_KUSAGE 0x2 +#define EXFLAG_XKUSAGE 0x4 +#define EXFLAG_NSCERT 0x8 + +#define EXFLAG_CA 0x10 +#define EXFLAG_SS 0x20 +#define EXFLAG_V1 0x40 +#define EXFLAG_INVALID 0x80 +#define EXFLAG_SET 0x100 +#define EXFLAG_CRITICAL 0x200 + +#define KU_DIGITAL_SIGNATURE 0x0080 +#define KU_NON_REPUDIATION 0x0040 +#define KU_KEY_ENCIPHERMENT 0x0020 +#define KU_DATA_ENCIPHERMENT 0x0010 +#define KU_KEY_AGREEMENT 0x0008 +#define KU_KEY_CERT_SIGN 0x0004 +#define KU_CRL_SIGN 0x0002 +#define KU_ENCIPHER_ONLY 0x0001 +#define KU_DECIPHER_ONLY 0x8000 + +#define NS_SSL_CLIENT 0x80 +#define NS_SSL_SERVER 0x40 +#define NS_SMIME 0x20 +#define NS_OBJSIGN 0x10 +#define NS_SSL_CA 0x04 +#define NS_SMIME_CA 0x02 +#define NS_OBJSIGN_CA 0x01 +#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) + +#define XKU_SSL_SERVER 0x1 +#define XKU_SSL_CLIENT 0x2 +#define XKU_SMIME 0x4 +#define XKU_CODE_SIGN 0x8 +#define XKU_SGC 0x10 +#define XKU_OCSP_SIGN 0x20 +#define XKU_TIMESTAMP 0x40 + +#define X509_PURPOSE_DYNAMIC 0x1 +#define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; /* Default trust ID */ + int flags; + int (*check_purpose)(const struct x509_purpose_st *, + const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +#define X509_PURPOSE_SSL_CLIENT 1 +#define X509_PURPOSE_SSL_SERVER 2 +#define X509_PURPOSE_NS_SSL_SERVER 3 +#define X509_PURPOSE_SMIME_SIGN 4 +#define X509_PURPOSE_SMIME_ENCRYPT 5 +#define X509_PURPOSE_CRL_SIGN 6 +#define X509_PURPOSE_ANY 7 +#define X509_PURPOSE_OCSP_HELPER 8 + +#define X509_PURPOSE_MIN 1 +#define X509_PURPOSE_MAX 8 + +/* Flags for X509V3_EXT_print() */ + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +#define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +/* Flags for X509V3_add1_i2d */ + +#define X509V3_ADD_OP_MASK 0xfL +#define X509V3_ADD_DEFAULT 0L +#define X509V3_ADD_APPEND 1L +#define X509V3_ADD_REPLACE 2L +#define X509V3_ADD_REPLACE_EXISTING 3L +#define X509V3_ADD_KEEP_EXISTING 4L +#define X509V3_ADD_DELETE 5L +#define X509V3_ADD_SILENT 0x10 + +DECLARE_STACK_OF(X509_PURPOSE) + +DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +DECLARE_ASN1_FUNCTIONS(SXNET) +DECLARE_ASN1_FUNCTIONS(SXNETID) + +int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen); +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen); +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, int userlen); + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone); +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone); +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone); + +DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID) + +DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAME) + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret); +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen); + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES) + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist); +GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +DECLARE_ASN1_FUNCTIONS(OTHERNAME) +DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME) + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5); +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); + +DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) +int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a); + +DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) +DECLARE_ASN1_FUNCTIONS(POLICYINFO) +DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO) +DECLARE_ASN1_FUNCTIONS(USERNOTICE) +DECLARE_ASN1_FUNCTIONS(NOTICEREF) + +DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS) +DECLARE_ASN1_FUNCTIONS(DIST_POINT) +DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME) + +DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) +DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +#ifdef HEADER_CONF_H +GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, CONF_VALUE *cnf); +void X509V3_conf_free(CONF_VALUE *val); + +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value); +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value); +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk); +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509 *cert); +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req); +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl); + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, char *value); +X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value); +int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert); +int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req); +int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl); + +int X509V3_add_value_bool_nf(char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool); +int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint); +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf); +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash); +#endif + +char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section); +STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section); +void X509V3_string_free(X509V3_CTX *ctx, char *str); +void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); +char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint); +ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value); +char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint); +char * i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint); +int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist); +int X509V3_EXT_add_alias(int nid_to, int nid_from); +void X509V3_EXT_cleanup(void); + +X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext); +X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +int X509V3_add_standard_extensions(void); +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line); +void *X509V3_EXT_d2i(X509_EXTENSION *ext); +void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx); + + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags); + +char *hex_to_string(unsigned char *buffer, long len); +unsigned char *string_to_hex(char *str, long *len); +int name_cmp(const char *name, const char *cmp); + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml); +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent); +int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); + +int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent); + +int X509_check_purpose(X509 *x, int id, int ca); +int X509_supported_extension(X509_EXTENSION *ex); +int X509_PURPOSE_set(int *p, int purpose); +int X509_check_issued(X509 *issuer, X509 *subject); +int X509_PURPOSE_get_count(void); +X509_PURPOSE * X509_PURPOSE_get0(int idx); +int X509_PURPOSE_get_by_sname(char *sname); +int X509_PURPOSE_get_by_id(int id); +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck)(const X509_PURPOSE *, const X509 *, int), + char *name, char *sname, void *arg); +char *X509_PURPOSE_get0_name(X509_PURPOSE *xp); +char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp); +int X509_PURPOSE_get_trust(X509_PURPOSE *xp); +void X509_PURPOSE_cleanup(void); +int X509_PURPOSE_get_id(X509_PURPOSE *); + +STACK *X509_get1_email(X509 *x); +STACK *X509_REQ_get1_email(X509_REQ *x); +void X509_email_free(STACK *sk); + + +/* 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. */ -#define X509v3_N_KU_digitalSignature 0 -#define X509v3_N_KU_nonRepudiation 1 -#define X509v3_N_KU_keyEncipherment 2 -#define X509v3_N_KU_dataEncipherment 3 -#define X509v3_N_KU_keyAgreement 4 -#define X509v3_N_KU_keyCertSign 5 -#define X509v3_N_KU_cRLSign 6 -#define X509v3_N_KU_encipherOnly 7 -#define X509v3_N_KU_decipherOnly 8 -#define X509v3_N_KU_NUM 9 -#define X509v3_S_KU_digitalSignature "digitalSignature" -#define X509v3_S_KU_nonRepudiation "nonRepudiation" -#define X509v3_S_KU_keyEncipherment "keyEncipherment" -#define X509v3_S_KU_dataEncipherment "dataEncipherment" -#define X509v3_S_KU_keyAgreement "keyAgreement" -#define X509v3_S_KU_keyCertSign "keyCertSign" -#define X509v3_S_KU_cRLSign "cRLSign" -#define X509v3_S_KU_encipherOnly "encipherOnly" -#define X509v3_S_KU_decipherOnly "decipherOnly" - - -void X509_ex_clear(X509_EXTENSION *a); -int X509_ex_get_bool(X509_EXTENSION *a,int num); -int X509_ex_set_bool(X509_EXTENSION *a,int num,int value); -int X509_ex_get_str(X509_EXTENSION *a,int index,char **p,int *len); -int X509_ex_set_str(X509_EXTENSION *a,int oid,int index,char *p,int len); -char *X509_ex_get_struct(X509_EXTENSION *a,int oid,int index,char **p); -int X509_ex_set_struct(X509_EXTENSION *a,int index,char *p); -int a2i_X509_EXTENSION(BIO *bp,X509_EXTENSION *a,char *buf,int len); -int i2a_X509_EXTENSION(BIO *bp,X509_EXTENSION *a); +void ERR_load_X509V3_strings(void); + +/* Error codes for the X509V3 functions. */ + +/* Function codes. */ +#define X509V3_F_COPY_EMAIL 122 +#define X509V3_F_COPY_ISSUER 123 +#define X509V3_F_DO_EXT_CONF 124 +#define X509V3_F_DO_EXT_I2D 135 +#define X509V3_F_HEX_TO_STRING 111 +#define X509V3_F_I2S_ASN1_ENUMERATED 121 +#define X509V3_F_I2S_ASN1_INTEGER 120 +#define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138 +#define X509V3_F_NOTICE_SECTION 132 +#define X509V3_F_NREF_NOS 133 +#define X509V3_F_POLICY_SECTION 131 +#define X509V3_F_R2I_CERTPOL 130 +#define X509V3_F_S2I_ASN1_IA5STRING 100 +#define X509V3_F_S2I_ASN1_INTEGER 108 +#define X509V3_F_S2I_ASN1_OCTET_STRING 112 +#define X509V3_F_S2I_ASN1_SKEY_ID 114 +#define X509V3_F_S2I_S2I_SKEY_ID 115 +#define X509V3_F_STRING_TO_HEX 113 +#define X509V3_F_SXNET_ADD_ASC 125 +#define X509V3_F_SXNET_ADD_ID_INTEGER 126 +#define X509V3_F_SXNET_ADD_ID_ULONG 127 +#define X509V3_F_SXNET_GET_ID_ASC 128 +#define X509V3_F_SXNET_GET_ID_ULONG 129 +#define X509V3_F_V2I_ACCESS_DESCRIPTION 139 +#define X509V3_F_V2I_ASN1_BIT_STRING 101 +#define X509V3_F_V2I_AUTHORITY_KEYID 119 +#define X509V3_F_V2I_BASIC_CONSTRAINTS 102 +#define X509V3_F_V2I_CRLD 134 +#define X509V3_F_V2I_EXT_KU 103 +#define X509V3_F_V2I_GENERAL_NAME 117 +#define X509V3_F_V2I_GENERAL_NAMES 118 +#define X509V3_F_V3_GENERIC_EXTENSION 116 +#define X509V3_F_X509V3_ADD_I2D 140 +#define X509V3_F_X509V3_ADD_VALUE 105 +#define X509V3_F_X509V3_EXT_ADD 104 +#define X509V3_F_X509V3_EXT_ADD_ALIAS 106 +#define X509V3_F_X509V3_EXT_CONF 107 +#define X509V3_F_X509V3_EXT_I2D 136 +#define X509V3_F_X509V3_GET_VALUE_BOOL 110 +#define X509V3_F_X509V3_PARSE_LIST 109 +#define X509V3_F_X509_PURPOSE_ADD 137 +#define X509V3_F_X509_PURPOSE_SET 141 + +/* Reason codes. */ +#define X509V3_R_BAD_IP_ADDRESS 118 +#define X509V3_R_BAD_OBJECT 119 +#define X509V3_R_BN_DEC2BN_ERROR 100 +#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101 +#define X509V3_R_DUPLICATE_ZONE_ID 133 +#define X509V3_R_ERROR_CONVERTING_ZONE 131 +#define X509V3_R_ERROR_CREATING_EXTENSION 144 +#define X509V3_R_ERROR_IN_EXTENSION 128 +#define X509V3_R_EXPECTED_A_SECTION_NAME 137 +#define X509V3_R_EXTENSION_EXISTS 145 +#define X509V3_R_EXTENSION_NAME_ERROR 115 +#define X509V3_R_EXTENSION_NOT_FOUND 102 +#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103 +#define X509V3_R_EXTENSION_VALUE_ERROR 116 +#define X509V3_R_ILLEGAL_HEX_DIGIT 113 +#define X509V3_R_INVALID_BOOLEAN_STRING 104 +#define X509V3_R_INVALID_EXTENSION_STRING 105 +#define X509V3_R_INVALID_NAME 106 +#define X509V3_R_INVALID_NULL_ARGUMENT 107 +#define X509V3_R_INVALID_NULL_NAME 108 +#define X509V3_R_INVALID_NULL_VALUE 109 +#define X509V3_R_INVALID_NUMBER 140 +#define X509V3_R_INVALID_NUMBERS 141 +#define X509V3_R_INVALID_OBJECT_IDENTIFIER 110 +#define X509V3_R_INVALID_OPTION 138 +#define X509V3_R_INVALID_POLICY_IDENTIFIER 134 +#define X509V3_R_INVALID_PURPOSE 146 +#define X509V3_R_INVALID_SECTION 135 +#define X509V3_R_INVALID_SYNTAX 143 +#define X509V3_R_ISSUER_DECODE_ERROR 126 +#define X509V3_R_MISSING_VALUE 124 +#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142 +#define X509V3_R_NO_CONFIG_DATABASE 136 +#define X509V3_R_NO_ISSUER_CERTIFICATE 121 +#define X509V3_R_NO_ISSUER_DETAILS 127 +#define X509V3_R_NO_POLICY_IDENTIFIER 139 +#define X509V3_R_NO_PUBLIC_KEY 114 +#define X509V3_R_NO_SUBJECT_DETAILS 125 +#define X509V3_R_ODD_NUMBER_OF_DIGITS 112 +#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122 +#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123 +#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111 +#define X509V3_R_UNKNOWN_EXTENSION 129 +#define X509V3_R_UNKNOWN_EXTENSION_NAME 130 +#define X509V3_R_UNKNOWN_OPTION 120 +#define X509V3_R_UNSUPPORTED_OPTION 117 +#define X509V3_R_USER_TOO_LONG 132 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/libssl/LICENSE b/src/lib/libssl/LICENSE index b9e18d5e7b..7b93e0dbce 100644 --- a/src/lib/libssl/LICENSE +++ b/src/lib/libssl/LICENSE @@ -12,7 +12,7 @@ --------------- /* ==================================================================== - * Copyright (c) 1998-1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2002 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 diff --git a/src/lib/libssl/bio_ssl.c b/src/lib/libssl/bio_ssl.c index 58a6d69b9b..467e149947 100644 --- a/src/lib/libssl/bio_ssl.c +++ b/src/lib/libssl/bio_ssl.c @@ -60,27 +60,18 @@ #include #include #include -#include "crypto.h" -#include "bio.h" -#include "err.h" -#include "ssl.h" - -#ifndef NOPROTO -static int ssl_write(BIO *h,char *buf,int num); -static int ssl_read(BIO *h,char *buf,int size); -static int ssl_puts(BIO *h,char *str); -static long ssl_ctrl(BIO *h,int cmd,long arg1,char *arg2); +#include +#include +#include +#include + +static int ssl_write(BIO *h, const char *buf, int num); +static int ssl_read(BIO *h, char *buf, int size); +static int ssl_puts(BIO *h, const char *str); +static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int ssl_new(BIO *h); static int ssl_free(BIO *data); -#else -static int ssl_write(); -static int ssl_read(); -static int ssl_puts(); -static long ssl_ctrl(); -static int ssl_new(); -static int ssl_free(); -#endif - +static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); typedef struct bio_ssl_st { SSL *ssl; /* The ssl handle :-) */ @@ -102,19 +93,19 @@ static BIO_METHOD methods_sslp= ssl_ctrl, ssl_new, ssl_free, + ssl_callback_ctrl, }; -BIO_METHOD *BIO_f_ssl() +BIO_METHOD *BIO_f_ssl(void) { return(&methods_sslp); } -static int ssl_new(bi) -BIO *bi; +static int ssl_new(BIO *bi) { BIO_SSL *bs; - bs=(BIO_SSL *)Malloc(sizeof(BIO_SSL)); + bs=(BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL)); if (bs == NULL) { BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE); @@ -127,8 +118,7 @@ BIO *bi; return(1); } -static int ssl_free(a) -BIO *a; +static int ssl_free(BIO *a) { BIO_SSL *bs; @@ -143,14 +133,11 @@ BIO *a; a->flags=0; } if (a->ptr != NULL) - Free(a->ptr); + OPENSSL_free(a->ptr); return(1); } -static int ssl_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int ssl_read(BIO *b, char *out, int outl) { int ret=1; BIO_SSL *sb; @@ -219,6 +206,10 @@ int outl; BIO_set_retry_special(b); retry_reason=BIO_RR_SSL_X509_LOOKUP; break; + case SSL_ERROR_WANT_ACCEPT: + BIO_set_retry_special(b); + retry_reason=BIO_RR_ACCEPT; + break; case SSL_ERROR_WANT_CONNECT: BIO_set_retry_special(b); retry_reason=BIO_RR_CONNECT; @@ -234,10 +225,7 @@ int outl; return(ret); } -static int ssl_write(b,out,outl) -BIO *b; -char *out; -int outl; +static int ssl_write(BIO *b, const char *out, int outl) { int ret,r=0; int retry_reason=0; @@ -305,11 +293,7 @@ int outl; return(ret); } -static long ssl_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) { SSL **sslp,*ssl; BIO_SSL *bs; @@ -466,7 +450,14 @@ char *ptr; ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); break; case BIO_CTRL_SET_CALLBACK: - SSL_set_info_callback(ssl,(void (*)())ptr); + { +#if 0 /* FIXME: Should this be used? -- Richard Levitte */ + BIOerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ret = -1; +#else + ret=0; +#endif + } break; case BIO_CTRL_GET_CALLBACK: { @@ -483,9 +474,31 @@ char *ptr; return(ret); } -static int ssl_puts(bp,str) -BIO *bp; -char *str; +static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + SSL *ssl; + BIO_SSL *bs; + long ret=1; + + bs=(BIO_SSL *)b->ptr; + ssl=bs->ssl; + switch (cmd) + { + case BIO_CTRL_SET_CALLBACK: + { + /* FIXME: setting this via a completely different prototype + seems like a crap idea */ + SSL_set_info_callback(ssl,(void (*)(const SSL *,int,int))fp); + } + break; + default: + ret=BIO_callback_ctrl(ssl->rbio,cmd,fp); + break; + } + return(ret); + } + +static int ssl_puts(BIO *bp, const char *str) { int n,ret; @@ -494,8 +507,7 @@ char *str; return(ret); } -BIO *BIO_new_buffer_ssl_connect(ctx) -SSL_CTX *ctx; +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) { BIO *ret=NULL,*buf=NULL,*ssl=NULL; @@ -512,8 +524,7 @@ err: return(NULL); } -BIO *BIO_new_ssl_connect(ctx) -SSL_CTX *ctx; +BIO *BIO_new_ssl_connect(SSL_CTX *ctx) { BIO *ret=NULL,*con=NULL,*ssl=NULL; @@ -530,9 +541,7 @@ err: return(NULL); } -BIO *BIO_new_ssl(ctx,client) -SSL_CTX *ctx; -int client; +BIO *BIO_new_ssl(SSL_CTX *ctx, int client) { BIO *ret; SSL *ssl; @@ -553,8 +562,7 @@ int client; return(ret); } -int BIO_ssl_copy_session_id(t,f) -BIO *t,*f; +int BIO_ssl_copy_session_id(BIO *t, BIO *f) { t=BIO_find_type(t,BIO_TYPE_SSL); f=BIO_find_type(f,BIO_TYPE_SSL); @@ -567,8 +575,7 @@ BIO *t,*f; return(1); } -void BIO_ssl_shutdown(b) -BIO *b; +void BIO_ssl_shutdown(BIO *b) { SSL *s; diff --git a/src/lib/libssl/doc/openssl.cnf b/src/lib/libssl/doc/openssl.cnf index d70dd25622..eca51c3322 100644 --- a/src/lib/libssl/doc/openssl.cnf +++ b/src/lib/libssl/doc/openssl.cnf @@ -3,8 +3,13 @@ # This is mostly being used for generation of certificate requests. # +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . RANDFILE = $ENV::HOME/.rnd -oid_file = $ENV::HOME/.oid + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid oid_section = new_oids # To use this configuration file with the "-extfile" option of the @@ -43,6 +48,14 @@ RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs # so this is commented out by default to leave a V1 CRL. # crl_extensions = crl_ext @@ -86,6 +99,22 @@ distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # The extentions to add to the self signed cert +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = AU @@ -111,7 +140,7 @@ commonName = Common Name (eg, YOUR name) commonName_max = 64 emailAddress = Email Address -emailAddress_max = 40 +emailAddress_max = 64 # SET-ex3 = SET extension number 3 @@ -159,6 +188,9 @@ authorityKeyIdentifier=keyid,issuer:always # This stuff is for subjectAltName and issuerAltname. # Import the email address. # subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move # Copy subject details # issuerAltName=issuer:copy @@ -170,8 +202,16 @@ authorityKeyIdentifier=keyid,issuer:always #nsCaPolicyUrl #nsSslServerName +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + [ v3_ca ] + # Extensions for a typical CA @@ -200,10 +240,11 @@ basicConstraints = CA:true # Copy issuer details # issuerAltName=issuer:copy -# RAW DER hex encoding of an extension: beware experts only! -# 1.2.3.5=RAW:02:03 +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object # You can even override a supported extension: -# basicConstraints= critical, RAW:30:03:01:01:FF +# basicConstraints= critical, DER:30:03:01:01:FF [ crl_ext ] diff --git a/src/lib/libssl/doc/openssl.txt b/src/lib/libssl/doc/openssl.txt index 91b85e5f14..5da519e7e4 100644 --- a/src/lib/libssl/doc/openssl.txt +++ b/src/lib/libssl/doc/openssl.txt @@ -1,53 +1,12 @@ This is some preliminary documentation for OpenSSL. -============================================================================== - BUFFER Library -============================================================================== - -The buffer library handles simple character arrays. Buffers are used for -various purposes in the library, most notably memory BIOs. - -The library uses the BUF_MEM structure defined in buffer.h: - -typedef struct buf_mem_st -{ - int length; /* current number of bytes */ - char *data; - int max; /* size of buffer */ -} BUF_MEM; - -'length' is the current size of the buffer in bytes, 'max' is the amount of -memory allocated to the buffer. There are three functions which handle these -and one "miscellaneous" function. - -BUF_MEM *BUF_MEM_new() - -This allocates a new buffer of zero size. Returns the buffer or NULL on error. - -void BUF_MEM_free(BUF_MEM *a) - -This frees up an already existing buffer. The data is zeroed before freeing -up in case the buffer contains sensitive data. - -int BUF_MEM_grow(BUF_MEM *str, int len) +Contents: -This changes the size of an already existing buffer. It returns zero on error -or the new size (i.e. 'len'). Any data already in the buffer is preserved if -it increases in size. + OpenSSL X509V3 extension configuration + X509V3 Extension code: programmers guide + PKCS#12 Library -char * BUF_strdup(char *str) - -This is the previously mentioned strdup function: like the standard library -strdup() it copies a null terminated string into a block of allocated memory -and returns a pointer to the allocated block. - -Unlike the standard C library strdup() this function uses Malloc() and so -should be used in preference to the standard library strdup() because it can -be used for memory leak checking or replacing the malloc() function. - -The memory allocated from BUF_strdup() should be freed up using the Free() -function. ============================================================================== OpenSSL X509V3 extension configuration @@ -188,7 +147,7 @@ email.1=steve@here email.2=steve@there This is because the configuration file code cannot handle the same name -occurring twice in the same extension. +occurring twice in the same section. The syntax of raw extensions is governed by the extension code: it can for example contain data in multiple sections. The correct syntax to @@ -315,6 +274,41 @@ TRUE. An end user certificate MUST NOT have the CA value set to true. According to PKIX recommendations it should exclude the extension entirely, however some software may require CA set to FALSE for end entity certificates. +Extended Key Usage. + +This extensions consists of a list of usages. + +These can either be object short names of the dotted numerical form of OIDs. +While any OID can be used only certain values make sense. In particular the +following PKIX, NS and MS values are meaningful: + +Value Meaning +----- ------- +serverAuth SSL/TLS Web Server Authentication. +clientAuth SSL/TLS Web Client Authentication. +codeSigning Code signing. +emailProtection E-mail Protection (S/MIME). +timeStamping Trusted Timestamping +msCodeInd Microsoft Individual Code Signing (authenticode) +msCodeCom Microsoft Commercial Code Signing (authenticode) +msCTLSign Microsoft Trust List Signing +msSGC Microsoft Server Gated Crypto +msEFS Microsoft Encrypted File System +nsSGC Netscape Server Gated Crypto + +For example, under IE5 a CA can be used for any purpose: by including a list +of the above usages the CA can be restricted to only authorised uses. + +Note: software packages may place additional interpretations on certificate +use, in particular some usages may only work for selected CAs. Don't for example +expect just including msSGC or nsSGC will automatically mean that a certificate +can be used for SGC ("step up" encryption) otherwise anyone could use it. + +Examples: + +extendedKeyUsage=critical,codeSigning,1.2.3.4 +extendedKeyUsage=nsSGC,msSGC + Subject Key Identifier. This is really a string extension and can take two possible values. Either @@ -361,6 +355,24 @@ that would not make sense. It does support an additional issuer:copy option that will copy all the subject alternative name values from the issuer certificate (if possible). +Example: + +issuserAltName = issuer:copy + +Authority Info Access. + +The authority information access extension gives details about how to access +certain information relating to the CA. Its syntax is accessOID;location +where 'location' has the same syntax as subject alternative name (except +that email:copy is not supported). accessOID can be any valid OID but only +certain values are meaningful for example OCSP and caIssuers. OCSP gives the +location of an OCSP responder: this is used by Netscape PSM and other software. + +Example: + +authorityInfoAccess = OCSP;URI:http://ocsp.my.host/ +authorityInfoAccess = caIssuers;URI:http://my.ca/ca.html + CRL distribution points. This is a multi-valued extension that supports all the literal options of @@ -459,16 +471,16 @@ extension in a human or machine readable form. 1. Initialisation and cleanup. -X509V3_add_standard_extensions(); - -This function should be called before any other extension code. It adds support -for some common PKIX and Netscape extensions. Additional custom extensions can -be added as well (see later). +No special initialisation is needed before calling the extension functions. +You used to have to call X509V3_add_standard_extensions(); but this is no longer +required and this function no longer does anything. void X509V3_EXT_cleanup(void); -This function should be called last to cleanup the extension code. After this -call no other extension calls should be made. +This function should be called to cleanup the extension code if any custom +extensions have been added. If no custom extensions have been added then this +call does nothing. After this call all custom extension code is freed up but +you can still use the standard extensions. 2. Printing and parsing extensions. @@ -495,6 +507,47 @@ details about the structures returned. The returned structure should be freed after use using the relevant free function, BASIC_CONSTRAINTS_free() for example. +void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); +void * X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx); +void * X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx); +void * X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx); + +These functions combine the operations of searching for extensions and +parsing them. They search a certificate, a CRL a CRL entry or a stack +of extensions respectively for extension whose NID is 'nid' and return +the parsed result of NULL if an error occurred. For example: + +BASIC_CONSTRAINTS *bs; +bs = X509_get_ext_d2i(cert, NID_basic_constraints, NULL, NULL); + +This will search for the basicConstraints extension and either return +it value or NULL. NULL can mean either the extension was not found, it +occurred more than once or it could not be parsed. + +If 'idx' is NULL then an extension is only parsed if it occurs precisely +once. This is standard behaviour because extensions normally cannot occur +more than once. If however more than one extension of the same type can +occur it can be used to parse successive extensions for example: + +int i; +void *ext; + +i = -1; +for(;;) { + ext = X509_get_ext_d2i(x, nid, crit, &idx); + if(ext == NULL) break; + /* Do something with ext */ +} + +If 'crit' is not NULL and the extension was found then the int it points to +is set to 1 for critical extensions and 0 for non critical. Therefore if the +function returns NULL but 'crit' is set to 0 or 1 then the extension was +found but it could not be parsed. + +The int pointed to by crit will be set to -1 if the extension was not found +and -2 if the extension occurred more than once (this will only happen if +idx is NULL). In both cases the function will return NULL. + 3. Generating extensions. An extension will typically be generated from a configuration file, or some @@ -512,7 +565,7 @@ or CRL is due to be signed. Both return 0 on error on non zero for success. In each case 'conf' is the LHASH pointer of the configuration file to use and 'section' is the section containing the extension details. -See the 'context functions' section for a description of the ctx paramater. +See the 'context functions' section for a description of the ctx parameter. X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, @@ -531,7 +584,7 @@ takes the NID of the extension rather than its name. For example to produce basicConstraints with the CA flag and a path length of 10: -x = X509V3_EXT_conf_nid(NULL, NULL, NID_basicConstraints, "CA:TRUE,pathlen:10"); +x = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,"CA:TRUE,pathlen:10"); X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); @@ -659,7 +712,7 @@ The same as above but for an unsigned character value. int X509V3_add_value_bool(const char *name, int asn1_bool, STACK_OF(CONF_VALUE) **extlist); -This adds either "TRUE" or "FALSE" depending on the value of 'ans1_bool' +This adds either "TRUE" or "FALSE" depending on the value of 'asn1_bool' int X509V3_add_value_bool_nf(char *name, int asn1_bool, STACK_OF(CONF_VALUE) **extlist); @@ -686,7 +739,7 @@ Multi value extensions are passed a STACK_OF(CONF_VALUE) name and value pairs or return a STACK_OF(CONF_VALUE). Raw extensions are just passed a BIO or a value and it is the extensions -responsiblity to handle all the necessary printing. +responsibility to handle all the necessary printing. There are two ways to add an extension. One is simply as an alias to an already existing extension. An alias is an extension that is identical in ASN1 structure @@ -811,7 +864,7 @@ int i2r(struct v3_ext_method *method, void *ext, BIO *out, int indent); This function is passed the internal extension structure in the ext parameter and sends out a human readable version of the extension to out. The 'indent' -paremeter should be noted to determine the necessary amount of indentation +parameter should be noted to determine the necessary amount of indentation needed on the output. void * r2i(struct v3_ext_method *method, struct v3_ext_ctx *ctx, char *str); @@ -882,7 +935,7 @@ d2i_PKCS12_fp(fp, p12) This is the same but for a FILE pointer. -3. Parsing and creation functions. +3. High level functions. 3.1 Parsing with PKCS12_parse(). @@ -920,6 +973,14 @@ p12 = PKCS12_create(pass, "My Certificate", pkey, cert, NULL, 0,0,0,0,0); i2d_PKCS12_fp(fp, p12); PKCS12_free(p12); +3.3 Changing a PKCS#12 structure password. + +int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass); + +This changes the password of an already existing PKCS#12 structure. oldpass +is the old password and newpass is the new one. An error occurs if the old +password is incorrect. + LOW LEVEL FUNCTIONS. In some cases the high level functions do not provide the necessary diff --git a/src/lib/libssl/doc/standards.txt b/src/lib/libssl/doc/standards.txt index 61ccc5d7e0..596d9001e6 100644 --- a/src/lib/libssl/doc/standards.txt +++ b/src/lib/libssl/doc/standards.txt @@ -24,7 +24,8 @@ http://www.rsasecurity.com/rsalabs/pkcs/. Implemented: ------------ -These are documents that describe things that are implemented in OpenSSL. +These are documents that describe things that are implemented (in +whole or at least great parts) in OpenSSL. 1319 The MD2 Message-Digest Algorithm. B. Kaliski. April 1992. (Format: TXT=25661 bytes) (Status: INFORMATIONAL) @@ -59,6 +60,11 @@ PKCS#8: Private-Key Information Syntax Standard PKCS#12: Personal Information Exchange Syntax Standard, version 1.0. +2560 X.509 Internet Public Key Infrastructure Online Certificate + Status Protocol - OCSP. M. Myers, R. Ankney, A. Malpani, S. Galperin, + C. Adams. June 1999. (Format: TXT=43243 bytes) (Status: PROPOSED + STANDARD) + Related: -------- @@ -84,6 +90,10 @@ STARTTLS documents. Certification and Related Services. B. Kaliski. February 1993. (Format: TXT=17537 bytes) (Status: PROPOSED STANDARD) +2256 A Summary of the X.500(96) User Schema for use with LDAPv3. M. + Wahl. December 1997. (Format: TXT=32377 bytes) (Status: PROPOSED + STANDARD) + 2487 SMTP Service Extension for Secure SMTP over TLS. P. Hoffman. January 1999. (Format: TXT=15120 bytes) (Status: PROPOSED STANDARD) @@ -114,8 +124,7 @@ To be implemented: These are documents that describe things that are planed to be implemented in the hopefully short future. -2560 X.509 Internet Public Key Infrastructure Online Certificate - Status Protocol - OCSP. M. Myers, R. Ankney, A. Malpani, S. Galperin, - C. Adams. June 1999. (Format: TXT=43243 bytes) (Status: PROPOSED - STANDARD) +2712 Addition of Kerberos Cipher Suites to Transport Layer Security + (TLS). A. Medvinsky, M. Hur. October 1999. (Format: TXT=13763 bytes) + (Status: PROPOSED STANDARD) diff --git a/src/lib/libssl/s23_clnt.c b/src/lib/libssl/s23_clnt.c index a4661ebb68..b2be8340fb 100644 --- a/src/lib/libssl/s23_clnt.c +++ b/src/lib/libssl/s23_clnt.c @@ -57,28 +57,22 @@ */ #include -#include "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" +#include +#include +#include +#include #include "ssl_locl.h" -#define BREAK break - -#ifndef NOPROTO +static SSL_METHOD *ssl23_get_client_method(int ver); static int ssl23_client_hello(SSL *s); static int ssl23_get_server_hello(SSL *s); -#else -static int ssl23_client_hello(); -static int ssl23_get_server_hello(); -#endif - -static SSL_METHOD *ssl23_get_client_method(ver) -int ver; +static SSL_METHOD *ssl23_get_client_method(int ver) { +#ifndef OPENSSL_NO_SSL2 if (ver == SSL2_VERSION) return(SSLv2_client_method()); - else if (ver == SSL3_VERSION) +#endif + if (ver == SSL3_VERSION) return(SSLv3_client_method()); else if (ver == TLS1_VERSION) return(TLSv1_client_method()); @@ -86,32 +80,31 @@ int ver; return(NULL); } -SSL_METHOD *SSLv23_client_method() +SSL_METHOD *SSLv23_client_method(void) { static int init=1; static SSL_METHOD SSLv23_client_data; if (init) { - init=0; memcpy((char *)&SSLv23_client_data, (char *)sslv23_base_method(),sizeof(SSL_METHOD)); SSLv23_client_data.ssl_connect=ssl23_connect; SSLv23_client_data.get_ssl_method=ssl23_get_client_method; + init=0; } return(&SSLv23_client_data); } -int ssl23_connect(s) -SSL *s; +int ssl23_connect(SSL *s) { BUF_MEM *buf; unsigned long Time=time(NULL); - void (*cb)()=NULL; + void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state; - RAND_seed((unsigned char *)&Time,sizeof(Time)); + RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); @@ -120,8 +113,8 @@ SSL *s; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; - if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); for (;;) { @@ -134,6 +127,13 @@ SSL *s; case SSL_ST_BEFORE|SSL_ST_CONNECT: case SSL_ST_OK|SSL_ST_CONNECT: + if (s->session != NULL) + { + SSLerr(SSL_F_SSL23_CONNECT,SSL_R_SSL23_DOING_SESSION_ID_REUSE); + ret= -1; + goto end; + } + s->server=0; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); /* s->version=TLS1_VERSION; */ @@ -159,7 +159,7 @@ SSL *s; ssl3_init_finished_mac(s); s->state=SSL23_ST_CW_CLNT_HELLO_A; - s->ctx->sess_connect++; + s->ctx->stats.sess_connect++; s->init_num=0; break; @@ -179,7 +179,7 @@ SSL *s; ret=ssl23_get_server_hello(s); if (ret >= 0) cb=NULL; goto end; - break; + /* break; */ default: SSLerr(SSL_F_SSL23_CONNECT,SSL_R_UNKNOWN_STATE); @@ -188,7 +188,7 @@ SSL *s; /* break; */ } - if (s->debug) BIO_flush(s->wbio); + if (s->debug) { (void)BIO_flush(s->wbio); } if ((cb != NULL) && (s->state != state)) { @@ -206,12 +206,12 @@ end: } -static int ssl23_client_hello(s) -SSL *s; +static int ssl23_client_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; int i,ch_len; + int ret; buf=(unsigned char *)s->init_buf->data; if (s->state == SSL23_ST_CW_CLNT_HELLO_A) @@ -225,7 +225,7 @@ SSL *s; #endif p=s->s3->client_random; - RAND_bytes(p,SSL3_RANDOM_SIZE); + RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE); /* Do the message type and length last */ d= &(buf[2]); @@ -236,16 +236,19 @@ SSL *s; { *(d++)=TLS1_VERSION_MAJOR; *(d++)=TLS1_VERSION_MINOR; + s->client_version=TLS1_VERSION; } else if (!(s->options & SSL_OP_NO_SSLv3)) { *(d++)=SSL3_VERSION_MAJOR; *(d++)=SSL3_VERSION_MINOR; + s->client_version=SSL3_VERSION; } else if (!(s->options & SSL_OP_NO_SSLv2)) { *(d++)=SSL2_VERSION_MAJOR; *(d++)=SSL2_VERSION_MINOR; + s->client_version=SSL2_VERSION; } else { @@ -283,7 +286,7 @@ SSL *s; i=ch_len; s2n(i,d); memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE); - RAND_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i); + RAND_pseudo_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i); memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i); p+=i; @@ -300,15 +303,18 @@ SSL *s; } /* SSL3_ST_CW_CLNT_HELLO_B */ - return(ssl23_write_bytes(s)); + ret = ssl23_write_bytes(s); + if (ret >= 2) + if (s->msg_callback) + s->msg_callback(1, SSL2_VERSION, 0, s->init_buf->data+2, ret-2, s, s->msg_callback_arg); /* CLIENT-HELLO */ + return ret; } -static int ssl23_get_server_hello(s) -SSL *s; +static int ssl23_get_server_hello(SSL *s) { char buf[8]; unsigned char *p; - int i,ch_len; + int i; int n; n=ssl23_read_bytes(s,7); @@ -321,9 +327,14 @@ SSL *s; if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) && (p[5] == 0x00) && (p[6] == 0x02)) { +#ifdef OPENSSL_NO_SSL2 + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); + goto err; +#else /* we are talking sslv2 */ /* we need to clean up the SSLv3 setup and put in the * sslv2 stuff. */ + int ch_len; if (s->options & SSL_OP_NO_SSLv2) { @@ -360,7 +371,9 @@ SSL *s; } s->state=SSL2_ST_GET_SERVER_HELLO_A; - s->s2->ssl2_rollback=1; + if (!(s->client_version == SSL2_VERSION)) + /* use special padding (SSL 3.0 draft/RFC 2246, App. E.2) */ + s->s2->ssl2_rollback=1; /* setup the 5 bytes we have read so we get them from * the sslv2 buffer */ @@ -376,6 +389,7 @@ SSL *s; s->method=SSLv2_client_method(); s->handshake_func=s->method->ssl_connect; +#endif } else if ((p[0] == SSL3_RT_HANDSHAKE) && (p[1] == SSL3_VERSION_MAJOR) && @@ -426,7 +440,7 @@ SSL *s; (p[3] == 0) && (p[4] == 2)) { - void (*cb)()=NULL; + void (*cb)(const SSL *ssl,int type,int val)=NULL; int j; /* An alert */ @@ -443,7 +457,7 @@ SSL *s; } s->rwstate=SSL_NOTHING; - SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,1000+p[6]); + SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_AD_REASON_OFFSET+p[6]); goto err; } else diff --git a/src/lib/libssl/s23_lib.c b/src/lib/libssl/s23_lib.c index e16f641101..b70002a647 100644 --- a/src/lib/libssl/s23_lib.c +++ b/src/lib/libssl/s23_lib.c @@ -57,28 +57,18 @@ */ #include -#include "objects.h" +#include #include "ssl_locl.h" -#ifndef NOPROTO static int ssl23_num_ciphers(void ); static SSL_CIPHER *ssl23_get_cipher(unsigned int u); -static int ssl23_read(SSL *s, char *buf, int len); -static int ssl23_write(SSL *s, char *buf, int len); +static int ssl23_read(SSL *s, void *buf, int len); +static int ssl23_peek(SSL *s, void *buf, int len); +static int ssl23_write(SSL *s, const void *buf, int len); static long ssl23_default_timeout(void ); -static int ssl23_put_cipher_by_char(SSL_CIPHER *c, unsigned char *p); -static SSL_CIPHER *ssl23_get_cipher_by_char(unsigned char *p); -#else -static int ssl23_num_ciphers(); -static SSL_CIPHER *ssl23_get_cipher(); -static int ssl23_read(); -static int ssl23_write(); -static long ssl23_default_timeout(); -static int ssl23_put_cipher_by_char(); -static SSL_CIPHER *ssl23_get_cipher_by_char(); -#endif - -char *SSL23_version_str="SSLv2/3 compatablity part of SSLeay 0.7.0 30-Jan-1997"; +static int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p); +static SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p); +const char *SSL23_version_str="SSLv2/3 compatibility" OPENSSL_VERSION_PTEXT; static SSL_METHOD SSLv23_data= { TLS1_VERSION, @@ -88,10 +78,11 @@ static SSL_METHOD SSLv23_data= { ssl_undefined_function, ssl_undefined_function, ssl23_read, - ssl_undefined_function, + ssl23_peek, ssl23_write, ssl_undefined_function, ssl_undefined_function, + ssl_ok, ssl3_ctrl, ssl3_ctx_ctrl, ssl23_get_cipher_by_char, @@ -102,38 +93,47 @@ static SSL_METHOD SSLv23_data= { ssl_bad_method, ssl23_default_timeout, &ssl3_undef_enc_method, + ssl_undefined_function, + ssl3_callback_ctrl, + ssl3_ctx_callback_ctrl, }; -static long ssl23_default_timeout() +static long ssl23_default_timeout(void) { return(300); } -SSL_METHOD *sslv23_base_method() +SSL_METHOD *sslv23_base_method(void) { return(&SSLv23_data); } -static int ssl23_num_ciphers() +static int ssl23_num_ciphers(void) { - return(ssl3_num_ciphers()+ssl2_num_ciphers()); + return(ssl3_num_ciphers() +#ifndef OPENSSL_NO_SSL2 + + ssl2_num_ciphers() +#endif + ); } -static SSL_CIPHER *ssl23_get_cipher(u) -unsigned int u; +static SSL_CIPHER *ssl23_get_cipher(unsigned int u) { unsigned int uu=ssl3_num_ciphers(); if (u < uu) return(ssl3_get_cipher(u)); else +#ifndef OPENSSL_NO_SSL2 return(ssl2_get_cipher(u-uu)); +#else + return(NULL); +#endif } /* This function needs to check if the ciphers required are actually * available */ -static SSL_CIPHER *ssl23_get_cipher_by_char(p) -unsigned char *p; +static SSL_CIPHER *ssl23_get_cipher_by_char(const unsigned char *p) { SSL_CIPHER c,*cp; unsigned long id; @@ -144,14 +144,14 @@ unsigned char *p; ((unsigned long)p[1]<<8L)|(unsigned long)p[2]; c.id=id; cp=ssl3_get_cipher_by_char(p); +#ifndef OPENSSL_NO_SSL2 if (cp == NULL) cp=ssl2_get_cipher_by_char(p); +#endif return(cp); } -static int ssl23_put_cipher_by_char(c,p) -SSL_CIPHER *c; -unsigned char *p; +static int ssl23_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p) { long l; @@ -166,20 +166,10 @@ unsigned char *p; return(3); } -static int ssl23_read(s,buf,len) -SSL *s; -char *buf; -int len; +static int ssl23_read(SSL *s, void *buf, int len) { int n; -#if 0 - if (s->shutdown & SSL_RECEIVED_SHUTDOWN) - { - s->rwstate=SSL_NOTHING; - return(0); - } -#endif clear_sys_error(); if (SSL_in_init(s) && (!s->in_handshake)) { @@ -199,20 +189,33 @@ int len; } } -static int ssl23_write(s,buf,len) -SSL *s; -char *buf; -int len; +static int ssl23_peek(SSL *s, void *buf, int len) { int n; -#if 0 - if (s->shutdown & SSL_SENT_SHUTDOWN) + clear_sys_error(); + if (SSL_in_init(s) && (!s->in_handshake)) { - s->rwstate=SSL_NOTHING; - return(0); + n=s->handshake_func(s); + if (n < 0) return(n); + if (n == 0) + { + SSLerr(SSL_F_SSL23_PEEK,SSL_R_SSL_HANDSHAKE_FAILURE); + return(-1); + } + return(SSL_peek(s,buf,len)); } -#endif + else + { + ssl_undefined_function(s); + return(-1); + } + } + +static int ssl23_write(SSL *s, const void *buf, int len) + { + int n; + clear_sys_error(); if (SSL_in_init(s) && (!s->in_handshake)) { diff --git a/src/lib/libssl/s23_pkt.c b/src/lib/libssl/s23_pkt.c index c25c312772..f45e1ce3d8 100644 --- a/src/lib/libssl/s23_pkt.c +++ b/src/lib/libssl/s23_pkt.c @@ -59,12 +59,11 @@ #include #include #define USE_SOCKETS -#include "evp.h" -#include "buffer.h" +#include +#include #include "ssl_locl.h" -int ssl23_write_bytes(s) -SSL *s; +int ssl23_write_bytes(SSL *s) { int i,num,tot; char *buf; @@ -76,7 +75,7 @@ SSL *s; { s->rwstate=SSL_WRITING; i=BIO_write(s->wbio,&(buf[tot]),num); - if (i < 0) + if (i <= 0) { s->init_off=tot; s->init_num=num; @@ -90,10 +89,8 @@ SSL *s; } } -/* only return when we have read 'n' bytes */ -int ssl23_read_bytes(s,n) -SSL *s; -int n; +/* return regularly only when we have read (at least) 'n' bytes */ +int ssl23_read_bytes(SSL *s, int n) { unsigned char *p; int j; diff --git a/src/lib/libssl/s23_srvr.c b/src/lib/libssl/s23_srvr.c index c7b9ecbcf2..9e89cc7f9a 100644 --- a/src/lib/libssl/s23_srvr.c +++ b/src/lib/libssl/s23_srvr.c @@ -55,28 +55,76 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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 "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" +#include +#include +#include +#include #include "ssl_locl.h" -#define BREAK break - -#ifndef NOPROTO +static SSL_METHOD *ssl23_get_server_method(int ver); int ssl23_get_client_hello(SSL *s); -#else -int ssl23_get_client_hello(); -#endif - -static SSL_METHOD *ssl23_get_server_method(ver) -int ver; +static SSL_METHOD *ssl23_get_server_method(int ver) { +#ifndef OPENSSL_NO_SSL2 if (ver == SSL2_VERSION) return(SSLv2_server_method()); - else if (ver == SSL3_VERSION) +#endif + if (ver == SSL3_VERSION) return(SSLv3_server_method()); else if (ver == TLS1_VERSION) return(TLSv1_server_method()); @@ -84,32 +132,31 @@ int ver; return(NULL); } -SSL_METHOD *SSLv23_server_method() +SSL_METHOD *SSLv23_server_method(void) { static int init=1; static SSL_METHOD SSLv23_server_data; if (init) { - init=0; memcpy((char *)&SSLv23_server_data, (char *)sslv23_base_method(),sizeof(SSL_METHOD)); SSLv23_server_data.ssl_accept=ssl23_accept; SSLv23_server_data.get_ssl_method=ssl23_get_server_method; + init=0; } return(&SSLv23_server_data); } -int ssl23_accept(s) -SSL *s; +int ssl23_accept(SSL *s) { BUF_MEM *buf; unsigned long Time=time(NULL); - void (*cb)()=NULL; + void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state; - RAND_seed((unsigned char *)&Time,sizeof(Time)); + RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); @@ -118,8 +165,8 @@ SSL *s; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; - if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); for (;;) { @@ -132,6 +179,7 @@ SSL *s; case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: + s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); /* s->version=SSL3_VERSION; */ @@ -155,7 +203,7 @@ SSL *s; ssl3_init_finished_mac(s); s->state=SSL23_ST_SR_CLNT_HELLO_A; - s->ctx->sess_accept++; + s->ctx->stats.sess_accept++; s->init_num=0; break; @@ -166,7 +214,7 @@ SSL *s; ret=ssl23_get_client_hello(s); if (ret >= 0) cb=NULL; goto end; - break; + /* break; */ default: SSLerr(SSL_F_SSL23_ACCEPT,SSL_R_UNKNOWN_STATE); @@ -184,31 +232,48 @@ SSL *s; } } end: + s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_ACCEPT_EXIT,ret); - s->in_handshake--; return(ret); } -int ssl23_get_client_hello(s) -SSL *s; +int ssl23_get_client_hello(SSL *s) { - char buf_space[8]; + char buf_space[11]; /* Request this many bytes in initial read. + * We can detect SSL 3.0/TLS 1.0 Client Hellos + * ('type == 3') correctly only when the following + * is in a single record, which is not guaranteed by + * the protocol specification: + * Byte Content + * 0 type \ + * 1/2 version > record header + * 3/4 length / + * 5 msg_type \ + * 6-8 length > Client Hello message + * 9/10 client_version / + */ char *buf= &(buf_space[0]); - unsigned char *p,*d,*dd; + unsigned char *p,*d,*d_len,*dd; unsigned int i; unsigned int csl,sil,cl; - int n=0,j,tls1=0; - int type=0,use_sslv2_strong=0; + int n=0,j; + int type=0; + int v[2]; +#ifndef OPENSSL_NO_RSA + int use_sslv2_strong=0; +#endif - /* read the initial header */ if (s->state == SSL23_ST_SR_CLNT_HELLO_A) { + /* read the initial header */ + v[0]=v[1]=0; + if (!ssl3_setup_buffers(s)) goto err; - n=ssl23_read_bytes(s,7); - if (n != 7) return(n); + n=ssl23_read_bytes(s, sizeof buf_space); + if (n != sizeof buf_space) return(n); /* n == -1 || n == 0 */ p=s->packet; @@ -216,124 +281,135 @@ SSL *s; if ((p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) { - /* SSLv2 header */ + /* + * SSLv2 header + */ if ((p[3] == 0x00) && (p[4] == 0x02)) { + v[0]=p[3]; v[1]=p[4]; /* SSLv2 */ if (!(s->options & SSL_OP_NO_SSLv2)) type=1; } else if (p[3] == SSL3_VERSION_MAJOR) { + v[0]=p[3]; v[1]=p[4]; /* SSLv3/TLSv1 */ if (p[4] >= TLS1_VERSION_MINOR) { if (!(s->options & SSL_OP_NO_TLSv1)) { - tls1=1; + s->version=TLS1_VERSION; + /* type=2; */ /* done later to survive restarts */ s->state=SSL23_ST_SR_CLNT_HELLO_B; } else if (!(s->options & SSL_OP_NO_SSLv3)) { + s->version=SSL3_VERSION; + /* type=2; */ s->state=SSL23_ST_SR_CLNT_HELLO_B; } + else if (!(s->options & SSL_OP_NO_SSLv2)) + { + type=1; + } } else if (!(s->options & SSL_OP_NO_SSLv3)) - s->state=SSL23_ST_SR_CLNT_HELLO_B; - - if (s->options & SSL_OP_NON_EXPORT_FIRST) { - STACK *sk; - SSL_CIPHER *c; - int ne2,ne3; - - j=((p[0]&0x7f)<<8)|p[1]; - if (j > (1024*4)) - { - SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE); - goto err; - } - - n=ssl23_read_bytes(s,j+2); - if (n <= 0) return(n); - p=s->packet; - - if ((buf=Malloc(n)) == NULL) - { - SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); - goto err; - } - memcpy(buf,p,n); - - p+=5; - n2s(p,csl); - p+=4; - - sk=ssl_bytes_to_cipher_list( - s,p,csl,NULL); - if (sk != NULL) - { - ne2=ne3=0; - for (j=0; jalgorithms & SSL_EXP)) - { - if ((c->id>>24L) == 2L) - ne2=1; - else - ne3=1; - } - } - if (ne2 && !ne3) - { - type=1; - use_sslv2_strong=1; - goto next_bit; - } - } + s->version=SSL3_VERSION; + /* type=2; */ + s->state=SSL23_ST_SR_CLNT_HELLO_B; } + else if (!(s->options & SSL_OP_NO_SSLv2)) + type=1; + } } else if ((p[0] == SSL3_RT_HANDSHAKE) && (p[1] == SSL3_VERSION_MAJOR) && - (p[5] == SSL3_MT_CLIENT_HELLO)) + (p[5] == SSL3_MT_CLIENT_HELLO) && + ((p[3] == 0 && p[4] < 5 /* silly record length? */) + || (p[9] == p[1]))) { - /* true SSLv3 or tls1 */ - if (p[2] >= TLS1_VERSION_MINOR) + /* + * SSLv3 or tls1 header + */ + + v[0]=p[1]; /* major version (= SSL3_VERSION_MAJOR) */ + /* We must look at client_version inside the Client Hello message + * to get the correct minor version. + * However if we have only a pathologically small fragment of the + * Client Hello message, this would be difficult, and we'd have + * to read more records to find out. + * No known SSL 3.0 client fragments ClientHello like this, + * so we simply assume TLS 1.0 to avoid protocol version downgrade + * attacks. */ + if (p[3] == 0 && p[4] < 6) + { +#if 0 + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL); + goto err; +#else + v[1] = TLS1_VERSION_MINOR; +#endif + } + else + v[1]=p[10]; /* minor version according to client_version */ + if (v[1] >= TLS1_VERSION_MINOR) { if (!(s->options & SSL_OP_NO_TLSv1)) { + s->version=TLS1_VERSION; type=3; - tls1=1; } else if (!(s->options & SSL_OP_NO_SSLv3)) + { + s->version=SSL3_VERSION; + type=3; + } + } + else + { + /* client requests SSL 3.0 */ + if (!(s->options & SSL_OP_NO_SSLv3)) + { + s->version=SSL3_VERSION; type=3; + } + else if (!(s->options & SSL_OP_NO_TLSv1)) + { + /* we won't be able to use TLS of course, + * but this will send an appropriate alert */ + s->version=TLS1_VERSION; + type=3; + } } - else if (!(s->options & SSL_OP_NO_SSLv3)) - type=3; } - else if ((strncmp("GET ", p,4) == 0) || - (strncmp("POST ",p,5) == 0) || - (strncmp("HEAD ",p,5) == 0) || - (strncmp("PUT ", p,4) == 0)) + else if ((strncmp("GET ", (char *)p,4) == 0) || + (strncmp("POST ",(char *)p,5) == 0) || + (strncmp("HEAD ",(char *)p,5) == 0) || + (strncmp("PUT ", (char *)p,4) == 0)) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTP_REQUEST); goto err; } - else if (strncmp("CONNECT",p,7) == 0) + else if (strncmp("CONNECT",(char *)p,7) == 0) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_HTTPS_PROXY_REQUEST); goto err; } } -next_bit: if (s->state == SSL23_ST_SR_CLNT_HELLO_B) { - /* we have a SSLv3/TLSv1 in a SSLv2 header */ + /* we have SSLv3/TLSv1 in an SSLv2 header + * (other cases skip this state) */ + type=2; p=s->packet; + v[0] = p[3]; /* == SSL3_VERSION_MAJOR */ + v[1] = p[4]; + n=((p[0]&0x7f)<<8)|p[1]; if (n > (1024*4)) { @@ -344,7 +420,9 @@ next_bit: j=ssl23_read_bytes(s,n+2); if (j <= 0) return(j); - ssl3_finish_mac(s,&(s->packet[2]),s->packet_length-2); + ssl3_finish_mac(s, s->packet+2, s->packet_length-2); + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, s->packet+2, s->packet_length-2, s, s->msg_callback_arg); /* CLIENT-HELLO */ p=s->packet; p+=5; @@ -358,14 +436,18 @@ next_bit: goto err; } - *(d++)=SSL3_VERSION_MAJOR; - if (tls1) - *(d++)=TLS1_VERSION_MINOR; - else - *(d++)=SSL3_VERSION_MINOR; + /* record header: msg_type ... */ + *(d++) = SSL3_MT_CLIENT_HELLO; + /* ... and length (actual value will be written later) */ + d_len = d; + d += 3; + + /* client_version */ + *(d++) = SSL3_VERSION_MAJOR; /* == v[0] */ + *(d++) = v[1]; /* lets populate the random area */ - /* get the chalenge_length */ + /* get the challenge_length */ i=(cl > SSL3_RANDOM_SIZE)?SSL3_RANDOM_SIZE:cl; memset(d,0,SSL3_RANDOM_SIZE); memcpy(&(d[SSL3_RANDOM_SIZE-i]),&(p[csl+sil]),i); @@ -387,11 +469,12 @@ next_bit: } s2n(j,dd); - /* compression */ + /* COMPRESSION */ *(d++)=1; *(d++)=0; - i=(d-(unsigned char *)s->init_buf->data); + i = (d-(unsigned char *)s->init_buf->data) - 4; + l2n3((long)i, d_len); /* get the data reused from the init_buf */ s->s3->tmp.reuse_message=1; @@ -399,8 +482,15 @@ next_bit: s->s3->tmp.message_size=i; } + /* imaginary new state (for program structure): */ + /* s->state = SSL23_SR_CLNT_HELLO_C */ + if (type == 1) { +#ifdef OPENSSL_NO_SSL2 + SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_UNSUPPORTED_PROTOCOL); + goto err; +#else /* we are talking sslv2 */ /* we need to clean up the SSLv3/TLSv1 setup and put in the * sslv2 stuff. */ @@ -423,12 +513,15 @@ next_bit: s->state=SSL2_ST_GET_CLIENT_HELLO_A; if ((s->options & SSL_OP_MSIE_SSLV2_RSA_PADDING) || - use_sslv2_strong) + use_sslv2_strong || + (s->options & SSL_OP_NO_TLSv1 && s->options & SSL_OP_NO_SSLv3)) s->s2->ssl2_rollback=0; else + /* reject SSL 2.0 session if client supports SSL 3.0 or TLS 1.0 + * (SSL 3.0 draft/RFC 2246, App. E.2) */ s->s2->ssl2_rollback=1; - /* setup the 5 bytes we have read so we get them from + /* setup the n bytes we have read so we get them from * the sslv2 buffer */ s->rstate=SSL_ST_READ_HEADER; s->packet_length=n; @@ -439,11 +532,12 @@ next_bit: s->method=SSLv2_server_method(); s->handshake_func=s->method->ssl_accept; +#endif } if ((type == 2) || (type == 3)) { - /* we have SSLv3/TLSv1 */ + /* we have SSLv3/TLSv1 (type 2: SSL2 style, type 3: SSL3/TLS style) */ if (!ssl_init_wbio_buffer(s,1)) goto err; @@ -468,16 +562,13 @@ next_bit: s->s3->rbuf.offset=0; } - if (tls1) - { - s->version=TLS1_VERSION; - s->method=TLSv1_server_method(); - } + if (s->version == TLS1_VERSION) + s->method = TLSv1_server_method(); else - { - s->version=SSL3_VERSION; - s->method=SSLv3_server_method(); - } + s->method = SSLv3_server_method(); +#if 0 /* ssl3_get_client_hello does this */ + s->client_version=(v[0]<<8)|v[1]; +#endif s->handshake_func=s->method->ssl_accept; } @@ -489,11 +580,10 @@ next_bit: } s->init_num=0; - if (buf != buf_space) Free(buf); + if (buf != buf_space) OPENSSL_free(buf); s->first_packet=1; return(SSL_accept(s)); err: - if (buf != buf_space) Free(buf); + if (buf != buf_space) OPENSSL_free(buf); return(-1); } - diff --git a/src/lib/libssl/s3_both.c b/src/lib/libssl/s3_both.c index 6de62e1591..58a24cd883 100644 --- a/src/lib/libssl/s3_both.c +++ b/src/lib/libssl/s3_both.c @@ -55,26 +55,95 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include #include "ssl_locl.h" -#define BREAK break - -/* SSL3err(SSL_F_SSL3_GET_FINISHED,SSL_R_EXCESSIVE_MESSAGE_SIZE); - */ +/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ +int ssl3_do_write(SSL *s, int type) + { + int ret; + + ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off], + s->init_num); + if (ret < 0) return(-1); + if (type == SSL3_RT_HANDSHAKE) + /* should not be done for 'Hello Request's, but in that case + * we'll ignore the result anyway */ + ssl3_finish_mac(s,(unsigned char *)&s->init_buf->data[s->init_off],ret); + + if (ret == s->init_num) + { + if (s->msg_callback) + s->msg_callback(1, s->version, type, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg); + return(1); + } + s->init_off+=ret; + s->init_num-=ret; + return(0); + } -int ssl3_send_finished(s,a,b,sender,slen) -SSL *s; -int a; -int b; -unsigned char *sender; -int slen; +int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) { unsigned char *p,*d; int i; @@ -88,10 +157,19 @@ int slen; i=s->method->ssl3_enc->final_finish_mac(s, &(s->s3->finish_dgst1), &(s->s3->finish_dgst2), - sender,slen,p); + sender,slen,s->s3->tmp.finish_md); + s->s3->tmp.finish_md_len = i; + memcpy(p, s->s3->tmp.finish_md, i); p+=i; l=i; +#ifdef OPENSSL_SYS_WIN16 + /* MSVC 1.5 does not clear the top bytes of the word unless + * I do this. + */ + l&=0xffff; +#endif + *(d++)=SSL3_MT_FINISHED; l2n3(l,d); s->init_num=(int)l+4; @@ -104,17 +182,14 @@ int slen; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -int ssl3_get_finished(s,a,b) -SSL *s; -int a; -int b; +int ssl3_get_finished(SSL *s, int a, int b) { int al,i,ok; long n; unsigned char *p; /* the mac has already been generated when we received the - * change cipher spec message and is in s->s3->tmp.in_dgst[12] + * change cipher spec message and is in s->s3->tmp.peer_finish_md */ n=ssl3_get_message(s, @@ -126,7 +201,7 @@ int b; if (!ok) return((int)n); - /* If this occurs if we has missed a message */ + /* If this occurs, we have missed a message */ if (!s->s3->change_cipher_spec) { al=SSL_AD_UNEXPECTED_MESSAGE; @@ -135,9 +210,8 @@ int b; } s->s3->change_cipher_spec=0; - p=(unsigned char *)s->init_buf->data; - - i=s->method->ssl3_enc->finish_mac_length; + p = (unsigned char *)s->init_msg; + i = s->s3->tmp.peer_finish_md_len; if (i != n) { @@ -146,7 +220,7 @@ int b; goto f_err; } - if (memcmp( p, (char *)&(s->s3->tmp.finish_md[0]),i) != 0) + if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED); @@ -167,9 +241,7 @@ f_err: * ssl->session->read_compression assign * ssl->session->read_hash assign */ -int ssl3_send_change_cipher_spec(s,a,b) -SSL *s; -int a,b; +int ssl3_send_change_cipher_spec(SSL *s, int a, int b) { unsigned char *p; @@ -187,9 +259,7 @@ int a,b; return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } -unsigned long ssl3_output_cert_chain(s,x) -SSL *s; -X509 *x; +unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; int n,i; @@ -207,7 +277,11 @@ X509 *x; } if (x != NULL) { - X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL); + if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL)) + { + SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); + return(0); + } for (;;) { @@ -236,6 +310,23 @@ X509 *x; X509_STORE_CTX_cleanup(&xs_ctx); } + /* Thawte special :-) */ + if (s->ctx->extra_certs != NULL) + for (i=0; ictx->extra_certs); i++) + { + x=sk_X509_value(s->ctx->extra_certs,i); + n=i2d_X509(x,NULL); + if (!BUF_MEM_grow(buf,(int)(n+l+3))) + { + SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); + return(0); + } + p=(unsigned char *)&(buf->data[l]); + l2n3(n,p); + i2d_X509(x,&p); + l+=n+3; + } + l-=7; p=(unsigned char *)&(buf->data[4]); l2n3(l,p); @@ -247,11 +338,12 @@ X509 *x; return(l); } -long ssl3_get_message(s,st1,stn,mt,max,ok) -SSL *s; -int st1,stn,mt; -long max; -int *ok; +/* Obtain handshake message of message type 'mt' (any if mt == -1), + * maximum acceptable body length 'max'. + * The first four bytes (msg_type and length) are read in state 'st1', + * the body is read in state 'stn'. + */ +long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) { unsigned char *p; unsigned long l; @@ -268,21 +360,51 @@ int *ok; goto f_err; } *ok=1; - return((int)s->s3->tmp.message_size); + s->init_msg = s->init_buf->data + 4; + s->init_num = (int)s->s3->tmp.message_size; + return s->init_num; } p=(unsigned char *)s->init_buf->data; - if (s->state == st1) + if (s->state == st1) /* s->init_num < 4 */ { - i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE, - (char *)&(p[s->init_num]), - 4-s->init_num); - if (i < (4-s->init_num)) + int skip_message; + + do { - *ok=0; - return(ssl3_part_read(s,i)); + while (s->init_num < 4) + { + i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num], + 4 - s->init_num, 0); + if (i <= 0) + { + s->rwstate=SSL_READING; + *ok = 0; + return i; + } + s->init_num+=i; + } + + skip_message = 0; + if (!s->server) + if (p[0] == SSL3_MT_HELLO_REQUEST) + /* The server may always send 'Hello Request' messages -- + * we are doing a handshake anyway now, so ignore them + * if their format is correct. Does not count for + * 'Finished' MAC. */ + if (p[1] == 0 && p[2] == 0 &&p[3] == 0) + { + s->init_num = 0; + skip_message = 1; + + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg); + } } + while (skip_message); + + /* s->init_num == 4 */ if ((mt >= 0) && (*p != mt)) { @@ -290,6 +412,18 @@ int *ok; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } + if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) && + (st1 == SSL3_ST_SR_CERT_A) && + (stn == SSL3_ST_SR_CERT_B)) + { + /* At this point we have got an MS SGC second client + * hello (maybe we should always allow the client to + * start a new handshake?). We need to restart the mac. + * Don't increment {num,total}_renegotiations because + * we have not completed the handshake. */ + ssl3_init_finished_mac(s); + } + s->s3->tmp.message_type= *(p++); n2l3(p,l); @@ -299,7 +433,13 @@ int *ok; SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); goto f_err; } - if (l && !BUF_MEM_grow(s->init_buf,(int)l)) + if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */ + { + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_MESSAGE,SSL_R_EXCESSIVE_MESSAGE_SIZE); + goto f_err; + } + if (l && !BUF_MEM_grow(s->init_buf,(int)l+4)) { SSLerr(SSL_F_SSL3_GET_MESSAGE,ERR_R_BUF_LIB); goto err; @@ -307,24 +447,30 @@ int *ok; s->s3->tmp.message_size=l; s->state=stn; - s->init_num=0; + s->init_msg = s->init_buf->data + 4; + s->init_num = 0; } /* next state (stn) */ - p=(unsigned char *)s->init_buf->data; - n=s->s3->tmp.message_size; - if (n > 0) + p = s->init_msg; + n = s->s3->tmp.message_size - s->init_num; + while (n > 0) { - i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE, - (char *)&(p[s->init_num]),(int)n); - if (i != (int)n) + i=ssl3_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0); + if (i <= 0) { - *ok=0; - return(ssl3_part_read(s,i)); + s->rwstate=SSL_READING; + *ok = 0; + return i; } + s->init_num += i; + n -= i; } + ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg); *ok=1; - return(n); + return s->init_num; f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: @@ -332,9 +478,7 @@ err: return(-1); } -int ssl_cert_type(x,pkey) -X509 *x; -EVP_PKEY *pkey; +int ssl_cert_type(X509 *x, EVP_PKEY *pkey) { EVP_PKEY *pk; int ret= -1,i,j; @@ -380,11 +524,11 @@ EVP_PKEY *pkey; ret= -1; err: + if(!pkey) EVP_PKEY_free(pk); return(ret); } -int ssl_verify_alarm_type(type) -long type; +int ssl_verify_alarm_type(long type) { int al; @@ -392,6 +536,7 @@ long type; { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: al=SSL_AD_UNKNOWN_CA; break; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: @@ -403,6 +548,8 @@ long type; case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CERT_UNTRUSTED: + case X509_V_ERR_CERT_REJECTED: al=SSL_AD_BAD_CERTIFICATE; break; case X509_V_ERR_CERT_SIGNATURE_FAILURE: @@ -424,11 +571,16 @@ long type; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + case X509_V_ERR_INVALID_CA: al=SSL_AD_UNKNOWN_CA; break; case X509_V_ERR_APPLICATION_VERIFICATION: al=SSL_AD_HANDSHAKE_FAILURE; break; + case X509_V_ERR_INVALID_PURPOSE: + al=SSL_AD_UNSUPPORTED_CERTIFICATE; + break; default: al=SSL_AD_CERTIFICATE_UNKNOWN; break; @@ -436,11 +588,11 @@ long type; return(al); } -int ssl3_setup_buffers(s) -SSL *s; +int ssl3_setup_buffers(SSL *s) { unsigned char *p; unsigned int extra; + size_t len; if (s->s3->rbuf.buf == NULL) { @@ -448,18 +600,21 @@ SSL *s; extra=SSL3_RT_MAX_EXTRA; else extra=0; - if ((p=(unsigned char *)Malloc(SSL3_RT_MAX_PACKET_SIZE+extra)) - == NULL) + len = SSL3_RT_MAX_PACKET_SIZE + extra; + if ((p=OPENSSL_malloc(len)) == NULL) goto err; - s->s3->rbuf.buf=p; + s->s3->rbuf.buf = p; + s->s3->rbuf.len = len; } if (s->s3->wbuf.buf == NULL) { - if ((p=(unsigned char *)Malloc(SSL3_RT_MAX_PACKET_SIZE)) - == NULL) + len = SSL3_RT_MAX_PACKET_SIZE; + len += SSL3_RT_HEADER_LENGTH + 256; /* extra space for empty fragment */ + if ((p=OPENSSL_malloc(len)) == NULL) goto err; - s->s3->wbuf.buf=p; + s->s3->wbuf.buf = p; + s->s3->wbuf.len = len; } s->packet= &(s->s3->rbuf.buf[0]); return(1); diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c index 940c6a458f..e5853ede95 100644 --- a/src/lib/libssl/s3_clnt.c +++ b/src/lib/libssl/s3_clnt.c @@ -55,29 +55,74 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" +#include +#include +#include +#include #include "ssl_locl.h" +#include "kssl_lcl.h" +#include -#define BREAK break -/* SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_SERVER_DONE,ERR_R_MALLOC_FAILURE); -SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SSL3_SESSION_ID_TOO_SHORT); - */ - -#ifndef NOPROTO +static SSL_METHOD *ssl3_get_client_method(int ver); static int ssl3_client_hello(SSL *s); static int ssl3_get_server_hello(SSL *s); static int ssl3_get_certificate_request(SSL *s); -static int ca_dn_cmp(X509_NAME **a,X509_NAME **b); +static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b); static int ssl3_get_server_done(SSL *s); static int ssl3_send_client_verify(SSL *s); static int ssl3_send_client_certificate(SSL *s); @@ -85,22 +130,7 @@ static int ssl3_send_client_key_exchange(SSL *s); static int ssl3_get_key_exchange(SSL *s); static int ssl3_get_server_certificate(SSL *s); static int ssl3_check_cert_and_algorithm(SSL *s); -#else -static int ssl3_client_hello(); -static int ssl3_get_server_hello(); -static int ssl3_get_certificate_request(); -static int ca_dn_cmp(); -static int ssl3_get_server_done(); -static int ssl3_send_client_verify(); -static int ssl3_send_client_certificate(); -static int ssl3_send_client_key_exchange(); -static int ssl3_get_key_exchange(); -static int ssl3_get_server_certificate(); -static int ssl3_check_cert_and_algorithm(); -#endif - -static SSL_METHOD *ssl3_get_client_method(ver) -int ver; +static SSL_METHOD *ssl3_get_client_method(int ver) { if (ver == SSL3_VERSION) return(SSLv3_client_method()); @@ -108,7 +138,7 @@ int ver; return(NULL); } -SSL_METHOD *SSLv3_client_method() +SSL_METHOD *SSLv3_client_method(void) { static int init=1; static SSL_METHOD SSLv3_client_data; @@ -124,18 +154,16 @@ SSL_METHOD *SSLv3_client_method() return(&SSLv3_client_data); } -int ssl3_connect(s) -SSL *s; +int ssl3_connect(SSL *s) { BUF_MEM *buf; unsigned long Time=time(NULL),l; long num1; - void (*cb)()=NULL; + void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; - BIO *under; int new_state,state,skip=0;; - RAND_seed((unsigned char *)&Time,sizeof(Time)); + RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); @@ -144,8 +172,8 @@ SSL *s; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; - if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); for (;;) { @@ -156,17 +184,23 @@ SSL *s; case SSL_ST_RENEGOTIATE: s->new_session=1; s->state=SSL_ST_CONNECT; - s->ctx->sess_connect_renegotiate++; + s->ctx->stats.sess_connect_renegotiate++; /* break */ case SSL_ST_BEFORE: case SSL_ST_CONNECT: case SSL_ST_BEFORE|SSL_ST_CONNECT: case SSL_ST_OK|SSL_ST_CONNECT: + s->server=0; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version & 0xff00 ) != 0x0300) - abort(); + { + SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + /* s->version=SSL3_VERSION; */ s->type=SSL_ST_CONNECT; @@ -195,7 +229,7 @@ SSL *s; ssl3_init_finished_mac(s); s->state=SSL3_ST_CW_CLNT_HELLO_A; - s->ctx->sess_connect++; + s->ctx->stats.sess_connect++; s->init_num=0; break; @@ -278,6 +312,7 @@ SSL *s; case SSL3_ST_CW_CERT_A: case SSL3_ST_CW_CERT_B: case SSL3_ST_CW_CERT_C: + case SSL3_ST_CW_CERT_D: ret=ssl3_send_client_certificate(s); if (ret <= 0) goto end; s->state=SSL3_ST_CW_KEY_EXCH_A; @@ -324,6 +359,11 @@ SSL *s; s->init_num=0; s->session->cipher=s->s3->tmp.new_cipher; + if (s->s3->tmp.new_compression == NULL) + s->session->compress_meth=0; + else + s->session->compress_meth= + s->s3->tmp.new_compression->id; if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; @@ -343,8 +383,8 @@ SSL *s; case SSL3_ST_CW_FINISHED_B: ret=ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B, - s->method->ssl3_enc->client_finished, - s->method->ssl3_enc->client_finished_len); + s->method->ssl3_enc->client_finished_label, + s->method->ssl3_enc->client_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_CW_FLUSH; @@ -399,38 +439,33 @@ SSL *s; /* clean a few things up */ ssl3_cleanup_key_block(s); - BUF_MEM_free(s->init_buf); - s->init_buf=NULL; - - if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER)) + if (s->init_buf != NULL) { - /* remove buffering */ - under=BIO_pop(s->wbio); - if (under != NULL) - s->wbio=under; - else - abort(); /* ok */ - - BIO_free(s->bbio); - s->bbio=NULL; + BUF_MEM_free(s->init_buf); + s->init_buf=NULL; } - /* else do it later */ + + /* If we are not 'joining' the last two packets, + * remove the buffering now */ + if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER)) + ssl_free_wbio_buffer(s); + /* else do it later in ssl3_write */ s->init_num=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); - if (s->hit) s->ctx->sess_hit++; + if (s->hit) s->ctx->stats.sess_hit++; ret=1; /* s->server=0; */ s->handshake_func=ssl3_connect; - s->ctx->sess_connect_good++; + s->ctx->stats.sess_connect_good++; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); goto end; - break; + /* break; */ default: SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE); @@ -459,26 +494,27 @@ SSL *s; skip=0; } end: + s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_CONNECT_EXIT,ret); - s->in_handshake--; return(ret); } -static int ssl3_client_hello(s) -SSL *s; +static int ssl3_client_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; - int i; + int i,j; unsigned long Time,l; + SSL_COMP *comp; buf=(unsigned char *)s->init_buf->data; if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { if ((s->session == NULL) || - (s->session->ssl_version != s->version)) + (s->session->ssl_version != s->version) || + (s->session->not_resumable)) { if (!ssl_get_new_session(s,0)) goto err; @@ -488,13 +524,14 @@ SSL *s; p=s->s3->client_random; Time=time(NULL); /* Time */ l2n(Time,p); - RAND_bytes(&(p[4]),SSL3_RANDOM_SIZE-sizeof(Time)); + RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); /* Do the message type and length last */ d=p= &(buf[4]); *(p++)=s->version>>8; *(p++)=s->version&0xff; + s->client_version=s->version; /* Random stuff */ memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); @@ -522,9 +559,18 @@ SSL *s; s2n(i,p); p+=i; - /* hardwire in the NULL compression algorithm. */ - *(p++)=1; - *(p++)=0; + /* COMPRESSION */ + if (s->ctx->comp_methods == NULL) + j=0; + else + j=sk_SSL_COMP_num(s->ctx->comp_methods); + *(p++)=1+j; + for (i=0; ictx->comp_methods,i); + *(p++)=comp->id; + } + *(p++)=0; /* Add the NULL method */ l=(p-d); d=buf; @@ -543,15 +589,15 @@ err: return(-1); } -static int ssl3_get_server_hello(s) -SSL *s; +static int ssl3_get_server_hello(SSL *s) { - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *c; unsigned char *p,*d; int i,al,ok; unsigned int j; long n; + SSL_COMP *comp; n=ssl3_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, @@ -561,7 +607,7 @@ SSL *s; &ok); if (!ok) return((int)n); - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; if ((p[0] != (s->version>>8)) || (p[1] != (s->version&0xff))) { @@ -590,9 +636,18 @@ SSL *s; goto f_err; } } - if ((j != 0) && (j == s->session->session_id_length) && - (memcmp(p,s->session->session_id,j) == 0)) - s->hit=1; + if (j != 0 && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { + if(s->sid_ctx_length != s->session->sid_ctx_length + || memcmp(s->session->sid_ctx,s->sid_ctx,s->sid_ctx_length)) + { + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); + goto f_err; + } + s->hit=1; + } else /* a miss or crap from the other end */ { /* If we were trying for session-id reuse, make a new @@ -621,7 +676,7 @@ SSL *s; p+=ssl_put_cipher_by_char(s,NULL,NULL); sk=ssl_get_ciphers_by_id(s); - i=sk_find(sk,(char *)c); + i=sk_SSL_CIPHER_find(sk,c); if (i < 0) { /* we did not say we would use this cipher */ @@ -643,13 +698,23 @@ SSL *s; s->s3->tmp.new_cipher=c; /* lets get the compression algorithm */ + /* COMPRESSION */ j= *(p++); - if (j != 0) + if (j == 0) + comp=NULL; + else + comp=ssl3_comp_find(s->ctx->comp_methods,j); + + if ((j != 0) && (comp == NULL)) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); goto f_err; } + else + { + s->s3->tmp.new_compression=comp; + } if (p != (d+n)) { @@ -666,26 +731,22 @@ err: return(-1); } -static int ssl3_get_server_certificate(s) -SSL *s; +static int ssl3_get_server_certificate(SSL *s) { int al,i,ok,ret= -1; unsigned long n,nc,llen,l; X509 *x=NULL; unsigned char *p,*d,*q; - STACK *sk=NULL; - CERT *c; + STACK_OF(X509) *sk=NULL; + SESS_CERT *sc; EVP_PKEY *pkey=NULL; + int need_cert = 1; /* VRS: 0=> will allow null cert if auth == KRB5 */ n=ssl3_get_message(s, SSL3_ST_CR_CERT_A, SSL3_ST_CR_CERT_B, -1, -#if defined(MSDOS) && !defined(WIN32) - 1024*30, /* 30k max cert list :-) */ -#else - 1024*100, /* 100k max cert list :-) */ -#endif + s->max_cert_list, &ok); if (!ok) return((int)n); @@ -702,9 +763,9 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE); goto f_err; } - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; - if ((sk=sk_new_null()) == NULL) + if ((sk=sk_X509_new_null()) == NULL) { SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -741,7 +802,7 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } - if (!sk_push(sk,(char *)x)) + if (!sk_X509_push(sk,x)) { SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -752,53 +813,91 @@ SSL *s; } i=ssl_verify_cert_chain(s,sk); - if ((s->verify_mode != SSL_VERIFY_NONE) && (!i)) + if ((s->verify_mode != SSL_VERIFY_NONE) && (!i) +#ifndef OPENSSL_NO_KRB5 + && (s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK)) + != (SSL_aKRB5|SSL_kKRB5) +#endif /* OPENSSL_NO_KRB5 */ + ) { al=ssl_verify_alarm_type(s->verify_result); SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); goto f_err; } + ERR_clear_error(); /* but we keep s->verify_result */ - c=ssl_cert_new(); - if (c == NULL) goto err; + sc=ssl_sess_cert_new(); + if (sc == NULL) goto err; - if (s->session->cert) ssl_cert_free(s->session->cert); - s->session->cert=c; + if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert); + s->session->sess_cert=sc; - c->cert_chain=sk; - x=(X509 *)sk_value(sk,0); + sc->cert_chain=sk; + /* Inconsistency alert: cert_chain does include the peer's + * certificate, which we don't include in s3_srvr.c */ + x=sk_X509_value(sk,0); sk=NULL; + /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/ pkey=X509_get_pubkey(x); - if (EVP_PKEY_missing_parameters(pkey)) + /* VRS: allow null cert if auth == KRB5 */ + need_cert = ((s->s3->tmp.new_cipher->algorithms + & (SSL_MKEY_MASK|SSL_AUTH_MASK)) + == (SSL_aKRB5|SSL_kKRB5))? 0: 1; + +#ifdef KSSL_DEBUG + printf("pkey,x = %p, %p\n", pkey,x); + printf("ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x,pkey)); + printf("cipher, alg, nc = %s, %lx, %d\n", s->s3->tmp.new_cipher->name, + s->s3->tmp.new_cipher->algorithms, need_cert); +#endif /* KSSL_DEBUG */ + + if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))) { x=NULL; al=SSL3_AL_FATAL; - SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); goto f_err; } i=ssl_cert_type(x,pkey); - if (i < 0) + if (need_cert && i < 0) { x=NULL; al=SSL3_AL_FATAL; - SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNKNOWN_CERTIFICATE_TYPE); + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto f_err; } - c->cert_type=i; - CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); - if (c->pkeys[i].x509 != NULL) - X509_free(c->pkeys[i].x509); - c->pkeys[i].x509=x; - c->key= &(c->pkeys[i]); - - if ((s->session != NULL) && (s->session->peer != NULL)) - X509_free(s->session->peer); - CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); - s->session->peer=x; + if (need_cert) + { + sc->peer_cert_type=i; + CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); + /* Why would the following ever happen? + * We just created sc a couple of lines ago. */ + if (sc->peer_pkeys[i].x509 != NULL) + X509_free(sc->peer_pkeys[i].x509); + sc->peer_pkeys[i].x509=x; + sc->peer_key= &(sc->peer_pkeys[i]); + + if (s->session->peer != NULL) + X509_free(s->session->peer); + CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); + s->session->peer=x; + } + else + { + sc->peer_cert_type=i; + sc->peer_key= NULL; + + if (s->session->peer != NULL) + X509_free(s->session->peer); + s->session->peer=NULL; + } + s->session->verify_result = s->verify_result; x=NULL; ret=1; @@ -809,15 +908,15 @@ f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); } err: - if (x != NULL) X509_free(x); - if (sk != NULL) sk_pop_free(sk,X509_free); + EVP_PKEY_free(pkey); + X509_free(x); + sk_X509_pop_free(sk,X509_free); return(ret); } -static int ssl3_get_key_exchange(s) -SSL *s; +static int ssl3_get_key_exchange(SSL *s) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA unsigned char *q,md_buf[EVP_MAX_MD_SIZE*2]; #endif EVP_MD_CTX md_ctx; @@ -825,16 +924,20 @@ SSL *s; int al,i,j,param_len,ok; long n,alg; EVP_PKEY *pkey=NULL; +#ifndef OPENSSL_NO_RSA RSA *rsa=NULL; -#ifndef NO_DH +#endif +#ifndef OPENSSL_NO_DH DH *dh=NULL; #endif + /* use same message size as in ssl3_get_certificate_request() + * as ServerKeyExchange message may be skipped */ n=ssl3_get_message(s, SSL3_ST_CR_KEY_EXCH_A, SSL3_ST_CR_KEY_EXCH_B, -1, - 1024*8, /* ?? */ + s->max_cert_list, &ok); if (!ok) return((int)n); @@ -845,34 +948,35 @@ SSL *s; return(1); } - param=p=(unsigned char *)s->init_buf->data; + param=p=(unsigned char *)s->init_msg; - if (s->session->cert != NULL) + if (s->session->sess_cert != NULL) { -#ifndef NO_RSA - if (s->session->cert->rsa_tmp != NULL) +#ifndef OPENSSL_NO_RSA + if (s->session->sess_cert->peer_rsa_tmp != NULL) { - RSA_free(s->session->cert->rsa_tmp); - s->session->cert->rsa_tmp=NULL; + RSA_free(s->session->sess_cert->peer_rsa_tmp); + s->session->sess_cert->peer_rsa_tmp=NULL; } #endif -#ifndef NO_DH - if (s->session->cert->dh_tmp) +#ifndef OPENSSL_NO_DH + if (s->session->sess_cert->peer_dh_tmp) { - DH_free(s->session->cert->dh_tmp); - s->session->cert->dh_tmp=NULL; + DH_free(s->session->sess_cert->peer_dh_tmp); + s->session->sess_cert->peer_dh_tmp=NULL; } #endif } else { - s->session->cert=ssl_cert_new(); + s->session->sess_cert=ssl_sess_cert_new(); } param_len=0; alg=s->s3->tmp.new_cipher->algorithms; + EVP_MD_CTX_init(&md_ctx); -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (alg & SSL_kRSA) { if ((rsa=RSA_new()) == NULL) @@ -911,21 +1015,23 @@ SSL *s; p+=i; n-=param_len; -/* s->session->cert->rsa_tmp=rsa;*/ /* this should be because we are using an export cipher */ if (alg & SSL_aRSA) - pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509); + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); else { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } - s->session->cert->rsa_tmp=rsa; + s->session->sess_cert->peer_rsa_tmp=rsa; + rsa=NULL; } - else +#else /* OPENSSL_NO_RSA */ + if (0) + ; #endif -#ifndef NO_DH - if (alg & SSL_kEDH) +#ifndef OPENSSL_NO_DH + else if (alg & SSL_kEDH) { if ((dh=DH_new()) == NULL) { @@ -978,18 +1084,21 @@ SSL *s; p+=i; n-=param_len; -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (alg & SSL_aRSA) - pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509); - else + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); +#else + if (0) + ; #endif -#ifndef NO_DSA - if (alg & SSL_aDSS) - pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_DSA_SIGN].x509); +#ifndef OPENSSL_NO_DSA + else if (alg & SSL_aDSS) + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509); #endif /* else anonymous DH, so no certificate or pkey. */ - s->session->cert->dh_tmp=dh; + s->session->sess_cert->peer_dh_tmp=dh; + dh=NULL; } else if ((alg & SSL_kDHr) || (alg & SSL_kDHd)) { @@ -997,7 +1106,14 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); goto f_err; } -#endif +#endif /* !OPENSSL_NO_DH */ + if (alg & SSL_aFZA) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); + goto f_err; + } + /* p points to the next byte, there are 'n' bytes left */ @@ -1014,10 +1130,10 @@ SSL *s; /* wrong packet length */ al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH); - goto err; + goto f_err; } -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { int num; @@ -1026,24 +1142,24 @@ SSL *s; q=md_buf; for (num=2; num > 0; num--) { - EVP_DigestInit(&md_ctx,(num == 2) - ?s->ctx->md5:s->ctx->sha1); + EVP_DigestInit_ex(&md_ctx,(num == 2) + ?s->ctx->md5:s->ctx->sha1, NULL); EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,param,param_len); - EVP_DigestFinal(&md_ctx,q,(unsigned int *)&i); + EVP_DigestFinal_ex(&md_ctx,q,(unsigned int *)&i); q+=i; j+=i; } - i=RSA_public_decrypt((int)n,p,p,pkey->pkey.rsa, - RSA_PKCS1_PADDING); - if (i <= 0) + i=RSA_verify(NID_md5_sha1, md_buf, j, p, n, + pkey->pkey.rsa); + if (i < 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); goto f_err; } - if ((j != i) || (memcmp(p,md_buf,i) != 0)) + if (i == 0) { /* bad signature */ al=SSL_AD_DECRYPT_ERROR; @@ -1053,11 +1169,11 @@ SSL *s; } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { /* lets do DSS */ - EVP_VerifyInit(&md_ctx,EVP_dss1()); + EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL); EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_VerifyUpdate(&md_ctx,param,param_len); @@ -1072,7 +1188,7 @@ SSL *s; else #endif { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } } @@ -1081,7 +1197,7 @@ SSL *s; /* still data left over */ if (!(alg & SSL_aNULL)) { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } if (n != 0) @@ -1091,33 +1207,39 @@ SSL *s; goto f_err; } } - + EVP_PKEY_free(pkey); + EVP_MD_CTX_cleanup(&md_ctx); return(1); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: + EVP_PKEY_free(pkey); +#ifndef OPENSSL_NO_RSA + if (rsa != NULL) + RSA_free(rsa); +#endif +#ifndef OPENSSL_NO_DH + if (dh != NULL) + DH_free(dh); +#endif + EVP_MD_CTX_cleanup(&md_ctx); return(-1); } -static int ssl3_get_certificate_request(s) -SSL *s; +static int ssl3_get_certificate_request(SSL *s) { int ok,ret=0; unsigned long n,nc,l; unsigned int llen,ctype_num,i; X509_NAME *xn=NULL; unsigned char *p,*d,*q; - STACK *ca_sk=NULL; + STACK_OF(X509_NAME) *ca_sk=NULL; n=ssl3_get_message(s, SSL3_ST_CR_CERT_REQ_A, SSL3_ST_CR_CERT_REQ_B, -1, -#if defined(MSDOS) && !defined(WIN32) - 1024*30, /* 30k max cert list :-) */ -#else - 1024*100, /* 100k max cert list :-) */ -#endif + s->max_cert_list, &ok); if (!ok) return((int)n); @@ -1149,9 +1271,9 @@ SSL *s; } } - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; - if ((ca_sk=sk_new(ca_dn_cmp)) == NULL) + if ((ca_sk=sk_X509_NAME_new(ca_dn_cmp)) == NULL) { SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); goto err; @@ -1167,6 +1289,15 @@ SSL *s; /* get the CA RDNs */ n2s(p,llen); +#if 0 +{ +FILE *out; +out=fopen("/tmp/vsign.der","w"); +fwrite(p,1,llen,out); +fclose(out); +} +#endif + if ((llen+ctype_num+2+1) != n) { ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR); @@ -1190,7 +1321,7 @@ SSL *s; if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL) { - /* If netscape tollerance is on, ignore errors */ + /* If netscape tolerance is on, ignore errors */ if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG) goto cont; else @@ -1207,7 +1338,7 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_CA_DN_LENGTH_MISMATCH); goto err; } - if (!sk_push(ca_sk,(char *)xn)) + if (!sk_X509_NAME_push(ca_sk,xn)) { SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,ERR_R_MALLOC_FAILURE); goto err; @@ -1223,28 +1354,26 @@ cont: ERR_clear_error(); } - /* we should setup a certficate to return.... */ + /* we should setup a certificate to return.... */ s->s3->tmp.cert_req=1; s->s3->tmp.ctype_num=ctype_num; if (s->s3->tmp.ca_names != NULL) - sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free); s->s3->tmp.ca_names=ca_sk; ca_sk=NULL; ret=1; err: - if (ca_sk != NULL) sk_pop_free(ca_sk,X509_NAME_free); + if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free); return(ret); } -static int ca_dn_cmp(a,b) -X509_NAME **a,**b; +static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b) { return(X509_NAME_cmp(*a,*b)); } -static int ssl3_get_server_done(s) -SSL *s; +static int ssl3_get_server_done(SSL *s) { int ok,ret=0; long n; @@ -1262,18 +1391,24 @@ SSL *s; /* should contain no data */ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_SERVER_DONE,SSL_R_LENGTH_MISMATCH); + return -1; } ret=1; return(ret); } -static int ssl3_send_client_key_exchange(s) -SSL *s; +static int ssl3_send_client_key_exchange(SSL *s) { - unsigned char *p,*q,*d; + unsigned char *p,*d; int n; unsigned long l; +#ifndef OPENSSL_NO_RSA + unsigned char *q; EVP_PKEY *pkey=NULL; +#endif +#ifndef OPENSSL_NO_KRB5 + KSSL_ERR kssl_err; +#endif /* OPENSSL_NO_KRB5 */ if (s->state == SSL3_ST_CW_KEY_EXCH_A) { @@ -1282,30 +1417,34 @@ SSL *s; l=s->s3->tmp.new_cipher->algorithms; -#ifndef NO_RSA - if (l & SSL_kRSA) + /* Fool emacs indentation */ + if (0) {} +#ifndef OPENSSL_NO_RSA + else if (l & SSL_kRSA) { RSA *rsa; - unsigned char tmp_buf[48]; + unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - if (s->session->cert->rsa_tmp != NULL) - rsa=s->session->cert->rsa_tmp; + if (s->session->sess_cert->peer_rsa_tmp != NULL) + rsa=s->session->sess_cert->peer_rsa_tmp; else { - pkey=X509_get_pubkey(s->session->cert->pkeys[SSL_PKEY_RSA_ENC].x509); + pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } rsa=pkey->pkey.rsa; + EVP_PKEY_free(pkey); } - tmp_buf[0]=s->version>>8; - tmp_buf[1]=s->version&0xff; - RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2); + tmp_buf[0]=s->client_version>>8; + tmp_buf[1]=s->client_version&0xff; + if (RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2) <= 0) + goto err; s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH; @@ -1315,6 +1454,10 @@ SSL *s; p+=2; n=RSA_public_encrypt(SSL_MAX_MASTER_KEY_LENGTH, tmp_buf,p,rsa,RSA_PKCS1_PADDING); +#ifdef PKCS1_CHECK + if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++; + if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70; +#endif if (n <= 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT); @@ -1331,18 +1474,144 @@ SSL *s; s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, - tmp_buf,48); - memset(tmp_buf,0,48); + tmp_buf,SSL_MAX_MASTER_KEY_LENGTH); + memset(tmp_buf,0,SSL_MAX_MASTER_KEY_LENGTH); } - else #endif -#ifndef NO_DH - if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) +#ifndef OPENSSL_NO_KRB5 + else if (l & SSL_kKRB5) + { + krb5_error_code krb5rc; + KSSL_CTX *kssl_ctx = s->kssl_ctx; + /* krb5_data krb5_ap_req; */ + krb5_data *enc_ticket; + krb5_data authenticator, *authp = NULL; + EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER *enc = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH + + EVP_MAX_IV_LENGTH]; + int padl, outl = sizeof(epms); + + EVP_CIPHER_CTX_init(&ciph_ctx); + +#ifdef KSSL_DEBUG + printf("ssl3_send_client_key_exchange(%lx & %lx)\n", + l, SSL_kKRB5); +#endif /* KSSL_DEBUG */ + + authp = NULL; +#ifdef KRB5SENDAUTH + if (KRB5SENDAUTH) authp = &authenticator; +#endif /* KRB5SENDAUTH */ + + krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, + &kssl_err); + enc = kssl_map_enc(kssl_ctx->enctype); + if (enc == NULL) + goto err; +#ifdef KSSL_DEBUG + { + printf("kssl_cget_tkt rtn %d\n", krb5rc); + if (krb5rc && kssl_err.text) + printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); + } +#endif /* KSSL_DEBUG */ + + if (krb5rc) + { + ssl3_send_alert(s,SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); + goto err; + } + + /* 20010406 VRS - Earlier versions used KRB5 AP_REQ + ** in place of RFC 2712 KerberosWrapper, as in: + ** + ** Send ticket (copy to *p, set n = length) + ** n = krb5_ap_req.length; + ** memcpy(p, krb5_ap_req.data, krb5_ap_req.length); + ** if (krb5_ap_req.data) + ** kssl_krb5_free_data_contents(NULL,&krb5_ap_req); + ** + ** Now using real RFC 2712 KerberosWrapper + ** (Thanks to Simon Wilkinson ) + ** Note: 2712 "opaque" types are here replaced + ** with a 2-byte length followed by the value. + ** Example: + ** KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms + ** Where "xx xx" = length bytes. Shown here with + ** optional authenticator omitted. + */ + + /* KerberosWrapper.Ticket */ + s2n(enc_ticket->length,p); + memcpy(p, enc_ticket->data, enc_ticket->length); + p+= enc_ticket->length; + n = enc_ticket->length + 2; + + /* KerberosWrapper.Authenticator */ + if (authp && authp->length) + { + s2n(authp->length,p); + memcpy(p, authp->data, authp->length); + p+= authp->length; + n+= authp->length + 2; + + free(authp->data); + authp->data = NULL; + authp->length = 0; + } + else + { + s2n(0,p);/* null authenticator length */ + n+=2; + } + + if (RAND_bytes(tmp_buf,SSL_MAX_MASTER_KEY_LENGTH) <= 0) + goto err; + + /* 20010420 VRS. Tried it this way; failed. + ** EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); + ** EVP_CIPHER_CTX_set_key_length(&ciph_ctx, + ** kssl_ctx->length); + ** EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); + */ + + memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + EVP_EncryptInit_ex(&ciph_ctx,enc, NULL, + kssl_ctx->key,iv); + EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf, + SSL_MAX_MASTER_KEY_LENGTH); + EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); + outl += padl; + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + /* KerberosWrapper.EncryptedPreMasterSecret */ + s2n(outl,p); + memcpy(p, epms, outl); + p+=outl; + n+=outl + 2; + + s->session->master_key_length= + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, + tmp_buf, SSL_MAX_MASTER_KEY_LENGTH); + + memset(tmp_buf, 0, SSL_MAX_MASTER_KEY_LENGTH); + memset(epms, 0, outl); + } +#endif +#ifndef OPENSSL_NO_DH + else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { DH *dh_srvr,*dh_clnt; - if (s->session->cert->dh_tmp != NULL) - dh_srvr=s->session->cert->dh_tmp; + if (s->session->sess_cert->peer_dh_tmp != NULL) + dh_srvr=s->session->sess_cert->peer_dh_tmp; else { /* we get them from the cert */ @@ -1391,11 +1660,11 @@ SSL *s; /* perhaps clean things up a bit EAY EAY EAY EAY*/ } - else #endif + else { ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } @@ -1414,15 +1683,16 @@ err: return(-1); } -static int ssl3_send_client_verify(s) -SSL *s; +static int ssl3_send_client_verify(SSL *s) { unsigned char *p,*d; unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; EVP_PKEY *pkey; - int i=0; +#ifndef OPENSSL_NO_RSA + unsigned u=0; +#endif unsigned long n; -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA int j; #endif @@ -1435,26 +1705,24 @@ SSL *s; s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2), &(data[MD5_DIGEST_LENGTH])); -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst1),&(data[0])); - i=RSA_private_encrypt( - MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, - data,&(p[2]),pkey->pkey.rsa, - RSA_PKCS1_PADDING); - if (i <= 0) + if (RSA_sign(NID_md5_sha1, data, + MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, + &(p[2]), &u, pkey->pkey.rsa) <= 0 ) { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB); goto err; } - s2n(i,p); - n=i+2; + s2n(u,p); + n=u+2; } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { if (!DSA_sign(pkey->save_type, @@ -1471,7 +1739,7 @@ SSL *s; else #endif { - SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); goto err; } *(d++)=SSL3_MT_CERTIFICATE_VERIFY; @@ -1485,8 +1753,7 @@ err: return(-1); } -static int ssl3_send_client_certificate(s) -SSL *s; +static int ssl3_send_client_certificate(SSL *s) { X509 *x509=NULL; EVP_PKEY *pkey=NULL; @@ -1565,38 +1832,46 @@ SSL *s; #define has_bits(i,m) (((i)&(m)) == (m)) -static int ssl3_check_cert_and_algorithm(s) -SSL *s; +static int ssl3_check_cert_and_algorithm(SSL *s) { int i,idx; long algs; EVP_PKEY *pkey=NULL; - CERT *c; + SESS_CERT *sc; +#ifndef OPENSSL_NO_RSA RSA *rsa; +#endif +#ifndef OPENSSL_NO_DH DH *dh; +#endif - c=s->session->cert; + sc=s->session->sess_cert; - if (c == NULL) + if (sc == NULL) { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR); goto err; } algs=s->s3->tmp.new_cipher->algorithms; /* we don't have a certificate */ - if (algs & (SSL_aDH|SSL_aNULL)) + if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) return(1); - rsa=s->session->cert->rsa_tmp; - dh=s->session->cert->dh_tmp; +#ifndef OPENSSL_NO_RSA + rsa=s->session->sess_cert->peer_rsa_tmp; +#endif +#ifndef OPENSSL_NO_DH + dh=s->session->sess_cert->peer_dh_tmp; +#endif /* This is the passed certificate */ - idx=c->cert_type; - pkey=X509_get_pubkey(c->pkeys[idx].x509); - i=X509_certificate_type(c->pkeys[idx].x509,pkey); + idx=sc->peer_cert_type; + pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); + i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); + EVP_PKEY_free(pkey); /* Check that we have a certificate if we require one */ @@ -1605,22 +1880,23 @@ SSL *s; SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_SIGNING_CERT); goto f_err; } -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA else if ((algs & SSL_aDSS) && !has_bits(i,EVP_PK_DSA|EVP_PKT_SIGN)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DSA_SIGNING_CERT); goto f_err; } #endif - +#ifndef OPENSSL_NO_RSA if ((algs & SSL_kRSA) && !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); goto f_err; } -#ifndef NO_DH - else if ((algs & SSL_kEDH) && +#endif +#ifndef OPENSSL_NO_DH + if ((algs & SSL_kEDH) && !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); @@ -1631,7 +1907,7 @@ SSL *s; SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); goto f_err; } -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA else if ((algs & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); @@ -1640,12 +1916,13 @@ SSL *s; #endif #endif - if ((algs & SSL_EXP) && !has_bits(i,EVP_PKT_EXP)) + if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (algs & SSL_kRSA) { - if ((rsa == NULL) || (RSA_size(rsa) > 512)) + if (rsa == NULL + || RSA_size(rsa) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY); goto f_err; @@ -1653,10 +1930,11 @@ SSL *s; } else #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) - { - if ((dh == NULL) || (DH_size(dh) > 512)) + { + if (dh == NULL + || DH_size(dh) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY); goto f_err; diff --git a/src/lib/libssl/s3_lib.c b/src/lib/libssl/s3_lib.c index 0fd945025d..686992406c 100644 --- a/src/lib/libssl/s3_lib.c +++ b/src/lib/libssl/s3_lib.c @@ -55,40 +55,99 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "objects.h" +#include #include "ssl_locl.h" +#include "kssl_lcl.h" +#include -char *ssl3_version_str="SSLv3 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *ssl3_version_str="SSLv3" OPENSSL_VERSION_PTEXT; #define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER)) -#ifndef NOPROTO static long ssl3_default_timeout(void ); -#else -static long ssl3_default_timeout(); -#endif -SSL_CIPHER ssl3_ciphers[]={ +OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ /* The RSA ciphers */ /* Cipher 01 */ { 1, SSL3_TXT_RSA_NULL_MD5, SSL3_CK_RSA_NULL_MD5, - SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3, + SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_MD5|SSL_SSLV3, + SSL_NOT_EXP, + 0, + 0, 0, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 02 */ { 1, SSL3_TXT_RSA_NULL_SHA, SSL3_CK_RSA_NULL_SHA, - SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP, + 0, + 0, 0, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* anon DH */ @@ -97,45 +156,65 @@ SSL_CIPHER ssl3_ciphers[]={ 1, SSL3_TXT_ADH_RC4_40_MD5, SSL3_CK_ADH_RC4_40_MD5, - SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5 |SSL_EXP|SSL_SSLV3, + SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 18 */ { 1, SSL3_TXT_ADH_RC4_128_MD5, SSL3_CK_ADH_RC4_128_MD5, - SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3, + SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, 0, + 128, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 19 */ { 1, SSL3_TXT_ADH_DES_40_CBC_SHA, SSL3_CK_ADH_DES_40_CBC_SHA, - SSL_kEDH |SSL_aNULL|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + SSL_kEDH |SSL_aNULL|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 1A */ { 1, SSL3_TXT_ADH_DES_64_CBC_SHA, SSL3_CK_ADH_DES_64_CBC_SHA, - SSL_kEDH |SSL_aNULL|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + SSL_kEDH |SSL_aNULL|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, 0, + 56, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 1B */ { 1, SSL3_TXT_ADH_DES_192_CBC_SHA, SSL3_CK_ADH_DES_192_CBC_SHA, - SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 168, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* RSA again */ @@ -144,72 +223,104 @@ SSL_CIPHER ssl3_ciphers[]={ 1, SSL3_TXT_RSA_RC4_40_MD5, SSL3_CK_RSA_RC4_40_MD5, - SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5 |SSL_EXP|SSL_SSLV3, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 04 */ { 1, SSL3_TXT_RSA_RC4_128_MD5, SSL3_CK_RSA_RC4_128_MD5, - SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, 0, + 128, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 05 */ { 1, SSL3_TXT_RSA_RC4_128_SHA, SSL3_CK_RSA_RC4_128_SHA, - SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, 0, + 128, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 06 */ { 1, SSL3_TXT_RSA_RC2_40_MD5, SSL3_CK_RSA_RC2_40_MD5, - SSL_kRSA|SSL_aRSA|SSL_RC2 |SSL_MD5 |SSL_EXP|SSL_SSLV3, + SSL_kRSA|SSL_aRSA|SSL_RC2 |SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 07 */ { 1, SSL3_TXT_RSA_IDEA_128_SHA, SSL3_CK_RSA_IDEA_128_SHA, - SSL_kRSA|SSL_aRSA|SSL_IDEA |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_MEDIUM, + SSL_kRSA|SSL_aRSA|SSL_IDEA |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, 0, + 128, + 128, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 08 */ { 1, SSL3_TXT_RSA_DES_40_CBC_SHA, SSL3_CK_RSA_DES_40_CBC_SHA, - SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 09 */ { 1, SSL3_TXT_RSA_DES_64_CBC_SHA, SSL3_CK_RSA_DES_64_CBC_SHA, - SSL_kRSA|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + SSL_kRSA|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, 0, + 56, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 0A */ { 1, SSL3_TXT_RSA_DES_192_CBC3_SHA, SSL3_CK_RSA_DES_192_CBC3_SHA, - SSL_kRSA|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + SSL_kRSA|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 168, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* The DH ciphers */ @@ -218,54 +329,78 @@ SSL_CIPHER ssl3_ciphers[]={ 0, SSL3_TXT_DH_DSS_DES_40_CBC_SHA, SSL3_CK_DH_DSS_DES_40_CBC_SHA, - SSL_kDHd |SSL_aDH|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + SSL_kDHd |SSL_aDH|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 0C */ { 0, SSL3_TXT_DH_DSS_DES_64_CBC_SHA, SSL3_CK_DH_DSS_DES_64_CBC_SHA, - SSL_kDHd |SSL_aDH|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + SSL_kDHd |SSL_aDH|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, 0, + 56, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 0D */ { 0, SSL3_TXT_DH_DSS_DES_192_CBC3_SHA, SSL3_CK_DH_DSS_DES_192_CBC3_SHA, - SSL_kDHd |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + SSL_kDHd |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 168, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 0E */ { 0, SSL3_TXT_DH_RSA_DES_40_CBC_SHA, SSL3_CK_DH_RSA_DES_40_CBC_SHA, - SSL_kDHr |SSL_aDH|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + SSL_kDHr |SSL_aDH|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 0F */ { 0, SSL3_TXT_DH_RSA_DES_64_CBC_SHA, SSL3_CK_DH_RSA_DES_64_CBC_SHA, - SSL_kDHr |SSL_aDH|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + SSL_kDHr |SSL_aDH|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, 0, + 56, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 10 */ { 0, SSL3_TXT_DH_RSA_DES_192_CBC3_SHA, SSL3_CK_DH_RSA_DES_192_CBC3_SHA, - SSL_kDHr |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + SSL_kDHr |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 168, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* The Ephemeral DH ciphers */ @@ -274,54 +409,78 @@ SSL_CIPHER ssl3_ciphers[]={ 1, SSL3_TXT_EDH_DSS_DES_40_CBC_SHA, SSL3_CK_EDH_DSS_DES_40_CBC_SHA, - SSL_kEDH|SSL_aDSS|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + SSL_kEDH|SSL_aDSS|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 12 */ { 1, SSL3_TXT_EDH_DSS_DES_64_CBC_SHA, SSL3_CK_EDH_DSS_DES_64_CBC_SHA, - SSL_kEDH|SSL_aDSS|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + SSL_kEDH|SSL_aDSS|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, 0, + 56, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 13 */ { 1, SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA, SSL3_CK_EDH_DSS_DES_192_CBC3_SHA, - SSL_kEDH|SSL_aDSS|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + SSL_kEDH|SSL_aDSS|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 168, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 14 */ { 1, SSL3_TXT_EDH_RSA_DES_40_CBC_SHA, SSL3_CK_EDH_RSA_DES_40_CBC_SHA, - SSL_kEDH|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_EXP|SSL_SSLV3, + SSL_kEDH|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, 0, + 40, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 15 */ { 1, SSL3_TXT_EDH_RSA_DES_64_CBC_SHA, SSL3_CK_EDH_RSA_DES_64_CBC_SHA, - SSL_kEDH|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_LOW, + SSL_kEDH|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, 0, + 56, + 56, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 16 */ { 1, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, SSL3_CK_EDH_RSA_DES_192_CBC3_SHA, - SSL_kEDH|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3|SSL_HIGH, + SSL_kEDH|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 168, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Fortezza */ @@ -330,9 +489,13 @@ SSL_CIPHER ssl3_ciphers[]={ 0, SSL3_TXT_FZA_DMS_NULL_SHA, SSL3_CK_FZA_DMS_NULL_SHA, - SSL_kFZA|SSL_aFZA |SSL_eNULL |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + SSL_kFZA|SSL_aFZA |SSL_eNULL |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP, + 0, + 0, 0, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 1D */ @@ -340,9 +503,13 @@ SSL_CIPHER ssl3_ciphers[]={ 0, SSL3_TXT_FZA_DMS_FZA_SHA, SSL3_CK_FZA_DMS_FZA_SHA, - SSL_kFZA|SSL_aFZA |SSL_eFZA |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + SSL_kFZA|SSL_aFZA |SSL_eFZA |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP, + 0, + 0, 0, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, /* Cipher 1E */ @@ -350,10 +517,359 @@ SSL_CIPHER ssl3_ciphers[]={ 0, SSL3_TXT_FZA_DMS_RC4_SHA, SSL3_CK_FZA_DMS_RC4_SHA, - SSL_kFZA|SSL_aFZA |SSL_RC4 |SSL_SHA1|SSL_NOT_EXP|SSL_SSLV3, + SSL_kFZA|SSL_aFZA |SSL_RC4 |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +#ifndef OPENSSL_NO_KRB5 +/* The Kerberos ciphers +** 20000107 VRS: And the first shall be last, +** in hopes of avoiding the lynx ssl renegotiation problem. +*/ +/* Cipher 21 VRS */ + { + 1, + SSL3_TXT_KRB5_DES_40_CBC_SHA, + SSL3_CK_KRB5_DES_40_CBC_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_SHA1 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +/* Cipher 22 VRS */ + { + 1, + SSL3_TXT_KRB5_DES_40_CBC_MD5, + SSL3_CK_KRB5_DES_40_CBC_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +/* Cipher 23 VRS */ + { + 1, + SSL3_TXT_KRB5_DES_64_CBC_SHA, + SSL3_CK_KRB5_DES_64_CBC_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_SHA1 |SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +/* Cipher 24 VRS */ + { + 1, + SSL3_TXT_KRB5_DES_64_CBC_MD5, + SSL3_CK_KRB5_DES_64_CBC_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +/* Cipher 25 VRS */ + { + 1, + SSL3_TXT_KRB5_DES_192_CBC3_SHA, + SSL3_CK_KRB5_DES_192_CBC3_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_3DES|SSL_SHA1 |SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 112, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +/* Cipher 26 VRS */ + { + 1, + SSL3_TXT_KRB5_DES_192_CBC3_MD5, + SSL3_CK_KRB5_DES_192_CBC3_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_3DES|SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, 0, + 112, + 168, SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, }, +#endif /* OPENSSL_NO_KRB5 */ + + +#if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES + /* New TLS Export CipherSuites */ + /* Cipher 60 */ + { + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5, + TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 61 */ + { + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, + TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 62 */ + { + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA, + TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 63 */ + { + 1, + TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, + TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, + SSL_kEDH|SSL_aDSS|SSL_DES|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 64 */ + { + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA, + TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 65 */ + { + 1, + TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, + TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, + SSL_kEDH|SSL_aDSS|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 66 */ + { + 1, + TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA, + TLS1_CK_DHE_DSS_WITH_RC4_128_SHA, + SSL_kEDH|SSL_aDSS|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + }, +#endif + /* New AES ciphersuites */ + + /* Cipher 2F */ + { + 1, + TLS1_TXT_RSA_WITH_AES_128_SHA, + TLS1_CK_RSA_WITH_AES_128_SHA, + SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA |SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 30 */ + { + 0, + TLS1_TXT_DH_DSS_WITH_AES_128_SHA, + TLS1_CK_DH_DSS_WITH_AES_128_SHA, + SSL_kDHd|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 31 */ + { + 0, + TLS1_TXT_DH_RSA_WITH_AES_128_SHA, + TLS1_CK_DH_RSA_WITH_AES_128_SHA, + SSL_kDHr|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 32 */ + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_128_SHA, + TLS1_CK_DHE_DSS_WITH_AES_128_SHA, + SSL_kEDH|SSL_aDSS|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 33 */ + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, + TLS1_CK_DHE_RSA_WITH_AES_128_SHA, + SSL_kEDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 34 */ + { + 1, + TLS1_TXT_ADH_WITH_AES_128_SHA, + TLS1_CK_ADH_WITH_AES_128_SHA, + SSL_kEDH|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + + /* Cipher 35 */ + { + 1, + TLS1_TXT_RSA_WITH_AES_256_SHA, + TLS1_CK_RSA_WITH_AES_256_SHA, + SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA |SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 36 */ + { + 0, + TLS1_TXT_DH_DSS_WITH_AES_256_SHA, + TLS1_CK_DH_DSS_WITH_AES_256_SHA, + SSL_kDHd|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 37 */ + { + 0, + TLS1_TXT_DH_RSA_WITH_AES_256_SHA, + TLS1_CK_DH_RSA_WITH_AES_256_SHA, + SSL_kDHr|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 38 */ + { + 1, + TLS1_TXT_DHE_DSS_WITH_AES_256_SHA, + TLS1_CK_DHE_DSS_WITH_AES_256_SHA, + SSL_kEDH|SSL_aDSS|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 39 */ + { + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, + TLS1_CK_DHE_RSA_WITH_AES_256_SHA, + SSL_kEDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + /* Cipher 3A */ + { + 1, + TLS1_TXT_ADH_WITH_AES_256_SHA, + TLS1_CK_ADH_WITH_AES_256_SHA, + SSL_kEDH|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, /* end of list */ }; @@ -384,6 +900,7 @@ static SSL_METHOD SSLv3_data= { ssl3_write, ssl3_shutdown, ssl3_renegotiate, + ssl3_renegotiate_check, ssl3_ctrl, ssl3_ctx_ctrl, ssl3_get_cipher_by_char, @@ -394,27 +911,29 @@ static SSL_METHOD SSLv3_data= { ssl_bad_method, ssl3_default_timeout, &SSLv3_enc_data, + ssl_undefined_function, + ssl3_callback_ctrl, + ssl3_ctx_callback_ctrl, }; -static long ssl3_default_timeout() +static long ssl3_default_timeout(void) { /* 2 hours, the 24 hours mentioned in the SSLv3 spec * is way too long for http, the cache would over fill */ return(60*60*2); } -SSL_METHOD *sslv3_base_method() +SSL_METHOD *sslv3_base_method(void) { return(&SSLv3_data); } -int ssl3_num_ciphers() +int ssl3_num_ciphers(void) { return(SSL3_NUM_CIPHERS); } -SSL_CIPHER *ssl3_get_cipher(u) -unsigned int u; +SSL_CIPHER *ssl3_get_cipher(unsigned int u) { if (u < SSL3_NUM_CIPHERS) return(&(ssl3_ciphers[SSL3_NUM_CIPHERS-1-u])); @@ -422,29 +941,24 @@ unsigned int u; return(NULL); } -/* The problem is that it may not be the correct record type */ -int ssl3_pending(s) -SSL *s; +int ssl3_pending(SSL *s) { - return(s->s3->rrec.length); + if (s->rstate == SSL_ST_READ_BODY) + return 0; + + return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0; } -int ssl3_new(s) -SSL *s; +int ssl3_new(SSL *s) { - SSL3_CTX *s3; + SSL3_STATE *s3; - if ((s3=(SSL3_CTX *)Malloc(sizeof(SSL3_CTX))) == NULL) goto err; - memset(s3,0,sizeof(SSL3_CTX)); + if ((s3=OPENSSL_malloc(sizeof *s3)) == NULL) goto err; + memset(s3,0,sizeof *s3); + EVP_MD_CTX_init(&s3->finish_dgst1); + EVP_MD_CTX_init(&s3->finish_dgst2); s->s3=s3; - /* - s->s3->tmp.ca_names=NULL; - s->s3->tmp.key_block=NULL; - s->s3->tmp.key_block_length=0; - s->s3->rbuf.buf=NULL; - s->s3->wbuf.buf=NULL; - */ s->method->ssl_clear(s); return(1); @@ -452,40 +966,66 @@ err: return(0); } -void ssl3_free(s) -SSL *s; +void ssl3_free(SSL *s) { + if(s == NULL) + return; + ssl3_cleanup_key_block(s); if (s->s3->rbuf.buf != NULL) - Free(s->s3->rbuf.buf); + OPENSSL_free(s->s3->rbuf.buf); if (s->s3->wbuf.buf != NULL) - Free(s->s3->wbuf.buf); -#ifndef NO_DH + OPENSSL_free(s->s3->wbuf.buf); + if (s->s3->rrec.comp != NULL) + OPENSSL_free(s->s3->rrec.comp); +#ifndef OPENSSL_NO_DH if (s->s3->tmp.dh != NULL) DH_free(s->s3->tmp.dh); #endif if (s->s3->tmp.ca_names != NULL) - sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free); - memset(s->s3,0,sizeof(SSL3_CTX)); - Free(s->s3); + sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + EVP_MD_CTX_cleanup(&s->s3->finish_dgst1); + EVP_MD_CTX_cleanup(&s->s3->finish_dgst2); + memset(s->s3,0,sizeof *s->s3); + OPENSSL_free(s->s3); s->s3=NULL; } -void ssl3_clear(s) -SSL *s; +void ssl3_clear(SSL *s) { unsigned char *rp,*wp; + size_t rlen, wlen; ssl3_cleanup_key_block(s); if (s->s3->tmp.ca_names != NULL) - sk_pop_free(s->s3->tmp.ca_names,X509_NAME_free); + sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free); - rp=s->s3->rbuf.buf; - wp=s->s3->wbuf.buf; + if (s->s3->rrec.comp != NULL) + { + OPENSSL_free(s->s3->rrec.comp); + s->s3->rrec.comp=NULL; + } +#ifndef OPENSSL_NO_DH + if (s->s3->tmp.dh != NULL) + DH_free(s->s3->tmp.dh); +#endif + + rp = s->s3->rbuf.buf; + wp = s->s3->wbuf.buf; + rlen = s->s3->rbuf.len; + wlen = s->s3->wbuf.len; + + EVP_MD_CTX_cleanup(&s->s3->finish_dgst1); + EVP_MD_CTX_cleanup(&s->s3->finish_dgst2); + + memset(s->s3,0,sizeof *s->s3); + s->s3->rbuf.buf = rp; + s->s3->wbuf.buf = wp; + s->s3->rbuf.len = rlen; + s->s3->wbuf.len = wlen; + + ssl_free_wbio_buffer(s); - memset(s->s3,0,sizeof(SSL3_CTX)); - if (rp != NULL) s->s3->rbuf.buf=rp; - if (wp != NULL) s->s3->wbuf.buf=wp; s->packet_length=0; s->s3->renegotiate=0; s->s3->total_renegotiations=0; @@ -494,14 +1034,30 @@ SSL *s; s->version=SSL3_VERSION; } -long ssl3_ctrl(s,cmd,larg,parg) -SSL *s; -int cmd; -long larg; -char *parg; +long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) { int ret=0; +#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_RSA) + if ( +#ifndef OPENSSL_NO_RSA + cmd == SSL_CTRL_SET_TMP_RSA || + cmd == SSL_CTRL_SET_TMP_RSA_CB || +#endif +#ifndef OPENSSL_NO_DSA + cmd == SSL_CTRL_SET_TMP_DH || + cmd == SSL_CTRL_SET_TMP_DH_CB || +#endif + 0) + { + if (!ssl_cert_inst(&s->cert)) + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE); + return(0); + } + } +#endif + switch (cmd) { case SSL_CTRL_GET_SESSION_REUSED: @@ -519,25 +1075,137 @@ char *parg; case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS: ret=s->s3->total_renegotiations; break; + case SSL_CTRL_GET_FLAGS: + ret=(int)(s->s3->flags); + break; +#ifndef OPENSSL_NO_RSA + case SSL_CTRL_NEED_TMP_RSA: + if ((s->cert != NULL) && (s->cert->rsa_tmp == NULL) && + ((s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) || + (EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > (512/8)))) + ret = 1; + break; + case SSL_CTRL_SET_TMP_RSA: + { + RSA *rsa = (RSA *)parg; + if (rsa == NULL) + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return(ret); + } + if ((rsa = RSAPrivateKey_dup(rsa)) == NULL) + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_RSA_LIB); + return(ret); + } + if (s->cert->rsa_tmp != NULL) + RSA_free(s->cert->rsa_tmp); + s->cert->rsa_tmp = rsa; + ret = 1; + } + break; + case SSL_CTRL_SET_TMP_RSA_CB: + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return(ret); + } + break; +#endif +#ifndef OPENSSL_NO_DH + case SSL_CTRL_SET_TMP_DH: + { + DH *dh = (DH *)parg; + if (dh == NULL) + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return(ret); + } + if ((dh = DHparams_dup(dh)) == NULL) + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); + return(ret); + } + if (!(s->options & SSL_OP_SINGLE_DH_USE)) + { + if (!DH_generate_key(dh)) + { + DH_free(dh); + SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB); + return(ret); + } + } + if (s->cert->dh_tmp != NULL) + DH_free(s->cert->dh_tmp); + s->cert->dh_tmp = dh; + ret = 1; + } + break; + case SSL_CTRL_SET_TMP_DH_CB: + { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return(ret); + } + break; +#endif default: break; } return(ret); } -long ssl3_ctx_ctrl(ctx,cmd,larg,parg) -SSL_CTX *ctx; -int cmd; -long larg; -char *parg; +long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)()) + { + int ret=0; + +#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_RSA) + if ( +#ifndef OPENSSL_NO_RSA + cmd == SSL_CTRL_SET_TMP_RSA_CB || +#endif +#ifndef OPENSSL_NO_DSA + cmd == SSL_CTRL_SET_TMP_DH_CB || +#endif + 0) + { + if (!ssl_cert_inst(&s->cert)) + { + SSLerr(SSL_F_SSL3_CALLBACK_CTRL, ERR_R_MALLOC_FAILURE); + return(0); + } + } +#endif + + switch (cmd) + { +#ifndef OPENSSL_NO_RSA + case SSL_CTRL_SET_TMP_RSA_CB: + { + s->cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))fp; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case SSL_CTRL_SET_TMP_DH_CB: + { + s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + } + break; +#endif + default: + break; + } + return(ret); + } + +long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { CERT *cert; - cert=ctx->default_cert; + cert=ctx->cert; switch (cmd) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA case SSL_CTRL_NEED_TMP_RSA: if ( (cert->rsa_tmp == NULL) && ((cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) || @@ -546,7 +1214,7 @@ char *parg; return(1); else return(0); - break; + /* break; */ case SSL_CTRL_SET_TMP_RSA: { RSA *rsa; @@ -574,35 +1242,83 @@ char *parg; return(1); } } - break; + /* break; */ case SSL_CTRL_SET_TMP_RSA_CB: - cert->rsa_tmp_cb=(RSA *(*)())parg; + { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return(0); + } break; #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH case SSL_CTRL_SET_TMP_DH: { DH *new=NULL,*dh; dh=(DH *)parg; - if ( ((new=DHparams_dup(dh)) == NULL) || - (!DH_generate_key(new))) + if ((new=DHparams_dup(dh)) == NULL) { SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB); - if (new != NULL) DH_free(new); - return(0); + return 0; } - else + if (!(ctx->options & SSL_OP_SINGLE_DH_USE)) { - if (cert->dh_tmp != NULL) - DH_free(cert->dh_tmp); - cert->dh_tmp=new; - return(1); + if (!DH_generate_key(new)) + { + SSLerr(SSL_F_SSL3_CTX_CTRL,ERR_R_DH_LIB); + DH_free(new); + return 0; + } } + if (cert->dh_tmp != NULL) + DH_free(cert->dh_tmp); + cert->dh_tmp=new; + return 1; + } + /*break; */ + case SSL_CTRL_SET_TMP_DH_CB: + { + SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return(0); } break; +#endif + /* A Thawte special :-) */ + case SSL_CTRL_EXTRA_CHAIN_CERT: + if (ctx->extra_certs == NULL) + { + if ((ctx->extra_certs=sk_X509_new_null()) == NULL) + return(0); + } + sk_X509_push(ctx->extra_certs,(X509 *)parg); + break; + + default: + return(0); + } + return(1); + } + +long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)()) + { + CERT *cert; + + cert=ctx->cert; + + switch (cmd) + { +#ifndef OPENSSL_NO_RSA + case SSL_CTRL_SET_TMP_RSA_CB: + { + cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))fp; + } + break; +#endif +#ifndef OPENSSL_NO_DH case SSL_CTRL_SET_TMP_DH_CB: - cert->dh_tmp_cb=(DH *(*)())parg; + { + cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp; + } break; #endif default: @@ -613,8 +1329,7 @@ char *parg; /* This function needs to check if the ciphers required are actually * available */ -SSL_CIPHER *ssl3_get_cipher_by_char(p) -unsigned char *p; +SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p) { static int init=1; static SSL_CIPHER *sorted[SSL3_NUM_CIPHERS]; @@ -624,7 +1339,7 @@ unsigned char *p; if (init) { - init=0; + CRYPTO_w_lock(CRYPTO_LOCK_SSL); for (i=0; ivalid) return(NULL); else return(*cpp); } -int ssl3_put_cipher_by_char(c,p) -SSL_CIPHER *c; -unsigned char *p; +int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p) { long l; @@ -662,114 +1379,141 @@ unsigned char *p; return(2); } -int ssl3_part_read(s,i) -SSL *s; -int i; - { - s->rwstate=SSL_READING; - - if (i < 0) - { - return(i); - } - else - { - s->init_num+=i; - return(0); - } - } - -SSL_CIPHER *ssl3_choose_cipher(s,have,pref) -SSL *s; -STACK *have,*pref; +SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, + STACK_OF(SSL_CIPHER) *srvr) { SSL_CIPHER *c,*ret=NULL; + STACK_OF(SSL_CIPHER) *prio, *allow; int i,j,ok; CERT *cert; unsigned long alg,mask,emask; - /* Lets see which ciphers we can supported */ - if (s->cert != NULL) - cert=s->cert; + /* Let's see which ciphers we can support */ + cert=s->cert; + +#if 0 + /* Do not set the compare functions, because this may lead to a + * reordering by "id". We want to keep the original ordering. + * We may pay a price in performance during sk_SSL_CIPHER_find(), + * but would have to pay with the price of sk_SSL_CIPHER_dup(). + */ + sk_SSL_CIPHER_set_cmp_func(srvr, ssl_cipher_ptr_id_cmp); + sk_SSL_CIPHER_set_cmp_func(clnt, ssl_cipher_ptr_id_cmp); +#endif + +#ifdef CIPHER_DEBUG + printf("Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr), srvr); + for(i=0 ; i < sk_SSL_CIPHER_num(srvr) ; ++i) + { + c=sk_SSL_CIPHER_value(srvr,i); + printf("%p:%s\n",c,c->name); + } + printf("Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt), clnt); + for(i=0 ; i < sk_SSL_CIPHER_num(clnt) ; ++i) + { + c=sk_SSL_CIPHER_value(clnt,i); + printf("%p:%s\n",c,c->name); + } +#endif + + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) + { + prio = srvr; + allow = clnt; + } else - cert=s->ctx->default_cert; + { + prio = clnt; + allow = srvr; + } + + for (i=0; imask; - emask=cert->export_mask; + ssl_set_cert_masks(cert,c); + mask=cert->mask; + emask=cert->export_mask; - sk_set_cmp_func(pref,ssl_cipher_ptr_id_cmp); +#ifdef KSSL_DEBUG + printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms); +#endif /* KSSL_DEBUG */ - for (i=0; ialgorithms&(SSL_MKEY_MASK|SSL_AUTH_MASK); - if (alg & SSL_EXPORT) +#ifndef OPENSSL_NO_KRB5 + if (alg & SSL_KRB5) + { + if ( !kssl_keytab_is_available(s->kssl_ctx) ) + continue; + } +#endif /* OPENSSL_NO_KRB5 */ + if (SSL_C_IS_EXPORT(c)) { ok=((alg & emask) == alg)?1:0; #ifdef CIPHER_DEBUG - printf("%d:[%08lX:%08lX]%s\n",ok,alg,mask,c->name); + printf("%d:[%08lX:%08lX]%p:%s (export)\n",ok,alg,emask, + c,c->name); #endif } else { ok=((alg & mask) == alg)?1:0; #ifdef CIPHER_DEBUG - printf("%d:[%08lX:%08lX]%s\n",ok,alg,mask,c->name); + printf("%d:[%08lX:%08lX]%p:%s\n",ok,alg,mask,c, + c->name); #endif } if (!ok) continue; - j=sk_find(pref,(char *)c); + j=sk_SSL_CIPHER_find(allow,c); if (j >= 0) { - ret=(SSL_CIPHER *)sk_value(pref,j); + ret=sk_SSL_CIPHER_value(allow,j); break; } } return(ret); } -int ssl3_get_req_cert_type(s,p) -SSL *s; -unsigned char *p; +int ssl3_get_req_cert_type(SSL *s, unsigned char *p) { int ret=0; unsigned long alg; alg=s->s3->tmp.new_cipher->algorithms; -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (alg & (SSL_kDHr|SSL_kEDH)) { -#ifndef NO_RSA +# ifndef OPENSSL_NO_RSA p[ret++]=SSL3_CT_RSA_FIXED_DH; -#endif -#ifndef NO_DSA +# endif +# ifndef OPENSSL_NO_DSA p[ret++]=SSL3_CT_DSS_FIXED_DH; -#endif +# endif } if ((s->version == SSL3_VERSION) && (alg & (SSL_kEDH|SSL_kDHd|SSL_kDHr))) { -#ifndef NO_RSA +# ifndef OPENSSL_NO_RSA p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH; -#endif -#ifndef NO_DSA +# endif +# ifndef OPENSSL_NO_DSA p[ret++]=SSL3_CT_DSS_EPHEMERAL_DH; -#endif +# endif } -#endif /* !NO_DH */ -#ifndef NO_RSA +#endif /* !OPENSSL_NO_DH */ +#ifndef OPENSSL_NO_RSA p[ret++]=SSL3_CT_RSA_SIGN; #endif +#ifndef OPENSSL_NO_DSA p[ret++]=SSL3_CT_DSS_SIGN; +#endif return(ret); } -int ssl3_shutdown(s) -SSL *s; +int ssl3_shutdown(SSL *s) { /* Don't do anything much if we have not done the handshake or @@ -799,7 +1543,7 @@ SSL *s; else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { /* If we are waiting for a close from our peer, we are closed */ - ssl3_read_bytes(s,0,NULL,0); + ssl3_read_bytes(s,0,NULL,0,0); } if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) && @@ -809,13 +1553,9 @@ SSL *s; return(0); } -int ssl3_write(s,buf,len) -SSL *s; -char *buf; -int len; +int ssl3_write(SSL *s, const void *buf, int len) { int ret,n; - BIO *under; #if 0 if (s->shutdown & SSL_SEND_SHUTDOWN) @@ -838,7 +1578,7 @@ int len; if (s->s3->delay_buf_pop_ret == 0) { ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA, - (char *)buf,len); + buf,len); if (ret <= 0) return(ret); s->s3->delay_buf_pop_ret=ret; @@ -849,43 +1589,40 @@ int len; if (n <= 0) return(n); s->rwstate=SSL_NOTHING; - /* We have flushed the buffer */ - under=BIO_pop(s->wbio); - s->wbio=under; - BIO_free(s->bbio); - s->bbio=NULL; + /* We have flushed the buffer, so remove it */ + ssl_free_wbio_buffer(s); + s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER; + ret=s->s3->delay_buf_pop_ret; s->s3->delay_buf_pop_ret=0; - - s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER; } else { ret=ssl3_write_bytes(s,SSL3_RT_APPLICATION_DATA, - (char *)buf,len); + buf,len); if (ret <= 0) return(ret); } return(ret); } -int ssl3_read(s,buf,len) -SSL *s; -char *buf; -int len; +static int ssl3_read_internal(SSL *s, void *buf, int len, int peek) { int ret; clear_sys_error(); if (s->s3->renegotiate) ssl3_renegotiate_check(s); s->s3->in_read_app_data=1; - ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len); - if ((ret == -1) && (s->s3->in_read_app_data == 0)) + ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek); + if ((ret == -1) && (s->s3->in_read_app_data == 2)) { - ERR_get_error(); /* clear the error */ - s->s3->in_read_app_data=0; + /* ssl3_read_bytes decided to call s->handshake_func, which + * called ssl3_read_bytes to read handshake data. + * However, ssl3_read_bytes actually found application data + * and thinks that application data makes sense here; so disable + * handshake processing and try to read application data again. */ s->in_handshake++; - ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len); + ret=ssl3_read_bytes(s,SSL3_RT_APPLICATION_DATA,buf,len,peek); s->in_handshake--; } else @@ -894,33 +1631,17 @@ int len; return(ret); } -int ssl3_peek(s,buf,len) -SSL *s; -char *buf; -int len; +int ssl3_read(SSL *s, void *buf, int len) { - SSL3_RECORD *rr; - int n; - - rr= &(s->s3->rrec); - if ((rr->length == 0) || (rr->type != SSL3_RT_APPLICATION_DATA)) - { - n=ssl3_read(s,buf,1); - if (n <= 0) return(n); - rr->length++; - rr->off--; - } + return ssl3_read_internal(s, buf, len, 0); + } - if ((unsigned int)len > rr->length) - n=rr->length; - else - n=len; - memcpy(buf,&(rr->data[rr->off]),(unsigned int)n); - return(n); +int ssl3_peek(SSL *s, void *buf, int len) + { + return ssl3_read_internal(s, buf, len, 1); } -int ssl3_renegotiate(s) -SSL *s; +int ssl3_renegotiate(SSL *s) { if (s->handshake_func == NULL) return(1); @@ -932,8 +1653,7 @@ SSL *s; return(1); } -int ssl3_renegotiate_check(s) -SSL *s; +int ssl3_renegotiate_check(SSL *s) { int ret=0; @@ -945,7 +1665,7 @@ SSL *s; { /* if we are the server, and we have sent a 'RENEGOTIATE' message, we -need to go to SSL_ST_ACCEPT. +need to go to SSL_ST_ACCEPT. */ /* SSL_ST_ACCEPT */ s->state=SSL_ST_RENEGOTIATE; @@ -958,4 +1678,3 @@ need to go to SSL_ST_ACCEPT. return(ret); } - diff --git a/src/lib/libssl/s3_pkt.c b/src/lib/libssl/s3_pkt.c index 2385080347..43e8502b66 100644 --- a/src/lib/libssl/s3_pkt.c +++ b/src/lib/libssl/s3_pkt.c @@ -55,150 +55,165 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 #define USE_SOCKETS -#include "evp.h" -#include "buffer.h" +#include +#include #include "ssl_locl.h" -/* SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_BAD_RECORD_MAC); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_NO_CERTIFICATE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_BAD_CERTIFICATE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN); - * SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER); - */ - -#ifndef NOPROTO -static int do_ssl3_write(SSL *s, int type, char *buf, unsigned int len); -static int ssl3_write_pending(SSL *s, int type, char *buf, unsigned int len); +static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + unsigned int len, int create_empty_fragment); +static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, + unsigned int len); static int ssl3_get_record(SSL *s); static int do_compress(SSL *ssl); static int do_uncompress(SSL *ssl); static int do_change_cipher_spec(SSL *ssl); -#else -static int do_ssl3_write(); -static int ssl3_write_pending(); -static int ssl3_get_record(); -static int do_compress(); -static int do_uncompress(); -static int do_change_cipher_spec(); -#endif -static int ssl3_read_n(s,n,max,extend) -SSL *s; -int n; -int max; -int extend; +/* used only by ssl3_get_record */ +static int ssl3_read_n(SSL *s, int n, int max, int extend) { + /* If extend == 0, obtain new n-byte packet; if extend == 1, increase + * packet by another n bytes. + * The packet will be in the sub-array of s->s3->rbuf.buf specified + * by s->packet and s->packet_length. + * (If s->read_ahead is set, 'max' bytes may be stored in rbuf + * [plus s->packet_length bytes if extend == 1].) + */ int i,off,newb; - /* if there is stuff still in the buffer from a previous read, - * and there is more than we want, take some. */ + if (!extend) + { + /* start with empty packet ... */ + if (s->s3->rbuf.left == 0) + s->s3->rbuf.offset = 0; + s->packet = s->s3->rbuf.buf + s->s3->rbuf.offset; + s->packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } + + /* if there is enough in the buffer from a previous read, take some */ if (s->s3->rbuf.left >= (int)n) { - if (extend) - s->packet_length+=n; - else - { - s->packet= &(s->s3->rbuf.buf[s->s3->rbuf.offset]); - s->packet_length=n; - } + s->packet_length+=n; s->s3->rbuf.left-=n; s->s3->rbuf.offset+=n; return(n); } /* else we need to read more data */ - if (!s->read_ahead) max=n; - if (max > SSL3_RT_MAX_PACKET_SIZE) - max=SSL3_RT_MAX_PACKET_SIZE; - - /* First check if there is some left or we want to extend */ - off=0; - if ( (s->s3->rbuf.left != 0) || - ((s->packet_length != 0) && extend)) - { - newb=s->s3->rbuf.left; - if (extend) - { - /* Copy bytes back to the front of the buffer - * Take the bytes already pointed to by 'packet' - * and take the extra ones on the end. */ - off=s->packet_length; - if (s->packet != s->s3->rbuf.buf) - memcpy(s->s3->rbuf.buf,s->packet,newb+off); - } - else if (s->s3->rbuf.offset != 0) - { /* so the data is not at the start of the buffer */ - memcpy(s->s3->rbuf.buf, - &(s->s3->rbuf.buf[s->s3->rbuf.offset]),newb); - s->s3->rbuf.offset=0; - } + if (!s->read_ahead) + max=n; - s->s3->rbuf.left=0; + { + /* avoid buffer overflow */ + int max_max = s->s3->rbuf.len - s->packet_length; + if (max > max_max) + max = max_max; + } + if (n > max) /* does not happen */ + { + SSLerr(SSL_F_SSL3_READ_N,ERR_R_INTERNAL_ERROR); + return -1; } - else - newb=0; - /* So we now have 'newb' bytes at the front of - * s->s3->rbuf.buf and need to read some more in on the end - * We start reading into the buffer at 's->s3->rbuf.offset' - */ - s->packet=s->s3->rbuf.buf; + off = s->packet_length; + newb = s->s3->rbuf.left; + /* Move any available bytes to front of buffer: + * 'off' bytes already pointed to by 'packet', + * 'newb' extra ones at the end */ + if (s->packet != s->s3->rbuf.buf) + { + /* off > 0 */ + memmove(s->s3->rbuf.buf, s->packet, off+newb); + s->packet = s->s3->rbuf.buf; + } while (newb < n) { + /* Now we have off+newb bytes at the front of s->s3->rbuf.buf and need + * to read in more until we have off+n (up to off+max if possible) */ + clear_sys_error(); if (s->rbio != NULL) { s->rwstate=SSL_READING; - i=BIO_read(s->rbio, - (char *)&(s->s3->rbuf.buf[off+newb]), - max-newb); + i=BIO_read(s->rbio, &(s->s3->rbuf.buf[off+newb]), max-newb); } else { SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); - i= -1; + i = -1; } if (i <= 0) { - s->s3->rbuf.left+=newb; + s->s3->rbuf.left = newb; return(i); } newb+=i; } - /* record used data read */ - if (newb > n) - { - s->s3->rbuf.offset=n+off; - s->s3->rbuf.left=newb-n; - } - else - { - s->s3->rbuf.offset=0; - s->s3->rbuf.left=0; - } - - if (extend) - s->packet_length+=n; - else - s->packet_length+=n; + /* done reading, now the book-keeping */ + s->s3->rbuf.offset = off + n; + s->s3->rbuf.left = newb - n; + s->packet_length += n; + s->rwstate=SSL_NOTHING; return(n); } @@ -206,41 +221,45 @@ int extend; * It will return <= 0 if more data is needed, normally due to an error * or non-blocking IO. * When it finishes, one packet has been decoded and can be found in - * ssl->s3->rrec.type - is the type of record - * ssl->s3->rrec.data, - data + * ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data, - data * ssl->s3->rrec.length, - number of bytes */ -static int ssl3_get_record(s) -SSL *s; +/* used only by ssl3_read_bytes */ +static int ssl3_get_record(SSL *s) { - char tmp_buf[512]; int ssl_major,ssl_minor,al; - int n,i,ret= -1; - SSL3_BUFFER *rb; + int enc_err,n,i,ret= -1; SSL3_RECORD *rr; SSL_SESSION *sess; unsigned char *p; unsigned char md[EVP_MAX_MD_SIZE]; short version; unsigned int mac_size; - int clear=0,extra; + int clear=0; + size_t extra; rr= &(s->s3->rrec); - rb= &(s->s3->rbuf); sess=s->session; if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) extra=SSL3_RT_MAX_EXTRA; else extra=0; + if (extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE) + { + /* actually likely an application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER + * set after ssl3_setup_buffers() was done */ + SSLerr(SSL_F_SSL3_GET_RECORD, ERR_R_INTERNAL_ERROR); + return -1; + } again: /* check if we have the header */ if ( (s->rstate != SSL_ST_READ_BODY) || (s->packet_length < SSL3_RT_HEADER_LENGTH)) { - n=ssl3_read_n(s,SSL3_RT_HEADER_LENGTH, - SSL3_RT_MAX_PACKET_SIZE,0); + n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); if (n <= 0) return(n); /* error or non-blocking */ s->rstate=SSL_ST_READ_BODY; @@ -277,35 +296,33 @@ again: goto err; } - if (rr->length > - (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) { al=SSL_AD_RECORD_OVERFLOW; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG); goto f_err; } - s->rstate=SSL_ST_READ_BODY; + /* now s->rstate == SSL_ST_READ_BODY */ } - /* get and decode the data */ - if (s->rstate == SSL_ST_READ_BODY) + /* s->rstate == SSL_ST_READ_BODY, get and decode the data */ + + if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH) { - if (rr->length > (s->packet_length-SSL3_RT_HEADER_LENGTH)) - { - i=rr->length; - /*-(s->packet_length-SSL3_RT_HEADER_LENGTH); */ - n=ssl3_read_n(s,i,i,1); - if (n <= 0) return(n); /* error or non-blocking io */ - } - s->rstate=SSL_ST_READ_HEADER; + /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ + i=rr->length; + n=ssl3_read_n(s,i,i,1); + if (n <= 0) return(n); /* error or non-blocking io */ + /* now n == rr->length, + * and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */ } - /* At this point, we have the data in s->packet and there should be - * s->packet_length bytes, we must not 'overrun' this buffer :-) - * One of the following functions will copy the data from the - * s->packet buffer */ + s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */ + /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, + * and we have that many bytes in s->packet + */ rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]); /* ok, we can now read from 's->packet' data into 'rr' @@ -315,14 +332,11 @@ again: * When the data is 'copied' into the rr->data buffer, * rr->input will be pointed at the new buffer */ - /* Set the state for the following operations */ - s->rstate=SSL_ST_READ_HEADER; - /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] * rr->length bytes of encrypted compressed stuff. */ - /* check is not needed I belive */ - if (rr->length > (unsigned int)SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) + /* check is not needed I believe */ + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) { al=SSL_AD_RECORD_OVERFLOW; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_ENCRYPTED_LENGTH_TOO_LONG); @@ -331,18 +345,24 @@ again: /* decrypt in place in 'rr->input' */ rr->data=rr->input; - memcpy(tmp_buf,rr->input,(rr->length > 512)?512:rr->length); - if (!s->method->ssl3_enc->enc(s,0)) + enc_err = s->method->ssl3_enc->enc(s,0); + if (enc_err <= 0) { - al=SSL_AD_DECRYPT_ERROR; - goto f_err; + if (enc_err == 0) + /* SSLerr() and ssl3_send_alert() have been called */ + goto err; + + /* otherwise enc_err == -1 */ + goto decryption_failed_or_bad_record_mac; } + #ifdef TLS_DEBUG printf("dec %d\n",rr->length); -{ int z; for (z=0; zlength; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } +{ unsigned int z; for (z=0; zlength; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } printf("\n"); #endif + /* r->length is now the compressed data plus mac */ if ( (sess == NULL) || (s->enc_read_ctx == NULL) || @@ -355,33 +375,37 @@ printf("\n"); if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) { +#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ al=SSL_AD_RECORD_OVERFLOW; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); goto f_err; +#else + goto decryption_failed_or_bad_record_mac; +#endif } - /* check MAC for rr->input' */ + /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ if (rr->length < mac_size) { +#if 0 /* OK only for stream ciphers */ al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); goto f_err; +#else + goto decryption_failed_or_bad_record_mac; +#endif } rr->length-=mac_size; i=s->method->ssl3_enc->mac(s,md,0); if (memcmp(md,&(rr->data[rr->length]),mac_size) != 0) { - al=SSL_AD_BAD_RECORD_MAC; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BAD_MAC_DECODE); - ret= -1; - goto f_err; + goto decryption_failed_or_bad_record_mac; } } /* r->length is now just compressed */ - if ((sess != NULL) && (sess->read_compression != NULL)) + if (s->expand != NULL) { - if (rr->length > - (unsigned int)SSL3_RT_MAX_COMPRESSED_LENGTH+extra) + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra) { al=SSL_AD_RECORD_OVERFLOW; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_COMPRESSED_LENGTH_TOO_LONG); @@ -395,7 +419,7 @@ printf("\n"); } } - if (rr->length > (unsigned int)SSL3_RT_MAX_PLAIN_LENGTH+extra) + if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) { al=SSL_AD_RECORD_OVERFLOW; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DATA_LENGTH_TOO_LONG); @@ -418,33 +442,62 @@ printf("\n"); if (rr->length == 0) goto again; return(1); + +decryption_failed_or_bad_record_mac: + /* Separate 'decryption_failed' alert was introduced with TLS 1.0, + * SSL 3.0 only has 'bad_record_mac'. But unless a decryption + * failure is directly visible from the ciphertext anyway, + * we should not reveal which kind of error occured -- this + * might become visible to an attacker (e.g. via logfile) */ + al=SSL_AD_BAD_RECORD_MAC; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: return(ret); } -static int do_uncompress(ssl) -SSL *ssl; +static int do_uncompress(SSL *ssl) { + int i; + SSL3_RECORD *rr; + + rr= &(ssl->s3->rrec); + i=COMP_expand_block(ssl->expand,rr->comp, + SSL3_RT_MAX_PLAIN_LENGTH,rr->data,(int)rr->length); + if (i < 0) + return(0); + else + rr->length=i; + rr->data=rr->comp; + return(1); } -static int do_compress(ssl) -SSL *ssl; +static int do_compress(SSL *ssl) { + int i; + SSL3_RECORD *wr; + + wr= &(ssl->s3->wrec); + i=COMP_compress_block(ssl->compress,wr->data, + SSL3_RT_MAX_COMPRESSED_LENGTH, + wr->input,(int)wr->length); + if (i < 0) + return(0); + else + wr->length=i; + + wr->input=wr->data; return(1); } -/* Call this to write data +/* Call this to write data in records of type 'type' * It will return <= 0 if not all data has been sent or non-blocking IO. */ -int ssl3_write_bytes(s,type,buf,len) -SSL *s; -int type; -char *buf; -int len; +int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { + const unsigned char *buf=buf_; unsigned int tot,n,nw; int i; @@ -459,7 +512,7 @@ int len; if (i == 0) { SSLerr(SSL_F_SSL3_WRITE_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); + return -1; } } @@ -470,37 +523,41 @@ int len; nw=SSL3_RT_MAX_PLAIN_LENGTH; else nw=n; - - i=do_ssl3_write(s,type,&(buf[tot]),nw); + + i=do_ssl3_write(s, type, &(buf[tot]), nw, 0); if (i <= 0) { s->s3->wnum=tot; - return(i); + return i; } - if (type == SSL3_RT_HANDSHAKE) - ssl3_finish_mac(s,(unsigned char *)&(buf[tot]),i); - - if (i == (int)n) return(tot+i); + if ((i == (int)n) || + (type == SSL3_RT_APPLICATION_DATA && + (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) + { + /* next chunk of data should get another prepended empty fragment + * in ciphersuites with known-IV weakness: */ + s->s3->empty_fragment_done = 0; + + return tot+i; + } n-=i; tot+=i; } } -static int do_ssl3_write(s,type,buf,len) -SSL *s; -int type; -char *buf; -unsigned int len; +static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + unsigned int len, int create_empty_fragment) { unsigned char *p,*plen; int i,mac_size,clear=0; + int prefix_len = 0; SSL3_RECORD *wr; SSL3_BUFFER *wb; SSL_SESSION *sess; - /* first check is there is a SSL3_RECORD still being written + /* first check if there is a SSL3_BUFFER still being written * out. This will happen with non blocking IO */ if (s->s3->wbuf.left != 0) return(ssl3_write_pending(s,type,buf,len)); @@ -514,8 +571,9 @@ unsigned int len; /* if it went, fall through and send more stuff */ } - if (len <= 0) return(len); - + if (len == 0 && !create_empty_fragment) + return 0; + wr= &(s->s3->wrec); wb= &(s->s3->wbuf); sess=s->session; @@ -530,19 +588,47 @@ unsigned int len; else mac_size=EVP_MD_size(s->write_hash); - p=wb->buf; + /* 'create_empty_fragment' is true only when this function calls itself */ + if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done) + { + /* countermeasure against known-IV weakness in CBC ciphersuites + * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ + + if (s->s3->need_empty_fragments && type == SSL3_RT_APPLICATION_DATA) + { + /* recursive function call with 'create_empty_fragment' set; + * this prepares and buffers the data for an empty fragment + * (these 'prefix_len' bytes are sent out later + * together with the actual payload) */ + prefix_len = do_ssl3_write(s, type, buf, 0, 1); + if (prefix_len <= 0) + goto err; + + if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE) + { + /* insufficient space */ + SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + s->s3->empty_fragment_done = 1; + } + + p = wb->buf + prefix_len; /* write the header */ + *(p++)=type&0xff; wr->type=type; *(p++)=(s->version>>8); *(p++)=s->version&0xff; - - /* record where we are to write out packet length */ + + /* field where we are to write out packet length */ plen=p; p+=2; - + /* lets setup the record stuff. */ wr->data=p; wr->length=(int)len; @@ -552,7 +638,7 @@ unsigned int len; * wr->data */ /* first we compress */ - if ((sess != NULL) && (sess->write_compression != NULL)) + if (s->compress != NULL) { if (!do_compress(s)) { @@ -590,32 +676,40 @@ unsigned int len; wr->type=type; /* not needed but helps for debugging */ wr->length+=SSL3_RT_HEADER_LENGTH; - /* Now lets setup wb */ - wb->left=wr->length; - wb->offset=0; + if (create_empty_fragment) + { + /* we are in a recursive call; + * just return the length, don't write out anything here + */ + return wr->length; + } + + /* now let's set up wb */ + wb->left = prefix_len + wr->length; + wb->offset = 0; + /* memorize arguments so that ssl3_write_pending can detect bad write retries later */ s->s3->wpend_tot=len; s->s3->wpend_buf=buf; s->s3->wpend_type=type; s->s3->wpend_ret=len; /* we now just need to write the buffer */ - return(ssl3_write_pending(s,type,buf,len)); + return ssl3_write_pending(s,type,buf,len); err: - return(-1); + return -1; } /* if s->s3->wbuf.left != 0, we need to call this */ -static int ssl3_write_pending(s,type,buf,len) -SSL *s; -int type; -char *buf; -unsigned int len; +static int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, + unsigned int len) { int i; /* XXXX */ - if ((s->s3->wpend_tot > (int)len) || (s->s3->wpend_buf != buf) + if ((s->s3->wpend_tot > (int)len) + || ((s->s3->wpend_buf != buf) && + !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || (s->s3->wpend_type != type)) { SSLerr(SSL_F_SSL3_WRITE_PENDING,SSL_R_BAD_WRITE_RETRY); @@ -650,23 +744,77 @@ unsigned int len; } } -int ssl3_read_bytes(s,type,buf,len) -SSL *s; -int type; -char *buf; -int len; +/* Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + * - 0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify), ChangeCipherSpec records (not really + * a surprise, but handled as if it were), or renegotiation requests. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + * Change cipher spec protocol + * just 1 byte needed, no need for keeping anything stored + * Alert protocol + * 2 bytes needed (AlertLevel, AlertDescription) + * Handshake protocol + * 4 bytes needed (HandshakeType, uint24 length) -- we just have + * to detect unexpected Client Hello and Hello Request messages + * here, anything else is handled by higher layers + * Application data protocol + * none of our business + */ +int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) { - int al,i,j,n,ret; + int al,i,j,ret; + unsigned int n; SSL3_RECORD *rr; - void (*cb)()=NULL; - BIO *bio; + void (*cb)(const SSL *ssl,int type2,int val)=NULL; - if (s->s3->rbuf.buf == NULL) /* Not initalised yet */ + if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ if (!ssl3_setup_buffers(s)) return(-1); + if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type) || + (peek && (type != SSL3_RT_APPLICATION_DATA))) + { + SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR); + return -1; + } + + if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0)) + /* (partially) satisfy request from storage */ + { + unsigned char *src = s->s3->handshake_fragment; + unsigned char *dst = buf; + unsigned int k; + + /* peek == 0 */ + n = 0; + while ((len > 0) && (s->s3->handshake_fragment_len > 0)) + { + *dst++ = *src++; + len--; s->s3->handshake_fragment_len--; + n++; + } + /* move any remaining fragment bytes: */ + for (k = 0; k < s->s3->handshake_fragment_len; k++) + s->s3->handshake_fragment[k] = *src++; + return n; + } + + /* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */ + if (!s->in_handshake && SSL_in_init(s)) { + /* type == SSL3_RT_APPLICATION_DATA */ i=s->handshake_func(s); if (i < 0) return(i); if (i == 0) @@ -678,13 +826,13 @@ int len; start: s->rwstate=SSL_NOTHING; - /* s->s3->rrec.type - is the type of record - * s->s3->rrec.data, - data - * s->s3->rrec.off, - ofset into 'data' for next read - * s->s3->rrec.length, - number of bytes. */ - rr= &(s->s3->rrec); + /* s->s3->rrec.type - is the type of record + * s->s3->rrec.data, - data + * s->s3->rrec.off, - offset into 'data' for next read + * s->s3->rrec.length, - number of bytes. */ + rr = &(s->s3->rrec); - /* get new packet */ + /* get new packet if necessary */ if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) { ret=ssl3_get_record(s); @@ -693,14 +841,17 @@ start: /* we now have a packet which can be read and processed */ - if (s->s3->change_cipher_spec && (rr->type != SSL3_RT_HANDSHAKE)) + if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, + * reset by ssl3_get_finished */ + && (rr->type != SSL3_RT_HANDSHAKE)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); goto err; } - /* If the other end has shutdown, throw anything we read away */ + /* If the other end has shut down, throw anything we read away + * (even in 'peek' mode) */ if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { rr->length=0; @@ -708,19 +859,107 @@ start: return(0); } - /* Check for an incoming 'Client Request' message */ - if ((rr->type == SSL3_RT_HANDSHAKE) && (rr->length == 4) && - (rr->data[0] == SSL3_MT_CLIENT_REQUEST) && + + if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ + { + /* make sure that we are not getting application data when we + * are doing a handshake for the first time */ + if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && + (s->enc_read_ctx == NULL)) + { + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE); + goto f_err; + } + + if (len <= 0) return(len); + + if ((unsigned int)len > rr->length) + n = rr->length; + else + n = (unsigned int)len; + + memcpy(buf,&(rr->data[rr->off]),n); + if (!peek) + { + rr->length-=n; + rr->off+=n; + if (rr->length == 0) + { + s->rstate=SSL_ST_READ_HEADER; + rr->off=0; + } + } + return(n); + } + + + /* If we get here, then type != rr->type; if we have a handshake + * message, then it was unexpected (Hello Request or Client Hello). */ + + /* In case of record types for which we have 'fragment' storage, + * fill that so that we can process the data at a fixed place. + */ + { + unsigned int dest_maxlen = 0; + unsigned char *dest = NULL; + unsigned int *dest_len = NULL; + + if (rr->type == SSL3_RT_HANDSHAKE) + { + dest_maxlen = sizeof s->s3->handshake_fragment; + dest = s->s3->handshake_fragment; + dest_len = &s->s3->handshake_fragment_len; + } + else if (rr->type == SSL3_RT_ALERT) + { + dest_maxlen = sizeof s->s3->alert_fragment; + dest = s->s3->alert_fragment; + dest_len = &s->s3->alert_fragment_len; + } + + if (dest_maxlen > 0) + { + n = dest_maxlen - *dest_len; /* available space in 'dest' */ + if (rr->length < n) + n = rr->length; /* available bytes */ + + /* now move 'n' bytes: */ + while (n-- > 0) + { + dest[(*dest_len)++] = rr->data[rr->off++]; + rr->length--; + } + + if (*dest_len < dest_maxlen) + goto start; /* fragment was too small */ + } + } + + /* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; + * s->s3->alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT. + * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ + + /* If we are a client, check for an incoming 'Hello Request': */ + if ((!s->server) && + (s->s3->handshake_fragment_len >= 4) && + (s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && (s->session != NULL) && (s->session->cipher != NULL)) { - if ((rr->data[1] != 0) || (rr->data[2] != 0) || - (rr->data[3] != 0)) + s->s3->handshake_fragment_len = 0; + + if ((s->s3->handshake_fragment[1] != 0) || + (s->s3->handshake_fragment[2] != 0) || + (s->s3->handshake_fragment[3] != 0)) { al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CLIENT_REQUEST); + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); goto err; } + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg); + if (SSL_is_init_finished(s) && !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && !s->s3->renegotiate) @@ -728,228 +967,231 @@ start: ssl3_renegotiate(s); if (ssl3_renegotiate_check(s)) { - n=s->handshake_func(s); - if (n < 0) return(n); - if (n == 0) + i=s->handshake_func(s); + if (i < 0) return(i); + if (i == 0) { SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); return(-1); } + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) + { + if (s->s3->rbuf.left == 0) /* no read-ahead left? */ + { + BIO *bio; + /* In the case where we try to read application data, + * but we trigger an SSL handshake, we return -1 with + * the retry option set. Otherwise renegotiation may + * cause nasty problems in the blocking world */ + s->rwstate=SSL_READING; + bio=SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return(-1); + } + } } } - rr->length=0; -/* ZZZ */ goto start; + /* we either finished a handshake or ignored the request, + * now try again to obtain the (application) data we were asked for */ + goto start; } - /* if it is not the type we want, or we have shutdown and want - * the peer shutdown */ - if ((rr->type != type) || (s->shutdown & SSL_SENT_SHUTDOWN)) + if (s->s3->alert_fragment_len >= 2) { - if (rr->type == SSL3_RT_ALERT) - { - if ((rr->length != 2) || (rr->off != 0)) - { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_ALERT_RECORD); - goto f_err; - } + int alert_level = s->s3->alert_fragment[0]; + int alert_descr = s->s3->alert_fragment[1]; - i=rr->data[0]; - n=rr->data[1]; + s->s3->alert_fragment_len = 0; - /* clear from buffer */ - rr->length=0; + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_ALERT, s->s3->alert_fragment, 2, s, s->msg_callback_arg); - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; + if (s->info_callback != NULL) + cb=s->info_callback; + else if (s->ctx->info_callback != NULL) + cb=s->ctx->info_callback; - if (cb != NULL) - { - j=(i<<8)|n; - cb(s,SSL_CB_READ_ALERT,j); - } + if (cb != NULL) + { + j = (alert_level << 8) | alert_descr; + cb(s, SSL_CB_READ_ALERT, j); + } - if (i == 1) - { - s->s3->warn_alert=n; - if (n == SSL_AD_CLOSE_NOTIFY) - { - s->shutdown|=SSL_RECEIVED_SHUTDOWN; - return(0); - } - } - else if (i == 2) + if (alert_level == 1) /* warning */ + { + s->s3->warn_alert = alert_descr; + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { - char tmp[16]; - - s->rwstate=SSL_NOTHING; - s->s3->fatal_alert=n; - SSLerr(SSL_F_SSL3_READ_BYTES,1000+n); - sprintf(tmp,"%d",n); - ERR_add_error_data(2,"SSL alert number ",tmp); - s->shutdown|=SSL_RECEIVED_SHUTDOWN; - SSL_CTX_remove_session(s->ctx,s->session); + s->shutdown |= SSL_RECEIVED_SHUTDOWN; return(0); } - else - { - al=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE); - goto f_err; - } - - rr->length=0; - goto start; } - - if (s->shutdown & SSL_SENT_SHUTDOWN) + else if (alert_level == 2) /* fatal */ { + char tmp[16]; + s->rwstate=SSL_NOTHING; - rr->length=0; + s->s3->fatal_alert = alert_descr; + SSLerr(SSL_F_SSL3_READ_BYTES, SSL_AD_REASON_OFFSET + alert_descr); + BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr); + ERR_add_error_data(2,"SSL alert number ",tmp); + s->shutdown|=SSL_RECEIVED_SHUTDOWN; + SSL_CTX_remove_session(s->ctx,s->session); return(0); } - - if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) + else { - if ( (rr->length != 1) || (rr->off != 0) || - (rr->data[0] != SSL3_MT_CCS)) - { - i=SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto err; - } - - rr->length=0; - s->s3->change_cipher_spec=1; - if (!do_change_cipher_spec(s)) - goto err; - else - goto start; + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE); + goto f_err; } - /* else we have a handshake */ - if ((rr->type == SSL3_RT_HANDSHAKE) && - !s->in_handshake) + goto start; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */ + { + s->rwstate=SSL_NOTHING; + rr->length=0; + return(0); + } + + if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) + { + /* 'Change Cipher Spec' is just a single byte, so we know + * exactly what the record payload has to look like */ + if ( (rr->length != 1) || (rr->off != 0) || + (rr->data[0] != SSL3_MT_CCS)) { - if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && - !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) - { - s->state=SSL_ST_BEFORE; - s->new_session=1; - } - n=s->handshake_func(s); - if (n < 0) return(n); - if (n == 0) - { - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } + i=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC); + goto err; + } + + rr->length=0; - /* In the case where we try to read application data - * the first time, but we trigger an SSL handshake, we - * return -1 with the retry option set. I do this - * otherwise renegotiation can cause nasty problems - * in the non-blocking world */ + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg); - s->rwstate=SSL_READING; - bio=SSL_get_rbio(s); - BIO_clear_retry_flags(bio); - BIO_set_retry_read(bio); + s->s3->change_cipher_spec=1; + if (!do_change_cipher_spec(s)) + goto err; + else + goto start; + } + + /* Unexpected handshake message (Client Hello, or protocol violation) */ + if ((s->s3->handshake_fragment_len >= 4) && !s->in_handshake) + { + if (((s->state&SSL_ST_MASK) == SSL_ST_OK) && + !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) + { +#if 0 /* worked only because C operator preferences are not as expected (and + * because this is not really needed for clients except for detecting + * protocol violations): */ + s->state=SSL_ST_BEFORE|(s->server) + ?SSL_ST_ACCEPT + :SSL_ST_CONNECT; +#else + s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; +#endif + s->new_session=1; + } + i=s->handshake_func(s); + if (i < 0) return(i); + if (i == 0) + { + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE); return(-1); } - switch (rr->type) + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { - default: -#ifndef NO_TLS - /* TLS just ignores unknown message types */ - if (s->version == TLS1_VERSION) - { - goto start; - } -#endif - case SSL3_RT_CHANGE_CIPHER_SPEC: - case SSL3_RT_ALERT: - case SSL3_RT_HANDSHAKE: - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); - goto f_err; - case SSL3_RT_APPLICATION_DATA: - /* At this point, we were expecting something else, - * but have application data. What we do is set the - * error, and return -1. On the way out, if the - * library was running inside ssl3_read() and it makes - * sense to read application data at this point, we - * will indulge it. This will mostly happen during - * session renegotiation. - */ - if (s->s3->in_read_app_data && - (s->s3->total_renegotiations != 0) && - (( - (s->state & SSL_ST_CONNECT) && - (s->state >= SSL3_ST_CW_CLNT_HELLO_A) && - (s->state <= SSL3_ST_CR_SRVR_HELLO_A) - ) || ( - (s->state & SSL_ST_ACCEPT) && - (s->state <= SSL3_ST_SW_HELLO_REQ_A) && - (s->state >= SSL3_ST_SR_CLNT_HELLO_A) - ) - )) + if (s->s3->rbuf.left == 0) /* no read-ahead left? */ { - s->s3->in_read_app_data=0; + BIO *bio; + /* In the case where we try to read application data, + * but we trigger an SSL handshake, we return -1 with + * the retry option set. Otherwise renegotiation may + * cause nasty problems in the blocking world */ + s->rwstate=SSL_READING; + bio=SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); return(-1); } - else - { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); - goto f_err; - } } + goto start; } - /* make sure that we are not getting application data when we - * are doing a handshake for the first time */ - if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && - (s->enc_read_ctx == NULL)) + switch (rr->type) { + default: +#ifndef OPENSSL_NO_TLS + /* TLS just ignores unknown message types */ + if (s->version == TLS1_VERSION) + { + rr->length = 0; + goto start; + } +#endif al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE); + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); goto f_err; + case SSL3_RT_CHANGE_CIPHER_SPEC: + case SSL3_RT_ALERT: + case SSL3_RT_HANDSHAKE: + /* we already handled all of these, with the possible exception + * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that + * should not happen when type != rr->type */ + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,ERR_R_INTERNAL_ERROR); + goto f_err; + case SSL3_RT_APPLICATION_DATA: + /* At this point, we were expecting handshake data, + * but have application data. If the library was + * running inside ssl3_read() (i.e. in_read_app_data + * is set) and it makes sense to read application data + * at this point (session renegotiation not yet started), + * we will indulge it. + */ + if (s->s3->in_read_app_data && + (s->s3->total_renegotiations != 0) && + (( + (s->state & SSL_ST_CONNECT) && + (s->state >= SSL3_ST_CW_CLNT_HELLO_A) && + (s->state <= SSL3_ST_CR_SRVR_HELLO_A) + ) || ( + (s->state & SSL_ST_ACCEPT) && + (s->state <= SSL3_ST_SW_HELLO_REQ_A) && + (s->state >= SSL3_ST_SR_CLNT_HELLO_A) + ) + )) + { + s->s3->in_read_app_data=2; + return(-1); + } + else + { + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD); + goto f_err; + } } + /* not reached */ - if (len <= 0) return(len); - - if ((unsigned int)len > rr->length) - n=rr->length; - else - n=len; - - memcpy(buf,&(rr->data[rr->off]),(unsigned int)n); - rr->length-=n; - rr->off+=n; - if (rr->length <= 0) - { - s->rstate=SSL_ST_READ_HEADER; - rr->off=0; - } - - if (type == SSL3_RT_HANDSHAKE) - ssl3_finish_mac(s,(unsigned char *)buf,n); - return(n); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: return(-1); } -static int do_change_cipher_spec(s) -SSL *s; +static int do_change_cipher_spec(SSL *s) { int i; - unsigned char *sender; + const char *sender; int slen; if (s->state & SSL_ST_ACCEPT) @@ -971,46 +1213,29 @@ SSL *s; * the finished message */ if (s->state & SSL_ST_CONNECT) { - sender=s->method->ssl3_enc->server_finished; - slen=s->method->ssl3_enc->server_finished_len; + sender=s->method->ssl3_enc->server_finished_label; + slen=s->method->ssl3_enc->server_finished_label_len; } else { - sender=s->method->ssl3_enc->client_finished; - slen=s->method->ssl3_enc->client_finished_len; + sender=s->method->ssl3_enc->client_finished_label; + slen=s->method->ssl3_enc->client_finished_label_len; } - s->method->ssl3_enc->final_finish_mac(s, + s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, &(s->s3->finish_dgst1), &(s->s3->finish_dgst2), - sender,slen,&(s->s3->tmp.finish_md[0])); + sender,slen,s->s3->tmp.peer_finish_md); return(1); } -int ssl3_do_write(s,type) -SSL *s; -int type; - { - int ret; - - ret=ssl3_write_bytes(s,type,(char *) - &(s->init_buf->data[s->init_off]),s->init_num); - if (ret == s->init_num) - return(1); - if (ret < 0) return(-1); - s->init_off+=ret; - s->init_num-=ret; - return(0); - } - -void ssl3_send_alert(s,level,desc) -SSL *s; -int level; -int desc; +void ssl3_send_alert(SSL *s, int level, int desc) { /* Map tls/ssl alert value to correct one */ desc=s->method->ssl3_enc->alert_value(desc); + if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) + desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */ if (desc < 0) return; /* If a fatal one, remove from cache */ if ((level == 2) && (s->session != NULL)) @@ -1019,37 +1244,39 @@ int desc; s->s3->alert_dispatch=1; s->s3->send_alert[0]=level; s->s3->send_alert[1]=desc; - if (s->s3->wbuf.left == 0) /* data still being written out */ + if (s->s3->wbuf.left == 0) /* data still being written out? */ ssl3_dispatch_alert(s); /* else data is still being written out, we will get written * some time in the future */ } -int ssl3_dispatch_alert(s) -SSL *s; +int ssl3_dispatch_alert(SSL *s) { int i,j; - void (*cb)()=NULL; + void (*cb)(const SSL *ssl,int type,int val)=NULL; s->s3->alert_dispatch=0; - i=do_ssl3_write(s,SSL3_RT_ALERT,&(s->s3->send_alert[0]),2); + i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0); if (i <= 0) { s->s3->alert_dispatch=1; } else { - /* If it is important, send it now. If the message - * does not get sent due to non-blocking IO, we will - * not worry too much. */ + /* Alert sent to BIO. If it is important, flush it now. + * If the message does not get sent due to non-blocking IO, + * we will not worry too much. */ if (s->s3->send_alert[0] == SSL3_AL_FATAL) - BIO_flush(s->wbio); + (void)BIO_flush(s->wbio); + + if (s->msg_callback) + s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s, s->msg_callback_arg); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; - + if (cb != NULL) { j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1]; @@ -1058,4 +1285,3 @@ SSL *s; } return(i); } - diff --git a/src/lib/libssl/s3_srvr.c b/src/lib/libssl/s3_srvr.c index 64903af151..99b6a86983 100644 --- a/src/lib/libssl/s3_srvr.c +++ b/src/lib/libssl/s3_srvr.c @@ -55,52 +55,88 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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). + * + */ #define REUSE_CIPHER_BUG +#define NETSCAPE_HANG_BUG + #include -#include "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include +#include #include "ssl_locl.h" +#include "kssl_lcl.h" +#include -#define BREAK break -/* SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_MALLOC_FAILURE); - * SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); - */ - -#ifndef NOPROTO +static SSL_METHOD *ssl3_get_server_method(int ver); static int ssl3_get_client_hello(SSL *s); +static int ssl3_check_client_hello(SSL *s); static int ssl3_send_server_hello(SSL *s); static int ssl3_send_server_key_exchange(SSL *s); static int ssl3_send_certificate_request(SSL *s); static int ssl3_send_server_done(SSL *s); -static int ssl3_get_cert_verify(SSL *s); static int ssl3_get_client_key_exchange(SSL *s); static int ssl3_get_client_certificate(SSL *s); +static int ssl3_get_cert_verify(SSL *s); static int ssl3_send_hello_request(SSL *s); -#else - -static int ssl3_get_client_hello(); -static int ssl3_send_server_hello(); -static int ssl3_send_server_key_exchange(); -static int ssl3_send_certificate_request(); -static int ssl3_send_server_done(); -static int ssl3_get_cert_verify(); -static int ssl3_get_client_key_exchange(); -static int ssl3_get_client_certificate(); -static int ssl3_send_hello_request(); - -#endif - -static SSL_METHOD *ssl3_get_server_method(ver) -int ver; +static SSL_METHOD *ssl3_get_server_method(int ver) { if (ver == SSL3_VERSION) return(SSLv3_server_method()); @@ -108,35 +144,32 @@ int ver; return(NULL); } -SSL_METHOD *SSLv3_server_method() +SSL_METHOD *SSLv3_server_method(void) { static int init=1; static SSL_METHOD SSLv3_server_data; if (init) { - init=0; memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(), sizeof(SSL_METHOD)); SSLv3_server_data.ssl_accept=ssl3_accept; SSLv3_server_data.get_ssl_method=ssl3_get_server_method; + init=0; } return(&SSLv3_server_data); } -int ssl3_accept(s) -SSL *s; +int ssl3_accept(SSL *s) { BUF_MEM *buf; unsigned long l,Time=time(NULL); - void (*cb)()=NULL; + void (*cb)(const SSL *ssl,int type,int val)=NULL; long num1; int ret= -1; - CERT *ct; - BIO *under; int new_state,state,skip=0; - RAND_seed((unsigned char *)&Time,sizeof(Time)); + RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); @@ -146,20 +179,14 @@ SSL *s; cb=s->ctx->info_callback; /* init things to blank */ - if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); -#ifdef undef - /* FIX THIS EAY EAY EAY */ - /* we don't actually need a cert, we just need a cert or a DH_tmp */ - if (((s->session == NULL) || (s->session->cert == NULL)) && - (s->cert == NULL)) + if (s->cert == NULL) { SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET); - ret= -1; - goto end; + return(-1); } -#endif for (;;) { @@ -176,11 +203,14 @@ SSL *s; case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: + s->server=1; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version>>8) != 3) - abort(); - /* s->version=SSL3_VERSION; */ + { + SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); + return -1; + } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) @@ -204,22 +234,24 @@ SSL *s; goto end; } - /* Ok, we now need to push on a buffering BIO so that - * the output is sent in a way that TCP likes :-) - */ - if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } - s->init_num=0; if (s->state != SSL_ST_RENEGOTIATE) { - s->state=SSL3_ST_SR_CLNT_HELLO_A; + /* Ok, we now need to push on a buffering BIO so that + * the output is sent in a way that TCP likes :-) + */ + if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } + ssl3_init_finished_mac(s); - s->ctx->sess_accept++; + s->state=SSL3_ST_SR_CLNT_HELLO_A; + s->ctx->stats.sess_accept++; } else { - s->ctx->sess_accept_renegotiate++; + /* s->state == SSL_ST_RENEGOTIATE, + * we will just send a HelloRequest */ + s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; @@ -238,19 +270,8 @@ SSL *s; break; case SSL3_ST_SW_HELLO_REQ_C: - /* remove buffering on output */ - under=BIO_pop(s->wbio); - if (under != NULL) - s->wbio=under; - else - abort(); /* ok */ - BIO_free(s->bbio); - s->bbio=NULL; - s->state=SSL_ST_OK; - ret=1; - goto end; - /* break; */ + break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: @@ -259,6 +280,7 @@ SSL *s; s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; + s->new_session = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; break; @@ -292,40 +314,34 @@ SSL *s; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: l=s->s3->tmp.new_cipher->algorithms; - if (s->session->cert == NULL) - { - if (s->cert != NULL) - { - CRYPTO_add(&s->cert->references,1,CRYPTO_LOCK_SSL_CERT); - s->session->cert=s->cert; - } - else - { - CRYPTO_add(&s->ctx->default_cert->references,1,CRYPTO_LOCK_SSL_CERT); - s->session->cert=s->ctx->default_cert; - } - } - ct=s->session->cert; /* clear this, it may get reset by * send_server_key_exchange */ - if (s->options & SSL_OP_EPHEMERAL_RSA) + if ((s->options & SSL_OP_EPHEMERAL_RSA) +#ifndef OPENSSL_NO_KRB5 + && !(l & SSL_KRB5) +#endif /* OPENSSL_NO_KRB5 */ + ) + /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key + * even when forbidden by protocol specs + * (handshake may fail as clients are not required to + * be able to handle this) */ s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; /* only send if a DH key exchange, fortezza or * RSA but we have a sign only certificate */ - if ( s->s3->tmp.use_rsa_tmp || - (l & (SSL_DH|SSL_kFZA)) || - ((l & SSL_kRSA) && - ((ct->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL)|| - ((l & SSL_EXPORT) && - (EVP_PKEY_size(ct->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > 512) - ) - ) + if (s->s3->tmp.use_rsa_tmp + || (l & (SSL_DH|SSL_kFZA)) + || ((l & SSL_kRSA) + && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL + || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) + && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) + ) + ) + ) ) - ) { ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; @@ -339,9 +355,21 @@ SSL *s; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: - if (!(s->verify_mode & SSL_VERIFY_PEER) || + if (/* don't request cert unless asked for it: */ + !(s->verify_mode & SSL_VERIFY_PEER) || + /* if SSL_VERIFY_CLIENT_ONCE is set, + * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && - (s->verify_mode & SSL_VERIFY_CLIENT_ONCE))) + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || + /* never request cert in anonymous ciphersuites + * (see section "Certificate request" in SSL 3 drafts + * and in RFC 2246): */ + ((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) && + /* ... except when the application insists on verification + * (against the specs, but s3_clnt.c accepts this for SSL 3) */ + !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || + /* never request cert in Kerberos ciphersuites */ + (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5)) { /* no cert request */ skip=1; @@ -353,7 +381,12 @@ SSL *s; s->s3->tmp.cert_request=1; ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; +#ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; +#else + s->state=SSL3_ST_SW_FLUSH; + s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; +#endif s->init_num=0; } break; @@ -383,12 +416,20 @@ SSL *s; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: - /* could be sent for a DH cert, even if we - * have not asked for it :-) */ - ret=ssl3_get_client_certificate(s); - if (ret <= 0) goto end; - s->init_num=0; - s->state=SSL3_ST_SR_KEY_EXCH_A; + /* Check for second client hello (MS SGC) */ + ret = ssl3_check_client_hello(s); + if (ret <= 0) + goto end; + if (ret == 2) + s->state = SSL3_ST_SR_CLNT_HELLO_C; + else { + /* could be sent for a DH cert, even if we + * have not asked for it :-) */ + ret=ssl3_get_client_certificate(s); + if (ret <= 0) goto end; + s->init_num=0; + s->state=SSL3_ST_SR_KEY_EXCH_A; + } break; case SSL3_ST_SR_KEY_EXCH_A: @@ -402,10 +443,10 @@ SSL *s; * a client cert, it can be verified */ s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst1), - &(s->s3->tmp.finish_md[0])); + &(s->s3->tmp.cert_verify_md[0])); s->method->ssl3_enc->cert_verify_mac(s, &(s->s3->finish_dgst2), - &(s->s3->tmp.finish_md[MD5_DIGEST_LENGTH])); + &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH])); break; @@ -459,8 +500,8 @@ SSL *s; case SSL3_ST_SW_FINISHED_B: ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, - s->method->ssl3_enc->server_finished, - s->method->ssl3_enc->server_finished_len); + s->method->ssl3_enc->server_finished_label, + s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) @@ -478,26 +519,27 @@ SSL *s; s->init_buf=NULL; /* remove buffering on output */ - under=BIO_pop(s->wbio); - if (under != NULL) - s->wbio=under; - else - abort(); /* ok */ - BIO_free(s->bbio); - s->bbio=NULL; + ssl_free_wbio_buffer(s); - s->new_session=0; s->init_num=0; - ssl_update_cache(s,SSL_SESS_CACHE_SERVER); - - s->ctx->sess_accept_good++; - /* s->server=1; */ - s->handshake_func=ssl3_accept; - ret=1; - - if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); - + if (s->new_session == 2) /* skipped if we just sent a HelloRequest */ + { + /* actually not necessarily a 'new' session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ + + s->new_session=0; + + ssl_update_cache(s,SSL_SESS_CACHE_SERVER); + + s->ctx->stats.sess_accept_good++; + /* s->server=1; */ + s->handshake_func=ssl3_accept; + + if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); + } + + ret = 1; goto end; /* break; */ @@ -530,21 +572,20 @@ SSL *s; end: /* BIO_flush(s->wbio); */ + s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_ACCEPT_EXIT,ret); - s->in_handshake--; return(ret); } -static int ssl3_send_hello_request(s) -SSL *s; +static int ssl3_send_hello_request(SSL *s) { unsigned char *p; if (s->state == SSL3_ST_SW_HELLO_REQ_A) { p=(unsigned char *)s->init_buf->data; - *(p++)=SSL3_MT_CLIENT_REQUEST; + *(p++)=SSL3_MT_HELLO_REQUEST; *(p++)=0; *(p++)=0; *(p++)=0; @@ -559,15 +600,48 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_get_client_hello(s) -SSL *s; +static int ssl3_check_client_hello(SSL *s) + { + int ok; + long n; + + /* this function is called when we really expect a Certificate message, + * so permit appropriate message length */ + n=ssl3_get_message(s, + SSL3_ST_SR_CERT_A, + SSL3_ST_SR_CERT_B, + -1, + s->max_cert_list, + &ok); + if (!ok) return((int)n); + s->s3->tmp.reuse_message = 1; + if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) + { + /* Throw away what we have done so far in the current handshake, + * which will now be aborted. (A full SSL_clear would be too much.) + * I hope that tmp.dh is the only thing that may need to be cleared + * when a handshake is not completed ... */ +#ifndef OPENSSL_NO_DH + if (s->s3->tmp.dh != NULL) + { + DH_free(s->s3->tmp.dh); + s->s3->tmp.dh = NULL; + } +#endif + return 2; + } + return 1; +} + +static int ssl3_get_client_hello(SSL *s) { int i,j,ok,al,ret= -1; long n; unsigned long id; - unsigned char *p,*d; + unsigned char *p,*d,*q; SSL_CIPHER *c; - STACK *ciphers=NULL; + SSL_COMP *comp=NULL; + STACK_OF(SSL_CIPHER) *ciphers=NULL; /* We do this so that we will respond with our native type. * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, @@ -588,13 +662,25 @@ SSL *s; &ok); if (!ok) return((int)n); - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; - /* The version number has already been checked in ssl3_get_message. - * I a native TLSv1/SSLv3 method, the match must be correct except - * perhaps for the first message */ + /* use version from inside client hello, not from record header + * (may differ: see RFC 2246, Appendix E, second paragraph) */ + s->client_version=(((int)p[0])<<8)|(int)p[1]; p+=2; + if (s->client_version < s->version) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); + if ((s->client_version>>8) == SSL3_VERSION_MAJOR) + { + /* similar to ssl3_get_record, send alert using remote version number */ + s->version = s->client_version; + } + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + /* load the client random */ memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; @@ -603,7 +689,15 @@ SSL *s; j= *(p++); s->hit=0; - if (j == 0) + /* Versions before 0.9.7 always allow session reuse during renegotiation + * (i.e. when s->new_session is true), option + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7. + * Maybe this optional behaviour should always have been the default, + * but we cannot safely change the default behaviour (or new applications + * might be written that become totally unsecure when compiled with + * an earlier library version) + */ + if (j == 0 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { if (!ssl_get_new_session(s,1)) goto err; @@ -615,7 +709,9 @@ SSL *s; { /* previous session */ s->hit=1; } - else + else if (i == -1) + goto err; + else /* i == 0 */ { if (!ssl_get_new_session(s,1)) goto err; @@ -631,7 +727,7 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_CIPHERS_SPECIFIED); goto f_err; } - if ((i+p) > (d+n)) + if ((p+i) >= (d+n)) { /* not enough data */ al=SSL_AD_DECODE_ERROR; @@ -651,9 +747,16 @@ SSL *s; j=0; id=s->session->cipher->id; - for (i=0; iid == id) { j=1; @@ -662,11 +765,11 @@ SSL *s; } if (j == 0) { - if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_num(ciphers) == 1)) + if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1)) { /* Very bad for multi-threading.... */ - s->session->cipher= - (SSL_CIPHER *)sk_value(ciphers,0); + s->session->cipher=sk_SSL_CIPHER_value(ciphers, + 0); } else { @@ -681,8 +784,18 @@ SSL *s; /* compression */ i= *(p++); + if ((p+i) > (d+n)) + { + /* not enough data */ + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); + goto f_err; + } + q=p; for (j=0; j= i) @@ -693,10 +806,39 @@ SSL *s; goto f_err; } + /* Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have i-1 compression + * algorithms from the client, starting at q. */ + s->s3->tmp.new_compression=NULL; + if (s->ctx->comp_methods != NULL) + { /* See if we have a match */ + int m,nn,o,v,done=0; + + nn=sk_SSL_COMP_num(s->ctx->comp_methods); + for (m=0; mctx->comp_methods,m); + v=comp->id; + for (o=0; os3->tmp.new_compression=comp; + else + comp=NULL; + } + /* TLS does not mind if there is extra stuff */ if (s->version == SSL3_VERSION) { - if (p > (d+n)) + if (p < (d+n)) { /* wrong number of bytes, * there could be more to follow */ @@ -706,15 +848,14 @@ SSL *s; } } - /* do nothing with compression */ - - /* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must + /* Given s->session->ciphers and SSL_get_ciphers, we must * pick a cipher */ if (!s->hit) { + s->session->compress_meth=(comp == NULL)?0:comp->id; if (s->session->ciphers != NULL) - sk_free(s->session->ciphers); + sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers=ciphers; if (ciphers == NULL) { @@ -724,7 +865,7 @@ SSL *s; } ciphers=NULL; c=ssl3_choose_cipher(s,s->session->ciphers, - ssl_get_ciphers_by_id(s)); + SSL_get_ciphers(s)); if (c == NULL) { @@ -738,19 +879,19 @@ SSL *s; { /* Session-id reuse */ #ifdef REUSE_CIPHER_BUG - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *nc=NULL; SSL_CIPHER *ec=NULL; if (s->options & SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) { sk=s->session->ciphers; - for (i=0; ialgorithms & SSL_eNULL) nc=c; - if (c->algorithms & SSL_EXP) + if (SSL_C_IS_EXPORT(c)) ec=c; } if (nc != NULL) @@ -772,7 +913,7 @@ SSL *s; * compression - basically ignored right now * ssl version is set - sslv3 * s->session - The ssl session has been setup. - * s->hit - sesson reuse flag + * s->hit - session reuse flag * s->tmp.new_cipher - the new cipher to use. */ @@ -783,12 +924,11 @@ f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); } err: - if (ciphers != NULL) sk_free(ciphers); + if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); return(ret); } -static int ssl3_send_server_hello(s) -SSL *s; +static int ssl3_send_server_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; @@ -801,7 +941,7 @@ SSL *s; p=s->s3->server_random; Time=time(NULL); /* Time */ l2n(Time,p); - RAND_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); + RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); /* Do the message type and length last */ d=p= &(buf[4]); @@ -833,7 +973,10 @@ SSL *s; p+=i; /* put the compression method */ - *(p++)=0; + if (s->s3->tmp.new_compression == NULL) + *(p++)=0; + else + *(p++)=s->s3->tmp.new_compression->id; /* do the header */ l=(p-d); @@ -851,8 +994,7 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_send_server_done(s) -SSL *s; +static int ssl3_send_server_done(SSL *s) { unsigned char *p; @@ -876,17 +1018,17 @@ SSL *s; return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_send_server_key_exchange(s) -SSL *s; +static int ssl3_send_server_key_exchange(SSL *s) { -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA unsigned char *q; int j,num; RSA *rsa; unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; + unsigned int u; #endif -#ifndef NO_DH - DH *dh,*dhp; +#ifndef OPENSSL_NO_DH + DH *dh=NULL,*dhp; #endif EVP_PKEY *pkey; unsigned char *p,*d; @@ -899,25 +1041,32 @@ SSL *s; BUF_MEM *buf; EVP_MD_CTX md_ctx; + EVP_MD_CTX_init(&md_ctx); if (s->state == SSL3_ST_SW_KEY_EXCH_A) { type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK; - cert=s->session->cert; + cert=s->cert; buf=s->init_buf; r[0]=r[1]=r[2]=r[3]=NULL; n=0; -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (type & SSL_kRSA) { rsa=cert->rsa_tmp; - if ((rsa == NULL) && (s->ctx->default_cert->rsa_tmp_cb != NULL)) + if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) + { + rsa=s->cert->rsa_tmp_cb(s, + SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), + SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); + if(rsa == NULL) { - rsa=s->ctx->default_cert->rsa_tmp_cb(s, - (s->s3->tmp.new_cipher->algorithms| - SSL_NOT_EXP)?0:1); - CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY); + goto f_err; + } + RSA_up_ref(rsa); cert->rsa_tmp=rsa; } if (rsa == NULL) @@ -932,20 +1081,28 @@ SSL *s; } else #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (type & SSL_kEDH) { dhp=cert->dh_tmp; - if ((dhp == NULL) && (cert->dh_tmp_cb != NULL)) - dhp=cert->dh_tmp_cb(s, - (s->s3->tmp.new_cipher->algorithms| - SSL_NOT_EXP)?0:1); + if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) + dhp=s->cert->dh_tmp_cb(s, + SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), + SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); if (dhp == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); goto f_err; } + + if (s->s3->tmp.dh != NULL) + { + DH_free(dh); + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((dh=DHparams_dup(dhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); @@ -953,13 +1110,16 @@ SSL *s; } s->s3->tmp.dh=dh; - if (((dhp->pub_key == NULL) || - (dhp->priv_key == NULL) || - (s->options & SSL_OP_SINGLE_DH_USE)) && - (!DH_generate_key(dh))) + if ((dhp->pub_key == NULL || + dhp->priv_key == NULL || + (s->options & SSL_OP_SINGLE_DH_USE))) { - SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; + if(!DH_generate_key(dh)) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, + ERR_R_DH_LIB); + goto err; + } } else { @@ -1025,40 +1185,39 @@ SSL *s; { /* n is the length of the params, they start at &(d[4]) * and p points to the space at the end. */ -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { q=md_buf; j=0; for (num=2; num > 0; num--) { - EVP_DigestInit(&md_ctx,(num == 2) - ?s->ctx->md5:s->ctx->sha1); + EVP_DigestInit_ex(&md_ctx,(num == 2) + ?s->ctx->md5:s->ctx->sha1, NULL); EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(d[4]),n); - EVP_DigestFinal(&md_ctx,q, + EVP_DigestFinal_ex(&md_ctx,q, (unsigned int *)&i); q+=i; j+=i; } - i=RSA_private_encrypt(j,md_buf,&(p[2]), - pkey->pkey.rsa,RSA_PKCS1_PADDING); - if (i <= 0) + if (RSA_sign(NID_md5_sha1, md_buf, j, + &(p[2]), &u, pkey->pkey.rsa) <= 0) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); goto err; } - s2n(i,p); - n+=i+2; + s2n(u,p); + n+=u+2; } else #endif -#if !defined(NO_DSA) +#if !defined(OPENSSL_NO_DSA) if (pkey->type == EVP_PKEY_DSA) { /* lets do DSS */ - EVP_SignInit(&md_ctx,EVP_dss1()); + EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(d[4]),n); @@ -1090,20 +1249,21 @@ SSL *s; s->init_off=0; } - /* SSL3_ST_SW_KEY_EXCH_B */ + s->state = SSL3_ST_SW_KEY_EXCH_B; + EVP_MD_CTX_cleanup(&md_ctx); return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: + EVP_MD_CTX_cleanup(&md_ctx); return(-1); } -static int ssl3_send_certificate_request(s) -SSL *s; +static int ssl3_send_certificate_request(SSL *s) { unsigned char *p,*d; int i,j,nl,off,n; - STACK *sk=NULL; + STACK_OF(X509_NAME) *sk=NULL; X509_NAME *name; BUF_MEM *buf; @@ -1128,9 +1288,9 @@ SSL *s; nl=0; if (sk != NULL) { - for (i=0; iinit_num=n+4; s->init_off=0; +#ifdef NETSCAPE_HANG_BUG + p=(unsigned char *)s->init_buf->data + s->init_num; + + /* do the header */ + *(p++)=SSL3_MT_SERVER_DONE; + *(p++)=0; + *(p++)=0; + *(p++)=0; + s->init_num += 4; +#endif + } /* SSL3_ST_SW_CERT_REQ_B */ @@ -1176,44 +1347,44 @@ err: return(-1); } -static int ssl3_get_client_key_exchange(s) -SSL *s; +static int ssl3_get_client_key_exchange(SSL *s) { int i,al,ok; long n; unsigned long l; unsigned char *p; +#ifndef OPENSSL_NO_RSA RSA *rsa=NULL; EVP_PKEY *pkey=NULL; -#ifndef NO_DH +#endif +#ifndef OPENSSL_NO_DH BIGNUM *pub=NULL; DH *dh_srvr; #endif +#ifndef OPENSSL_NO_KRB5 + KSSL_ERR kssl_err; +#endif /* OPENSSL_NO_KRB5 */ n=ssl3_get_message(s, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, - 400, /* ???? */ + 2048, /* ??? */ &ok); if (!ok) return((int)n); - p=(unsigned char *)s->init_buf->data; + p=(unsigned char *)s->init_msg; l=s->s3->tmp.new_cipher->algorithms; -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (l & SSL_kRSA) { /* FIX THIS UP EAY EAY EAY EAY */ if (s->s3->tmp.use_rsa_tmp) { - if ((s->session->cert != NULL) && - (s->session->cert->rsa_tmp != NULL)) - rsa=s->session->cert->rsa_tmp; - else if ((s->ctx->default_cert != NULL) && - (s->ctx->default_cert->rsa_tmp != NULL)) - rsa=s->ctx->default_cert->rsa_tmp; + if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL)) + rsa=s->cert->rsa_tmp; /* Don't do a callback because rsa_tmp should * be sent already */ if (rsa == NULL) @@ -1258,33 +1429,53 @@ SSL *s; i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING); -#if 1 - /* If a bad decrypt, use a dud master key */ - if ((i != SSL_MAX_MASTER_KEY_LENGTH) || - ((p[0] != (s->version>>8)) || - (p[1] != (s->version & 0xff)))) - { - p[0]=(s->version>>8); - p[1]=(s->version & 0xff); - RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2); - i=SSL_MAX_MASTER_KEY_LENGTH; - } -#else + al = -1; + if (i != SSL_MAX_MASTER_KEY_LENGTH) { al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); - goto f_err; } - if ((p[0] != (s->version>>8)) || (p[1] != (s->version & 0xff))) + if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff)))) { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); - goto f_err; + /* The premaster secret must contain the same version number as the + * ClientHello to detect version rollback attacks (strangely, the + * protocol does not offer such protection for DH ciphersuites). + * However, buggy clients exist that send the negotiated protocol + * version instead if the server does not support the requested + * protocol version. + * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */ + if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) && + (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff)))) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); + goto f_err; + } } -#endif + if (al != -1) + { +#if 0 + goto f_err; +#else + /* Some decryption failure -- use random value instead as countermeasure + * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding + * (see RFC 2246, section 7.4.7.1). + * But note that due to length and protocol version checking, the + * attack is impractical anyway (see section 5 in D. Bleichenbacher: + * "Chosen Ciphertext Attacks Against Protocols Based on the RSA + * Encryption Standard PKCS #1", CRYPTO '98, LNCS 1462, pp. 1-12). + */ + ERR_clear_error(); + i = SSL_MAX_MASTER_KEY_LENGTH; + p[0] = s->client_version >> 8; + p[1] = s->client_version & 0xff; + RAND_pseudo_bytes(p+2, i-2); /* should be RAND_bytes, but we cannot work around a failure */ +#endif + } + s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, @@ -1293,7 +1484,7 @@ SSL *s; } else #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { n2s(p,i); @@ -1352,26 +1543,175 @@ SSL *s; s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,p,i); + memset(p,0,i); } else #endif +#ifndef OPENSSL_NO_KRB5 + if (l & SSL_kKRB5) + { + krb5_error_code krb5rc; + krb5_data enc_ticket; + krb5_data authenticator; + krb5_data enc_pms; + KSSL_CTX *kssl_ctx = s->kssl_ctx; + EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER *enc = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH + + EVP_MAX_IV_LENGTH + 1]; + int padl, outl = sizeof(pms); + krb5_timestamp authtime = 0; + krb5_ticket_times ttimes; + + EVP_CIPHER_CTX_init(&ciph_ctx); + + if (!kssl_ctx) kssl_ctx = kssl_ctx_new(); + + n2s(p,i); + enc_ticket.length = i; + enc_ticket.data = (char *)p; + p+=enc_ticket.length; + + n2s(p,i); + authenticator.length = i; + authenticator.data = (char *)p; + p+=authenticator.length; + + n2s(p,i); + enc_pms.length = i; + enc_pms.data = (char *)p; + p+=enc_pms.length; + + if (n != enc_ticket.length + authenticator.length + + enc_pms.length + 6) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + + if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes, + &kssl_err)) != 0) + { +#ifdef KSSL_DEBUG + printf("kssl_sget_tkt rtn %d [%d]\n", + krb5rc, kssl_err.reason); + if (kssl_err.text) + printf("kssl_err text= %s\n", kssl_err.text); +#endif /* KSSL_DEBUG */ + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); + goto err; + } + + /* Note: no authenticator is not considered an error, + ** but will return authtime == 0. + */ + if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator, + &authtime, &kssl_err)) != 0) + { +#ifdef KSSL_DEBUG + printf("kssl_check_authent rtn %d [%d]\n", + krb5rc, kssl_err.reason); + if (kssl_err.text) + printf("kssl_err text= %s\n", kssl_err.text); +#endif /* KSSL_DEBUG */ + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); + goto err; + } + + if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, krb5rc); + goto err; + } + +#ifdef KSSL_DEBUG + kssl_ctx_show(kssl_ctx); +#endif /* KSSL_DEBUG */ + + enc = kssl_map_enc(kssl_ctx->enctype); + if (enc == NULL) + goto err; + + memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + + if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DECRYPTION_FAILED); + goto err; + } + if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl, + (unsigned char *)enc_pms.data, enc_pms.length)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DECRYPTION_FAILED); + goto err; + } + if (outl > SSL_MAX_MASTER_KEY_LENGTH) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DECRYPTION_FAILED); + goto err; + } + outl += padl; + if (outl > SSL_MAX_MASTER_KEY_LENGTH) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + s->session->master_key_length= + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, pms, outl); + + if (kssl_ctx->client_princ) + { + int len = strlen(kssl_ctx->client_princ); + if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) + { + s->session->krb5_client_princ_len = len; + memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len); + } + } + + + /* Was doing kssl_ctx_free() here, + ** but it caused problems for apache. + ** kssl_ctx = kssl_ctx_free(kssl_ctx); + ** if (s->kssl_ctx) s->kssl_ctx = NULL; + */ + } + else +#endif /* OPENSSL_NO_KRB5 */ { al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNKNOWN_CIPHER_TYPE); + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_UNKNOWN_CIPHER_TYPE); goto f_err; } return(1); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); -#if !defined(NO_DH) || !defined(NO_RSA) +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) err: #endif return(-1); } -static int ssl3_get_cert_verify(s) -SSL *s; +static int ssl3_get_cert_verify(SSL *s) { EVP_PKEY *pkey=NULL; unsigned char *p; @@ -1436,7 +1776,7 @@ SSL *s; } /* we now have a signature that we need to verify */ - p=(unsigned char *)s->init_buf->data; + p=(unsigned char *)s->init_msg; n2s(p,i); n-=2; if (i > n) @@ -1454,19 +1794,19 @@ SSL *s; goto f_err; } -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { - i=RSA_public_decrypt(i,p,p,pkey->pkey.rsa,RSA_PKCS1_PADDING); + i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md, + MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i, + pkey->pkey.rsa); if (i < 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT); goto f_err; } - if ((i != (MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH)) || - memcmp(&(s->s3->tmp.finish_md[0]),p, - MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH)) + if (i == 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE); @@ -1475,11 +1815,11 @@ SSL *s; } else #endif -#ifndef NO_DSA +#ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { j=DSA_verify(pkey->save_type, - &(s->s3->tmp.finish_md[MD5_DIGEST_LENGTH]), + &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa); if (j <= 0) { @@ -1492,7 +1832,7 @@ SSL *s; else #endif { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR); al=SSL_AD_UNSUPPORTED_CERTIFICATE; goto f_err; } @@ -1505,27 +1845,23 @@ f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); } end: + EVP_PKEY_free(pkey); return(ret); } -static int ssl3_get_client_certificate(s) -SSL *s; +static int ssl3_get_client_certificate(SSL *s) { int i,ok,al,ret= -1; X509 *x=NULL; unsigned long l,nc,llen,n; unsigned char *p,*d,*q; - STACK *sk=NULL; + STACK_OF(X509) *sk=NULL; n=ssl3_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, -#if defined(MSDOS) && !defined(WIN32) - 1024*30, /* 30k max cert list :-) */ -#else - 1024*100, /* 100k max cert list :-) */ -#endif + s->max_cert_list, &ok); if (!ok) return((int)n); @@ -1539,7 +1875,7 @@ SSL *s; al=SSL_AD_HANDSHAKE_FAILURE; goto f_err; } - /* If tls asked for a client cert we must return a 0 list */ + /* If tls asked for a client cert, the client must return a 0 list */ if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); @@ -1556,9 +1892,9 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE); goto f_err; } - d=p=(unsigned char *)s->init_buf->data; + d=p=(unsigned char *)s->init_msg; - if ((sk=sk_new_null()) == NULL) + if ((sk=sk_X509_new_null()) == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -1594,7 +1930,7 @@ SSL *s; SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } - if (!sk_push(sk,(char *)x)) + if (!sk_X509_push(sk,x)) { SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; @@ -1603,7 +1939,7 @@ SSL *s; nc+=l+3; } - if (sk_num(sk) <= 0) + if (sk_X509_num(sk) <= 0) { /* TLS does not mind 0 certs returned */ if (s->version == SSL3_VERSION) @@ -1632,10 +1968,29 @@ SSL *s; } } - /* This should not be needed */ - if (s->session->peer != NULL) + if (s->session->peer != NULL) /* This should not be needed */ X509_free(s->session->peer); - s->session->peer=(X509 *)sk_shift(sk); + s->session->peer=sk_X509_shift(sk); + s->session->verify_result = s->verify_result; + + /* With the current implementation, sess_cert will always be NULL + * when we arrive here. */ + if (s->session->sess_cert == NULL) + { + s->session->sess_cert = ssl_sess_cert_new(); + if (s->session->sess_cert == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (s->session->sess_cert->cert_chain != NULL) + sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); + s->session->sess_cert->cert_chain=sk; + /* Inconsistency alert: cert_chain does *not* include the + * peer's own certificate, while we do include it in s3_clnt.c */ + + sk=NULL; ret=1; if (0) @@ -1645,12 +2000,11 @@ f_err: } err: if (x != NULL) X509_free(x); - if (sk != NULL) sk_pop_free(sk,X509_free); + if (sk != NULL) sk_X509_pop_free(sk,X509_free); return(ret); } -int ssl3_send_server_certificate(s) -SSL *s; +int ssl3_send_server_certificate(SSL *s) { unsigned long l; X509 *x; @@ -1658,9 +2012,13 @@ SSL *s; if (s->state == SSL3_ST_SW_CERT_A) { x=ssl_get_server_send_cert(s); - if (x == NULL) + if (x == NULL && + /* VRS: allow null cert if auth == KRB5 */ + (s->s3->tmp.new_cipher->algorithms + & (SSL_MKEY_MASK|SSL_AUTH_MASK)) + != (SSL_aKRB5|SSL_kKRB5)) { - SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR); return(0); } diff --git a/src/lib/libssl/ssl.h b/src/lib/libssl/ssl.h index cf8f9651b2..833f761690 100644 --- a/src/lib/libssl/ssl.h +++ b/src/lib/libssl/ssl.h @@ -55,10 +55,131 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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). + * + */ +/* ==================================================================== + * Copyright (c) 1998-2002 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_SSL_H #define HEADER_SSL_H +#include + +#ifndef OPENSSL_NO_COMP +#include +#endif +#ifndef OPENSSL_NO_BIO +#include +#endif +#ifndef OPENSSL_NO_X509 +#include +#endif +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -81,7 +202,18 @@ extern "C" { #define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 #define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA +/* VRS Additional Kerberos5 entries + */ +#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA +#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5 +#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA +#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5 +#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +#define SSL_MAX_KRB5_PRINCIPAL_LENGTH 256 + #define SSL_MAX_SSL_SESSION_ID_LENGTH 32 +#define SSL_MAX_SID_CTX_LENGTH 32 #define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) #define SSL_MAX_KEY_ARG_LENGTH 8 @@ -100,6 +232,10 @@ extern "C" { #define SSL_TXT_eNULL "eNULL" #define SSL_TXT_NULL "NULL" +#define SSL_TXT_kKRB5 "kKRB5" +#define SSL_TXT_aKRB5 "aKRB5" +#define SSL_TXT_KRB5 "KRB5" + #define SSL_TXT_kRSA "kRSA" #define SSL_TXT_kDHr "kDHr" #define SSL_TXT_kDHd "kDHd" @@ -117,33 +253,46 @@ extern "C" { #define SSL_TXT_RC4 "RC4" #define SSL_TXT_RC2 "RC2" #define SSL_TXT_IDEA "IDEA" +#define SSL_TXT_AES "AESdraft" /* AES ciphersuites are not yet official (thus excluded from 'ALL') */ #define SSL_TXT_MD5 "MD5" #define SSL_TXT_SHA1 "SHA1" #define SSL_TXT_SHA "SHA" #define SSL_TXT_EXP "EXP" #define SSL_TXT_EXPORT "EXPORT" +#define SSL_TXT_EXP40 "EXPORT40" +#define SSL_TXT_EXP56 "EXPORT56" #define SSL_TXT_SSLV2 "SSLv2" #define SSL_TXT_SSLV3 "SSLv3" +#define SSL_TXT_TLSV1 "TLSv1" #define SSL_TXT_ALL "ALL" -/* 'DEFAULT' at the start of the cipher list insert the following string - * in addition to this being the default cipher string */ -#ifndef NO_RSA -#define SSL_DEFAULT_CIPHER_LIST "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP" -#else -#define SSL_ALLOW_ADH -#define SSL_DEFAULT_CIPHER_LIST "HIGH:MEDIUM:LOW:ADH+3DES:ADH+RC4:ADH+DES:+EXP" -#endif +/* The following cipher list is used by default. + * It also is substituted when an application-defined cipher list string + * starts with 'DEFAULT'. */ +#define SSL_DEFAULT_CIPHER_LIST "ALL:!ADH:+RC4:@STRENGTH" /* low priority for RC4 */ /* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ #define SSL_SENT_SHUTDOWN 1 #define SSL_RECEIVED_SHUTDOWN 2 -#include "crypto.h" -#include "lhash.h" -#include "buffer.h" -#include "bio.h" -#include "x509.h" +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2) +#define OPENSSL_NO_SSL2 +#endif #define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 #define SSL_FILETYPE_PEM X509_FILETYPE_PEM @@ -157,44 +306,52 @@ typedef struct ssl_st *ssl_crock_st; typedef struct ssl_cipher_st { int valid; - char *name; /* text name */ + const char *name; /* text name */ unsigned long id; /* id, 4 bytes, first is version */ unsigned long algorithms; /* what ciphers are used */ + unsigned long algo_strength; /* strength and export flags */ unsigned long algorithm2; /* Extra flags */ + int strength_bits; /* Number of bits really used */ + int alg_bits; /* Number of bits for algorithm */ unsigned long mask; /* used for matching */ + unsigned long mask_strength; /* also used for matching */ } SSL_CIPHER; +DECLARE_STACK_OF(SSL_CIPHER) + +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ typedef struct ssl_method_st { int version; - int (*ssl_new)(); - void (*ssl_clear)(); - void (*ssl_free)(); - int (*ssl_accept)(); - int (*ssl_connect)(); - int (*ssl_read)(); - int (*ssl_peek)(); - int (*ssl_write)(); - int (*ssl_shutdown)(); - int (*ssl_renegotiate)(); - long (*ssl_ctrl)(); - long (*ssl_ctx_ctrl)(); - SSL_CIPHER *(*get_cipher_by_char)(); - int (*put_cipher_by_char)(); - int (*ssl_pending)(); - int (*num_ciphers)(); - SSL_CIPHER *(*get_cipher)(); - struct ssl_method_st *(*get_ssl_method)(); - long (*get_timeout)(); + int (*ssl_new)(SSL *s); + void (*ssl_clear)(SSL *s); + void (*ssl_free)(SSL *s); + int (*ssl_accept)(SSL *s); + int (*ssl_connect)(SSL *s); + int (*ssl_read)(SSL *s,void *buf,int len); + int (*ssl_peek)(SSL *s,void *buf,int len); + int (*ssl_write)(SSL *s,const void *buf,int len); + int (*ssl_shutdown)(SSL *s); + int (*ssl_renegotiate)(SSL *s); + int (*ssl_renegotiate_check)(SSL *s); + long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg); + long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg); + SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr); + int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr); + int (*ssl_pending)(SSL *s); + int (*num_ciphers)(void); + SSL_CIPHER *(*get_cipher)(unsigned ncipher); + struct ssl_method_st *(*get_ssl_method)(int version); + long (*get_timeout)(void); struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */ + int (*ssl_version)(); + long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)()); + long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)()); } SSL_METHOD; -typedef struct ssl_compression_st - { - char *stuff; - } SSL_COMPRESSION; - /* Lets make this into an ASN.1 type structure as follows * SSL_SESSION_ID ::= SEQUENCE { * version INTEGER, -- structure version number @@ -202,10 +359,14 @@ typedef struct ssl_compression_st * Cipher OCTET_STRING, -- the 3 byte cipher ID * Session_ID OCTET_STRING, -- the Session ID * Master_key OCTET_STRING, -- the master key + * KRB5_principal OCTET_STRING -- optional Kerberos principal * Key_Arg [ 0 ] IMPLICIT OCTET_STRING, -- the optional Key argument * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate + * Session_ID_context [ 4 ] EXPLICIT OCTET_STRING, -- the Session ID context + * Verify_result [ 5 ] EXPLICIT INTEGER -- X509_V_... code for `Peer' + * Compression [6] IMPLICIT ASN1_OBJECT -- compression OID XXXXX * } * Look in ssl/ssl_asn1.c for more details * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). @@ -223,29 +384,43 @@ typedef struct ssl_session_st /* session_id - valid? */ unsigned int session_id_length; unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + /* this is used to determine whether the session is being reused in + * the appropriate context. It is up to the application to set this, + * via SSL_new */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + +#ifndef OPENSSL_NO_KRB5 + unsigned int krb5_client_princ_len; + unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH]; +#endif /* OPENSSL_NO_KRB5 */ int not_resumable; /* The cert is the certificate used to establish this connection */ - struct cert_st /* CERT */ *cert; + struct sess_cert_st /* SESS_CERT */ *sess_cert; - /* This is the cert for the other end. On servers, it will be - * the same as cert->x509 */ + /* This is the cert for the other end. + * On clients, it will be the same as sess_cert->peer_key->x509 + * (the latter is not enough as sess_cert is not retained + * in the external representation of sessions, see ssl_asn1.c). */ X509 *peer; + /* when app_verify_callback accepts a session where the peer's certificate + * is not ok, we must remember the error for session reuse: */ + long verify_result; /* only for servers */ int references; long timeout; long time; - SSL_COMPRESSION *read_compression; - SSL_COMPRESSION *write_compression; + int compress_meth; /* Need to lookup the method */ SSL_CIPHER *cipher; unsigned long cipher_id; /* when ASN.1 loaded, this * needs to be used to load * the 'cipher' structure */ - STACK /* SSL_CIPHER */ *ciphers; /* shared ciphers? */ + STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */ CRYPTO_EX_DATA ex_data; /* application specific data */ @@ -262,47 +437,126 @@ typedef struct ssl_session_st #define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L #define SSL_OP_TLS_D5_BUG 0x00000100L -#define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L +#define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L -/* If set, only use tmp_dh parameters once */ +/* If set, always create a new key when using tmp_dh parameters */ #define SSL_OP_SINGLE_DH_USE 0x00100000L -/* Set to also use the tmp_rsa key when doing RSA operations. */ +/* Set to always use the tmp_rsa key when doing RSA operations, + * even when this violates protocol specs */ #define SSL_OP_EPHEMERAL_RSA 0x00200000L - +/* Set on servers to choose the cipher according to the server's + * preferences */ +#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L +/* If set, a server will allow a client to issue a SSLv3.0 version number + * as latest version supported in the premaster secret, even when TLSv1.0 + * (version 3.1) was announced in the client hello. Normally this is + * forbidden to prevent version rollback attacks. */ +#define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L +/* As server, disallow session resumption on renegotiation */ +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x01000000L + +/* The next flag deliberately changes the ciphertest, this is a check + * for the PKCS#1 attack */ +#define SSL_OP_PKCS1_CHECK_1 0x08000000L +#define SSL_OP_PKCS1_CHECK_2 0x10000000L #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L -#define SSL_OP_NON_EXPORT_FIRST 0x40000000L -#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x80000000L +#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L #define SSL_OP_ALL 0x000FFFFFL -#define SSL_CTX_set_options(ctx,op) ((ctx)->options|=(op)) -#define SSL_set_options(ssl,op) ((ssl)->options|=(op)) - #define SSL_OP_NO_SSLv2 0x01000000L #define SSL_OP_NO_SSLv3 0x02000000L #define SSL_OP_NO_TLSv1 0x04000000L -/* Normally you will only use these if your application wants to use - * the certificate store in other places, perhaps PKCS7 */ -#define SSL_CTX_get_cert_store(ctx) ((ctx)->cert_store) -#define SSL_CTX_set_cert_store(ctx,cs) \ - (X509_STORE_free((ctx)->cert_store),(ctx)->cert_store=(cs)) - +/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): */ +#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L +/* Make it possible to retry SSL_write() with changed buffer location + * (buffer contents must stay the same!); this is not the default to avoid + * the misconception that non-blocking SSL_write() behaves like + * non-blocking write(): */ +#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L +/* Never bother the application with retries if the transport + * is blocking: */ +#define SSL_MODE_AUTO_RETRY 0x00000004L + +/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, + * they cannot be used to clear bits. */ + +#define SSL_CTX_set_options(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_CTX_get_options(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL) +#define SSL_set_options(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_get_options(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL) + +#define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +#define SSL_CTX_get_mode(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +#define SSL_set_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +#define SSL_get_mode(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) + + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) + + + +#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32) +#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */ +#else +#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */ +#endif #define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20) -typedef struct ssl_ctx_st +/* This callback type is used inside SSL_CTX, SSL, and in the functions that set + * them. It is used to override the generation of SSL/TLS session IDs in a + * server. Return value should be zero on an error, non-zero to proceed. Also, + * callbacks should themselves check if the id they generate is unique otherwise + * the SSL handshake will fail with an error - callbacks can do this using the + * 'ssl' value they're passed by; + * SSL_has_matching_session_id(ssl, id, *id_len) + * The length value passed in is set at the maximum size the session ID can be. + * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback + * can alter this length to be less if desired, but under SSLv2 session IDs are + * supposed to be fixed at 16 bytes so the id will be padded after the callback + * returns in this case. It is also an error for the callback to set the size to + * zero. */ +typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id, + unsigned int *id_len); + +typedef struct ssl_comp_st + { + int id; + char *name; +#ifndef OPENSSL_NO_COMP + COMP_METHOD *method; +#else + char *method; +#endif + } SSL_COMP; + +DECLARE_STACK_OF(SSL_COMP) + +struct ssl_ctx_st { SSL_METHOD *method; - unsigned long options; - STACK /* SSL_CIPHER */ *cipher_list; + STACK_OF(SSL_CIPHER) *cipher_list; /* same as above but sorted for lookup */ - STACK /* SSL_CIPHER */ *cipher_list_by_id; + STACK_OF(SSL_CIPHER) *cipher_list_by_id; struct x509_store_st /* X509_STORE */ *cert_store; - struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSION's */ + struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSIONs */ /* Most session-ids that will be cached, default is - * SSL_SESSION_CACHE_SIZE_DEFAULT. 0 is unlimited. */ + * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */ unsigned long session_cache_size; struct ssl_session_st *session_cache_head; struct ssl_session_st *session_cache_tail; @@ -325,67 +579,95 @@ typedef struct ssl_ctx_st * SSL_SESSION_free() when it has finished using it. Otherwise, * on 0, it means the callback has finished with it. * If remove_session_cb is not null, it will be called when - * a session-id is removed from the cache. Again, a return - * of 0 mens that SSLeay should not SSL_SESSION_free() since - * the application is doing something with it. */ -#ifndef NOPROTO + * a session-id is removed from the cache. After the call, + * OpenSSL will SSL_SESSION_free() it. */ int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess); void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess); SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy); -#else - int (*new_session_cb)(); - void (*remove_session_cb)(); - SSL_SESSION *(*get_session_cb)(); -#endif - int sess_connect; /* SSL new connection - started */ - int sess_connect_renegotiate;/* SSL renegotiatene - requested */ - int sess_connect_good; /* SSL new connection/renegotiate - finished */ - int sess_accept; /* SSL new accept - started */ - int sess_accept_renegotiate;/* SSL renegotiatene - requested */ - int sess_accept_good; /* SSL accept/renegotiate - finished */ - int sess_miss; /* session lookup misses */ - int sess_timeout; /* session reuse attempt on timeouted session */ - int sess_cache_full; /* session removed due to full cache */ - int sess_hit; /* session reuse actually done */ - int sess_cb_hit; /* session-id that was not in the cache was - * passed back via the callback. This - * indicates that the application is supplying - * session-id's from other processes - - * spooky :-) */ + struct + { + int sess_connect; /* SSL new conn - started */ + int sess_connect_renegotiate;/* SSL reneg - requested */ + int sess_connect_good; /* SSL new conne/reneg - finished */ + int sess_accept; /* SSL new accept - started */ + int sess_accept_renegotiate;/* SSL reneg - requested */ + int sess_accept_good; /* SSL accept/reneg - finished */ + int sess_miss; /* session lookup misses */ + int sess_timeout; /* reuse attempt on timeouted session */ + int sess_cache_full; /* session removed due to full cache */ + int sess_hit; /* session reuse actually done */ + int sess_cb_hit; /* session-id that was not + * in the cache was + * passed back via the callback. This + * indicates that the application is + * supplying session-id's from other + * processes - spooky :-) */ + } stats; int references; - void (*info_callback)(); - /* if defined, these override the X509_verify_cert() calls */ - int (*app_verify_callback)(); - char *app_verify_arg; - - /* default values to use in SSL structures */ - struct cert_st /* CERT */ *default_cert; - int default_read_ahead; - int default_verify_mode; - int (*default_verify_callback)(); + int (*app_verify_callback)(X509_STORE_CTX *, void *); + void *app_verify_arg; + /* before OpenSSL 0.9.7, 'app_verify_arg' was ignored + * ('app_verify_callback' was called with just one argument) */ /* Default password callback. */ - int (*default_passwd_callback)(); + pem_password_cb *default_passwd_callback; + + /* Default password callback user data. */ + void *default_passwd_callback_userdata; /* get client cert callback */ - int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */); + int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey); - /* what we put in client requests */ - STACK *client_CA; + CRYPTO_EX_DATA ex_data; - int quiet_shutdown; + const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */ + const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ + const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */ - CRYPTO_EX_DATA ex_data; + STACK_OF(X509) *extra_certs; + STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ + + + /* Default values used when no per-SSL value is defined follow */ + + void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */ + + /* what we put in client cert requests */ + STACK_OF(X509_NAME) *client_CA; - EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */ - EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ - EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */ - } SSL_CTX; + + /* Default values to use in SSL structures follow (these are copied by SSL_new) */ + + unsigned long options; + unsigned long mode; + long max_cert_list; + + struct cert_st /* CERT */ *cert; + int read_ahead; + + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; + + int verify_mode; + int verify_depth; + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */ + + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ + + int quiet_shutdown; + }; #define SSL_SESS_CACHE_OFF 0x0000 #define SSL_SESS_CACHE_CLIENT 0x0001 @@ -397,23 +679,31 @@ typedef struct ssl_ctx_st * defined, this will still get called. */ #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 -#define SSL_CTX_sessions(ctx) ((ctx)->sessions) -/* You will need to include lhash.h to access the following #define */ -#define SSL_CTX_sess_number(ctx) ((ctx)->sessions->num_items) -#define SSL_CTX_sess_connect(ctx) ((ctx)->sess_connect) -#define SSL_CTX_sess_connect_good(ctx) ((ctx)->sess_connect_good) -#define SSL_CTX_sess_accept(ctx) ((ctx)->sess_accept) -#define SSL_CTX_sess_accept_renegotiate(ctx) ((ctx)->sess_accept_renegotiate) -#define SSL_CTX_sess_connect_renegotiate(ctx) ((ctx)->sess_connect_renegotiate) -#define SSL_CTX_sess_accept_good(ctx) ((ctx)->sess_accept_good) -#define SSL_CTX_sess_hits(ctx) ((ctx)->sess_hit) -#define SSL_CTX_sess_cb_hits(ctx) ((ctx)->sess_cb_hit) -#define SSL_CTX_sess_misses(ctx) ((ctx)->sess_miss) -#define SSL_CTX_sess_timeouts(ctx) ((ctx)->sess_timeout) -#define SSL_CTX_sess_cache_full(ctx) ((ctx)->sess_cache_full) - -#define SSL_CTX_sess_set_cache_size(ctx,t) ((ctx)->session_cache_size=(t)) -#define SSL_CTX_sess_get_cache_size(ctx) ((ctx)->session_cache_size) + struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx); +#define SSL_CTX_sess_number(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +#define SSL_CTX_sess_connect(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +#define SSL_CTX_sess_connect_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +#define SSL_CTX_sess_connect_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +#define SSL_CTX_sess_accept_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +#define SSL_CTX_sess_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +#define SSL_CTX_sess_cb_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +#define SSL_CTX_sess_misses(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +#define SSL_CTX_sess_timeouts(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +#define SSL_CTX_sess_cache_full(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) #define SSL_CTX_sess_set_new_cb(ctx,cb) ((ctx)->new_session_cb=(cb)) #define SSL_CTX_sess_get_new_cb(ctx) ((ctx)->new_session_cb) @@ -421,15 +711,8 @@ typedef struct ssl_ctx_st #define SSL_CTX_sess_get_remove_cb(ctx) ((ctx)->remove_session_cb) #define SSL_CTX_sess_set_get_cb(ctx,cb) ((ctx)->get_session_cb=(cb)) #define SSL_CTX_sess_get_get_cb(ctx) ((ctx)->get_session_cb) -#define SSL_CTX_set_session_cache_mode(ctx,m) ((ctx)->session_cache_mode=(m)) -#define SSL_CTX_get_session_cache_mode(ctx) ((ctx)->session_cache_mode) -#define SSL_CTX_set_timeout(ctx,t) ((ctx)->session_timeout=(t)) -#define SSL_CTX_get_timeout(ctx) ((ctx)->session_timeout) - #define SSL_CTX_set_info_callback(ctx,cb) ((ctx)->info_callback=(cb)) #define SSL_CTX_get_info_callback(ctx) ((ctx)->info_callback) -#define SSL_CTX_set_default_read_ahead(ctx,m) (((ctx)->default_read_ahead)=(m)) - #define SSL_CTX_set_client_cert_cb(ctx,cb) ((ctx)->client_cert_cb=(cb)) #define SSL_CTX_get_client_cert_cb(ctx) ((ctx)->client_cert_cb) @@ -439,18 +722,16 @@ typedef struct ssl_ctx_st #define SSL_X509_LOOKUP 4 /* These will only be used when doing non-blocking IO */ -#define SSL_want(s) ((s)->rwstate) -#define SSL_want_nothing(s) ((s)->rwstate == SSL_NOTHING) -#define SSL_want_read(s) ((s)->rwstate == SSL_READING) -#define SSL_want_write(s) ((s)->rwstate == SSL_WRITING) -#define SSL_want_x509_lookup(s) ((s)->rwstate == SSL_X509_LOOKUP) +#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING) +#define SSL_want_read(s) (SSL_want(s) == SSL_READING) +#define SSL_want_write(s) (SSL_want(s) == SSL_WRITING) +#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP) -typedef struct ssl_st +struct ssl_st { - /* procol version - * 2 for SSLv2 - * 3 for SSLv3 - * -3 for SSLv3 but accept SSLv2 */ + /* protocol version + * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION) + */ int version; int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */ @@ -460,10 +741,10 @@ typedef struct ssl_st * same. This is so data can be read and written to different * handlers */ -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO BIO *rbio; /* used by SSL_read */ BIO *wbio; /* used by SSL_write */ - BIO *bbio; /* used during session-id reuse to concatinate + BIO *bbio; /* used during session-id reuse to concatenate * messages */ #else char *rbio; /* used by SSL_read */ @@ -480,9 +761,22 @@ typedef struct ssl_st int in_handshake; int (*handshake_func)(); -/* int server;*/ /* are we the server side? */ - - int new_session;/* 1 if we are to use a new session */ + /* Imagine that here's a boolean member "init" that is + * switched as soon as SSL_set_{accept/connect}_state + * is called for the first time, so that "state" and + * "handshake_func" are properly initialized. But as + * handshake_func is == 0 until then, we use this + * test instead of an "init" member. + */ + + int server; /* are we the server side? - mostly used by SSL_clear*/ + + int new_session;/* 1 if we are to use a new session. + * 2 if we are a server and are inside a handshake + * (i.e. not just sending a HelloRequest) + * NB: For servers, the 'new' session may actually be a previously + * cached session or even the previous session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ int quiet_shutdown;/* don't send shutdown packets */ int shutdown; /* we have shut things down, 0x01 sent, 0x02 * for received */ @@ -490,6 +784,7 @@ typedef struct ssl_st int rstate; /* where we are when reading */ BUF_MEM *init_buf; /* buffer used during init */ + void *init_msg; /* pointer to handshake message body, set by ssl3_get_message() */ int init_num; /* amount read/written */ int init_off; /* amount read/written */ @@ -497,26 +792,43 @@ typedef struct ssl_st unsigned char *packet; unsigned int packet_length; - struct ssl2_ctx_st *s2; /* SSLv2 variables */ - struct ssl3_ctx_st *s3; /* SSLv3 variables */ + struct ssl2_state_st *s2; /* SSLv2 variables */ + struct ssl3_state_st *s3; /* SSLv3 variables */ + + int read_ahead; /* Read as many input bytes as possible + * (for non-blocking reads) */ + + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; - int read_ahead; /* Read as many input bytes as possible */ int hit; /* reusing a previous session */ + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ + /* crypto */ - STACK /* SSL_CIPHER */ *cipher_list; - STACK /* SSL_CIPHER */ *cipher_list_by_id; + STACK_OF(SSL_CIPHER) *cipher_list; + STACK_OF(SSL_CIPHER) *cipher_list_by_id; - /* These are the ones being used, the ones is SSL_SESSION are + /* These are the ones being used, the ones in SSL_SESSION are * the ones to be 'copied' into these ones */ EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ - EVP_MD *read_hash; /* used for mac generation */ - SSL_COMPRESSION *read_compression; /* compression */ + const EVP_MD *read_hash; /* used for mac generation */ +#ifndef OPENSSL_NO_COMP + COMP_CTX *expand; /* uncompress */ +#else + char *expand; +#endif EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ - EVP_MD *write_hash; /* used for mac generation */ - SSL_COMPRESSION *write_compression; /* compression */ + const EVP_MD *write_hash; /* used for mac generation */ +#ifndef OPENSSL_NO_COMP + COMP_CTX *compress; /* compression */ +#else + char *compress; +#endif /* session info */ @@ -524,18 +836,32 @@ typedef struct ssl_st /* This is used to hold the server certificate used */ struct cert_st /* CERT */ *cert; + /* the session_id_context is used to ensure sessions are only reused + * in the appropriate context */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + /* This can also be in the session once a session is established */ SSL_SESSION *session; + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + /* Used in SSL2 and SSL3 */ int verify_mode; /* 0 don't care about verify failure. * 1 fail if verify fails */ - int (*verify_callback)(); /* fail if callback returns 0 */ - void (*info_callback)(); /* optional informational callback */ + int verify_depth; + int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */ + + void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */ int error; /* error bytes to be written */ int error_code; /* actual code */ +#ifndef OPENSSL_NO_KRB5 + KSSL_CTX *kssl_ctx; /* Kerberos 5 context */ +#endif /* OPENSSL_NO_KRB5 */ + SSL_CTX *ctx; /* set this flag to 1 and a sleep(1) is put into all SSL_read() * and SSL_write() calls, good for nbio debuging :-) */ @@ -546,19 +872,31 @@ typedef struct ssl_st CRYPTO_EX_DATA ex_data; /* for server side, keep the list of CA_dn we can use */ - STACK /* X509_NAME */ *client_CA; + STACK_OF(X509_NAME) *client_CA; int references; - unsigned long options; + unsigned long options; /* protocol behaviour */ + unsigned long mode; /* API behaviour */ + long max_cert_list; int first_packet; - } SSL; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ + }; -#include "ssl2.h" -#include "ssl3.h" -#include "tls1.h" /* This is mostly sslv3 with a few tweaks */ -#include "ssl23.h" +#ifdef __cplusplus +} +#endif -/* compatablity */ +#include +#include +#include /* This is mostly sslv3 with a few tweaks */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* compatibility */ #define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg)) #define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) #define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0,(char *)a)) @@ -567,7 +905,7 @@ typedef struct ssl_st #define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg)) /* The following are the possible values for ssl->state are are - * used to indicate where we are upto in the SSL connection establishment. + * used to indicate where we are up to in the SSL connection establishment. * The macros that follow are about the only things you should need to use * and even then, only when using non-blocking IO. * It can also be useful to work out where you were when the connection @@ -609,6 +947,13 @@ typedef struct ssl_st #define SSL_ST_READ_BODY 0xF1 #define SSL_ST_READ_DONE 0xF2 +/* Obtain latest Finished message + * -- that we sent (SSL_get_finished) + * -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. */ +size_t SSL_get_finished(SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(SSL *s, void *buf, size_t count); + /* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options * are 'ored' with SSL_VERIFY_PEER if they are desired */ #define SSL_VERIFY_NONE 0x00 @@ -616,7 +961,10 @@ typedef struct ssl_st #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 #define SSL_VERIFY_CLIENT_ONCE 0x04 -/* this is for backward compatablility */ +#define OpenSSL_add_ssl_algorithms() SSL_library_init() +#define SSLeay_add_ssl_algorithms() SSL_library_init() + +/* this is for backward compatibility */ #if 0 /* NEW_SSLEAY */ #define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c) #define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n) @@ -624,7 +972,7 @@ typedef struct ssl_st #define SSL_remove_session(a,b) SSL_CTX_remove_session((a),(b)) #define SSL_flush_sessions(a,b) SSL_CTX_flush_sessions((a),(b)) #endif -/* More backward compatablity */ +/* More backward compatibility */ #define SSL_get_cipher(s) \ SSL_CIPHER_get_name(SSL_get_current_cipher(s)) #define SSL_get_cipher_bits(s,np) \ @@ -638,28 +986,25 @@ typedef struct ssl_st #define SSL_get_timeout(a) SSL_SESSION_get_timeout(a) #define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b)) -/* VMS linker has a 31 char name limit */ -#define SSL_CTX_set_cert_verify_callback(a,b,c) \ - SSL_CTX_set_cert_verify_cb((a),(b),(c)) - #if 1 /*SSLEAY_MACROS*/ #define d2i_SSL_SESSION_bio(bp,s_id) (SSL_SESSION *)ASN1_d2i_bio( \ (char *(*)())SSL_SESSION_new,(char *(*)())d2i_SSL_SESSION, \ (bp),(unsigned char **)(s_id)) #define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio(i2d_SSL_SESSION, \ bp,(unsigned char *)s_id) -#define PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \ - (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb) -#define PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \ - (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb) +#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u) +#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb,u) #define PEM_write_SSL_SESSION(fp,x) \ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \ - PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL) + PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL) #define PEM_write_bio_SSL_SESSION(bp,x) \ PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \ - PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL) + PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL,NULL) #endif +#define SSL_AD_REASON_OFFSET 1000 /* These alert types are for SSLv3 and TLSv1 */ #define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY #define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE /* fatal */ @@ -679,11 +1024,11 @@ typedef struct ssl_st #define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED /* fatal */ #define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR /* fatal */ #define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR -#define SSL_AD_EXPORT_RESTRICION TLS1_AD_EXPORT_RESTRICION/* fatal */ +#define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION/* fatal */ #define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION /* fatal */ #define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY/* fatal */ #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */ -#define SSL_AD_USER_CANCLED TLS1_AD_USER_CANCLED +#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION #define SSL_ERROR_NONE 0 @@ -691,21 +1036,53 @@ typedef struct ssl_st #define SSL_ERROR_WANT_READ 2 #define SSL_ERROR_WANT_WRITE 3 #define SSL_ERROR_WANT_X509_LOOKUP 4 -#define SSL_ERROR_SYSCALL 5 /* look at errno */ +#define SSL_ERROR_SYSCALL 5 /* look at error stack/return value/errno */ #define SSL_ERROR_ZERO_RETURN 6 #define SSL_ERROR_WANT_CONNECT 7 +#define SSL_ERROR_WANT_ACCEPT 8 #define SSL_CTRL_NEED_TMP_RSA 1 #define SSL_CTRL_SET_TMP_RSA 2 #define SSL_CTRL_SET_TMP_DH 3 #define SSL_CTRL_SET_TMP_RSA_CB 4 #define SSL_CTRL_SET_TMP_DH_CB 5 -/* Add these ones */ + #define SSL_CTRL_GET_SESSION_REUSED 6 #define SSL_CTRL_GET_CLIENT_CERT_REQUEST 7 #define SSL_CTRL_GET_NUM_RENEGOTIATIONS 8 #define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 9 #define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 10 +#define SSL_CTRL_GET_FLAGS 11 +#define SSL_CTRL_EXTRA_CHAIN_CERT 12 + +#define SSL_CTRL_SET_MSG_CALLBACK 13 +#define SSL_CTRL_SET_MSG_CALLBACK_ARG 14 + +/* Stats */ +#define SSL_CTRL_SESS_NUMBER 20 +#define SSL_CTRL_SESS_CONNECT 21 +#define SSL_CTRL_SESS_CONNECT_GOOD 22 +#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 +#define SSL_CTRL_SESS_ACCEPT 24 +#define SSL_CTRL_SESS_ACCEPT_GOOD 25 +#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 +#define SSL_CTRL_SESS_HIT 27 +#define SSL_CTRL_SESS_CB_HIT 28 +#define SSL_CTRL_SESS_MISSES 29 +#define SSL_CTRL_SESS_TIMEOUTS 30 +#define SSL_CTRL_SESS_CACHE_FULL 31 +#define SSL_CTRL_OPTIONS 32 +#define SSL_CTRL_MODE 33 + +#define SSL_CTRL_GET_READ_AHEAD 40 +#define SSL_CTRL_SET_READ_AHEAD 41 +#define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +#define SSL_CTRL_GET_SESS_CACHE_SIZE 43 +#define SSL_CTRL_SET_SESS_CACHE_MODE 44 +#define SSL_CTRL_GET_SESS_CACHE_MODE 45 + +#define SSL_CTRL_GET_MAX_CERT_LIST 50 +#define SSL_CTRL_SET_MAX_CERT_LIST 51 #define SSL_session_reused(ssl) \ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) @@ -723,18 +1100,17 @@ typedef struct ssl_st #define SSL_CTX_set_tmp_dh(ctx,dh) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh) -/* For the next 2, the callbacks are - * RSA *tmp_rsa_cb(int export) - * DH *tmp_dh_cb(int export) - */ -#define SSL_CTX_set_tmp_rsa_callback(ctx,cb) \ - SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb) -#define SSL_CTX_set_tmp_dh_callback(ctx,dh) \ - SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh) +#define SSL_need_tmp_RSA(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL) +#define SSL_set_tmp_rsa(ssl,rsa) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +#define SSL_set_tmp_dh(ssl,dh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh) -#ifndef NOPROTO +#define SSL_CTX_add_extra_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO BIO_METHOD *BIO_f_ssl(void); BIO *BIO_new_ssl(SSL_CTX *ctx,int client); BIO *BIO_new_ssl_connect(SSL_CTX *ctx); @@ -744,60 +1120,84 @@ void BIO_ssl_shutdown(BIO *ssl_bio); #endif -int SSL_CTX_set_cipher_list(SSL_CTX *,char *str); +int SSL_CTX_set_cipher_list(SSL_CTX *,const char *str); SSL_CTX *SSL_CTX_new(SSL_METHOD *meth); void SSL_CTX_free(SSL_CTX *); -void SSL_clear(SSL *s); +long SSL_CTX_set_timeout(SSL_CTX *ctx,long t); +long SSL_CTX_get_timeout(SSL_CTX *ctx); +X509_STORE *SSL_CTX_get_cert_store(SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *); +int SSL_want(SSL *s); +int SSL_clear(SSL *s); + void SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm); SSL_CIPHER *SSL_get_current_cipher(SSL *s); int SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits); char * SSL_CIPHER_get_version(SSL_CIPHER *c); -char * SSL_CIPHER_get_name(SSL_CIPHER *c); +const char * SSL_CIPHER_get_name(SSL_CIPHER *c); int SSL_get_fd(SSL *s); -char * SSL_get_cipher_list(SSL *s,int n); +int SSL_get_rfd(SSL *s); +int SSL_get_wfd(SSL *s); +const char * SSL_get_cipher_list(SSL *s,int n); char * SSL_get_shared_ciphers(SSL *s, char *buf, int len); int SSL_get_read_ahead(SSL * s); int SSL_pending(SSL *s); -#ifndef NO_SOCK +#ifndef OPENSSL_NO_SOCK int SSL_set_fd(SSL *s, int fd); int SSL_set_rfd(SSL *s, int fd); int SSL_set_wfd(SSL *s, int fd); #endif -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO void SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio); BIO * SSL_get_rbio(SSL *s); BIO * SSL_get_wbio(SSL *s); #endif -int SSL_set_cipher_list(SSL *s, char *str); +int SSL_set_cipher_list(SSL *s, const char *str); void SSL_set_read_ahead(SSL *s, int yes); int SSL_get_verify_mode(SSL *s); -int (*SSL_get_verify_callback(SSL *s))(); -void SSL_set_verify(SSL *s, int mode, int (*callback) ()); +int SSL_get_verify_depth(SSL *s); +int (*SSL_get_verify_callback(SSL *s))(int,X509_STORE_CTX *); +void SSL_set_verify(SSL *s, int mode, + int (*callback)(int ok,X509_STORE_CTX *ctx)); +void SSL_set_verify_depth(SSL *s, int depth); +#ifndef OPENSSL_NO_RSA int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +#endif int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, unsigned char *d, long len); int SSL_use_certificate(SSL *ssl, X509 *x); -int SSL_use_certificate_ASN1(SSL *ssl, int len, unsigned char *d); - -#ifndef NO_STDIO -int SSL_use_RSAPrivateKey_file(SSL *ssl, char *file, int type); -int SSL_use_PrivateKey_file(SSL *ssl, char *file, int type); -int SSL_use_certificate_file(SSL *ssl, char *file, int type); -int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type); -int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type); -int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type); -STACK * SSL_load_client_CA_file(char *file); +int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len); + +#ifndef OPENSSL_NO_STDIO +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_certificate_file(SSL *ssl, const char *file, int type); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *file); +#ifndef OPENSSL_SYS_WIN32 +#ifndef OPENSSL_SYS_VMS +#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */ +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *dir); +#endif +#endif +#endif + #endif -void ERR_load_SSL_strings(void ); void SSL_load_error_strings(void ); -char * SSL_state_string(SSL *s); -char * SSL_rstate_string(SSL *s); -char * SSL_state_string_long(SSL *s); -char * SSL_rstate_string_long(SSL *s); +const char *SSL_state_string(const SSL *s); +const char *SSL_rstate_string(const SSL *s); +const char *SSL_state_string_long(const SSL *s); +const char *SSL_rstate_string_long(const SSL *s); long SSL_SESSION_get_time(SSL_SESSION *s); long SSL_SESSION_set_time(SSL_SESSION *s, long t); long SSL_SESSION_get_timeout(SSL_SESSION *s); @@ -807,10 +1207,10 @@ void SSL_copy_session_id(SSL *to,SSL *from); SSL_SESSION *SSL_SESSION_new(void); unsigned long SSL_SESSION_hash(SSL_SESSION *a); int SSL_SESSION_cmp(SSL_SESSION *a,SSL_SESSION *b); -#ifndef NO_FP_API +#ifndef OPENSSL_NO_FP_API int SSL_SESSION_print_fp(FILE *fp,SSL_SESSION *ses); #endif -#ifdef HEADER_BIO_H +#ifndef OPENSSL_NO_BIO int SSL_SESSION_print(BIO *fp,SSL_SESSION *ses); #endif void SSL_SESSION_free(SSL_SESSION *ses); @@ -818,19 +1218,28 @@ int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp); int SSL_set_session(SSL *to, SSL_SESSION *session); int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c); int SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c); +int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB); +int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB); +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len); SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,unsigned char **pp,long length); #ifdef HEADER_X509_H X509 * SSL_get_peer_certificate(SSL *s); #endif -STACK * SSL_get_peer_cert_chain(SSL *s); +STACK_OF(X509) *SSL_get_peer_cert_chain(SSL *s); int SSL_CTX_get_verify_mode(SSL_CTX *ctx); -int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))(); -void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*callback)()); -void SSL_CTX_set_cert_verify_cb(SSL_CTX *ctx, int (*cb)(),char *arg); +int SSL_CTX_get_verify_depth(SSL_CTX *ctx); +int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))(int,X509_STORE_CTX *); +void SSL_CTX_set_verify(SSL_CTX *ctx,int mode, + int (*callback)(int, X509_STORE_CTX *)); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg); +#ifndef OPENSSL_NO_RSA int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +#endif int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len); int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx, @@ -838,24 +1247,37 @@ int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx, int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d); -void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,int (*cb)()); +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); int SSL_CTX_check_private_key(SSL_CTX *ctx); int SSL_check_private_key(SSL *ctx); +int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + SSL * SSL_new(SSL_CTX *ctx); -void SSL_clear(SSL *s); +int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose); +int SSL_set_purpose(SSL *s, int purpose); +int SSL_CTX_set_trust(SSL_CTX *s, int trust); +int SSL_set_trust(SSL *s, int trust); + void SSL_free(SSL *ssl); int SSL_accept(SSL *ssl); int SSL_connect(SSL *ssl); -int SSL_read(SSL *ssl,char *buf,int num); -int SSL_peek(SSL *ssl,char *buf,int num); -int SSL_write(SSL *ssl,char *buf,int num); -long SSL_ctrl(SSL *ssl,int cmd, long larg, char *parg); -long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, char *parg); +int SSL_read(SSL *ssl,void *buf,int num); +int SSL_peek(SSL *ssl,void *buf,int num); +int SSL_write(SSL *ssl,const void *buf,int num); +long SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg); +long SSL_callback_ctrl(SSL *, int, void (*)()); +long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg); +long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)()); int SSL_get_error(SSL *s,int ret_code); -char * SSL_get_version(SSL *s); +const char *SSL_get_version(SSL *s); /* This sets the 'default' SSL version that SSL_new() will create */ int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth); @@ -876,23 +1298,24 @@ SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */ SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */ SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */ -STACK *SSL_get_ciphers(SSL *s); +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(SSL *s); int SSL_do_handshake(SSL *s); int SSL_renegotiate(SSL *s); +int SSL_renegotiate_pending(SSL *s); int SSL_shutdown(SSL *s); SSL_METHOD *SSL_get_ssl_method(SSL *s); int SSL_set_ssl_method(SSL *s,SSL_METHOD *method); -char *SSL_alert_type_string_long(int value); -char *SSL_alert_type_string(int value); -char *SSL_alert_desc_string_long(int value); -char *SSL_alert_desc_string(int value); - -void SSL_set_client_CA_list(SSL *s, STACK *list); -void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK *list); -STACK *SSL_get_client_CA_list(SSL *s); -STACK *SSL_CTX_get_client_CA_list(SSL_CTX *s); +const char *SSL_alert_type_string_long(int value); +const char *SSL_alert_type_string(int value); +const char *SSL_alert_desc_string_long(int value); +const char *SSL_alert_desc_string(int value); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *list); +STACK_OF(X509_NAME) *SSL_get_client_CA_list(SSL *s); +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(SSL_CTX *s); int SSL_add_client_CA(SSL *ssl,X509 *x); int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x); @@ -901,10 +1324,10 @@ void SSL_set_accept_state(SSL *s); long SSL_get_default_timeout(SSL *s); -void SSLeay_add_ssl_algorithms(void ); +int SSL_library_init(void ); char *SSL_CIPHER_description(SSL_CIPHER *,char *buf,int size); -STACK *SSL_dup_CA_list(STACK *sk); +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk); SSL *SSL_dup(SSL *ssl); @@ -919,242 +1342,92 @@ void SSL_set_shutdown(SSL *ssl,int mode); int SSL_get_shutdown(SSL *ssl); int SSL_version(SSL *ssl); int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); -int SSL_CTX_load_verify_locations(SSL_CTX *ctx,char *CAfile,char *CApath); +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +#define SSL_get0_session SSL_get_session /* just peek at pointer */ SSL_SESSION *SSL_get_session(SSL *ssl); +SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ SSL_CTX *SSL_get_SSL_CTX(SSL *ssl); -void SSL_set_info_callback(SSL *ssl,void (*cb)()); -void (*SSL_get_info_callback(SSL *ssl))(); +void SSL_set_info_callback(SSL *ssl, + void (*cb)(const SSL *ssl,int type,int val)); +void (*SSL_get_info_callback(SSL *ssl))(const SSL *ssl,int type,int val); int SSL_state(SSL *ssl); void SSL_set_verify_result(SSL *ssl,long v); long SSL_get_verify_result(SSL *ssl); -int SSL_set_ex_data(SSL *ssl,int idx,char *data); -char *SSL_get_ex_data(SSL *ssl,int idx); -int SSL_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); - -int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,char *data); -char *SSL_SESSION_get_ex_data(SSL_SESSION *ss,int idx); -int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); - -int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,char *data); -char *SSL_CTX_get_ex_data(SSL_CTX *ssl,int idx); -int SSL_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(), - int (*dup_func)(), void (*free_func)()); - -#else - -BIO_METHOD *BIO_f_ssl(); -BIO *BIO_new_ssl(); -BIO *BIO_new_ssl_connect(); -BIO *BIO_new_buffer_ssl_connect(); -int BIO_ssl_copy_session_id(); -void BIO_ssl_shutdown(); - -int SSL_CTX_set_cipher_list(); -SSL_CTX *SSL_CTX_new(); -void SSL_CTX_free(); -void SSL_clear(); -void SSL_CTX_flush_sessions(); - -SSL_CIPHER *SSL_get_current_cipher(); -int SSL_CIPHER_get_bits(); -char * SSL_CIPHER_get_version(); -char * SSL_CIPHER_get_name(); - -int SSL_get_fd(); -char * SSL_get_cipher_list(); -char * SSL_get_shared_ciphers(); -int SSL_get_read_ahead(); -int SSL_pending(); -#ifndef NO_SOCK -int SSL_set_fd(); -int SSL_set_rfd(); -int SSL_set_wfd(); -#endif -#ifdef HEADER_BIO_H -void SSL_set_bio(); -BIO * SSL_get_rbio(); -BIO * SSL_get_wbio(); -#endif -int SSL_set_cipher_list(); -void SSL_set_read_ahead(); -int SSL_get_verify_mode(); - -void SSL_set_verify(); -int SSL_use_RSAPrivateKey(); -int SSL_use_RSAPrivateKey_ASN1(); -int SSL_use_PrivateKey(); -int SSL_use_PrivateKey_ASN1(); -int SSL_use_certificate(); -int SSL_use_certificate_ASN1(); - -#ifndef NO_STDIO -int SSL_use_RSAPrivateKey_file(); -int SSL_use_PrivateKey_file(); -int SSL_use_certificate_file(); -int SSL_CTX_use_RSAPrivateKey_file(); -int SSL_CTX_use_PrivateKey_file(); -int SSL_CTX_use_certificate_file(); -STACK * SSL_load_client_CA_file(); -#endif - -void ERR_load_SSL_strings(); -void SSL_load_error_strings(); -char * SSL_state_string(); -char * SSL_rstate_string(); -char * SSL_state_string_long(); -char * SSL_rstate_string_long(); -long SSL_SESSION_get_time(); -long SSL_SESSION_set_time(); -long SSL_SESSION_get_timeout(); -long SSL_SESSION_set_timeout(); -void SSL_copy_session_id(); - -SSL_SESSION *SSL_SESSION_new(); -unsigned long SSL_SESSION_hash(); -int SSL_SESSION_cmp(); -#ifndef NO_FP_API -int SSL_SESSION_print_fp(); -#endif -#ifdef HEADER_BIO_H -int SSL_SESSION_print(); -#endif -void SSL_SESSION_free(); -int i2d_SSL_SESSION(); -int SSL_set_session(); -int SSL_CTX_add_session(); -int SSL_CTX_remove_session(); -SSL_SESSION *d2i_SSL_SESSION(); - -#ifdef HEADER_X509_H -X509 * SSL_get_peer_certificate(); +int SSL_set_ex_data(SSL *ssl,int idx,void *data); +void *SSL_get_ex_data(SSL *ssl,int idx); +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data); +void *SSL_SESSION_get_ex_data(SSL_SESSION *ss,int idx); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data); +void *SSL_CTX_get_ex_data(SSL_CTX *ssl,int idx); +int SSL_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 SSL_get_ex_data_X509_STORE_CTX_idx(void ); + +#define SSL_CTX_sess_set_cache_size(ctx,t) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +#define SSL_CTX_sess_get_cache_size(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +#define SSL_CTX_set_session_cache_mode(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +#define SSL_CTX_get_session_cache_mode(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +#define SSL_CTX_get_read_ahead(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +#define SSL_CTX_set_read_ahead(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +#define SSL_CTX_get_max_cert_list(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_CTX_set_max_cert_list(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +#define SSL_get_max_cert_list(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_set_max_cert_list(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + + /* NB: the keylength is only applicable when is_export is true */ +#ifndef OPENSSL_NO_RSA +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*cb)(SSL *ssl,int is_export, + int keylength)); + +void SSL_set_tmp_rsa_callback(SSL *ssl, + RSA *(*cb)(SSL *ssl,int is_export, + int keylength)); #endif - -STACK * SSL_get_peer_cert_chain(); - -int SSL_CTX_get_verify_mode(); -int (*SSL_CTX_get_verify_callback())(); -void SSL_CTX_set_verify(); -void SSL_CTX_set_cert_verify_cb(); -int SSL_CTX_use_RSAPrivateKey(); -int SSL_CTX_use_RSAPrivateKey_ASN1(); -int SSL_CTX_use_PrivateKey(); -int SSL_CTX_use_PrivateKey_ASN1(); -int SSL_CTX_use_certificate(); -int SSL_CTX_use_certificate_ASN1(); - -void SSL_CTX_set_default_passwd_cb(); - -int SSL_CTX_check_private_key(); -int SSL_check_private_key(); - -SSL * SSL_new(); -void SSL_clear(); -void SSL_free(); -int SSL_accept(); -int SSL_connect(); -int SSL_read(); -int SSL_peek(); -int SSL_write(); -long SSL_ctrl(); -long SSL_CTX_ctrl(); - -int SSL_get_error(); -char * SSL_get_version(); - -int SSL_CTX_set_ssl_version(); - -SSL_METHOD *SSLv2_method(); -SSL_METHOD *SSLv2_server_method(); -SSL_METHOD *SSLv2_client_method(); - -SSL_METHOD *SSLv3_method(); -SSL_METHOD *SSLv3_server_method(); -SSL_METHOD *SSLv3_client_method(); - -SSL_METHOD *SSLv23_method(); -SSL_METHOD *SSLv23_server_method(); -SSL_METHOD *SSLv23_client_method(); - -SSL_METHOD *TLSv1_method(); -SSL_METHOD *TLSv1_server_method(); -SSL_METHOD *TLSv1_client_method(); - -STACK *SSL_get_ciphers(); - -int SSL_do_handshake(); -int SSL_renegotiate(); -int SSL_shutdown(); - -SSL_METHOD *SSL_get_ssl_method(); -int SSL_set_ssl_method(); -char *SSL_alert_type_string_long(); -char *SSL_alert_type_string(); -char *SSL_alert_desc_string_long(); -char *SSL_alert_desc_string(); - -void SSL_set_client_CA_list(); -void SSL_CTX_set_client_CA_list(); -STACK *SSL_get_client_CA_list(); -STACK *SSL_CTX_get_client_CA_list(); -int SSL_add_client_CA(); -int SSL_CTX_add_client_CA(); - -void SSL_set_connect_state(); -void SSL_set_accept_state(); - -long SSL_get_default_timeout(); - -void SSLeay_add_ssl_algorithms(); - -char *SSL_CIPHER_description(); -STACK *SSL_dup_CA_list(); - -SSL *SSL_dup(); - -X509 *SSL_get_certificate(); -/* EVP * */ struct evp_pkey_st *SSL_get_privatekey(); - -#ifdef this_is_for_mk1mf_pl -EVP *SSL_get_privatekey(); - -void SSL_CTX_set_quiet_shutdown(); -int SSL_CTX_get_quiet_shutdown(); -void SSL_set_quiet_shutdown(); -int SSL_get_quiet_shutdown(); -void SSL_set_shutdown(); -int SSL_get_shutdown(); -int SSL_version(); -int SSL_CTX_set_default_verify_paths(); -int SSL_CTX_load_verify_locations(); -SSL_SESSION *SSL_get_session(); -SSL_CTX *SSL_get_SSL_CTX(); -void SSL_set_info_callback(); -int (*SSL_get_info_callback())(); -int SSL_state(); -void SSL_set_verify_result(); -long SSL_get_verify_result(); - -int SSL_set_ex_data(); -char *SSL_get_ex_data(); -int SSL_get_ex_new_index(); - -int SSL_SESSION_set_ex_data(); -char *SSL_SESSION_get_ex_data(); -int SSL_SESSION_get_ex_new_index(); - -int SSL_CTX_set_ex_data(); -char *SSL_CTX_get_ex_data(); -int SSL_CTX_get_ex_new_index(); - +#ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh)(SSL *ssl,int is_export, + int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*dh)(SSL *ssl,int is_export, + int keylength)); #endif +#ifndef OPENSSL_NO_COMP +int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm); +#else +int SSL_COMP_add_compression_method(int id,char *cm); #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. + */ +void ERR_load_SSL_strings(void); + /* Error codes for the SSL functions. */ /* Function codes. */ @@ -1178,21 +1451,27 @@ int SSL_CTX_get_ex_new_index(); #define SSL_F_SSL23_CONNECT 117 #define SSL_F_SSL23_GET_CLIENT_HELLO 118 #define SSL_F_SSL23_GET_SERVER_HELLO 119 +#define SSL_F_SSL23_PEEK 237 #define SSL_F_SSL23_READ 120 #define SSL_F_SSL23_WRITE 121 #define SSL_F_SSL2_ACCEPT 122 #define SSL_F_SSL2_CONNECT 123 #define SSL_F_SSL2_ENC_INIT 124 +#define SSL_F_SSL2_PEEK 234 #define SSL_F_SSL2_READ 125 +#define SSL_F_SSL2_READ_INTERNAL 236 #define SSL_F_SSL2_SET_CERTIFICATE 126 #define SSL_F_SSL2_WRITE 127 #define SSL_F_SSL3_ACCEPT 128 +#define SSL_F_SSL3_CALLBACK_CTRL 233 #define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 #define SSL_F_SSL3_CLIENT_HELLO 131 #define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTRL 213 #define SSL_F_SSL3_CTX_CTRL 133 #define SSL_F_SSL3_ENC 134 +#define SSL_F_SSL3_GENERATE_KEY_BLOCK 238 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 #define SSL_F_SSL3_GET_CERT_VERIFY 136 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137 @@ -1206,6 +1485,7 @@ int SSL_CTX_get_ex_new_index(); #define SSL_F_SSL3_GET_SERVER_DONE 145 #define SSL_F_SSL3_GET_SERVER_HELLO 146 #define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +#define SSL_F_SSL3_PEEK 235 #define SSL_F_SSL3_READ_BYTES 148 #define SSL_F_SSL3_READ_N 149 #define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150 @@ -1218,63 +1498,85 @@ int SSL_CTX_get_ex_new_index(); #define SSL_F_SSL3_SETUP_KEY_BLOCK 157 #define SSL_F_SSL3_WRITE_BYTES 158 #define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 +#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 #define SSL_F_SSL_BAD_METHOD 160 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_DUP 221 +#define SSL_F_SSL_CERT_INST 222 +#define SSL_F_SSL_CERT_INSTANTIATE 214 #define SSL_F_SSL_CERT_NEW 162 #define SSL_F_SSL_CHECK_PRIVATE_KEY 163 -#define SSL_F_SSL_CREATE_CIPHER_LIST 164 -#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 165 -#define SSL_F_SSL_CTX_NEW 166 -#define SSL_F_SSL_CTX_SET_SSL_VERSION 167 -#define SSL_F_SSL_CTX_USE_CERTIFICATE 168 -#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 169 -#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 170 -#define SSL_F_SSL_CTX_USE_PRIVATEKEY 171 -#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 172 -#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 173 -#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 174 -#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 175 -#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 176 -#define SSL_F_SSL_DO_HANDSHAKE 177 -#define SSL_F_SSL_GET_NEW_SESSION 178 -#define SSL_F_SSL_GET_SERVER_SEND_CERT 179 -#define SSL_F_SSL_GET_SIGN_PKEY 180 -#define SSL_F_SSL_INIT_WBIO_BUFFER 181 -#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 182 -#define SSL_F_SSL_NEW 183 -#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 184 -#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 185 -#define SSL_F_SSL_SESSION_NEW 186 -#define SSL_F_SSL_SESSION_PRINT_FP 187 -#define SSL_F_SSL_SET_CERT 188 -#define SSL_F_SSL_SET_FD 189 -#define SSL_F_SSL_SET_PKEY 190 -#define SSL_F_SSL_SET_RFD 191 -#define SSL_F_SSL_SET_SESSION 192 -#define SSL_F_SSL_SET_WFD 193 -#define SSL_F_SSL_UNDEFINED_FUNCTION 194 -#define SSL_F_SSL_USE_CERTIFICATE 195 -#define SSL_F_SSL_USE_CERTIFICATE_ASN1 196 -#define SSL_F_SSL_USE_CERTIFICATE_FILE 197 -#define SSL_F_SSL_USE_PRIVATEKEY 198 -#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 199 -#define SSL_F_SSL_USE_PRIVATEKEY_FILE 200 -#define SSL_F_SSL_USE_RSAPRIVATEKEY 201 -#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 202 -#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 203 -#define SSL_F_SSL_WRITE 204 -#define SSL_F_TLS1_CHANGE_CIPHER_STATE 205 -#define SSL_F_TLS1_ENC 206 -#define SSL_F_TLS1_SETUP_KEY_BLOCK 207 -#define SSL_F_WRITE_PENDING 208 +#define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230 +#define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 +#define SSL_F_SSL_CLEAR 164 +#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +#define SSL_F_SSL_CREATE_CIPHER_LIST 166 +#define SSL_F_SSL_CTRL 232 +#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 +#define SSL_F_SSL_CTX_NEW 169 +#define SSL_F_SSL_CTX_SET_PURPOSE 226 +#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 +#define SSL_F_SSL_CTX_SET_SSL_VERSION 170 +#define SSL_F_SSL_CTX_SET_TRUST 229 +#define SSL_F_SSL_CTX_USE_CERTIFICATE 171 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +#define SSL_F_SSL_DO_HANDSHAKE 180 +#define SSL_F_SSL_GET_NEW_SESSION 181 +#define SSL_F_SSL_GET_PREV_SESSION 217 +#define SSL_F_SSL_GET_SERVER_SEND_CERT 182 +#define SSL_F_SSL_GET_SIGN_PKEY 183 +#define SSL_F_SSL_INIT_WBIO_BUFFER 184 +#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 +#define SSL_F_SSL_NEW 186 +#define SSL_F_SSL_READ 223 +#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 +#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +#define SSL_F_SSL_SESSION_NEW 189 +#define SSL_F_SSL_SESSION_PRINT_FP 190 +#define SSL_F_SSL_SESS_CERT_NEW 225 +#define SSL_F_SSL_SET_CERT 191 +#define SSL_F_SSL_SET_FD 192 +#define SSL_F_SSL_SET_PKEY 193 +#define SSL_F_SSL_SET_PURPOSE 227 +#define SSL_F_SSL_SET_RFD 194 +#define SSL_F_SSL_SET_SESSION 195 +#define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 +#define SSL_F_SSL_SET_TRUST 228 +#define SSL_F_SSL_SET_WFD 196 +#define SSL_F_SSL_SHUTDOWN 224 +#define SSL_F_SSL_UNDEFINED_FUNCTION 197 +#define SSL_F_SSL_USE_CERTIFICATE 198 +#define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 +#define SSL_F_SSL_USE_CERTIFICATE_FILE 200 +#define SSL_F_SSL_USE_PRIVATEKEY 201 +#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 +#define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +#define SSL_F_SSL_USE_RSAPRIVATEKEY 204 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 +#define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +#define SSL_F_SSL_WRITE 208 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 +#define SSL_F_TLS1_ENC 210 +#define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +#define SSL_F_WRITE_PENDING 212 /* Reason codes. */ #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 #define SSL_R_BAD_ALERT_RECORD 101 #define SSL_R_BAD_AUTHENTICATION_TYPE 102 #define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 #define SSL_R_BAD_CHECKSUM 104 -#define SSL_R_BAD_CLIENT_REQUEST 105 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 #define SSL_R_BAD_DECOMPRESSION 107 #define SSL_R_BAD_DH_G_LENGTH 108 @@ -1282,6 +1584,8 @@ int SSL_CTX_get_ex_new_index(); #define SSL_R_BAD_DH_P_LENGTH 110 #define SSL_R_BAD_DIGEST_LENGTH 111 #define SSL_R_BAD_DSA_SIGNATURE 112 +#define SSL_R_BAD_HELLO_REQUEST 105 +#define SSL_R_BAD_LENGTH 271 #define SSL_R_BAD_MAC_DECODE 113 #define SSL_R_BAD_MESSAGE_TYPE 114 #define SSL_R_BAD_PACKET_LENGTH 115 @@ -1311,83 +1615,108 @@ int SSL_CTX_get_ex_new_index(); #define SSL_R_CIPHER_TABLE_SRC_ERROR 139 #define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140 #define SSL_R_COMPRESSION_FAILURE 141 -#define SSL_R_CONNECTION_ID_IS_DIFFERENT 142 -#define SSL_R_CONNECTION_TYPE_NOT_SET 143 -#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 144 -#define SSL_R_DATA_LENGTH_TOO_LONG 145 -#define SSL_R_DECRYPTION_FAILED 146 -#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 147 -#define SSL_R_DIGEST_CHECK_FAILED 148 -#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 149 -#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 150 -#define SSL_R_EXCESSIVE_MESSAGE_SIZE 151 -#define SSL_R_EXTRA_DATA_IN_MESSAGE 152 -#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 153 -#define SSL_R_HTTPS_PROXY_REQUEST 154 -#define SSL_R_HTTP_REQUEST 155 -#define SSL_R_INTERNAL_ERROR 156 -#define SSL_R_INVALID_CHALLENGE_LENGTH 157 -#define SSL_R_LENGTH_MISMATCH 158 -#define SSL_R_LENGTH_TOO_SHORT 159 -#define SSL_R_LIBRARY_HAS_NO_CIPHERS 160 -#define SSL_R_MISSING_DH_DSA_CERT 161 -#define SSL_R_MISSING_DH_KEY 162 -#define SSL_R_MISSING_DH_RSA_CERT 163 -#define SSL_R_MISSING_DSA_SIGNING_CERT 164 -#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 165 -#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 166 -#define SSL_R_MISSING_RSA_CERTIFICATE 167 -#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 168 -#define SSL_R_MISSING_RSA_SIGNING_CERT 169 -#define SSL_R_MISSING_TMP_DH_KEY 170 -#define SSL_R_MISSING_TMP_RSA_KEY 171 -#define SSL_R_MISSING_TMP_RSA_PKEY 172 -#define SSL_R_MISSING_VERIFY_MESSAGE 173 -#define SSL_R_NON_SSLV2_INITIAL_PACKET 174 -#define SSL_R_NO_CERTIFICATES_RETURNED 175 -#define SSL_R_NO_CERTIFICATE_ASSIGNED 176 -#define SSL_R_NO_CERTIFICATE_RETURNED 177 -#define SSL_R_NO_CERTIFICATE_SET 178 -#define SSL_R_NO_CERTIFICATE_SPECIFIED 179 -#define SSL_R_NO_CIPHERS_AVAILABLE 180 -#define SSL_R_NO_CIPHERS_PASSED 181 -#define SSL_R_NO_CIPHERS_SPECIFIED 182 -#define SSL_R_NO_CIPHER_LIST 183 -#define SSL_R_NO_CIPHER_MATCH 184 -#define SSL_R_NO_CLIENT_CERT_RECEIVED 185 -#define SSL_R_NO_COMPRESSION_SPECIFIED 186 -#define SSL_R_NO_PRIVATEKEY 187 -#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 188 -#define SSL_R_NO_PROTOCOLS_AVAILABLE 189 -#define SSL_R_NO_PUBLICKEY 190 -#define SSL_R_NO_SHARED_CIPHER 191 -#define SSL_R_NULL_SSL_CTX 192 -#define SSL_R_NULL_SSL_METHOD_PASSED 193 -#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 194 -#define SSL_R_PACKET_LENGTH_TOO_LONG 195 -#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 196 -#define SSL_R_PEER_ERROR 197 -#define SSL_R_PEER_ERROR_CERTIFICATE 198 -#define SSL_R_PEER_ERROR_NO_CERTIFICATE 199 -#define SSL_R_PEER_ERROR_NO_CIPHER 200 -#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 201 -#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 202 -#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 203 -#define SSL_R_PROTOCOL_IS_SHUTDOWN 204 -#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 205 -#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 206 -#define SSL_R_PUBLIC_KEY_NOT_RSA 207 -#define SSL_R_READ_BIO_NOT_SET 208 -#define SSL_R_READ_WRONG_PACKET_TYPE 209 -#define SSL_R_RECORD_LENGTH_MISMATCH 210 -#define SSL_R_RECORD_TOO_LARGE 211 -#define SSL_R_REQUIRED_CIPHER_MISSING 212 -#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 213 -#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 214 -#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 215 -#define SSL_R_SHORT_READ 216 -#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 217 -#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 218 +#define SSL_R_COMPRESSION_LIBRARY_ERROR 142 +#define SSL_R_CONNECTION_ID_IS_DIFFERENT 143 +#define SSL_R_CONNECTION_TYPE_NOT_SET 144 +#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 +#define SSL_R_DATA_LENGTH_TOO_LONG 146 +#define SSL_R_DECRYPTION_FAILED 147 +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 1109 +#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 +#define SSL_R_DIGEST_CHECK_FAILED 149 +#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 +#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 1092 +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151 +#define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 +#define SSL_R_EXTRA_DATA_IN_MESSAGE 153 +#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 +#define SSL_R_HTTPS_PROXY_REQUEST 155 +#define SSL_R_HTTP_REQUEST 156 +#define SSL_R_ILLEGAL_PADDING 1110 +#define SSL_R_INVALID_CHALLENGE_LENGTH 158 +#define SSL_R_INVALID_COMMAND 280 +#define SSL_R_INVALID_PURPOSE 278 +#define SSL_R_INVALID_TRUST 279 +#define SSL_R_KRB5 1104 +#define SSL_R_KRB5_C_CC_PRINC 1094 +#define SSL_R_KRB5_C_GET_CRED 1095 +#define SSL_R_KRB5_C_INIT 1096 +#define SSL_R_KRB5_C_MK_REQ 1097 +#define SSL_R_KRB5_S_BAD_TICKET 1098 +#define SSL_R_KRB5_S_INIT 1099 +#define SSL_R_KRB5_S_RD_REQ 1108 +#define SSL_R_KRB5_S_TKT_EXPIRED 1105 +#define SSL_R_KRB5_S_TKT_NYV 1106 +#define SSL_R_KRB5_S_TKT_SKEW 1107 +#define SSL_R_LENGTH_MISMATCH 159 +#define SSL_R_LENGTH_TOO_SHORT 160 +#define SSL_R_LIBRARY_BUG 274 +#define SSL_R_LIBRARY_HAS_NO_CIPHERS 161 +#define SSL_R_MESSAGE_TOO_LONG 1111 +#define SSL_R_MISSING_DH_DSA_CERT 162 +#define SSL_R_MISSING_DH_KEY 163 +#define SSL_R_MISSING_DH_RSA_CERT 164 +#define SSL_R_MISSING_DSA_SIGNING_CERT 165 +#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 166 +#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 167 +#define SSL_R_MISSING_RSA_CERTIFICATE 168 +#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 +#define SSL_R_MISSING_RSA_SIGNING_CERT 170 +#define SSL_R_MISSING_TMP_DH_KEY 171 +#define SSL_R_MISSING_TMP_RSA_KEY 172 +#define SSL_R_MISSING_TMP_RSA_PKEY 173 +#define SSL_R_MISSING_VERIFY_MESSAGE 174 +#define SSL_R_NON_SSLV2_INITIAL_PACKET 175 +#define SSL_R_NO_CERTIFICATES_RETURNED 176 +#define SSL_R_NO_CERTIFICATE_ASSIGNED 177 +#define SSL_R_NO_CERTIFICATE_RETURNED 178 +#define SSL_R_NO_CERTIFICATE_SET 179 +#define SSL_R_NO_CERTIFICATE_SPECIFIED 180 +#define SSL_R_NO_CIPHERS_AVAILABLE 181 +#define SSL_R_NO_CIPHERS_PASSED 182 +#define SSL_R_NO_CIPHERS_SPECIFIED 183 +#define SSL_R_NO_CIPHER_LIST 184 +#define SSL_R_NO_CIPHER_MATCH 185 +#define SSL_R_NO_CLIENT_CERT_RECEIVED 186 +#define SSL_R_NO_COMPRESSION_SPECIFIED 187 +#define SSL_R_NO_METHOD_SPECIFIED 188 +#define SSL_R_NO_PRIVATEKEY 189 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 +#define SSL_R_NO_PROTOCOLS_AVAILABLE 191 +#define SSL_R_NO_PUBLICKEY 192 +#define SSL_R_NO_SHARED_CIPHER 193 +#define SSL_R_NO_VERIFY_CALLBACK 194 +#define SSL_R_NULL_SSL_CTX 195 +#define SSL_R_NULL_SSL_METHOD_PASSED 196 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 +#define SSL_R_PACKET_LENGTH_TOO_LONG 198 +#define SSL_R_PATH_TOO_LONG 270 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 +#define SSL_R_PEER_ERROR 200 +#define SSL_R_PEER_ERROR_CERTIFICATE 201 +#define SSL_R_PEER_ERROR_NO_CERTIFICATE 202 +#define SSL_R_PEER_ERROR_NO_CIPHER 203 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204 +#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205 +#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206 +#define SSL_R_PROTOCOL_IS_SHUTDOWN 207 +#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208 +#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209 +#define SSL_R_PUBLIC_KEY_NOT_RSA 210 +#define SSL_R_READ_BIO_NOT_SET 211 +#define SSL_R_READ_WRONG_PACKET_TYPE 212 +#define SSL_R_RECORD_LENGTH_MISMATCH 213 +#define SSL_R_RECORD_TOO_LARGE 214 +#define SSL_R_RECORD_TOO_SMALL 1093 +#define SSL_R_REQUIRED_CIPHER_MISSING 215 +#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216 +#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217 +#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218 +#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 +#define SSL_R_SHORT_READ 219 +#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 +#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 +#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 #define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 @@ -1397,57 +1726,75 @@ int SSL_CTX_get_ex_new_index(); #define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 #define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 #define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE 219 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE 220 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER 221 -#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 222 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_CERTIFICATE 223 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CERTIFICATE 224 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_NO_CIPHER 225 +#define SSL_R_SSLV3_ALERT_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 226 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 -#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE 223 +#define SSL_R_SSLV3_ALERT_UNKNOWN_REMOTE_ERROR_TYPE 227 #define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 -#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 224 -#define SSL_R_SSL_HANDSHAKE_FAILURE 225 -#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 226 -#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 227 -#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 228 -#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 229 -#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 230 -#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 231 -#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 232 -#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 233 -#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 234 -#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 235 -#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 236 -#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 237 -#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 238 -#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 239 -#define SSL_R_UNEXPECTED_MESSAGE 240 -#define SSL_R_UNEXPECTED_RECORD 241 -#define SSL_R_UNKNOWN_ALERT_TYPE 242 -#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 243 -#define SSL_R_UNKNOWN_CIPHER_RETURNED 244 -#define SSL_R_UNKNOWN_CIPHER_TYPE 245 -#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 246 -#define SSL_R_UNKNOWN_PKEY_TYPE 247 -#define SSL_R_UNKNOWN_PROTOCOL 248 -#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 249 -#define SSL_R_UNKNOWN_SSL_VERSION 250 -#define SSL_R_UNKNOWN_STATE 251 -#define SSL_R_UNSUPPORTED_CIPHER 252 -#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 253 -#define SSL_R_UNSUPPORTED_PROTOCOL 254 -#define SSL_R_UNSUPPORTED_SSL_VERSION 255 -#define SSL_R_WRITE_BIO_NOT_SET 256 -#define SSL_R_WRONG_CIPHER_RETURNED 257 -#define SSL_R_WRONG_MESSAGE_TYPE 258 -#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 259 -#define SSL_R_WRONG_SIGNATURE_LENGTH 260 -#define SSL_R_WRONG_SIGNATURE_SIZE 261 -#define SSL_R_WRONG_SSL_VERSION 262 -#define SSL_R_WRONG_VERSION_NUMBER 263 -#define SSL_R_X509_LIB 264 - +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 +#define SSL_R_SSL_HANDSHAKE_FAILURE 229 +#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230 +#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 1102 +#define SSL_R_SSL_SESSION_ID_CONFLICT 1103 +#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273 +#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 1101 +#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 231 +#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 +#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 +#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234 +#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235 +#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 236 +#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 237 +#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 238 +#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 +#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 240 +#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 241 +#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 +#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +#define SSL_R_UNEXPECTED_MESSAGE 244 +#define SSL_R_UNEXPECTED_RECORD 245 +#define SSL_R_UNINITIALIZED 276 +#define SSL_R_UNKNOWN_ALERT_TYPE 246 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 +#define SSL_R_UNKNOWN_CIPHER_RETURNED 248 +#define SSL_R_UNKNOWN_CIPHER_TYPE 249 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 +#define SSL_R_UNKNOWN_PKEY_TYPE 251 +#define SSL_R_UNKNOWN_PROTOCOL 252 +#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253 +#define SSL_R_UNKNOWN_SSL_VERSION 254 +#define SSL_R_UNKNOWN_STATE 255 +#define SSL_R_UNSUPPORTED_CIPHER 256 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257 +#define SSL_R_UNSUPPORTED_OPTION 1091 +#define SSL_R_UNSUPPORTED_PROTOCOL 258 +#define SSL_R_UNSUPPORTED_SSL_VERSION 259 +#define SSL_R_WRITE_BIO_NOT_SET 260 +#define SSL_R_WRONG_CIPHER_RETURNED 261 +#define SSL_R_WRONG_MESSAGE_TYPE 262 +#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263 +#define SSL_R_WRONG_SIGNATURE_LENGTH 264 +#define SSL_R_WRONG_SIGNATURE_SIZE 265 +#define SSL_R_WRONG_SSL_VERSION 266 +#define SSL_R_WRONG_VERSION_NUMBER 267 +#define SSL_R_X509_LIB 268 +#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 + #ifdef __cplusplus } #endif #endif - diff --git a/src/lib/libssl/ssl2.h b/src/lib/libssl/ssl2.h index 3dc94e520b..99a52ea0dd 100644 --- a/src/lib/libssl/ssl2.h +++ b/src/lib/libssl/ssl2.h @@ -67,8 +67,8 @@ extern "C" { #define SSL2_VERSION 0x0002 #define SSL2_VERSION_MAJOR 0x00 #define SSL2_VERSION_MINOR 0x02 -#define SSL2_CLIENT_VERSION 0x0002 -#define SSL2_SERVER_VERSION 0x0002 +/* #define SSL2_CLIENT_VERSION 0x0002 */ +/* #define SSL2_SERVER_VERSION 0x0002 */ /* Protocol Message Codes */ #define SSL2_MT_ERROR 0 @@ -133,8 +133,12 @@ extern "C" { /* Upper/Lower Bounds */ #define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS 256 -#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER (unsigned int)32767 -#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383 /**/ +#ifdef OPENSSL_SYS_MPE +#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 29998u +#else +#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 32767u /* 2^15-1 */ +#endif +#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383 /* 2^14-1 */ #define SSL2_CHALLENGE_LENGTH 16 /*#define SSL2_CHALLENGE_LENGTH 32 */ @@ -151,7 +155,7 @@ extern "C" { #define CERT char #endif -typedef struct ssl2_ctx_st +typedef struct ssl2_state_st { int three_byte_header; int clear_text; /* clear text */ @@ -162,7 +166,7 @@ typedef struct ssl2_ctx_st * args were passwd */ unsigned int wnum; /* number of bytes sent so far */ int wpend_tot; - char *wpend_buf; + const unsigned char *wpend_buf; int wpend_off; /* offset to data to write */ int wpend_len; /* number of bytes passwd to write */ @@ -185,7 +189,6 @@ typedef struct ssl2_ctx_st unsigned char *ract_data; unsigned char *wact_data; unsigned char *mac_data; - unsigned char *pad_data; unsigned char *read_key; unsigned char *write_key; @@ -205,16 +208,16 @@ typedef struct ssl2_ctx_st unsigned int conn_id_length; unsigned int cert_type; unsigned int cert_length; - int csl; - int clear; + unsigned int csl; + unsigned int clear; unsigned int enc; unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH]; - int cipher_spec_length; + unsigned int cipher_spec_length; unsigned int session_id_length; unsigned int clen; unsigned int rlen; } tmp; - } SSL2_CTX; + } SSL2_STATE; /* SSLv2 */ /* client */ diff --git a/src/lib/libssl/ssl3.h b/src/lib/libssl/ssl3.h index 95772eef60..8fd6951d77 100644 --- a/src/lib/libssl/ssl3.h +++ b/src/lib/libssl/ssl3.h @@ -55,11 +55,69 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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_SSL3_H #define HEADER_SSL3_H -#include "buffer.h" +#ifndef OPENSSL_NO_COMP +#include +#endif +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -100,6 +158,22 @@ extern "C" { #define SSL3_CK_FZA_DMS_FZA_SHA 0x0300001D #define SSL3_CK_FZA_DMS_RC4_SHA 0x0300001E +/* VRS Additional Kerberos5 entries + */ +#define SSL3_CK_KRB5_DES_40_CBC_SHA 0x03000021 +#define SSL3_CK_KRB5_DES_40_CBC_MD5 0x03000022 +#define SSL3_CK_KRB5_DES_64_CBC_SHA 0x03000023 +#define SSL3_CK_KRB5_DES_64_CBC_MD5 0x03000024 +#define SSL3_CK_KRB5_DES_192_CBC3_SHA 0x03000025 +#define SSL3_CK_KRB5_DES_192_CBC3_MD5 0x03000026 + +#define SSL3_TXT_KRB5_DES_40_CBC_SHA "EXP-KRB5-DES-CBC-SHA" +#define SSL3_TXT_KRB5_DES_40_CBC_MD5 "EXP-KRB5-DES-CBC-MD5" +#define SSL3_TXT_KRB5_DES_64_CBC_SHA "KRB5-DES-CBC-SHA" +#define SSL3_TXT_KRB5_DES_64_CBC_MD5 "KRB5-DES-CBC-MD5" +#define SSL3_TXT_KRB5_DES_192_CBC3_SHA "KRB5-DES-CBC3-SHA" +#define SSL3_TXT_KRB5_DES_192_CBC3_MD5 "KRB5-DES-CBC3-MD5" + #define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" #define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" #define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" @@ -144,7 +218,8 @@ extern "C" { #define SSL3_RT_HEADER_LENGTH 5 /* Due to MS stuffing up, this can change.... */ -#if defined(WIN16) || (defined(MSDOS) && !defined(WIN32)) +#if defined(OPENSSL_SYS_WIN16) || \ + (defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)) #define SSL3_RT_MAX_EXTRA (14000) #else #define SSL3_RT_MAX_EXTRA (16384) @@ -156,24 +231,8 @@ extern "C" { #define SSL3_RT_MAX_PACKET_SIZE (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) #define SSL3_RT_MAX_DATA_SIZE (1024*1024) -/* the states that a SSL3_RECORD can be in - * For SSL_read it goes - * rbuf->ENCODED -> read - * ENCODED -> we need to decode everything - call decode_record - */ - -#define SSL3_RS_BLANK 1 -#define SSL3_RS_DATA - -#define SSL3_RS_ENCODED 2 -#define SSL3_RS_READ_MORE 3 -#define SSL3_RS_WRITE_MORE -#define SSL3_RS_PLAIN 3 -#define SSL3_RS_PART_READ 4 -#define SSL3_RS_PART_WRITE 5 - -#define SSL3_MD_CLIENT_FINISHED_CONST {0x43,0x4C,0x4E,0x54} -#define SSL3_MD_SERVER_FINISHED_CONST {0x53,0x52,0x56,0x52} +#define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +#define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" #define SSL3_VERSION 0x0300 #define SSL3_VERSION_MAJOR 0x03 @@ -202,28 +261,23 @@ extern "C" { typedef struct ssl3_record_st { -/*r */ int type; /* type of record */ -/* */ /*int state;*/ /* any data in it? */ -/*rw*/ unsigned int length; /* How many bytes available */ -/*r */ unsigned int off; /* read/write offset into 'buf' */ -/*rw*/ unsigned char *data; /* pointer to the record data */ -/*rw*/ unsigned char *input; /* where the decode bytes are */ -/*rw*/ unsigned char *comp; /* only used with decompression */ +/*r */ int type; /* type of record */ +/*rw*/ unsigned int length; /* How many bytes available */ +/*r */ unsigned int off; /* read/write offset into 'buf' */ +/*rw*/ unsigned char *data; /* pointer to the record data */ +/*rw*/ unsigned char *input; /* where the decode bytes are */ +/*r */ unsigned char *comp; /* only used with decompression - malloc()ed */ } SSL3_RECORD; typedef struct ssl3_buffer_st { -/*r */ int total; /* used in non-blocking writes */ -/*r */ int wanted; /* how many more bytes we need */ -/*rw*/ int left; /* how many bytes left */ -/*rw*/ int offset; /* where to 'copy from' */ -/*rw*/ unsigned char *buf; /* SSL3_RT_MAX_PACKET_SIZE bytes */ + unsigned char *buf; /* at least SSL3_RT_MAX_PACKET_SIZE bytes, + * see ssl3_setup_buffers() */ + size_t len; /* buffer size */ + int offset; /* where to 'copy from' */ + int left; /* how many bytes left */ } SSL3_BUFFER; -typedef struct ssl3_compression_st { - int nothing; - } SSL3_COMPRESSION; - #define SSL3_CT_RSA_SIGN 1 #define SSL3_CT_DSS_SIGN 2 #define SSL3_CT_RSA_FIXED_DH 3 @@ -236,36 +290,9 @@ typedef struct ssl3_compression_st { #define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 #define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002 #define SSL3_FLAGS_POP_BUFFER 0x0004 -#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008 - -#if 0 -#define AD_CLOSE_NOTIFY 0 -#define AD_UNEXPECTED_MESSAGE 1 -#define AD_BAD_RECORD_MAC 2 -#define AD_DECRYPTION_FAILED 3 -#define AD_RECORD_OVERFLOW 4 -#define AD_DECOMPRESSION_FAILURE 5 /* fatal */ -#define AD_HANDSHAKE_FAILURE 6 /* fatal */ -#define AD_NO_CERTIFICATE 7 /* Not under TLS */ -#define AD_BAD_CERTIFICATE 8 -#define AD_UNSUPPORTED_CERTIFICATE 9 -#define AD_CERTIFICATE_REVOKED 10 -#define AD_CERTIFICATE_EXPIRED 11 -#define AD_CERTIFICATE_UNKNOWN 12 -#define AD_ILLEGAL_PARAMETER 13 /* fatal */ -#define AD_UNKNOWN_CA 14 /* fatal */ -#define AD_ACCESS_DENIED 15 /* fatal */ -#define AD_DECODE_ERROR 16 /* fatal */ -#define AD_DECRYPT_ERROR 17 -#define AD_EXPORT_RESTRICION 18 /* fatal */ -#define AD_PROTOCOL_VERSION 19 /* fatal */ -#define AD_INSUFFICIENT_SECURITY 20 /* fatal */ -#define AD_INTERNAL_ERROR 21 /* fatal */ -#define AD_USER_CANCLED 22 -#define AD_NO_RENEGOTIATION 23 -#endif +#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008 -typedef struct ssl3_ctx_st +typedef struct ssl3_state_st { long flags; int delay_buf_pop_ret; @@ -278,19 +305,29 @@ typedef struct ssl3_ctx_st unsigned char server_random[SSL3_RANDOM_SIZE]; unsigned char client_random[SSL3_RANDOM_SIZE]; + /* flags for countermeasure against known-IV weakness */ + int need_empty_fragments; + int empty_fragment_done; + SSL3_BUFFER rbuf; /* read IO goes into here */ SSL3_BUFFER wbuf; /* write IO goes into here */ + SSL3_RECORD rrec; /* each decoded record goes in here */ SSL3_RECORD wrec; /* goes out from here */ - /* Used by ssl3_read_n to point - * to input data packet */ + + /* storage for Alert/Handshake protocol data received but not + * yet processed by ssl3_read_bytes: */ + unsigned char alert_fragment[2]; + unsigned int alert_fragment_len; + unsigned char handshake_fragment[4]; + unsigned int handshake_fragment_len; /* partial write - check the numbers match */ unsigned int wnum; /* number of bytes sent so far */ int wpend_tot; /* number bytes written */ int wpend_type; int wpend_ret; /* number of bytes submitted */ - char *wpend_buf; + const unsigned char *wpend_buf; /* used during startup, digest all incoming/outgoing packets */ EVP_MD_CTX finish_dgst1; @@ -302,10 +339,10 @@ typedef struct ssl3_ctx_st int warn_alert; int fatal_alert; - /* we alow one fatal and one warning alert to be outstanding, + /* we allow one fatal and one warning alert to be outstanding, * send close alert via the warning alert */ int alert_dispatch; - char send_alert[2]; + unsigned char send_alert[2]; /* This flag is set when we should renegotiate ASAP, basically when * there is no more data in the read or write buffers */ @@ -316,16 +353,23 @@ typedef struct ssl3_ctx_st int in_read_app_data; struct { - /* Actually only needs to be 16+20 for SSLv3 and 12 for TLS */ + /* actually only needs to be 16+20 */ + unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2]; + + /* actually only need to be 16+20 for SSLv3 and 12 for TLS */ unsigned char finish_md[EVP_MAX_MD_SIZE*2]; + int finish_md_len; + unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2]; + int peer_finish_md_len; unsigned long message_size; int message_type; /* used to hold the new cipher we are going to use */ SSL_CIPHER *new_cipher; +#ifndef OPENSSL_NO_DH DH *dh; - +#endif /* used when SSL_ST_FLUSH_DATA is entered */ int next_state; @@ -335,19 +379,24 @@ typedef struct ssl3_ctx_st int cert_req; int ctype_num; char ctype[SSL3_CT_NUMBER]; - STACK *ca_names; + STACK_OF(X509_NAME) *ca_names; int use_rsa_tmp; int key_block_length; unsigned char *key_block; - EVP_CIPHER *new_sym_enc; - EVP_MD *new_hash; - SSL_COMPRESSION *new_compression; + const EVP_CIPHER *new_sym_enc; + const EVP_MD *new_hash; +#ifndef OPENSSL_NO_COMP + const SSL_COMP *new_compression; +#else + char *new_compression; +#endif int cert_request; } tmp; - } SSL3_CTX; + + } SSL3_STATE; /* SSLv3 */ /*client */ @@ -425,7 +474,7 @@ typedef struct ssl3_ctx_st #define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT) #define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT) -#define SSL3_MT_CLIENT_REQUEST 0 +#define SSL3_MT_HELLO_REQUEST 0 #define SSL3_MT_CLIENT_HELLO 1 #define SSL3_MT_SERVER_HELLO 2 #define SSL3_MT_CERTIFICATE 11 diff --git a/src/lib/libssl/ssl_algs.c b/src/lib/libssl/ssl_algs.c index 65f3a59386..3d1299ee7b 100644 --- a/src/lib/libssl/ssl_algs.c +++ b/src/lib/libssl/ssl_algs.c @@ -57,46 +57,55 @@ */ #include -#include "objects.h" -#include "lhash.h" +#include +#include #include "ssl_locl.h" -void SSLeay_add_ssl_algorithms() +int SSL_library_init(void) { -#ifndef NO_DES + +#ifndef OPENSSL_NO_DES EVP_add_cipher(EVP_des_cbc()); EVP_add_cipher(EVP_des_ede3_cbc()); #endif -#ifndef NO_IDEA +#ifndef OPENSSL_NO_IDEA EVP_add_cipher(EVP_idea_cbc()); #endif -#ifndef NO_RC4 - EVP_add_cipher(EVP_rc4()); -#endif -#ifndef NO_RC2 - EVP_add_cipher(EVP_rc2_cbc()); +#ifndef OPENSSL_NO_RC4 + EVP_add_cipher(EVP_rc4()); #endif - -#ifndef NO_MD2 - EVP_add_digest(EVP_md2()); +#ifndef OPENSSL_NO_RC2 + EVP_add_cipher(EVP_rc2_cbc()); #endif -#ifndef NO_MD5 +#ifndef OPENSSL_NO_AES + EVP_add_cipher(EVP_aes_128_cbc()); + EVP_add_cipher(EVP_aes_192_cbc()); + EVP_add_cipher(EVP_aes_256_cbc()); +#endif +#ifndef OPENSSL_NO_MD2 + EVP_add_digest(EVP_md2()); +#endif +#ifndef OPENSSL_NO_MD5 EVP_add_digest(EVP_md5()); - EVP_add_alias(SN_md5,"ssl2-md5"); - EVP_add_alias(SN_md5,"ssl3-md5"); + EVP_add_digest_alias(SN_md5,"ssl2-md5"); + EVP_add_digest_alias(SN_md5,"ssl3-md5"); #endif -#ifndef NO_SHA1 +#ifndef OPENSSL_NO_SHA EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ - EVP_add_alias(SN_sha1,"ssl3-sha1"); + EVP_add_digest_alias(SN_sha1,"ssl3-sha1"); + EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA); #endif -#if !defined(NO_SHA1) && !defined(NO_DSA) +#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_DSA) EVP_add_digest(EVP_dss1()); /* DSA with sha1 */ + EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2); + EVP_add_digest_alias(SN_dsaWithSHA1,"DSS1"); + EVP_add_digest_alias(SN_dsaWithSHA1,"dss1"); #endif - /* If you want support for phased out ciphers, add the following */ #if 0 EVP_add_digest(EVP_sha()); EVP_add_digest(EVP_dss()); #endif + return(1); } diff --git a/src/lib/libssl/ssl_asn1.c b/src/lib/libssl/ssl_asn1.c index 116a83de64..c5eeeb6bc5 100644 --- a/src/lib/libssl/ssl_asn1.c +++ b/src/lib/libssl/ssl_asn1.c @@ -58,8 +58,9 @@ #include #include -#include "asn1_mac.h" -#include "objects.h" +#include +#include +#include #include "ssl_locl.h" typedef struct ssl_session_asn1_st @@ -69,24 +70,22 @@ typedef struct ssl_session_asn1_st ASN1_OCTET_STRING cipher; ASN1_OCTET_STRING master_key; ASN1_OCTET_STRING session_id; + ASN1_OCTET_STRING session_id_context; ASN1_OCTET_STRING key_arg; +#ifndef OPENSSL_NO_KRB5 + ASN1_OCTET_STRING krb5_princ; +#endif /* OPENSSL_NO_KRB5 */ ASN1_INTEGER time; ASN1_INTEGER timeout; + ASN1_INTEGER verify_result; } SSL_SESSION_ASN1; -/* - * SSLerr(SSL_F_I2D_SSL_SESSION,SSL_R_CIPHER_CODE_WRONG_LENGTH); - * SSLerr(SSL_F_D2I_SSL_SESSION,SSL_R_UNSUPPORTED_CIPHER); - */ - -int i2d_SSL_SESSION(in,pp) -SSL_SESSION *in; -unsigned char **pp; +int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) { #define LSIZE2 (sizeof(long)*2) - int v1=0,v2=0,v3=0; + int v1=0,v2=0,v3=0,v4=0,v5=0; unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2]; - unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2]; + unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2]; long l; SSL_SESSION_ASN1 a; M_ASN1_I2D_vars(in); @@ -95,8 +94,8 @@ unsigned char **pp; return(0); /* Note that I cheat in the following 2 assignments. I know - * that if the ASN1_INTERGER passed to ASN1_INTEGER_set - * is > sizeof(long)+1, the buffer will not be re-Malloc()ed. + * that if the ASN1_INTEGER passed to ASN1_INTEGER_set + * is > sizeof(long)+1, the buffer will not be re-OPENSSL_malloc()ed. * This is a bit evil but makes things simple, no dynamic allocation * to clean up :-) */ a.version.length=LSIZE2; @@ -138,10 +137,23 @@ unsigned char **pp; a.session_id.type=V_ASN1_OCTET_STRING; a.session_id.data=in->session_id; + a.session_id_context.length=in->sid_ctx_length; + a.session_id_context.type=V_ASN1_OCTET_STRING; + a.session_id_context.data=in->sid_ctx; + a.key_arg.length=in->key_arg_length; a.key_arg.type=V_ASN1_OCTET_STRING; a.key_arg.data=in->key_arg; +#ifndef OPENSSL_NO_KRB5 + if (in->krb5_client_princ_len) + { + a.krb5_princ.length=in->krb5_client_princ_len; + a.krb5_princ.type=V_ASN1_OCTET_STRING; + a.krb5_princ.data=in->krb5_client_princ; + } +#endif /* OPENSSL_NO_KRB5 */ + if (in->time != 0L) { a.time.length=LSIZE2; @@ -158,11 +170,24 @@ unsigned char **pp; ASN1_INTEGER_set(&(a.timeout),in->timeout); } + if (in->verify_result != X509_V_OK) + { + a.verify_result.length=LSIZE2; + a.verify_result.type=V_ASN1_INTEGER; + a.verify_result.data=ibuf5; + ASN1_INTEGER_set(&a.verify_result,in->verify_result); + } + + M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER); M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER); M_ASN1_I2D_len(&(a.cipher), i2d_ASN1_OCTET_STRING); M_ASN1_I2D_len(&(a.session_id), i2d_ASN1_OCTET_STRING); M_ASN1_I2D_len(&(a.master_key), i2d_ASN1_OCTET_STRING); +#ifndef OPENSSL_NO_KRB5 + if (in->krb5_client_princ_len) + M_ASN1_I2D_len(&(a.krb5_princ), i2d_ASN1_OCTET_STRING); +#endif /* OPENSSL_NO_KRB5 */ if (in->key_arg_length > 0) M_ASN1_I2D_len_IMP_opt(&(a.key_arg),i2d_ASN1_OCTET_STRING); if (in->time != 0L) @@ -171,6 +196,9 @@ unsigned char **pp; M_ASN1_I2D_len_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2); if (in->peer != NULL) M_ASN1_I2D_len_EXP_opt(in->peer,i2d_X509,3,v3); + M_ASN1_I2D_len_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4,v4); + if (in->verify_result != X509_V_OK) + M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5); M_ASN1_I2D_seq_total(); @@ -179,6 +207,10 @@ unsigned char **pp; M_ASN1_I2D_put(&(a.cipher), i2d_ASN1_OCTET_STRING); M_ASN1_I2D_put(&(a.session_id), i2d_ASN1_OCTET_STRING); M_ASN1_I2D_put(&(a.master_key), i2d_ASN1_OCTET_STRING); +#ifndef OPENSSL_NO_KRB5 + if (in->krb5_client_princ_len) + M_ASN1_I2D_put(&(a.krb5_princ), i2d_ASN1_OCTET_STRING); +#endif /* OPENSSL_NO_KRB5 */ if (in->key_arg_length > 0) M_ASN1_I2D_put_IMP_opt(&(a.key_arg),i2d_ASN1_OCTET_STRING,0); if (in->time != 0L) @@ -187,14 +219,15 @@ unsigned char **pp; M_ASN1_I2D_put_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2); if (in->peer != NULL) M_ASN1_I2D_put_EXP_opt(in->peer,i2d_X509,3,v3); - + M_ASN1_I2D_put_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4, + v4); + if (in->verify_result != X509_V_OK) + M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5); M_ASN1_I2D_finish(); } -SSL_SESSION *d2i_SSL_SESSION(a,pp,length) -SSL_SESSION **a; -unsigned char **pp; -long length; +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, + long length) { int version,ssl_version=0,i; long id; @@ -211,13 +244,13 @@ long length; ai.data=NULL; ai.length=0; M_ASN1_D2I_get(aip,d2i_ASN1_INTEGER); version=(int)ASN1_INTEGER_get(aip); - if (ai.data != NULL) { Free(ai.data); ai.data=NULL; ai.length=0; } + if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; } /* we don't care about the version right now :-) */ M_ASN1_D2I_get(aip,d2i_ASN1_INTEGER); ssl_version=(int)ASN1_INTEGER_get(aip); ret->ssl_version=ssl_version; - if (ai.data != NULL) { Free(ai.data); ai.data=NULL; ai.length=0; } + if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; } os.data=NULL; os.length=0; M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING); @@ -273,20 +306,39 @@ long length; memcpy(ret->master_key,os.data,ret->master_key_length); os.length=0; + +#ifndef OPENSSL_NO_KRB5 + os.length=0; + M_ASN1_D2I_get_opt(osp,d2i_ASN1_OCTET_STRING,V_ASN1_OCTET_STRING); + if (os.data) + { + if (os.length > SSL_MAX_KRB5_PRINCIPAL_LENGTH) + ret->krb5_client_princ_len=0; + else + ret->krb5_client_princ_len=os.length; + memcpy(ret->krb5_client_princ,os.data,ret->krb5_client_princ_len); + OPENSSL_free(os.data); + os.data = NULL; + os.length = 0; + } + else + ret->krb5_client_princ_len=0; +#endif /* OPENSSL_NO_KRB5 */ + M_ASN1_D2I_get_IMP_opt(osp,d2i_ASN1_OCTET_STRING,0,V_ASN1_OCTET_STRING); if (os.length > SSL_MAX_KEY_ARG_LENGTH) ret->key_arg_length=SSL_MAX_KEY_ARG_LENGTH; else ret->key_arg_length=os.length; memcpy(ret->key_arg,os.data,ret->key_arg_length); - if (os.data != NULL) Free(os.data); + if (os.data != NULL) OPENSSL_free(os.data); ai.length=0; M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,1); if (ai.data != NULL) { ret->time=ASN1_INTEGER_get(aip); - Free(ai.data); ai.data=NULL; ai.length=0; + OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; } else ret->time=time(NULL); @@ -296,7 +348,7 @@ long length; if (ai.data != NULL) { ret->timeout=ASN1_INTEGER_get(aip); - Free(ai.data); ai.data=NULL; ai.length=0; + OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; } else ret->timeout=3; @@ -308,6 +360,30 @@ long length; } M_ASN1_D2I_get_EXP_opt(ret->peer,d2i_X509,3); + os.length=0; + os.data=NULL; + M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,4); + + if(os.data != NULL) + { + if (os.length > SSL_MAX_SID_CTX_LENGTH) + SSLerr(SSL_F_D2I_SSL_SESSION,SSL_R_BAD_LENGTH); + ret->sid_ctx_length=os.length; + memcpy(ret->sid_ctx,os.data,os.length); + OPENSSL_free(os.data); os.data=NULL; os.length=0; + } + else + ret->sid_ctx_length=0; + + ai.length=0; + M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,5); + if (ai.data != NULL) + { + ret->verify_result=ASN1_INTEGER_get(aip); + OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; + } + else + ret->verify_result=X509_V_OK; + M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION); } - diff --git a/src/lib/libssl/ssl_cert.c b/src/lib/libssl/ssl_cert.c index c1cb86e1b7..3d31bbf05f 100644 --- a/src/lib/libssl/ssl_cert.c +++ b/src/lib/libssl/ssl_cert.c @@ -1,4 +1,4 @@ -/* ssl/ssl_cert.c */ +/*! \file ssl/ssl_cert.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -55,32 +55,113 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * 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 "objects.h" -#include "bio.h" -#include "pem.h" + +#include "e_os.h" +#ifndef NO_SYS_TYPES_H +# include +#endif + +#if !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_VMS) && !defined(NeXT) && !defined(MAC_OS_pre_X) +#include +#endif + +#if defined(WIN32) +#include +#endif + +#ifdef NeXT +#include +#define dirent direct +#endif + +#include +#include +#include +#include #include "ssl_locl.h" -CERT *ssl_cert_new() +int SSL_get_ex_data_X509_STORE_CTX_idx(void) + { + static volatile int ssl_x509_store_ctx_idx= -1; + + if (ssl_x509_store_ctx_idx < 0) + { + /* any write lock will do; usually this branch + * will only be taken once anyway */ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + + if (ssl_x509_store_ctx_idx < 0) + { + ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( + 0,"SSL for verify callback",NULL,NULL,NULL); + } + + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } + return ssl_x509_store_ctx_idx; + } + +CERT *ssl_cert_new(void) { CERT *ret; - ret=(CERT *)Malloc(sizeof(CERT)); + ret=(CERT *)OPENSSL_malloc(sizeof(CERT)); if (ret == NULL) { SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } memset(ret,0,sizeof(CERT)); -/* - ret->valid=0; - ret->mask=0; - ret->export_mask=0; - ret->cert_type=0; - ret->key->x509=NULL; - ret->key->publickey=NULL; - ret->key->privatekey=NULL; */ ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]); ret->references=1; @@ -88,11 +169,151 @@ CERT *ssl_cert_new() return(ret); } -void ssl_cert_free(c) -CERT *c; +CERT *ssl_cert_dup(CERT *cert) { + CERT *ret; int i; + ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); + if (ret == NULL) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); + return(NULL); + } + + memset(ret, 0, sizeof(CERT)); + + ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; + /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), + * if you find that more readable */ + + ret->valid = cert->valid; + ret->mask = cert->mask; + ret->export_mask = cert->export_mask; + +#ifndef OPENSSL_NO_RSA + if (cert->rsa_tmp != NULL) + { + RSA_up_ref(cert->rsa_tmp); + ret->rsa_tmp = cert->rsa_tmp; + } + ret->rsa_tmp_cb = cert->rsa_tmp_cb; +#endif + +#ifndef OPENSSL_NO_DH + if (cert->dh_tmp != NULL) + { + /* DH parameters don't have a reference count */ + ret->dh_tmp = DHparams_dup(cert->dh_tmp); + if (ret->dh_tmp == NULL) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB); + goto err; + } + if (cert->dh_tmp->priv_key) + { + BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); + if (!b) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); + goto err; + } + ret->dh_tmp->priv_key = b; + } + if (cert->dh_tmp->pub_key) + { + BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); + if (!b) + { + SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); + goto err; + } + ret->dh_tmp->pub_key = b; + } + } + ret->dh_tmp_cb = cert->dh_tmp_cb; +#endif + + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (cert->pkeys[i].x509 != NULL) + { + ret->pkeys[i].x509 = cert->pkeys[i].x509; + CRYPTO_add(&ret->pkeys[i].x509->references, 1, + CRYPTO_LOCK_X509); + } + + if (cert->pkeys[i].privatekey != NULL) + { + ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; + CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, + CRYPTO_LOCK_EVP_PKEY); + + switch(i) + { + /* If there was anything special to do for + * certain types of keys, we'd do it here. + * (Nothing at the moment, I think.) */ + + case SSL_PKEY_RSA_ENC: + case SSL_PKEY_RSA_SIGN: + /* We have an RSA key. */ + break; + + case SSL_PKEY_DSA_SIGN: + /* We have a DSA key. */ + break; + + case SSL_PKEY_DH_RSA: + case SSL_PKEY_DH_DSA: + /* We have a DH key. */ + break; + + default: + /* Can't happen. */ + SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG); + } + } + } + + /* ret->extra_certs *should* exist, but currently the own certificate + * chain is held inside SSL_CTX */ + + ret->references=1; + + return(ret); + +#ifndef OPENSSL_NO_DH /* avoid 'unreferenced label' warning if OPENSSL_NO_DH is defined */ +err: +#endif +#ifndef OPENSSL_NO_RSA + if (ret->rsa_tmp != NULL) + RSA_free(ret->rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH + if (ret->dh_tmp != NULL) + DH_free(ret->dh_tmp); +#endif + + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (ret->pkeys[i].x509 != NULL) + X509_free(ret->pkeys[i].x509); + if (ret->pkeys[i].privatekey != NULL) + EVP_PKEY_free(ret->pkeys[i].privatekey); + } + + return NULL; + } + + +void ssl_cert_free(CERT *c) + { + int i; + + if(c == NULL) + return; + i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT); #ifdef REF_PRINT REF_PRINT("CERT",c); @@ -106,10 +327,10 @@ CERT *c; } #endif -#ifndef NO_RSA +#ifndef OPENSSL_NO_RSA if (c->rsa_tmp) RSA_free(c->rsa_tmp); #endif -#ifndef NO_DH +#ifndef OPENSSL_NO_DH if (c->dh_tmp) DH_free(c->dh_tmp); #endif @@ -124,97 +345,209 @@ CERT *c; EVP_PKEY_free(c->pkeys[i].publickey); #endif } - if (c->cert_chain != NULL) - sk_pop_free(c->cert_chain,X509_free); - Free(c); + OPENSSL_free(c); } -int ssl_set_cert_type(c, type) -CERT *c; -int type; +int ssl_cert_inst(CERT **o) { - c->cert_type=type; + /* Create a CERT if there isn't already one + * (which cannot really happen, as it is initially created in + * SSL_CTX_new; but the earlier code usually allows for that one + * being non-existant, so we follow that behaviour, as it might + * turn out that there actually is a reason for it -- but I'm + * not sure that *all* of the existing code could cope with + * s->cert being NULL, otherwise we could do without the + * initialization in SSL_CTX_new). + */ + + if (o == NULL) + { + SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if (*o == NULL) + { + if ((*o = ssl_cert_new()) == NULL) + { + SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE); + return(0); + } + } return(1); } -int ssl_verify_cert_chain(s,sk) -SSL *s; -STACK *sk; + +SESS_CERT *ssl_sess_cert_new(void) + { + SESS_CERT *ret; + + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) + { + SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memset(ret, 0 ,sizeof *ret); + ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); + ret->references = 1; + + return ret; + } + +void ssl_sess_cert_free(SESS_CERT *sc) + { + int i; + + if (sc == NULL) + return; + + i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); +#ifdef REF_PRINT + REF_PRINT("SESS_CERT", sc); +#endif + if (i > 0) + return; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"ssl_sess_cert_free, bad reference count\n"); + abort(); /* ok */ + } +#endif + + /* i == 0 */ + if (sc->cert_chain != NULL) + sk_X509_pop_free(sc->cert_chain, X509_free); + for (i = 0; i < SSL_PKEY_NUM; i++) + { + if (sc->peer_pkeys[i].x509 != NULL) + X509_free(sc->peer_pkeys[i].x509); +#if 0 /* We don't have the peer's private key. These lines are just + * here as a reminder that we're still using a not-quite-appropriate + * data structure. */ + if (sc->peer_pkeys[i].privatekey != NULL) + EVP_PKEY_free(sc->peer_pkeys[i].privatekey); +#endif + } + +#ifndef OPENSSL_NO_RSA + if (sc->peer_rsa_tmp != NULL) + RSA_free(sc->peer_rsa_tmp); +#endif +#ifndef OPENSSL_NO_DH + if (sc->peer_dh_tmp != NULL) + DH_free(sc->peer_dh_tmp); +#endif + + OPENSSL_free(sc); + } + +int ssl_set_peer_cert_type(SESS_CERT *sc,int type) + { + sc->peer_cert_type = type; + return(1); + } + +int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) { X509 *x; int i; X509_STORE_CTX ctx; - if ((sk == NULL) || (sk_num(sk) == 0)) + if ((sk == NULL) || (sk_X509_num(sk) == 0)) return(0); - x=(X509 *)sk_value(sk,0); - X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk); - X509_STORE_CTX_set_app_data(&ctx,(char *)s); + x=sk_X509_value(sk,0); + if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk)) + { + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB); + return(0); + } + if (SSL_get_verify_depth(s) >= 0) + X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); + X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); + + /* We need to set the verify purpose. The purpose can be determined by + * the context: if its a server it will verify SSL client certificates + * or vice versa. + */ + if (s->server) + i = X509_PURPOSE_SSL_CLIENT; + else + i = X509_PURPOSE_SSL_SERVER; + + X509_STORE_CTX_purpose_inherit(&ctx, i, s->purpose, s->trust); + + if (s->verify_callback) + X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); if (s->ctx->app_verify_callback != NULL) - i=s->ctx->app_verify_callback(&ctx); +#if 1 /* new with OpenSSL 0.9.7 */ + i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); +#else + i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ +#endif else + { +#ifndef OPENSSL_NO_X509_VERIFY i=X509_verify_cert(&ctx); +#else + i=0; + ctx.error=X509_V_ERR_APPLICATION_VERIFICATION; + SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK); +#endif + } - X509_STORE_CTX_cleanup(&ctx); s->verify_result=ctx.error; + X509_STORE_CTX_cleanup(&ctx); return(i); } -static void set_client_CA_list(ca_list,list) -STACK **ca_list; -STACK *list; +static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *list) { if (*ca_list != NULL) - sk_pop_free(*ca_list,X509_NAME_free); + sk_X509_NAME_pop_free(*ca_list,X509_NAME_free); *ca_list=list; } -STACK *SSL_dup_CA_list(sk) -STACK *sk; +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) { int i; - STACK *ret; + STACK_OF(X509_NAME) *ret; X509_NAME *name; - ret=sk_new_null(); - for (i=0; iclient_CA),list); } -void SSL_CTX_set_client_CA_list(ctx,list) -SSL_CTX *ctx; -STACK *list; +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *list) { set_client_CA_list(&(ctx->client_CA),list); } -STACK *SSL_CTX_get_client_CA_list(ctx) -SSL_CTX *ctx; +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(SSL_CTX *ctx) { return(ctx->client_CA); } -STACK *SSL_get_client_CA_list(s) -SSL *s; +STACK_OF(X509_NAME) *SSL_get_client_CA_list(SSL *s) { if (s->type == SSL_ST_CONNECT) { /* we are in the client */ @@ -233,20 +566,18 @@ SSL *s; } } -static int add_client_CA(sk,x) -STACK **sk; -X509 *x; +static int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x) { X509_NAME *name; if (x == NULL) return(0); - if ((*sk == NULL) && ((*sk=sk_new_null()) == NULL)) + if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL)) return(0); if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL) return(0); - if (!sk_push(*sk,(char *)name)) + if (!sk_X509_NAME_push(*sk,name)) { X509_NAME_free(name); return(0); @@ -254,37 +585,39 @@ X509 *x; return(1); } -int SSL_add_client_CA(ssl,x) -SSL *ssl; -X509 *x; +int SSL_add_client_CA(SSL *ssl,X509 *x) { return(add_client_CA(&(ssl->client_CA),x)); } -int SSL_CTX_add_client_CA(ctx,x) -SSL_CTX *ctx; -X509 *x; +int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x) { return(add_client_CA(&(ctx->client_CA),x)); } -static int name_cmp(a,b) -X509_NAME **a,**b; +static int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) { return(X509_NAME_cmp(*a,*b)); } -#ifndef NO_STDIO -STACK *SSL_load_client_CA_file(file) -char *file; +#ifndef OPENSSL_NO_STDIO +/*! + * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; + * it doesn't really have anything to do with clients (except that a common use + * for a stack of CAs is to send it to the client). Actually, it doesn't have + * much to do with CAs, either, since it will load any old cert. + * \param file the file containing one or more certs. + * \return a ::STACK containing the certs. + */ +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { BIO *in; X509 *x=NULL; X509_NAME *xn=NULL; - STACK *ret,*sk; + STACK_OF(X509_NAME) *ret,*sk; - ret=sk_new(NULL); - sk=sk_new(name_cmp); + ret=sk_X509_NAME_new_null(); + sk=sk_X509_NAME_new(xname_cmp); in=BIO_new(BIO_s_file_internal()); @@ -299,31 +632,201 @@ char *file; for (;;) { - if (PEM_read_bio_X509(in,&x,NULL) == NULL) + if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) break; if ((xn=X509_get_subject_name(x)) == NULL) goto err; /* check for duplicates */ xn=X509_NAME_dup(xn); if (xn == NULL) goto err; - if (sk_find(sk,(char *)xn) >= 0) + if (sk_X509_NAME_find(sk,xn) >= 0) X509_NAME_free(xn); else { - sk_push(sk,(char *)xn); - sk_push(ret,(char *)xn); + sk_X509_NAME_push(sk,xn); + sk_X509_NAME_push(ret,xn); } } if (0) { err: - if (ret != NULL) sk_pop_free(ret,X509_NAME_free); + if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free); ret=NULL; } - if (sk != NULL) sk_free(sk); + if (sk != NULL) sk_X509_NAME_free(sk); if (in != NULL) BIO_free(in); if (x != NULL) X509_free(x); return(ret); } #endif +/*! + * Add a file of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *file) + { + BIO *in; + X509 *x=NULL; + X509_NAME *xn=NULL; + int ret=1; + int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); + + oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp); + + in=BIO_new(BIO_s_file_internal()); + + if (in == NULL) + { + SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in,file)) + goto err; + + for (;;) + { + if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) + break; + if ((xn=X509_get_subject_name(x)) == NULL) goto err; + xn=X509_NAME_dup(xn); + if (xn == NULL) goto err; + if (sk_X509_NAME_find(stack,xn) >= 0) + X509_NAME_free(xn); + else + sk_X509_NAME_push(stack,xn); + } + + if (0) + { +err: + ret=0; + } + if(in != NULL) + BIO_free(in); + if(x != NULL) + X509_free(x); + + sk_X509_NAME_set_cmp_func(stack,oldcmp); + + return ret; + } + +/*! + * Add a directory of certs to a stack. + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be + * included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +#ifndef OPENSSL_SYS_WIN32 +#ifndef OPENSSL_SYS_VMS /* XXXX This may be fixed in the future */ +#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! */ + +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *dir) + { + DIR *d; + struct dirent *dstruct; + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_READDIR); + d = opendir(dir); + + /* Note that a side effect is that the CAs will be sorted by name */ + if(!d) + { + SYSerr(SYS_F_OPENDIR, get_last_sys_error()); + ERR_add_error_data(3, "opendir('", dir, "')"); + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); + goto err; + } + + while((dstruct=readdir(d))) + { + char buf[1024]; + int r; + + if(strlen(dir)+strlen(dstruct->d_name)+2 > sizeof buf) + { + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); + goto err; + } + + r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,dstruct->d_name); + if (r <= 0 || r >= sizeof buf) + goto err; + if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) + goto err; + } + ret = 1; + +err: + if (d) closedir(d); + CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); + return ret; + } + +#endif +#endif + +#else + +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *dir) + { + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_READDIR); + + hFind = FindFirstFile(dir, &FindFileData); + /* Note that a side effect is that the CAs will be sorted by name */ + if(hFind == INVALID_HANDLE_VALUE) + { + SYSerr(SYS_F_OPENDIR, get_last_sys_error()); + ERR_add_error_data(3, "opendir('", dir, "')"); + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB); + goto err_noclose; + } + + do + { + char buf[1024]; + int r; + + if(strlen(dir)+strlen(FindFileData.cFileName)+2 > sizeof buf) + { + SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG); + goto err; + } + + r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,FindFileData.cFileName); + if (r <= 0 || r >= sizeof buf) + goto err; + if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) + goto err; + } + while (FindNextFile(hFind, &FindFileData) != FALSE); + ret = 1; + +err: + FindClose(hFind); +err_noclose: + CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); + return ret; + } + +#endif diff --git a/src/lib/libssl/ssl_ciph.c b/src/lib/libssl/ssl_ciph.c index 820994408b..cdd8dde128 100644 --- a/src/lib/libssl/ssl_ciph.c +++ b/src/lib/libssl/ssl_ciph.c @@ -57,7 +57,8 @@ */ #include -#include "objects.h" +#include +#include #include "ssl_locl.h" #define SSL_ENC_DES_IDX 0 @@ -67,37 +68,28 @@ #define SSL_ENC_IDEA_IDX 4 #define SSL_ENC_eFZA_IDX 5 #define SSL_ENC_NULL_IDX 6 -#define SSL_ENC_NUM_IDX 7 +#define SSL_ENC_AES128_IDX 7 +#define SSL_ENC_AES256_IDX 8 +#define SSL_ENC_NUM_IDX 9 -static EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={ +static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={ NULL,NULL,NULL,NULL,NULL,NULL, }; +static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL; + #define SSL_MD_MD5_IDX 0 #define SSL_MD_SHA1_IDX 1 #define SSL_MD_NUM_IDX 2 -static EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={ +static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={ NULL,NULL, }; -typedef struct cipher_sort_st - { - SSL_CIPHER *cipher; - int pref; - } CIPHER_SORT; - #define CIPHER_ADD 1 #define CIPHER_KILL 2 #define CIPHER_DEL 3 #define CIPHER_ORD 4 - -typedef struct cipher_choice_st - { - int type; - unsigned long algorithms; - unsigned long mask; - long top; - } CIPHER_CHOICE; +#define CIPHER_SPECIAL 5 typedef struct cipher_order_st { @@ -107,59 +99,62 @@ typedef struct cipher_order_st struct cipher_order_st *next,*prev; } CIPHER_ORDER; -static SSL_CIPHER cipher_aliases[]={ - {0,SSL_TXT_ALL, 0,SSL_ALL, 0,SSL_ALL}, /* must be first */ - {0,SSL_TXT_kRSA,0,SSL_kRSA, 0,SSL_MKEY_MASK}, - {0,SSL_TXT_kDHr,0,SSL_kDHr, 0,SSL_MKEY_MASK}, - {0,SSL_TXT_kDHd,0,SSL_kDHd, 0,SSL_MKEY_MASK}, - {0,SSL_TXT_kEDH,0,SSL_kEDH, 0,SSL_MKEY_MASK}, - {0,SSL_TXT_kFZA,0,SSL_kFZA, 0,SSL_MKEY_MASK}, - {0,SSL_TXT_DH, 0,SSL_DH, 0,SSL_MKEY_MASK}, - {0,SSL_TXT_EDH, 0,SSL_EDH, 0,SSL_MKEY_MASK|SSL_AUTH_MASK}, - - {0,SSL_TXT_aRSA,0,SSL_aRSA, 0,SSL_AUTH_MASK}, - {0,SSL_TXT_aDSS,0,SSL_aDSS, 0,SSL_AUTH_MASK}, - {0,SSL_TXT_aFZA,0,SSL_aFZA, 0,SSL_AUTH_MASK}, - {0,SSL_TXT_aNULL,0,SSL_aNULL,0,SSL_AUTH_MASK}, - {0,SSL_TXT_aDH, 0,SSL_aDH, 0,SSL_AUTH_MASK}, - {0,SSL_TXT_DSS, 0,SSL_DSS, 0,SSL_AUTH_MASK}, - - {0,SSL_TXT_DES, 0,SSL_DES, 0,SSL_ENC_MASK}, - {0,SSL_TXT_3DES,0,SSL_3DES, 0,SSL_ENC_MASK}, - {0,SSL_TXT_RC4, 0,SSL_RC4, 0,SSL_ENC_MASK}, - {0,SSL_TXT_RC2, 0,SSL_RC2, 0,SSL_ENC_MASK}, - {0,SSL_TXT_IDEA,0,SSL_IDEA, 0,SSL_ENC_MASK}, - {0,SSL_TXT_eNULL,0,SSL_eNULL,0,SSL_ENC_MASK}, - {0,SSL_TXT_eFZA,0,SSL_eFZA, 0,SSL_ENC_MASK}, - - {0,SSL_TXT_MD5, 0,SSL_MD5, 0,SSL_MAC_MASK}, - {0,SSL_TXT_SHA1,0,SSL_SHA1, 0,SSL_MAC_MASK}, - {0,SSL_TXT_SHA, 0,SSL_SHA, 0,SSL_MAC_MASK}, - - {0,SSL_TXT_NULL,0,SSL_NULL, 0,SSL_ENC_MASK}, - {0,SSL_TXT_RSA, 0,SSL_RSA, 0,SSL_AUTH_MASK|SSL_MKEY_MASK}, - {0,SSL_TXT_ADH, 0,SSL_ADH, 0,SSL_AUTH_MASK|SSL_MKEY_MASK}, - {0,SSL_TXT_FZA, 0,SSL_FZA, 0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK}, - - {0,SSL_TXT_EXP, 0,SSL_EXP, 0,SSL_EXP_MASK}, - {0,SSL_TXT_EXPORT,0,SSL_EXPORT,0,SSL_EXP_MASK}, - {0,SSL_TXT_SSLV2,0,SSL_SSLV2,0,SSL_SSL_MASK}, - {0,SSL_TXT_SSLV3,0,SSL_SSLV3,0,SSL_SSL_MASK}, - {0,SSL_TXT_LOW, 0,SSL_LOW,0,SSL_STRONG_MASK}, - {0,SSL_TXT_MEDIUM,0,SSL_MEDIUM,0,SSL_STRONG_MASK}, - {0,SSL_TXT_HIGH, 0,SSL_HIGH,0,SSL_STRONG_MASK}, +static const SSL_CIPHER cipher_aliases[]={ + /* Don't include eNULL unless specifically enabled. + * Similarly, don't include AES in ALL because these ciphers are not yet official. */ + {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL & ~SSL_AES, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL}, /* must be first */ + {0,SSL_TXT_kKRB5,0,SSL_kKRB5,0,0,0,0,SSL_MKEY_MASK,0}, /* VRS Kerberos5 */ + {0,SSL_TXT_kRSA,0,SSL_kRSA, 0,0,0,0,SSL_MKEY_MASK,0}, + {0,SSL_TXT_kDHr,0,SSL_kDHr, 0,0,0,0,SSL_MKEY_MASK,0}, + {0,SSL_TXT_kDHd,0,SSL_kDHd, 0,0,0,0,SSL_MKEY_MASK,0}, + {0,SSL_TXT_kEDH,0,SSL_kEDH, 0,0,0,0,SSL_MKEY_MASK,0}, + {0,SSL_TXT_kFZA,0,SSL_kFZA, 0,0,0,0,SSL_MKEY_MASK,0}, + {0,SSL_TXT_DH, 0,SSL_DH, 0,0,0,0,SSL_MKEY_MASK,0}, + {0,SSL_TXT_EDH, 0,SSL_EDH, 0,0,0,0,SSL_MKEY_MASK|SSL_AUTH_MASK,0}, + + {0,SSL_TXT_aKRB5,0,SSL_aKRB5,0,0,0,0,SSL_AUTH_MASK,0}, /* VRS Kerberos5 */ + {0,SSL_TXT_aRSA,0,SSL_aRSA, 0,0,0,0,SSL_AUTH_MASK,0}, + {0,SSL_TXT_aDSS,0,SSL_aDSS, 0,0,0,0,SSL_AUTH_MASK,0}, + {0,SSL_TXT_aFZA,0,SSL_aFZA, 0,0,0,0,SSL_AUTH_MASK,0}, + {0,SSL_TXT_aNULL,0,SSL_aNULL,0,0,0,0,SSL_AUTH_MASK,0}, + {0,SSL_TXT_aDH, 0,SSL_aDH, 0,0,0,0,SSL_AUTH_MASK,0}, + {0,SSL_TXT_DSS, 0,SSL_DSS, 0,0,0,0,SSL_AUTH_MASK,0}, + + {0,SSL_TXT_DES, 0,SSL_DES, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_3DES,0,SSL_3DES, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_RC4, 0,SSL_RC4, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_RC2, 0,SSL_RC2, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_IDEA,0,SSL_IDEA, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_eNULL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_eFZA,0,SSL_eFZA, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_AES, 0,SSL_AES, 0,0,0,0,SSL_ENC_MASK,0}, + + {0,SSL_TXT_MD5, 0,SSL_MD5, 0,0,0,0,SSL_MAC_MASK,0}, + {0,SSL_TXT_SHA1,0,SSL_SHA1, 0,0,0,0,SSL_MAC_MASK,0}, + {0,SSL_TXT_SHA, 0,SSL_SHA, 0,0,0,0,SSL_MAC_MASK,0}, + + {0,SSL_TXT_NULL,0,SSL_NULL, 0,0,0,0,SSL_ENC_MASK,0}, + {0,SSL_TXT_KRB5,0,SSL_KRB5, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0}, + {0,SSL_TXT_RSA, 0,SSL_RSA, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0}, + {0,SSL_TXT_ADH, 0,SSL_ADH, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0}, + {0,SSL_TXT_FZA, 0,SSL_FZA, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK,0}, + + {0,SSL_TXT_SSLV2, 0,SSL_SSLV2, 0,0,0,0,SSL_SSL_MASK,0}, + {0,SSL_TXT_SSLV3, 0,SSL_SSLV3, 0,0,0,0,SSL_SSL_MASK,0}, + {0,SSL_TXT_TLSV1, 0,SSL_TLSV1, 0,0,0,0,SSL_SSL_MASK,0}, + + {0,SSL_TXT_EXP ,0, 0,SSL_EXPORT, 0,0,0,0,SSL_EXP_MASK}, + {0,SSL_TXT_EXPORT,0, 0,SSL_EXPORT, 0,0,0,0,SSL_EXP_MASK}, + {0,SSL_TXT_EXP40, 0, 0, SSL_EXP40, 0,0,0,0,SSL_STRONG_MASK}, + {0,SSL_TXT_EXP56, 0, 0, SSL_EXP56, 0,0,0,0,SSL_STRONG_MASK}, + {0,SSL_TXT_LOW, 0, 0, SSL_LOW, 0,0,0,0,SSL_STRONG_MASK}, + {0,SSL_TXT_MEDIUM,0, 0,SSL_MEDIUM, 0,0,0,0,SSL_STRONG_MASK}, + {0,SSL_TXT_HIGH, 0, 0, SSL_HIGH, 0,0,0,0,SSL_STRONG_MASK}, }; static int init_ciphers=1; -static void load_ciphers(); - -static int cmp_by_name(a,b) -SSL_CIPHER **a,**b; - { - return(strcmp((*a)->name,(*b)->name)); - } -static void load_ciphers() +static void load_ciphers(void) { init_ciphers=0; ssl_cipher_methods[SSL_ENC_DES_IDX]= @@ -172,6 +167,10 @@ static void load_ciphers() EVP_get_cipherbyname(SN_rc2_cbc); ssl_cipher_methods[SSL_ENC_IDEA_IDX]= EVP_get_cipherbyname(SN_idea_cbc); + ssl_cipher_methods[SSL_ENC_AES128_IDX]= + EVP_get_cipherbyname(SN_aes_128_cbc); + ssl_cipher_methods[SSL_ENC_AES256_IDX]= + EVP_get_cipherbyname(SN_aes_256_cbc); ssl_digest_methods[SSL_MD_MD5_IDX]= EVP_get_digestbyname(SN_md5); @@ -179,14 +178,38 @@ static void load_ciphers() EVP_get_digestbyname(SN_sha1); } -int ssl_cipher_get_evp(c,enc,md) -SSL_CIPHER *c; -EVP_CIPHER **enc; -EVP_MD **md; +int ssl_cipher_get_evp(SSL_SESSION *s, const EVP_CIPHER **enc, + const EVP_MD **md, SSL_COMP **comp) { int i; + SSL_CIPHER *c; + c=s->cipher; if (c == NULL) return(0); + if (comp != NULL) + { + SSL_COMP ctmp; + + if (s->compress_meth == 0) + *comp=NULL; + else if (ssl_comp_methods == NULL) + { + /* bad */ + *comp=NULL; + } + else + { + + ctmp.id=s->compress_meth; + i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp); + if (i >= 0) + *comp=sk_SSL_COMP_value(ssl_comp_methods,i); + else + *comp=NULL; + } + } + + if ((enc == NULL) || (md == NULL)) return(0); switch (c->algorithms & SSL_ENC_MASK) { @@ -208,6 +231,13 @@ EVP_MD **md; case SSL_eNULL: i=SSL_ENC_NULL_IDX; break; + case SSL_AES: + switch(c->alg_bits) + { + case 128: i=SSL_ENC_AES128_IDX; break; + case 256: i=SSL_ENC_AES256_IDX; break; + default: i=-1; break; + } break; default: i= -1; @@ -250,8 +280,8 @@ EVP_MD **md; #define ITEM_SEP(a) \ (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) -static void ll_append_tail(head,curr,tail) -CIPHER_ORDER **head,*curr,**tail; +static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) { if (curr == *tail) return; if (curr == *head) @@ -266,181 +296,359 @@ CIPHER_ORDER **head,*curr,**tail; *tail=curr; } -STACK *ssl_create_cipher_list(ssl_method,cipher_list,cipher_list_by_id,str) -SSL_METHOD *ssl_method; -STACK **cipher_list,**cipher_list_by_id; -char *str; +static unsigned long ssl_cipher_get_disabled(void) { - SSL_CIPHER *c; - char *l; - STACK *ret=NULL,*ok=NULL; -#define CL_BUF 40 - char buf[CL_BUF]; - char *tmp_str=NULL; - unsigned long mask,algorithms,ma; - char *start; - int i,j,k,num=0,ch,multi; - unsigned long al; - STACK *ca_list=NULL; - int current_x,num_x; - CIPHER_CHOICE *ops=NULL; - CIPHER_ORDER *list=NULL,*head=NULL,*tail=NULL,*curr,*tail2,*curr2; - int list_num; - int type; - SSL_CIPHER c_tmp,*cp; - - if (str == NULL) return(NULL); - - if (strncmp(str,"DEFAULT",7) == 0) - { - i=strlen(str)+2+strlen(SSL_DEFAULT_CIPHER_LIST); - if ((tmp_str=Malloc(i)) == NULL) - { - SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); - goto err; - } - strcpy(tmp_str,SSL_DEFAULT_CIPHER_LIST); - strcat(tmp_str,":"); - strcat(tmp_str,&(str[7])); - str=tmp_str; - } - if (init_ciphers) load_ciphers(); - - num=ssl_method->num_ciphers(); - - if ((ret=(STACK *)sk_new(NULL)) == NULL) goto err; - if ((ca_list=(STACK *)sk_new(cmp_by_name)) == NULL) goto err; + unsigned long mask; - mask =SSL_kFZA; -#ifdef NO_RSA - mask|=SSL_aRSA|SSL_kRSA; + mask = SSL_kFZA; +#ifdef OPENSSL_NO_RSA + mask |= SSL_aRSA|SSL_kRSA; #endif -#ifdef NO_DSA - mask|=SSL_aDSS; +#ifdef OPENSSL_NO_DSA + mask |= SSL_aDSS; #endif -#ifdef NO_DH - mask|=SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH; +#ifdef OPENSSL_NO_DH + mask |= SSL_kDHr|SSL_kDHd|SSL_kEDH|SSL_aDH; +#endif +#ifdef OPENSSL_NO_KRB5 + mask |= SSL_kKRB5|SSL_aKRB5; #endif -#ifndef SSL_ALLOW_ENULL - mask|=SSL_eNULL; +#ifdef SSL_FORBID_ENULL + mask |= SSL_eNULL; #endif - mask|=(ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL)?SSL_DES :0; - mask|=(ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL)?SSL_3DES:0; - mask|=(ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL)?SSL_RC4 :0; - mask|=(ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL)?SSL_RC2 :0; - mask|=(ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL)?SSL_IDEA:0; - mask|=(ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL)?SSL_eFZA:0; + mask |= (ssl_cipher_methods[SSL_ENC_DES_IDX ] == NULL) ? SSL_DES :0; + mask |= (ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL) ? SSL_3DES:0; + mask |= (ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL) ? SSL_RC4 :0; + mask |= (ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL) ? SSL_RC2 :0; + mask |= (ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL) ? SSL_IDEA:0; + mask |= (ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL) ? SSL_eFZA:0; + mask |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES:0; - mask|=(ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL)?SSL_MD5 :0; - mask|=(ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL)?SSL_SHA1:0; + mask |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0; + mask |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0; - if ((list=(CIPHER_ORDER *)Malloc(sizeof(CIPHER_ORDER)*num)) == NULL) - goto err; + return(mask); + } + +static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, + int num_of_ciphers, unsigned long mask, CIPHER_ORDER *list, + CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) + { + int i, list_num; + SSL_CIPHER *c; + + /* + * We have num_of_ciphers descriptions compiled in, depending on the + * method selected (SSLv2 and/or SSLv3, TLSv1 etc). + * These will later be sorted in a linked list with at most num + * entries. + */ /* Get the initial list of ciphers */ - list_num=0; - for (i=0; iget_cipher((unsigned int)i); + c = ssl_method->get_cipher(i); /* drop those that use any of that is not available */ if ((c != NULL) && c->valid && !(c->algorithms & mask)) { - list[list_num].cipher=c; - list[list_num].next=NULL; - list[list_num].prev=NULL; - list[list_num].active=0; + list[list_num].cipher = c; + list[list_num].next = NULL; + list[list_num].prev = NULL; + list[list_num].active = 0; list_num++; +#ifdef KSSL_DEBUG + printf("\t%d: %s %lx %lx\n",i,c->name,c->id,c->algorithms); +#endif /* KSSL_DEBUG */ + /* if (!sk_push(ca_list,(char *)c)) goto err; + */ } } - - for (i=1; i 0) { - head= &(list[0]); - head->prev=NULL; - head->next= &(list[1]); - tail= &(list[list_num-1]); - tail->prev= &(list[list_num-2]); - tail->next=NULL; + (*head_p) = &(list[0]); + (*head_p)->prev = NULL; + (*head_p)->next = &(list[1]); + (*tail_p) = &(list[list_num - 1]); + (*tail_p)->prev = &(list[list_num - 2]); + (*tail_p)->next = NULL; } + } - /* special case */ - cipher_aliases[0].algorithms= ~mask; +static void ssl_cipher_collect_aliases(SSL_CIPHER **ca_list, + int num_of_group_aliases, unsigned long mask, + CIPHER_ORDER *head) + { + CIPHER_ORDER *ciph_curr; + SSL_CIPHER **ca_curr; + int i; - /* get the aliases */ - k=sizeof(cipher_aliases)/sizeof(SSL_CIPHER); - for (j=0; jcipher; + ca_curr++; + ciph_curr = ciph_curr->next; } - /* ca_list now holds a 'stack' of SSL_CIPHERS, some real, some - * 'aliases' */ + /* + * Now we add the available ones from the cipher_aliases[] table. + * They represent either an algorithm, that must be fully + * supported (not match any bit in mask) or represent a cipher + * strength value (will be added in any case because algorithms=0). + */ + for (i = 0; i < num_of_group_aliases; i++) + { + if ((i == 0) || /* always fetch "ALL" */ + !(cipher_aliases[i].algorithms & mask)) + { + *ca_curr = (SSL_CIPHER *)(cipher_aliases + i); + ca_curr++; + } + } - /* how many parameters are there? */ - num=1; - for (l=str; *l; l++) - if (ITEM_SEP(*l)) - num++; - ops=(CIPHER_CHOICE *)Malloc(sizeof(CIPHER_CHOICE)*num); - if (ops == NULL) goto err; - memset(ops,0,sizeof(CIPHER_CHOICE)*num); + *ca_curr = NULL; /* end of list */ + } + +static void ssl_cipher_apply_rule(unsigned long algorithms, unsigned long mask, + unsigned long algo_strength, unsigned long mask_strength, + int rule, int strength_bits, CIPHER_ORDER *list, + CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) + { + CIPHER_ORDER *head, *tail, *curr, *curr2, *tail2; + SSL_CIPHER *cp; + unsigned long ma, ma_s; - /* we now parse the input string and create our operations */ - l=str; - i=0; - current_x=0; +#ifdef CIPHER_DEBUG + printf("Applying rule %d with %08lx %08lx %08lx %08lx (%d)\n", + rule, algorithms, mask, algo_strength, mask_strength, + strength_bits); +#endif + curr = head = *head_p; + curr2 = head; + tail2 = tail = *tail_p; for (;;) { - ch= *l; + if ((curr == NULL) || (curr == tail2)) break; + curr = curr2; + curr2 = curr->next; + + cp = curr->cipher; + + /* + * Selection criteria is either the number of strength_bits + * or the algorithm used. + */ + if (strength_bits == -1) + { + ma = mask & cp->algorithms; + ma_s = mask_strength & cp->algo_strength; + +#ifdef CIPHER_DEBUG + printf("\nName: %s:\nAlgo = %08lx Algo_strength = %08lx\nMask = %08lx Mask_strength %08lx\n", cp->name, cp->algorithms, cp->algo_strength, mask, mask_strength); + printf("ma = %08lx ma_s %08lx, ma&algo=%08lx, ma_s&algos=%08lx\n", ma, ma_s, ma&algorithms, ma_s&algo_strength); +#endif + /* + * Select: if none of the mask bit was met from the + * cipher or not all of the bits were met, the + * selection does not apply. + */ + if (((ma == 0) && (ma_s == 0)) || + ((ma & algorithms) != ma) || + ((ma_s & algo_strength) != ma_s)) + continue; /* does not apply */ + } + else if (strength_bits != cp->strength_bits) + continue; /* does not apply */ + +#ifdef CIPHER_DEBUG + printf("Action = %d\n", rule); +#endif + + /* add the cipher if it has not been added yet. */ + if (rule == CIPHER_ADD) + { + if (!curr->active) + { + ll_append_tail(&head, curr, &tail); + curr->active = 1; + } + } + /* Move the added cipher to this location */ + else if (rule == CIPHER_ORD) + { + if (curr->active) + { + ll_append_tail(&head, curr, &tail); + } + } + else if (rule == CIPHER_DEL) + curr->active = 0; + else if (rule == CIPHER_KILL) + { + if (head == curr) + head = curr->next; + else + curr->prev->next = curr->next; + if (tail == curr) + tail = curr->prev; + curr->active = 0; + if (curr->next != NULL) + curr->next->prev = curr->prev; + if (curr->prev != NULL) + curr->prev->next = curr->next; + curr->next = NULL; + curr->prev = NULL; + } + } + + *head_p = head; + *tail_p = tail; + } + +static int ssl_cipher_strength_sort(CIPHER_ORDER *list, CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) + { + int max_strength_bits, i, *number_uses; + CIPHER_ORDER *curr; + + /* + * This routine sorts the ciphers with descending strength. The sorting + * must keep the pre-sorted sequence, so we apply the normal sorting + * routine as '+' movement to the end of the list. + */ + max_strength_bits = 0; + curr = *head_p; + while (curr != NULL) + { + if (curr->active && + (curr->cipher->strength_bits > max_strength_bits)) + max_strength_bits = curr->cipher->strength_bits; + curr = curr->next; + } - if (ch == '\0') break; + number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); + if (!number_uses) + { + SSLerr(SSL_F_SSL_CIPHER_STRENGTH_SORT,ERR_R_MALLOC_FAILURE); + return(0); + } + memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int)); + + /* + * Now find the strength_bits values actually used + */ + curr = *head_p; + while (curr != NULL) + { + if (curr->active) + number_uses[curr->cipher->strength_bits]++; + curr = curr->next; + } + /* + * Go through the list of used strength_bits values in descending + * order. + */ + for (i = max_strength_bits; i >= 0; i--) + if (number_uses[i] > 0) + ssl_cipher_apply_rule(0, 0, 0, 0, CIPHER_ORD, i, + list, head_p, tail_p); + + OPENSSL_free(number_uses); + return(1); + } + +static int ssl_cipher_process_rulestr(const char *rule_str, + CIPHER_ORDER *list, CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p, SSL_CIPHER **ca_list) + { + unsigned long algorithms, mask, algo_strength, mask_strength; + const char *l, *start, *buf; + int j, multi, found, rule, retval, ok, buflen; + char ch; + + retval = 1; + l = rule_str; + for (;;) + { + ch = *l; + if (ch == '\0') + break; /* done */ if (ch == '-') - { j=CIPHER_DEL; l++; } + { rule = CIPHER_DEL; l++; } else if (ch == '+') - { j=CIPHER_ORD; l++; } + { rule = CIPHER_ORD; l++; } else if (ch == '!') - { j=CIPHER_KILL; l++; } - else - { j=CIPHER_ADD; } + { rule = CIPHER_KILL; l++; } + else if (ch == '@') + { rule = CIPHER_SPECIAL; l++; } + else + { rule = CIPHER_ADD; } if (ITEM_SEP(ch)) { l++; continue; } - ops[current_x].type=j; - ops[current_x].algorithms=0; - ops[current_x].mask=0; + + algorithms = mask = algo_strength = mask_strength = 0; start=l; for (;;) { - ch= *l; - i=0; + ch = *l; + buf = l; + buflen = 0; +#ifndef CHARSET_EBCDIC while ( ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || ((ch >= 'a') && (ch <= 'z')) || (ch == '-')) +#else + while ( isalnum(ch) || (ch == '-')) +#endif { - buf[i]=ch; - ch= *(++l); - i++; - if (i >= (CL_BUF-2)) break; + ch = *(++l); + buflen++; } - buf[i]='\0'; + + if (buflen == 0) + { + /* + * We hit something we cannot deal with, + * it is no command or separator nor + * alphanumeric, so we call this an error. + */ + SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, + SSL_R_INVALID_COMMAND); + retval = found = 0; + l++; + break; + } + + if (rule == CIPHER_SPECIAL) + { + found = 0; /* unused -- avoid compiler warning */ + break; /* special treatment */ + } /* check for multi-part specification */ if (ch == '+') @@ -451,151 +659,262 @@ char *str; else multi=0; - c_tmp.name=buf; - j=sk_find(ca_list,(char *)&c_tmp); - if (j < 0) - goto end_loop; + /* + * Now search for the cipher alias in the ca_list. Be careful + * with the strncmp, because the "buflen" limitation + * will make the rule "ADH:SOME" and the cipher + * "ADH-MY-CIPHER" look like a match for buflen=3. + * So additionally check whether the cipher name found + * has the correct length. We can save a strlen() call: + * just checking for the '\0' at the right place is + * sufficient, we have to strncmp() anyway. + */ + j = found = 0; + while (ca_list[j]) + { + if ((ca_list[j]->name[buflen] == '\0') && + !strncmp(buf, ca_list[j]->name, buflen)) + { + found = 1; + break; + } + else + j++; + } + if (!found) + break; /* ignore this entry */ + + algorithms |= ca_list[j]->algorithms; + mask |= ca_list[j]->mask; + algo_strength |= ca_list[j]->algo_strength; + mask_strength |= ca_list[j]->mask_strength; - cp=(SSL_CIPHER *)sk_value(ca_list,j); - ops[current_x].algorithms|=cp->algorithms; - /* We add the SSL_SSL_MASK so we can match the - * SSLv2 and SSLv3 versions of RC4-MD5 */ - ops[current_x].mask|=cp->mask; if (!multi) break; } - current_x++; - if (ch == '\0') break; -end_loop: - /* Make sure we scan until the next valid start point */ - while ((*l != '\0') && ITEM_SEP(*l)) - l++; + + /* + * Ok, we have the rule, now apply it + */ + if (rule == CIPHER_SPECIAL) + { /* special command */ + ok = 0; + if ((buflen == 8) && + !strncmp(buf, "STRENGTH", 8)) + ok = ssl_cipher_strength_sort(list, + head_p, tail_p); + else + SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, + SSL_R_INVALID_COMMAND); + if (ok == 0) + retval = 0; + /* + * We do not support any "multi" options + * together with "@", so throw away the + * rest of the command, if any left, until + * end or ':' is found. + */ + while ((*l != '\0') && ITEM_SEP(*l)) + l++; + } + else if (found) + { + ssl_cipher_apply_rule(algorithms, mask, + algo_strength, mask_strength, rule, -1, + list, head_p, tail_p); + } + else + { + while ((*l != '\0') && ITEM_SEP(*l)) + l++; + } + if (*l == '\0') break; /* done */ } - num_x=current_x; - current_x=0; + return(retval); + } + +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, + STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) **cipher_list_by_id, + const char *rule_str) + { + int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; + unsigned long disabled_mask; + STACK_OF(SSL_CIPHER) *cipherstack; + const char *rule_p; + CIPHER_ORDER *list = NULL, *head = NULL, *tail = NULL, *curr; + SSL_CIPHER **ca_list = NULL; + + /* + * Return with error if nothing to do. + */ + if (rule_str == NULL) return(NULL); + + if (init_ciphers) load_ciphers(); - /* We will now process the list of ciphers, once for each category, to - * decide what we should do with it. */ - for (j=0; jnum_ciphers(); +#ifdef KSSL_DEBUG + printf("ssl_create_cipher_list() for %d ciphers\n", num_of_ciphers); +#endif /* KSSL_DEBUG */ + list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers); + if (list == NULL) { - algorithms=ops[j].algorithms; - type=ops[j].type; - mask=ops[j].mask; + SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); + return(NULL); /* Failure */ + } - curr=head; - curr2=head; - tail2=tail; - for (;;) - { - if ((curr == NULL) || (curr == tail2)) break; - curr=curr2; - curr2=curr->next; + ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, disabled_mask, + list, &head, &tail); + + /* + * We also need cipher aliases for selecting based on the rule_str. + * There might be two types of entries in the rule_str: 1) names + * of ciphers themselves 2) aliases for groups of ciphers. + * For 1) we need the available ciphers and for 2) the cipher + * groups of cipher_aliases added together in one list (otherwise + * we would be happy with just the cipher_aliases table). + */ + num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER); + num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1; + ca_list = + (SSL_CIPHER **)OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max); + if (ca_list == NULL) + { + OPENSSL_free(list); + SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE); + return(NULL); /* Failure */ + } + ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, disabled_mask, + head); + + /* + * If the rule_string begins with DEFAULT, apply the default rule + * before using the (possibly available) additional rules. + */ + ok = 1; + rule_p = rule_str; + if (strncmp(rule_str,"DEFAULT",7) == 0) + { + ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, + list, &head, &tail, ca_list); + rule_p += 7; + if (*rule_p == ':') + rule_p++; + } - cp=curr->cipher; - ma=mask & cp->algorithms; - if ((ma == 0) || ((ma & algorithms) != ma)) - { - /* does not apply */ - continue; - } + if (ok && (strlen(rule_p) > 0)) + ok = ssl_cipher_process_rulestr(rule_p, list, &head, &tail, + ca_list); - /* add the cipher if it has not been added yet. */ - if (type == CIPHER_ADD) - { - if (!curr->active) - { - ll_append_tail(&head,curr,&tail); - curr->active=1; - } - } - /* Move the added cipher to this location */ - else if (type == CIPHER_ORD) - { - if (curr->active) - { - ll_append_tail(&head,curr,&tail); - } - } - else if (type == CIPHER_DEL) - curr->active=0; - if (type == CIPHER_KILL) - { - if (head == curr) - head=curr->next; - else - curr->prev->next=curr->next; - if (tail == curr) - tail=curr->prev; - curr->active=0; - if (curr->next != NULL) - curr->next->prev=curr->prev; - if (curr->prev != NULL) - curr->prev->next=curr->next; - curr->next=NULL; - curr->prev=NULL; - } - } + OPENSSL_free(ca_list); /* Not needed anymore */ + + if (!ok) + { /* Rule processing failure */ + OPENSSL_free(list); + return(NULL); + } + /* + * Allocate new "cipherstack" for the result, return with error + * if we cannot get one. + */ + if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) + { + OPENSSL_free(list); + return(NULL); } - for (curr=head; curr != NULL; curr=curr->next) + /* + * The cipher selection for the list is done. The ciphers are added + * to the resulting precedence to the STACK_OF(SSL_CIPHER). + */ + for (curr = head; curr != NULL; curr = curr->next) { if (curr->active) { - sk_push(ret,(char *)curr->cipher); + sk_SSL_CIPHER_push(cipherstack, curr->cipher); #ifdef CIPHER_DEBUG printf("<%s>\n",curr->cipher->name); #endif } } - + OPENSSL_free(list); /* Not needed any longer */ + + /* + * The following passage is a little bit odd. If pointer variables + * were supplied to hold STACK_OF(SSL_CIPHER) return information, + * the old memory pointed to is free()ed. Then, however, the + * cipher_list entry will be assigned just a copy of the returned + * cipher stack. For cipher_list_by_id a copy of the cipher stack + * will be created. See next comment... + */ if (cipher_list != NULL) { if (*cipher_list != NULL) - sk_free(*cipher_list); - *cipher_list=ret; + sk_SSL_CIPHER_free(*cipher_list); + *cipher_list = cipherstack; } if (cipher_list_by_id != NULL) { if (*cipher_list_by_id != NULL) - sk_free(*cipher_list_by_id); - *cipher_list_by_id=sk_dup(ret); + sk_SSL_CIPHER_free(*cipher_list_by_id); + *cipher_list_by_id = sk_SSL_CIPHER_dup(cipherstack); } + /* + * Now it is getting really strange. If something failed during + * the previous pointer assignment or if one of the pointers was + * not requested, the error condition is met. That might be + * discussable. The strange thing is however that in this case + * the memory "ret" pointed to is "free()ed" and hence the pointer + * cipher_list becomes wild. The memory reserved for + * cipher_list_by_id however is not "free()ed" and stays intact. + */ if ( (cipher_list_by_id == NULL) || (*cipher_list_by_id == NULL) || (cipher_list == NULL) || (*cipher_list == NULL)) - goto err; - sk_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp); - - ok=ret; - ret=NULL; -err: - if (tmp_str) Free(tmp_str); - if (ops != NULL) Free(ops); - if (ret != NULL) sk_free(ret); - if (ca_list != NULL) sk_free(ca_list); - if (list != NULL) Free(list); - return(ok); + { + sk_SSL_CIPHER_free(cipherstack); + return(NULL); + } + + sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp); + + return(cipherstack); } -char *SSL_CIPHER_description(cipher,buf,len) -SSL_CIPHER *cipher; -char *buf; -int len; +char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len) { - int export; + int is_export,pkl,kl; char *ver,*exp; char *kx,*au,*enc,*mac; - unsigned long alg,alg2; + unsigned long alg,alg2,alg_s; +#ifdef KSSL_DEBUG + static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s AL=%lx\n"; +#else static char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s%s\n"; - +#endif /* KSSL_DEBUG */ + alg=cipher->algorithms; + alg_s=cipher->algo_strength; alg2=cipher->algorithm2; - export=(alg&SSL_EXP)?1:0; - exp=(export)?" export":""; + is_export=SSL_C_IS_EXPORT(cipher); + pkl=SSL_C_EXPORT_PKEYLENGTH(cipher); + kl=SSL_C_EXPORT_KEYLENGTH(cipher); + exp=is_export?" export":""; if (alg & SSL_SSLV2) ver="SSLv2"; @@ -607,7 +926,7 @@ int len; switch (alg&SSL_MKEY_MASK) { case SSL_kRSA: - kx=(export)?"RSA(512)":"RSA"; + kx=is_export?(pkl == 512 ? "RSA(512)" : "RSA(1024)"):"RSA"; break; case SSL_kDHr: kx="DH/RSA"; @@ -615,11 +934,15 @@ int len; case SSL_kDHd: kx="DH/DSS"; break; + case SSL_kKRB5: /* VRS */ + case SSL_KRB5: /* VRS */ + kx="KRB5"; + break; case SSL_kFZA: kx="Fortezza"; break; case SSL_kEDH: - kx=(export)?"DH(512)":"DH"; + kx=is_export?(pkl == 512 ? "DH(512)" : "DH(1024)"):"DH"; break; default: kx="unknown"; @@ -636,6 +959,10 @@ int len; case SSL_aDH: au="DH"; break; + case SSL_aKRB5: /* VRS */ + case SSL_KRB5: /* VRS */ + au="KRB5"; + break; case SSL_aFZA: case SSL_aNULL: au="None"; @@ -648,16 +975,17 @@ int len; switch (alg&SSL_ENC_MASK) { case SSL_DES: - enc=export?"DES(40)":"DES(56)"; + enc=(is_export && kl == 5)?"DES(40)":"DES(56)"; break; case SSL_3DES: enc="3DES(168)"; break; case SSL_RC4: - enc=export?"RC4(40)":((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)"); + enc=is_export?(kl == 5 ? "RC4(40)" : "RC4(56)") + :((alg2&SSL2_CF_8_BYTE_ENC)?"RC4(64)":"RC4(128)"); break; case SSL_RC2: - enc=export?"RC2(40)":"RC2(128)"; + enc=is_export?(kl == 5 ? "RC2(40)" : "RC2(56)"):"RC2(128)"; break; case SSL_IDEA: enc="IDEA(128)"; @@ -668,6 +996,15 @@ int len; case SSL_eNULL: enc="None"; break; + case SSL_AES: + switch(cipher->strength_bits) + { + case 128: enc="AESdraft(128)"; break; + case 192: enc="AESdraft(192)"; break; + case 256: enc="AESdraft(256)"; break; + default: enc="AESdraft(?""?""?)"; break; + } + break; default: enc="unknown"; break; @@ -688,18 +1025,22 @@ int len; if (buf == NULL) { - buf=Malloc(128); - if (buf == NULL) return("Malloc Error"); + len=128; + buf=OPENSSL_malloc(len); + if (buf == NULL) return("OPENSSL_malloc Error"); } else if (len < 128) return("Buffer too small"); - sprintf(buf,format,cipher->name,ver,kx,au,enc,mac,exp); +#ifdef KSSL_DEBUG + BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp,alg); +#else + BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,exp); +#endif /* KSSL_DEBUG */ return(buf); } -char *SSL_CIPHER_get_version(c) -SSL_CIPHER *c; +char *SSL_CIPHER_get_version(SSL_CIPHER *c) { int i; @@ -714,45 +1055,78 @@ SSL_CIPHER *c; } /* return the actual cipher being used */ -char *SSL_CIPHER_get_name(c) -SSL_CIPHER *c; +const char *SSL_CIPHER_get_name(SSL_CIPHER *c) { if (c != NULL) return(c->name); return("(NONE)"); } -/* number of bits for symetric cipher */ -int SSL_CIPHER_get_bits(c,alg_bits) -SSL_CIPHER *c; -int *alg_bits; +/* number of bits for symmetric cipher */ +int SSL_CIPHER_get_bits(SSL_CIPHER *c, int *alg_bits) { - int ret=0,a=0; - EVP_CIPHER *enc; - EVP_MD *md; + int ret=0; if (c != NULL) { - if (!ssl_cipher_get_evp(c,&enc,&md)) - return(0); + if (alg_bits != NULL) *alg_bits = c->alg_bits; + ret = c->strength_bits; + } + return(ret); + } - a=EVP_CIPHER_key_length(enc)*8; +SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n) + { + SSL_COMP *ctmp; + int i,nn; - if (c->algorithms & SSL_EXP) - { - ret=40; - } - else - { - if (c->algorithm2 & SSL2_CF_8_BYTE_ENC) - ret=64; - else - ret=a; - } + if ((n == 0) || (sk == NULL)) return(NULL); + nn=sk_SSL_COMP_num(sk); + for (i=0; iid == n) + return(ctmp); } + return(NULL); + } - if (alg_bits != NULL) *alg_bits=a; - - return(ret); +static int sk_comp_cmp(const SSL_COMP * const *a, + const SSL_COMP * const *b) + { + return((*a)->id-(*b)->id); } +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) + { + return(ssl_comp_methods); + } + +int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) + { + SSL_COMP *comp; + STACK_OF(SSL_COMP) *sk; + + if (cm == NULL || cm->type == NID_undef) + return 1; + + MemCheck_off(); + comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP)); + comp->id=id; + comp->method=cm; + if (ssl_comp_methods == NULL) + sk=ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp); + else + sk=ssl_comp_methods; + if ((sk == NULL) || !sk_SSL_COMP_push(sk,comp)) + { + MemCheck_on(); + SSLerr(SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,ERR_R_MALLOC_FAILURE); + return(0); + } + else + { + MemCheck_on(); + return(1); + } + } diff --git a/src/lib/libssl/ssl_err.c b/src/lib/libssl/ssl_err.c index bcbb98591f..c32c4ef6e9 100644 --- a/src/lib/libssl/ssl_err.c +++ b/src/lib/libssl/ssl_err.c @@ -1,66 +1,69 @@ -/* lib/ssl/ssl_err.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* ssl/ssl_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. 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. + * + * 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 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.] + * 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 "err.h" -#include "ssl.h" +#include +#include /* BEGIN ERROR CODES */ -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA SSL_str_functs[]= { {ERR_PACK(0,SSL_F_CLIENT_CERTIFICATE,0), "CLIENT_CERTIFICATE"}, @@ -83,21 +86,27 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL23_CONNECT,0), "SSL23_CONNECT"}, {ERR_PACK(0,SSL_F_SSL23_GET_CLIENT_HELLO,0), "SSL23_GET_CLIENT_HELLO"}, {ERR_PACK(0,SSL_F_SSL23_GET_SERVER_HELLO,0), "SSL23_GET_SERVER_HELLO"}, +{ERR_PACK(0,SSL_F_SSL23_PEEK,0), "SSL23_PEEK"}, {ERR_PACK(0,SSL_F_SSL23_READ,0), "SSL23_READ"}, {ERR_PACK(0,SSL_F_SSL23_WRITE,0), "SSL23_WRITE"}, {ERR_PACK(0,SSL_F_SSL2_ACCEPT,0), "SSL2_ACCEPT"}, {ERR_PACK(0,SSL_F_SSL2_CONNECT,0), "SSL2_CONNECT"}, {ERR_PACK(0,SSL_F_SSL2_ENC_INIT,0), "SSL2_ENC_INIT"}, +{ERR_PACK(0,SSL_F_SSL2_PEEK,0), "SSL2_PEEK"}, {ERR_PACK(0,SSL_F_SSL2_READ,0), "SSL2_READ"}, +{ERR_PACK(0,SSL_F_SSL2_READ_INTERNAL,0), "SSL2_READ_INTERNAL"}, {ERR_PACK(0,SSL_F_SSL2_SET_CERTIFICATE,0), "SSL2_SET_CERTIFICATE"}, {ERR_PACK(0,SSL_F_SSL2_WRITE,0), "SSL2_WRITE"}, {ERR_PACK(0,SSL_F_SSL3_ACCEPT,0), "SSL3_ACCEPT"}, +{ERR_PACK(0,SSL_F_SSL3_CALLBACK_CTRL,0), "SSL3_CALLBACK_CTRL"}, {ERR_PACK(0,SSL_F_SSL3_CHANGE_CIPHER_STATE,0), "SSL3_CHANGE_CIPHER_STATE"}, {ERR_PACK(0,SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,0), "SSL3_CHECK_CERT_AND_ALGORITHM"}, {ERR_PACK(0,SSL_F_SSL3_CLIENT_HELLO,0), "SSL3_CLIENT_HELLO"}, {ERR_PACK(0,SSL_F_SSL3_CONNECT,0), "SSL3_CONNECT"}, +{ERR_PACK(0,SSL_F_SSL3_CTRL,0), "SSL3_CTRL"}, {ERR_PACK(0,SSL_F_SSL3_CTX_CTRL,0), "SSL3_CTX_CTRL"}, {ERR_PACK(0,SSL_F_SSL3_ENC,0), "SSL3_ENC"}, +{ERR_PACK(0,SSL_F_SSL3_GENERATE_KEY_BLOCK,0), "SSL3_GENERATE_KEY_BLOCK"}, {ERR_PACK(0,SSL_F_SSL3_GET_CERTIFICATE_REQUEST,0), "SSL3_GET_CERTIFICATE_REQUEST"}, {ERR_PACK(0,SSL_F_SSL3_GET_CERT_VERIFY,0), "SSL3_GET_CERT_VERIFY"}, {ERR_PACK(0,SSL_F_SSL3_GET_CLIENT_CERTIFICATE,0), "SSL3_GET_CLIENT_CERTIFICATE"}, @@ -111,6 +120,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL3_GET_SERVER_DONE,0), "SSL3_GET_SERVER_DONE"}, {ERR_PACK(0,SSL_F_SSL3_GET_SERVER_HELLO,0), "SSL3_GET_SERVER_HELLO"}, {ERR_PACK(0,SSL_F_SSL3_OUTPUT_CERT_CHAIN,0), "SSL3_OUTPUT_CERT_CHAIN"}, +{ERR_PACK(0,SSL_F_SSL3_PEEK,0), "SSL3_PEEK"}, {ERR_PACK(0,SSL_F_SSL3_READ_BYTES,0), "SSL3_READ_BYTES"}, {ERR_PACK(0,SSL_F_SSL3_READ_N,0), "SSL3_READ_N"}, {ERR_PACK(0,SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,0), "SSL3_SEND_CERTIFICATE_REQUEST"}, @@ -123,16 +133,30 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL3_SETUP_KEY_BLOCK,0), "SSL3_SETUP_KEY_BLOCK"}, {ERR_PACK(0,SSL_F_SSL3_WRITE_BYTES,0), "SSL3_WRITE_BYTES"}, {ERR_PACK(0,SSL_F_SSL3_WRITE_PENDING,0), "SSL3_WRITE_PENDING"}, +{ERR_PACK(0,SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,0), "SSL_add_dir_cert_subjects_to_stack"}, +{ERR_PACK(0,SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,0), "SSL_add_file_cert_subjects_to_stack"}, {ERR_PACK(0,SSL_F_SSL_BAD_METHOD,0), "SSL_BAD_METHOD"}, {ERR_PACK(0,SSL_F_SSL_BYTES_TO_CIPHER_LIST,0), "SSL_BYTES_TO_CIPHER_LIST"}, +{ERR_PACK(0,SSL_F_SSL_CERT_DUP,0), "SSL_CERT_DUP"}, +{ERR_PACK(0,SSL_F_SSL_CERT_INST,0), "SSL_CERT_INST"}, +{ERR_PACK(0,SSL_F_SSL_CERT_INSTANTIATE,0), "SSL_CERT_INSTANTIATE"}, {ERR_PACK(0,SSL_F_SSL_CERT_NEW,0), "SSL_CERT_NEW"}, {ERR_PACK(0,SSL_F_SSL_CHECK_PRIVATE_KEY,0), "SSL_check_private_key"}, +{ERR_PACK(0,SSL_F_SSL_CIPHER_PROCESS_RULESTR,0), "SSL_CIPHER_PROCESS_RULESTR"}, +{ERR_PACK(0,SSL_F_SSL_CIPHER_STRENGTH_SORT,0), "SSL_CIPHER_STRENGTH_SORT"}, +{ERR_PACK(0,SSL_F_SSL_CLEAR,0), "SSL_clear"}, +{ERR_PACK(0,SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD,0), "SSL_COMP_add_compression_method"}, {ERR_PACK(0,SSL_F_SSL_CREATE_CIPHER_LIST,0), "SSL_CREATE_CIPHER_LIST"}, +{ERR_PACK(0,SSL_F_SSL_CTRL,0), "SSL_ctrl"}, {ERR_PACK(0,SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,0), "SSL_CTX_check_private_key"}, {ERR_PACK(0,SSL_F_SSL_CTX_NEW,0), "SSL_CTX_new"}, +{ERR_PACK(0,SSL_F_SSL_CTX_SET_PURPOSE,0), "SSL_CTX_set_purpose"}, +{ERR_PACK(0,SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,0), "SSL_CTX_set_session_id_context"}, {ERR_PACK(0,SSL_F_SSL_CTX_SET_SSL_VERSION,0), "SSL_CTX_set_ssl_version"}, +{ERR_PACK(0,SSL_F_SSL_CTX_SET_TRUST,0), "SSL_CTX_set_trust"}, {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE,0), "SSL_CTX_use_certificate"}, {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,0), "SSL_CTX_use_certificate_ASN1"}, +{ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,0), "SSL_CTX_use_certificate_chain_file"}, {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,0), "SSL_CTX_use_certificate_file"}, {ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY,0), "SSL_CTX_use_PrivateKey"}, {ERR_PACK(0,SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,0), "SSL_CTX_use_PrivateKey_ASN1"}, @@ -142,21 +166,28 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,0), "SSL_CTX_use_RSAPrivateKey_file"}, {ERR_PACK(0,SSL_F_SSL_DO_HANDSHAKE,0), "SSL_do_handshake"}, {ERR_PACK(0,SSL_F_SSL_GET_NEW_SESSION,0), "SSL_GET_NEW_SESSION"}, +{ERR_PACK(0,SSL_F_SSL_GET_PREV_SESSION,0), "SSL_GET_PREV_SESSION"}, {ERR_PACK(0,SSL_F_SSL_GET_SERVER_SEND_CERT,0), "SSL_GET_SERVER_SEND_CERT"}, {ERR_PACK(0,SSL_F_SSL_GET_SIGN_PKEY,0), "SSL_GET_SIGN_PKEY"}, {ERR_PACK(0,SSL_F_SSL_INIT_WBIO_BUFFER,0), "SSL_INIT_WBIO_BUFFER"}, {ERR_PACK(0,SSL_F_SSL_LOAD_CLIENT_CA_FILE,0), "SSL_load_client_CA_file"}, {ERR_PACK(0,SSL_F_SSL_NEW,0), "SSL_new"}, +{ERR_PACK(0,SSL_F_SSL_READ,0), "SSL_read"}, {ERR_PACK(0,SSL_F_SSL_RSA_PRIVATE_DECRYPT,0), "SSL_RSA_PRIVATE_DECRYPT"}, {ERR_PACK(0,SSL_F_SSL_RSA_PUBLIC_ENCRYPT,0), "SSL_RSA_PUBLIC_ENCRYPT"}, {ERR_PACK(0,SSL_F_SSL_SESSION_NEW,0), "SSL_SESSION_new"}, {ERR_PACK(0,SSL_F_SSL_SESSION_PRINT_FP,0), "SSL_SESSION_print_fp"}, +{ERR_PACK(0,SSL_F_SSL_SESS_CERT_NEW,0), "SSL_SESS_CERT_NEW"}, {ERR_PACK(0,SSL_F_SSL_SET_CERT,0), "SSL_SET_CERT"}, {ERR_PACK(0,SSL_F_SSL_SET_FD,0), "SSL_set_fd"}, {ERR_PACK(0,SSL_F_SSL_SET_PKEY,0), "SSL_SET_PKEY"}, +{ERR_PACK(0,SSL_F_SSL_SET_PURPOSE,0), "SSL_set_purpose"}, {ERR_PACK(0,SSL_F_SSL_SET_RFD,0), "SSL_set_rfd"}, {ERR_PACK(0,SSL_F_SSL_SET_SESSION,0), "SSL_set_session"}, +{ERR_PACK(0,SSL_F_SSL_SET_SESSION_ID_CONTEXT,0), "SSL_set_session_id_context"}, +{ERR_PACK(0,SSL_F_SSL_SET_TRUST,0), "SSL_set_trust"}, {ERR_PACK(0,SSL_F_SSL_SET_WFD,0), "SSL_set_wfd"}, +{ERR_PACK(0,SSL_F_SSL_SHUTDOWN,0), "SSL_shutdown"}, {ERR_PACK(0,SSL_F_SSL_UNDEFINED_FUNCTION,0), "SSL_UNDEFINED_FUNCTION"}, {ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE,0), "SSL_use_certificate"}, {ERR_PACK(0,SSL_F_SSL_USE_CERTIFICATE_ASN1,0), "SSL_use_certificate_ASN1"}, @@ -167,22 +198,23 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY,0), "SSL_use_RSAPrivateKey"}, {ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1,0), "SSL_use_RSAPrivateKey_ASN1"}, {ERR_PACK(0,SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,0), "SSL_use_RSAPrivateKey_file"}, +{ERR_PACK(0,SSL_F_SSL_VERIFY_CERT_CHAIN,0), "SSL_VERIFY_CERT_CHAIN"}, {ERR_PACK(0,SSL_F_SSL_WRITE,0), "SSL_write"}, {ERR_PACK(0,SSL_F_TLS1_CHANGE_CIPHER_STATE,0), "TLS1_CHANGE_CIPHER_STATE"}, {ERR_PACK(0,SSL_F_TLS1_ENC,0), "TLS1_ENC"}, {ERR_PACK(0,SSL_F_TLS1_SETUP_KEY_BLOCK,0), "TLS1_SETUP_KEY_BLOCK"}, {ERR_PACK(0,SSL_F_WRITE_PENDING,0), "WRITE_PENDING"}, -{0,NULL}, +{0,NULL} }; static ERR_STRING_DATA SSL_str_reasons[]= { {SSL_R_APP_DATA_IN_HANDSHAKE ,"app data in handshake"}, +{SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT,"attempt to reuse session in different context"}, {SSL_R_BAD_ALERT_RECORD ,"bad alert record"}, {SSL_R_BAD_AUTHENTICATION_TYPE ,"bad authentication type"}, {SSL_R_BAD_CHANGE_CIPHER_SPEC ,"bad change cipher spec"}, {SSL_R_BAD_CHECKSUM ,"bad checksum"}, -{SSL_R_BAD_CLIENT_REQUEST ,"bad client request"}, {SSL_R_BAD_DATA_RETURNED_BY_CALLBACK ,"bad data returned by callback"}, {SSL_R_BAD_DECOMPRESSION ,"bad decompression"}, {SSL_R_BAD_DH_G_LENGTH ,"bad dh g length"}, @@ -190,6 +222,8 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_BAD_DH_P_LENGTH ,"bad dh p length"}, {SSL_R_BAD_DIGEST_LENGTH ,"bad digest length"}, {SSL_R_BAD_DSA_SIGNATURE ,"bad dsa signature"}, +{SSL_R_BAD_HELLO_REQUEST ,"bad hello request"}, +{SSL_R_BAD_LENGTH ,"bad length"}, {SSL_R_BAD_MAC_DECODE ,"bad mac decode"}, {SSL_R_BAD_MESSAGE_TYPE ,"bad message type"}, {SSL_R_BAD_PACKET_LENGTH ,"bad packet length"}, @@ -219,25 +253,44 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_CIPHER_TABLE_SRC_ERROR ,"cipher table src error"}, {SSL_R_COMPRESSED_LENGTH_TOO_LONG ,"compressed length too long"}, {SSL_R_COMPRESSION_FAILURE ,"compression failure"}, +{SSL_R_COMPRESSION_LIBRARY_ERROR ,"compression library error"}, {SSL_R_CONNECTION_ID_IS_DIFFERENT ,"connection id is different"}, {SSL_R_CONNECTION_TYPE_NOT_SET ,"connection type not set"}, {SSL_R_DATA_BETWEEN_CCS_AND_FINISHED ,"data between ccs and finished"}, {SSL_R_DATA_LENGTH_TOO_LONG ,"data length too long"}, {SSL_R_DECRYPTION_FAILED ,"decryption failed"}, +{SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC,"decryption failed or bad record mac"}, {SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG ,"dh public value length is wrong"}, {SSL_R_DIGEST_CHECK_FAILED ,"digest check failed"}, {SSL_R_ENCRYPTED_LENGTH_TOO_LONG ,"encrypted length too long"}, +{SSL_R_ERROR_GENERATING_TMP_RSA_KEY ,"error generating tmp rsa key"}, {SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST ,"error in received cipher list"}, {SSL_R_EXCESSIVE_MESSAGE_SIZE ,"excessive message size"}, {SSL_R_EXTRA_DATA_IN_MESSAGE ,"extra data in message"}, {SSL_R_GOT_A_FIN_BEFORE_A_CCS ,"got a fin before a ccs"}, {SSL_R_HTTPS_PROXY_REQUEST ,"https proxy request"}, {SSL_R_HTTP_REQUEST ,"http request"}, -{SSL_R_INTERNAL_ERROR ,"internal error"}, +{SSL_R_ILLEGAL_PADDING ,"illegal padding"}, {SSL_R_INVALID_CHALLENGE_LENGTH ,"invalid challenge length"}, +{SSL_R_INVALID_COMMAND ,"invalid command"}, +{SSL_R_INVALID_PURPOSE ,"invalid purpose"}, +{SSL_R_INVALID_TRUST ,"invalid trust"}, +{SSL_R_KRB5 ,"krb5"}, +{SSL_R_KRB5_C_CC_PRINC ,"krb5 client cc principal (no tkt?)"}, +{SSL_R_KRB5_C_GET_CRED ,"krb5 client get cred"}, +{SSL_R_KRB5_C_INIT ,"krb5 client init"}, +{SSL_R_KRB5_C_MK_REQ ,"krb5 client mk_req (expired tkt?)"}, +{SSL_R_KRB5_S_BAD_TICKET ,"krb5 server bad ticket"}, +{SSL_R_KRB5_S_INIT ,"krb5 server init"}, +{SSL_R_KRB5_S_RD_REQ ,"krb5 server rd_req (keytab perms?)"}, +{SSL_R_KRB5_S_TKT_EXPIRED ,"krb5 server tkt expired"}, +{SSL_R_KRB5_S_TKT_NYV ,"krb5 server tkt not yet valid"}, +{SSL_R_KRB5_S_TKT_SKEW ,"krb5 server tkt skew"}, {SSL_R_LENGTH_MISMATCH ,"length mismatch"}, {SSL_R_LENGTH_TOO_SHORT ,"length too short"}, +{SSL_R_LIBRARY_BUG ,"library bug"}, {SSL_R_LIBRARY_HAS_NO_CIPHERS ,"library has no ciphers"}, +{SSL_R_MESSAGE_TOO_LONG ,"message too long"}, {SSL_R_MISSING_DH_DSA_CERT ,"missing dh dsa cert"}, {SSL_R_MISSING_DH_KEY ,"missing dh key"}, {SSL_R_MISSING_DH_RSA_CERT ,"missing dh rsa cert"}, @@ -264,15 +317,18 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_NO_CIPHER_MATCH ,"no cipher match"}, {SSL_R_NO_CLIENT_CERT_RECEIVED ,"no client cert received"}, {SSL_R_NO_COMPRESSION_SPECIFIED ,"no compression specified"}, +{SSL_R_NO_METHOD_SPECIFIED ,"no method specified"}, {SSL_R_NO_PRIVATEKEY ,"no privatekey"}, {SSL_R_NO_PRIVATE_KEY_ASSIGNED ,"no private key assigned"}, {SSL_R_NO_PROTOCOLS_AVAILABLE ,"no protocols available"}, {SSL_R_NO_PUBLICKEY ,"no publickey"}, {SSL_R_NO_SHARED_CIPHER ,"no shared cipher"}, +{SSL_R_NO_VERIFY_CALLBACK ,"no verify callback"}, {SSL_R_NULL_SSL_CTX ,"null ssl ctx"}, {SSL_R_NULL_SSL_METHOD_PASSED ,"null ssl method passed"}, {SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED ,"old session cipher not returned"}, {SSL_R_PACKET_LENGTH_TOO_LONG ,"packet length too long"}, +{SSL_R_PATH_TOO_LONG ,"path too long"}, {SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE ,"peer did not return a certificate"}, {SSL_R_PEER_ERROR ,"peer error"}, {SSL_R_PEER_ERROR_CERTIFICATE ,"peer error certificate"}, @@ -289,12 +345,15 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_READ_WRONG_PACKET_TYPE ,"read wrong packet type"}, {SSL_R_RECORD_LENGTH_MISMATCH ,"record length mismatch"}, {SSL_R_RECORD_TOO_LARGE ,"record too large"}, +{SSL_R_RECORD_TOO_SMALL ,"record too small"}, {SSL_R_REQUIRED_CIPHER_MISSING ,"required cipher missing"}, {SSL_R_REUSE_CERT_LENGTH_NOT_ZERO ,"reuse cert length not zero"}, {SSL_R_REUSE_CERT_TYPE_NOT_ZERO ,"reuse cert type not zero"}, {SSL_R_REUSE_CIPHER_LIST_NOT_ZERO ,"reuse cipher list not zero"}, +{SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED ,"session id context uninitialized"}, {SSL_R_SHORT_READ ,"short read"}, {SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE,"signature for non signing certificate"}, +{SSL_R_SSL23_DOING_SESSION_ID_REUSE ,"ssl23 doing session id reuse"}, {SSL_R_SSL3_SESSION_ID_TOO_SHORT ,"ssl3 session id too short"}, {SSL_R_SSLV3_ALERT_BAD_CERTIFICATE ,"sslv3 alert bad certificate"}, {SSL_R_SSLV3_ALERT_BAD_RECORD_MAC ,"sslv3 alert bad record mac"}, @@ -315,7 +374,23 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION,"ssl ctx has no default ssl version"}, {SSL_R_SSL_HANDSHAKE_FAILURE ,"ssl handshake failure"}, {SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS ,"ssl library has no ciphers"}, +{SSL_R_SSL_SESSION_ID_CALLBACK_FAILED ,"ssl session id callback failed"}, +{SSL_R_SSL_SESSION_ID_CONFLICT ,"ssl session id conflict"}, +{SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG ,"ssl session id context too long"}, +{SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH ,"ssl session id has bad length"}, {SSL_R_SSL_SESSION_ID_IS_DIFFERENT ,"ssl session id is different"}, +{SSL_R_TLSV1_ALERT_ACCESS_DENIED ,"tlsv1 alert access denied"}, +{SSL_R_TLSV1_ALERT_DECODE_ERROR ,"tlsv1 alert decode error"}, +{SSL_R_TLSV1_ALERT_DECRYPTION_FAILED ,"tlsv1 alert decryption failed"}, +{SSL_R_TLSV1_ALERT_DECRYPT_ERROR ,"tlsv1 alert decrypt error"}, +{SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION ,"tlsv1 alert export restriction"}, +{SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY ,"tlsv1 alert insufficient security"}, +{SSL_R_TLSV1_ALERT_INTERNAL_ERROR ,"tlsv1 alert internal error"}, +{SSL_R_TLSV1_ALERT_NO_RENEGOTIATION ,"tlsv1 alert no renegotiation"}, +{SSL_R_TLSV1_ALERT_PROTOCOL_VERSION ,"tlsv1 alert protocol version"}, +{SSL_R_TLSV1_ALERT_RECORD_OVERFLOW ,"tlsv1 alert record overflow"}, +{SSL_R_TLSV1_ALERT_UNKNOWN_CA ,"tlsv1 alert unknown ca"}, +{SSL_R_TLSV1_ALERT_USER_CANCELLED ,"tlsv1 alert user cancelled"}, {SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER,"tls client cert req with anon cipher"}, {SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST,"tls peer did not respond with certificate list"}, {SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG,"tls rsa encrypted value length is wrong"}, @@ -330,6 +405,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES ,"unable to load ssl3 sha1 routines"}, {SSL_R_UNEXPECTED_MESSAGE ,"unexpected message"}, {SSL_R_UNEXPECTED_RECORD ,"unexpected record"}, +{SSL_R_UNINITIALIZED ,"uninitialized"}, {SSL_R_UNKNOWN_ALERT_TYPE ,"unknown alert type"}, {SSL_R_UNKNOWN_CERTIFICATE_TYPE ,"unknown certificate type"}, {SSL_R_UNKNOWN_CIPHER_RETURNED ,"unknown cipher returned"}, @@ -342,6 +418,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_UNKNOWN_STATE ,"unknown state"}, {SSL_R_UNSUPPORTED_CIPHER ,"unsupported cipher"}, {SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM ,"unsupported compression algorithm"}, +{SSL_R_UNSUPPORTED_OPTION ,"unsupported option"}, {SSL_R_UNSUPPORTED_PROTOCOL ,"unsupported protocol"}, {SSL_R_UNSUPPORTED_SSL_VERSION ,"unsupported ssl version"}, {SSL_R_WRITE_BIO_NOT_SET ,"write bio not set"}, @@ -353,19 +430,20 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_WRONG_SSL_VERSION ,"wrong ssl version"}, {SSL_R_WRONG_VERSION_NUMBER ,"wrong version number"}, {SSL_R_X509_LIB ,"x509 lib"}, -{0,NULL}, +{SSL_R_X509_VERIFICATION_SETUP_PROBLEMS ,"x509 verification setup problems"}, +{0,NULL} }; #endif -void ERR_load_SSL_strings() +void ERR_load_SSL_strings(void) { static int init=1; - if (init); - {; + if (init) + { init=0; -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_strings(ERR_LIB_SSL,SSL_str_functs); ERR_load_strings(ERR_LIB_SSL,SSL_str_reasons); #endif diff --git a/src/lib/libssl/ssl_err2.c b/src/lib/libssl/ssl_err2.c index 0b91f7b8d2..ea95a5f983 100644 --- a/src/lib/libssl/ssl_err2.c +++ b/src/lib/libssl/ssl_err2.c @@ -57,12 +57,12 @@ */ #include -#include "err.h" -#include "ssl.h" +#include +#include -void SSL_load_error_strings() +void SSL_load_error_strings(void) { -#ifndef NO_ERR +#ifndef OPENSSL_NO_ERR ERR_load_crypto_strings(); ERR_load_SSL_strings(); #endif diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index f562ec6b14..df307a80c5 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c @@ -1,4 +1,6 @@ -/* ssl/ssl_lib.c */ +/*! \file ssl/ssl_lib.c + * \brief Version independent SSL functions. + */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -55,52 +57,126 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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). + * + */ + +#ifdef REF_CHECK +# include +#endif #include -#include "objects.h" -#include "lhash.h" +#include +#include +#include #include "ssl_locl.h" +#include "kssl_lcl.h" -char *SSL_version_str="SSLeay 0.9.0b 29-Jun-1998"; - -static STACK *ssl_meth=NULL; -static STACK *ssl_ctx_meth=NULL; -static int ssl_meth_num=0; -static int ssl_ctx_meth_num=0; +const char *SSL_version_str=OPENSSL_VERSION_TEXT; -SSL3_ENC_METHOD ssl3_undef_enc_method={ - ssl_undefined_function, - ssl_undefined_function, - ssl_undefined_function, - ssl_undefined_function, - ssl_undefined_function, +OPENSSL_GLOBAL SSL3_ENC_METHOD ssl3_undef_enc_method={ + /* evil casts, but these functions are only called if there's a library bug */ + (int (*)(SSL *,int))ssl_undefined_function, + (int (*)(SSL *, unsigned char *, int))ssl_undefined_function, ssl_undefined_function, + (int (*)(SSL *, unsigned char *, unsigned char *, int))ssl_undefined_function, + (int (*)(SSL*, int))ssl_undefined_function, + (int (*)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char*, int, unsigned char *))ssl_undefined_function }; -void SSL_clear(s) -SSL *s; +int SSL_clear(SSL *s) { - int state; - if (s->method == NULL) return; + if (s->method == NULL) + { + SSLerr(SSL_F_SSL_CLEAR,SSL_R_NO_METHOD_SPECIFIED); + return(0); + } + + if (ssl_clear_bad_session(s)) + { + SSL_SESSION_free(s->session); + s->session=NULL; + } s->error=0; s->hit=0; + s->shutdown=0; +#if 0 /* Disabled since version 1.10 of this file (early return not + * needed because SSL_clear is not called when doing renegotiation) */ /* This is set if we are doing dynamic renegotiation so keep * the old cipher. It is sort of a SSL_clear_lite :-) */ - if (s->new_session) return; + if (s->new_session) return(1); +#else + if (s->new_session) + { + SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR); + return 0; + } +#endif - state=s->state; /* Keep to check if we throw away the session-id */ s->type=0; + s->state=SSL_ST_BEFORE|((s->server)?SSL_ST_ACCEPT:SSL_ST_CONNECT); + s->version=s->method->version; + s->client_version=s->version; s->rwstate=SSL_NOTHING; - s->state=SSL_ST_BEFORE; s->rstate=SSL_ST_READ_HEADER; - s->read_ahead=s->ctx->default_read_ahead; - -/* s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); */ +#if 0 + s->read_ahead=s->ctx->read_ahead; +#endif if (s->init_buf != NULL) { @@ -110,30 +186,34 @@ SSL *s; ssl_clear_cipher_ctx(s); - if (ssl_clear_bad_session(s)) - { - SSL_SESSION_free(s->session); - s->session=NULL; - } - - s->shutdown=(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); s->first_packet=0; - s->method->ssl_clear(s); +#if 1 + /* Check to see if we were changed into a different method, if + * so, revert back if we are not doing session-id reuse. */ + if (!s->in_handshake && (s->session == NULL) && (s->method != s->ctx->method)) + { + s->method->ssl_free(s); + s->method=s->ctx->method; + if (!s->method->ssl_new(s)) + return(0); + } + else +#endif + s->method->ssl_clear(s); + return(1); } -/* Used to change an SSL_CTXs default SSL method type */ -int SSL_CTX_set_ssl_version(ctx,meth) -SSL_CTX *ctx; -SSL_METHOD *meth; +/** Used to change an SSL_CTXs default SSL method type */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth) { - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; ctx->method=meth; sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list), &(ctx->cipher_list_by_id),SSL_DEFAULT_CIPHER_LIST); - if ((sk == NULL) || (sk_num(sk) <= 0)) + if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) { SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); return(0); @@ -141,8 +221,7 @@ SSL_METHOD *meth; return(1); } -SSL *SSL_new(ctx) -SSL_CTX *ctx; +SSL *SSL_new(SSL_CTX *ctx) { SSL *s; @@ -157,20 +236,50 @@ SSL_CTX *ctx; return(NULL); } - s=(SSL *)Malloc(sizeof(SSL)); + s=(SSL *)OPENSSL_malloc(sizeof(SSL)); if (s == NULL) goto err; memset(s,0,sizeof(SSL)); - if (ctx->default_cert != NULL) - { - CRYPTO_add(&ctx->default_cert->references,1, - CRYPTO_LOCK_SSL_CERT); - s->cert=ctx->default_cert; +#ifndef OPENSSL_NO_KRB5 + s->kssl_ctx = kssl_ctx_new(); +#endif /* OPENSSL_NO_KRB5 */ + + s->options=ctx->options; + s->mode=ctx->mode; + s->max_cert_list=ctx->max_cert_list; + + if (ctx->cert != NULL) + { + /* Earlier library versions used to copy the pointer to + * the CERT, not its contents; only when setting new + * parameters for the per-SSL copy, ssl_cert_new would be + * called (and the direct reference to the per-SSL_CTX + * settings would be lost, but those still were indirectly + * accessed for various purposes, and for that reason they + * used to be known as s->ctx->default_cert). + * Now we don't look at the SSL_CTX's CERT after having + * duplicated it once. */ + + s->cert = ssl_cert_dup(ctx->cert); + if (s->cert == NULL) + goto err; } else - s->cert=NULL; - s->verify_mode=ctx->default_verify_mode; + s->cert=NULL; /* Cannot really happen (see SSL_CTX_new) */ + + s->read_ahead=ctx->read_ahead; + s->msg_callback=ctx->msg_callback; + s->msg_callback_arg=ctx->msg_callback_arg; + s->verify_mode=ctx->verify_mode; + s->verify_depth=ctx->verify_depth; + s->sid_ctx_length=ctx->sid_ctx_length; + memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx)); s->verify_callback=ctx->default_verify_callback; + s->generate_session_id=ctx->generate_session_id; + s->purpose = ctx->purpose; + s->trust = ctx->trust; + s->quiet_shutdown=ctx->quiet_shutdown; + CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); s->ctx=ctx; @@ -179,30 +288,130 @@ SSL_CTX *ctx; s->method=ctx->method; if (!s->method->ssl_new(s)) - { - SSL_CTX_free(ctx); - Free(s); goto err; - } - s->quiet_shutdown=ctx->quiet_shutdown; s->references=1; - s->options=ctx->options; + s->server=(ctx->method->ssl_accept == ssl_undefined_function)?0:1; + SSL_clear(s); - CRYPTO_new_ex_data(ssl_meth,(char *)s,&s->ex_data); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); return(s); err: + if (s != NULL) + { + if (s->cert != NULL) + ssl_cert_free(s->cert); + if (s->ctx != NULL) + SSL_CTX_free(s->ctx); /* decrement reference count */ + OPENSSL_free(s); + } SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } -void SSL_free(s) -SSL *s; +int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx, + unsigned int sid_ctx_len) + { + if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) + { + SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ctx->sid_ctx_length=sid_ctx_len; + memcpy(ctx->sid_ctx,sid_ctx,sid_ctx_len); + + return 1; + } + +int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx, + unsigned int sid_ctx_len) + { + if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) + { + SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ssl->sid_ctx_length=sid_ctx_len; + memcpy(ssl->sid_ctx,sid_ctx,sid_ctx_len); + + return 1; + } + +int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) + { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + ctx->generate_session_id = cb; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + return 1; + } + +int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) + { + CRYPTO_w_lock(CRYPTO_LOCK_SSL); + ssl->generate_session_id = cb; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL); + return 1; + } + +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len) + { + /* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how + * we can "construct" a session to give us the desired check - ie. to + * find if there's a session in the hash table that would conflict with + * any new session built out of this id/id_len and the ssl_version in + * use by this SSL. */ + SSL_SESSION r, *p; + r.ssl_version = ssl->version; + r.session_id_length = id_len; + memcpy(r.session_id, id, id_len); + /* NB: SSLv2 always uses a fixed 16-byte session ID, so even if a + * callback is calling us to check the uniqueness of a shorter ID, it + * must be compared as a padded-out ID because that is what it will be + * converted to when the callback has finished choosing it. */ + if((r.ssl_version == SSL2_VERSION) && + (id_len < SSL2_SSL_SESSION_ID_LENGTH)) + { + memset(r.session_id + id_len, 0, + SSL2_SSL_SESSION_ID_LENGTH - id_len); + r.session_id_length = SSL2_SSL_SESSION_ID_LENGTH; + } + + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + p = (SSL_SESSION *)lh_retrieve(ssl->ctx->sessions, &r); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + return (p != NULL); + } + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) + { + return X509_PURPOSE_set(&s->purpose, purpose); + } + +int SSL_set_purpose(SSL *s, int purpose) + { + return X509_PURPOSE_set(&s->purpose, purpose); + } + +int SSL_CTX_set_trust(SSL_CTX *s, int trust) + { + return X509_TRUST_set(&s->trust, trust); + } + +int SSL_set_trust(SSL *s, int trust) + { + return X509_TRUST_set(&s->trust, trust); + } + +void SSL_free(SSL *s) { int i; + if(s == NULL) + return; + i=CRYPTO_add(&s->references,-1,CRYPTO_LOCK_SSL); #ifdef REF_PRINT REF_PRINT("SSL",s); @@ -216,7 +425,7 @@ SSL *s; } #endif - CRYPTO_free_ex_data(ssl_meth,(char *)s,&s->ex_data); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); if (s->bbio != NULL) { @@ -236,8 +445,8 @@ SSL *s; if (s->init_buf != NULL) BUF_MEM_free(s->init_buf); /* add extra stuff */ - if (s->cipher_list != NULL) sk_free(s->cipher_list); - if (s->cipher_list_by_id != NULL) sk_free(s->cipher_list_by_id); + if (s->cipher_list != NULL) sk_SSL_CIPHER_free(s->cipher_list); + if (s->cipher_list_by_id != NULL) sk_SSL_CIPHER_free(s->cipher_list_by_id); /* Make the next call work :-) */ if (s->session != NULL) @@ -254,17 +463,14 @@ SSL *s; if (s->ctx) SSL_CTX_free(s->ctx); if (s->client_CA != NULL) - sk_pop_free(s->client_CA,X509_NAME_free); + sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free); if (s->method != NULL) s->method->ssl_free(s); - Free((char *)s); + OPENSSL_free(s); } -void SSL_set_bio(s, rbio,wbio) -SSL *s; -BIO *rbio; -BIO *wbio; +void SSL_set_bio(SSL *s,BIO *rbio,BIO *wbio) { /* If the output buffering BIO is still in place, remove it */ @@ -284,16 +490,18 @@ BIO *wbio; s->wbio=wbio; } -BIO *SSL_get_rbio(s) -SSL *s; +BIO *SSL_get_rbio(SSL *s) { return(s->rbio); } -BIO *SSL_get_wbio(s) -SSL *s; +BIO *SSL_get_wbio(SSL *s) { return(s->wbio); } -int SSL_get_fd(s) -SSL *s; +int SSL_get_fd(SSL *s) + { + return(SSL_get_rfd(s)); + } + +int SSL_get_rfd(SSL *s) { int ret= -1; BIO *b,*r; @@ -305,10 +513,20 @@ SSL *s; return(ret); } -#ifndef NO_SOCK -int SSL_set_fd(s, fd) -SSL *s; -int fd; +int SSL_get_wfd(SSL *s) + { + int ret= -1; + BIO *b,*r; + + b=SSL_get_wbio(s); + r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR); + if (r != NULL) + BIO_get_fd(r,&ret); + return(ret); + } + +#ifndef OPENSSL_NO_SOCK +int SSL_set_fd(SSL *s,int fd) { int ret=0; BIO *bio=NULL; @@ -327,9 +545,7 @@ err: return(ret); } -int SSL_set_wfd(s, fd) -SSL *s; -int fd; +int SSL_set_wfd(SSL *s,int fd) { int ret=0; BIO *bio=NULL; @@ -351,9 +567,7 @@ err: return(ret); } -int SSL_set_rfd(s, fd) -SSL *s; -int fd; +int SSL_set_rfd(SSL *s,int fd) { int ret=0; BIO *bio=NULL; @@ -379,61 +593,104 @@ err: } #endif -int SSL_get_verify_mode(s) -SSL *s; + +/* return length of latest Finished message we sent, copy to 'buf' */ +size_t SSL_get_finished(SSL *s, void *buf, size_t count) + { + size_t ret = 0; + + if (s->s3 != NULL) + { + ret = s->s3->tmp.finish_md_len; + if (count > ret) + count = ret; + memcpy(buf, s->s3->tmp.finish_md, count); + } + return ret; + } + +/* return length of latest Finished message we expected, copy to 'buf' */ +size_t SSL_get_peer_finished(SSL *s, void *buf, size_t count) + { + size_t ret = 0; + + if (s->s3 != NULL) + { + ret = s->s3->tmp.peer_finish_md_len; + if (count > ret) + count = ret; + memcpy(buf, s->s3->tmp.peer_finish_md, count); + } + return ret; + } + + +int SSL_get_verify_mode(SSL *s) { return(s->verify_mode); } -int (*SSL_get_verify_callback(s))() -SSL *s; +int SSL_get_verify_depth(SSL *s) + { + return(s->verify_depth); + } + +int (*SSL_get_verify_callback(SSL *s))(int,X509_STORE_CTX *) { return(s->verify_callback); } -int SSL_CTX_get_verify_mode(ctx) -SSL_CTX *ctx; +int SSL_CTX_get_verify_mode(SSL_CTX *ctx) { - return(ctx->default_verify_mode); + return(ctx->verify_mode); } -int (*SSL_CTX_get_verify_callback(ctx))() -SSL_CTX *ctx; +int SSL_CTX_get_verify_depth(SSL_CTX *ctx) + { + return(ctx->verify_depth); + } + +int (*SSL_CTX_get_verify_callback(SSL_CTX *ctx))(int,X509_STORE_CTX *) { return(ctx->default_verify_callback); } -void SSL_set_verify(s, mode, callback) -SSL *s; -int mode; -int (*callback)(); +void SSL_set_verify(SSL *s,int mode, + int (*callback)(int ok,X509_STORE_CTX *ctx)) { s->verify_mode=mode; if (callback != NULL) s->verify_callback=callback; } -void SSL_set_read_ahead(s, yes) -SSL *s; -int yes; +void SSL_set_verify_depth(SSL *s,int depth) + { + s->verify_depth=depth; + } + +void SSL_set_read_ahead(SSL *s,int yes) { s->read_ahead=yes; } -int SSL_get_read_ahead(s) -SSL *s; +int SSL_get_read_ahead(SSL *s) { return(s->read_ahead); } -int SSL_pending(s) -SSL *s; +int SSL_pending(SSL *s) { + /* SSL_pending cannot work properly if read-ahead is enabled + * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), + * and it is impossible to fix since SSL_pending cannot report + * errors that may be observed while scanning the new data. + * (Note that SSL_pending() is often used as a boolean value, + * so we'd better not return -1.) + */ return(s->method->ssl_pending(s)); } -X509 *SSL_get_peer_certificate(s) -SSL *s; +X509 *SSL_get_peer_certificate(SSL *s) { X509 *r; @@ -449,23 +706,24 @@ SSL *s; return(r); } -STACK *SSL_get_peer_cert_chain(s) -SSL *s; +STACK_OF(X509) *SSL_get_peer_cert_chain(SSL *s) { - STACK *r; + STACK_OF(X509) *r; - if ((s == NULL) || (s->session == NULL) || (s->session->cert == NULL)) + if ((s == NULL) || (s->session == NULL) || (s->session->sess_cert == NULL)) r=NULL; else - r=s->session->cert->cert_chain; + r=s->session->sess_cert->cert_chain; + /* If we are a client, cert_chain includes the peer's own + * certificate; if we are a server, it does not. */ + return(r); } /* Now in theory, since the calling process own 't' it should be safe to * modify. We need to be able to read f without being hassled */ -void SSL_copy_session_id(t,f) -SSL *t,*f; +void SSL_copy_session_id(SSL *t,SSL *f) { CERT *tmp; @@ -490,30 +748,29 @@ SSL *t,*f; else t->cert=NULL; if (tmp != NULL) ssl_cert_free(tmp); + SSL_set_session_id_context(t,f->sid_ctx,f->sid_ctx_length); } /* Fix this so it checks all the valid key/cert options */ -int SSL_CTX_check_private_key(ctx) -SSL_CTX *ctx; +int SSL_CTX_check_private_key(SSL_CTX *ctx) { if ( (ctx == NULL) || - (ctx->default_cert == NULL) || - (ctx->default_cert->key->x509 == NULL)) + (ctx->cert == NULL) || + (ctx->cert->key->x509 == NULL)) { SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); return(0); } - if (ctx->default_cert->key->privatekey == NULL) + if (ctx->cert->key->privatekey == NULL) { SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_PRIVATE_KEY_ASSIGNED); return(0); } - return(X509_check_private_key(ctx->default_cert->key->x509, ctx->default_cert->key->privatekey)); + return(X509_check_private_key(ctx->cert->key->x509, ctx->cert->key->privatekey)); } /* Fix this function so that it takes an optional type parameter */ -int SSL_check_private_key(ssl) -SSL *ssl; +int SSL_check_private_key(SSL *ssl) { if (ssl == NULL) { @@ -521,7 +778,10 @@ SSL *ssl; return(0); } if (ssl->cert == NULL) - return(SSL_CTX_check_private_key(ssl->ctx)); + { + SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } if (ssl->cert->key->x509 == NULL) { SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED); @@ -536,29 +796,37 @@ SSL *ssl; ssl->cert->key->privatekey)); } -int SSL_accept(s) -SSL *s; +int SSL_accept(SSL *s) { + if (s->handshake_func == 0) + /* Not properly initialized yet */ + SSL_set_accept_state(s); + return(s->method->ssl_accept(s)); } -int SSL_connect(s) -SSL *s; +int SSL_connect(SSL *s) { + if (s->handshake_func == 0) + /* Not properly initialized yet */ + SSL_set_connect_state(s); + return(s->method->ssl_connect(s)); } -long SSL_get_default_timeout(s) -SSL *s; +long SSL_get_default_timeout(SSL *s) { return(s->method->get_timeout()); } -int SSL_read(s,buf,num) -SSL *s; -char *buf; -int num; +int SSL_read(SSL *s,void *buf,int num) { + if (s->handshake_func == 0) + { + SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED); + return -1; + } + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { s->rwstate=SSL_NOTHING; @@ -567,11 +835,14 @@ int num; return(s->method->ssl_read(s,buf,num)); } -int SSL_peek(s,buf,num) -SSL *s; -char *buf; -int num; +int SSL_peek(SSL *s,void *buf,int num) { + if (s->handshake_func == 0) + { + SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED); + return -1; + } + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { return(0); @@ -579,11 +850,14 @@ int num; return(s->method->ssl_peek(s,buf,num)); } -int SSL_write(s,buf,num) -SSL *s; -char *buf; -int num; +int SSL_write(SSL *s,const void *buf,int num) { + if (s->handshake_func == 0) + { + SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED); + return -1; + } + if (s->shutdown & SSL_SENT_SHUTDOWN) { s->rwstate=SSL_NOTHING; @@ -593,42 +867,176 @@ int num; return(s->method->ssl_write(s,buf,num)); } -int SSL_shutdown(s) -SSL *s; +int SSL_shutdown(SSL *s) { + /* Note that this function behaves differently from what one might + * expect. Return values are 0 for no success (yet), + * 1 for success; but calling it once is usually not enough, + * even if blocking I/O is used (see ssl3_shutdown). + */ + + if (s->handshake_func == 0) + { + SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED); + return -1; + } + if ((s != NULL) && !SSL_in_init(s)) return(s->method->ssl_shutdown(s)); else return(1); } -int SSL_renegotiate(s) -SSL *s; +int SSL_renegotiate(SSL *s) { - s->new_session=1; + if (s->new_session == 0) + { + s->new_session=1; + } return(s->method->ssl_renegotiate(s)); } -long SSL_ctrl(s,cmd,larg,parg) -SSL *s; -int cmd; -long larg; -char *parg; +int SSL_renegotiate_pending(SSL *s) + { + /* becomes true when negotiation is requested; + * false again once a handshake has finished */ + return (s->new_session != 0); + } + +long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) { - return(s->method->ssl_ctrl(s,cmd,larg,parg)); + long l; + + switch (cmd) + { + case SSL_CTRL_GET_READ_AHEAD: + return(s->read_ahead); + case SSL_CTRL_SET_READ_AHEAD: + l=s->read_ahead; + s->read_ahead=larg; + return(l); + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + s->msg_callback_arg = parg; + return 1; + + case SSL_CTRL_OPTIONS: + return(s->options|=larg); + case SSL_CTRL_MODE: + return(s->mode|=larg); + case SSL_CTRL_GET_MAX_CERT_LIST: + return(s->max_cert_list); + case SSL_CTRL_SET_MAX_CERT_LIST: + l=s->max_cert_list; + s->max_cert_list=larg; + return(l); + default: + return(s->method->ssl_ctrl(s,cmd,larg,parg)); + } + } + +long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)()) + { + switch(cmd) + { + case SSL_CTRL_SET_MSG_CALLBACK: + s->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); + return 1; + + default: + return(s->method->ssl_callback_ctrl(s,cmd,fp)); + } } -long SSL_CTX_ctrl(ctx,cmd,larg,parg) -SSL_CTX *ctx; -int cmd; -long larg; -char *parg; +struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx) { - return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); + return ctx->sessions; } -int ssl_cipher_id_cmp(a,b) -SSL_CIPHER *a,*b; +long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) + { + long l; + + switch (cmd) + { + case SSL_CTRL_GET_READ_AHEAD: + return(ctx->read_ahead); + case SSL_CTRL_SET_READ_AHEAD: + l=ctx->read_ahead; + ctx->read_ahead=larg; + return(l); + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + ctx->msg_callback_arg = parg; + return 1; + + case SSL_CTRL_GET_MAX_CERT_LIST: + return(ctx->max_cert_list); + case SSL_CTRL_SET_MAX_CERT_LIST: + l=ctx->max_cert_list; + ctx->max_cert_list=larg; + return(l); + + case SSL_CTRL_SET_SESS_CACHE_SIZE: + l=ctx->session_cache_size; + ctx->session_cache_size=larg; + return(l); + case SSL_CTRL_GET_SESS_CACHE_SIZE: + return(ctx->session_cache_size); + case SSL_CTRL_SET_SESS_CACHE_MODE: + l=ctx->session_cache_mode; + ctx->session_cache_mode=larg; + return(l); + case SSL_CTRL_GET_SESS_CACHE_MODE: + return(ctx->session_cache_mode); + + case SSL_CTRL_SESS_NUMBER: + return(ctx->sessions->num_items); + case SSL_CTRL_SESS_CONNECT: + return(ctx->stats.sess_connect); + case SSL_CTRL_SESS_CONNECT_GOOD: + return(ctx->stats.sess_connect_good); + case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: + return(ctx->stats.sess_connect_renegotiate); + case SSL_CTRL_SESS_ACCEPT: + return(ctx->stats.sess_accept); + case SSL_CTRL_SESS_ACCEPT_GOOD: + return(ctx->stats.sess_accept_good); + case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: + return(ctx->stats.sess_accept_renegotiate); + case SSL_CTRL_SESS_HIT: + return(ctx->stats.sess_hit); + case SSL_CTRL_SESS_CB_HIT: + return(ctx->stats.sess_cb_hit); + case SSL_CTRL_SESS_MISSES: + return(ctx->stats.sess_miss); + case SSL_CTRL_SESS_TIMEOUTS: + return(ctx->stats.sess_timeout); + case SSL_CTRL_SESS_CACHE_FULL: + return(ctx->stats.sess_cache_full); + case SSL_CTRL_OPTIONS: + return(ctx->options|=larg); + case SSL_CTRL_MODE: + return(ctx->mode|=larg); + default: + return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); + } + } + +long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)()) + { + switch(cmd) + { + case SSL_CTRL_SET_MSG_CALLBACK: + ctx->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); + return 1; + + default: + return(ctx->method->ssl_ctx_callback_ctrl(ctx,cmd,fp)); + } + } + +int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b) { long l; @@ -639,8 +1047,8 @@ SSL_CIPHER *a,*b; return((l > 0)?1:-1); } -int ssl_cipher_ptr_id_cmp(ap,bp) -SSL_CIPHER **ap,**bp; +int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap, + const SSL_CIPHER * const *bp) { long l; @@ -651,10 +1059,9 @@ SSL_CIPHER **ap,**bp; return((l > 0)?1:-1); } -/* return a STACK of the ciphers available for the SSL and in order of +/** return a STACK of the ciphers available for the SSL and in order of * preference */ -STACK *SSL_get_ciphers(s) -SSL *s; +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(SSL *s) { if ((s != NULL) && (s->cipher_list != NULL)) { @@ -668,10 +1075,9 @@ SSL *s; return(NULL); } -/* return a STACK of the ciphers available for the SSL and in order of +/** return a STACK of the ciphers available for the SSL and in order of * algorithm id */ -STACK *ssl_get_ciphers_by_id(s) -SSL *s; +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) { if ((s != NULL) && (s->cipher_list_by_id != NULL)) { @@ -685,29 +1091,25 @@ SSL *s; return(NULL); } -/* The old interface to get the same thing as SSL_get_ciphers() */ -char *SSL_get_cipher_list(s,n) -SSL *s; -int n; +/** The old interface to get the same thing as SSL_get_ciphers() */ +const char *SSL_get_cipher_list(SSL *s,int n) { SSL_CIPHER *c; - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; if (s == NULL) return(NULL); sk=SSL_get_ciphers(s); - if ((sk == NULL) || (sk_num(sk) <= n)) + if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n)) return(NULL); - c=(SSL_CIPHER *)sk_value(sk,n); + c=sk_SSL_CIPHER_value(sk,n); if (c == NULL) return(NULL); return(c->name); } -/* specify the ciphers to be used by defaut by the SSL_CTX */ -int SSL_CTX_set_cipher_list(ctx,str) -SSL_CTX *ctx; -char *str; +/** specify the ciphers to be used by default by the SSL_CTX */ +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, &ctx->cipher_list_by_id,str); @@ -715,12 +1117,10 @@ char *str; return((sk == NULL)?0:1); } -/* specify the ciphers to be used by the SSL */ -int SSL_set_cipher_list(s, str) -SSL *s; -char *str; +/** specify the ciphers to be used by the SSL */ +int SSL_set_cipher_list(SSL *s,const char *str) { - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, &s->cipher_list_by_id,str); @@ -729,13 +1129,11 @@ char *str; } /* works well for SSLv2, not so good for SSLv3 */ -char *SSL_get_shared_ciphers(s,buf,len) -SSL *s; -char *buf; -int len; +char *SSL_get_shared_ciphers(SSL *s,char *buf,int len) { - char *p,*cp; - STACK *sk; + char *p; + const char *cp; + STACK_OF(SSL_CIPHER) *sk; SSL_CIPHER *c; int i; @@ -745,11 +1143,11 @@ int len; p=buf; sk=s->session->ciphers; - for (i=0; iname; *cp; ) { if (len-- == 0) @@ -766,35 +1164,36 @@ int len; return(buf); } -int ssl_cipher_list_to_bytes(s,sk,p) -SSL *s; -STACK *sk; -unsigned char *p; +int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p) { int i,j=0; SSL_CIPHER *c; unsigned char *q; +#ifndef OPENSSL_NO_KRB5 + int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx); +#endif /* OPENSSL_NO_KRB5 */ if (sk == NULL) return(0); q=p; - for (i=0; ialgorithms & SSL_KRB5) && nokrb5) + continue; +#endif /* OPENSSL_NO_KRB5 */ j=ssl_put_cipher_by_char(s,c,p); p+=j; } return(p-q); } -STACK *ssl_bytes_to_cipher_list(s,p,num,skp) -SSL *s; -unsigned char *p; -int num; -STACK **skp; +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, + STACK_OF(SSL_CIPHER) **skp) { SSL_CIPHER *c; - STACK *sk; + STACK_OF(SSL_CIPHER) *sk; int i,n; n=ssl_put_cipher_by_char(s,NULL,NULL); @@ -804,11 +1203,11 @@ STACK **skp; return(NULL); } if ((skp == NULL) || (*skp == NULL)) - sk=sk_new(NULL); /* change perhaps later */ + sk=sk_SSL_CIPHER_new_null(); /* change perhaps later */ else { sk= *skp; - sk_zero(sk); + sk_SSL_CIPHER_zero(sk); } for (i=0; isession_id[0] )|(a->session_id[1]<< 8L)| - (a->session_id[2]<<16L)|(a->session_id[3]<<24L); + l=(unsigned long) + ((unsigned int) a->session_id[0] )| + ((unsigned int) a->session_id[1]<< 8L)| + ((unsigned long)a->session_id[2]<<16L)| + ((unsigned long)a->session_id[3]<<24L); return(l); } -int SSL_SESSION_cmp(a, b) -SSL_SESSION *a; -SSL_SESSION *b; +/* NB: If this function (or indeed the hash function which uses a sort of + * coarser function than this one) is changed, ensure + * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being + * able to construct an SSL_SESSION that will collide with any existing session + * with a matching session ID. */ +int SSL_SESSION_cmp(SSL_SESSION *a,SSL_SESSION *b) { if (a->ssl_version != b->ssl_version) return(1); @@ -855,17 +1259,29 @@ SSL_SESSION *b; return(memcmp(a->session_id,b->session_id,a->session_id_length)); } -SSL_CTX *SSL_CTX_new(meth) -SSL_METHOD *meth; +/* These wrapper functions should remain rather than redeclaring + * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each + * variable. The reason is that the functions aren't static, they're exposed via + * ssl.h. */ +static IMPLEMENT_LHASH_HASH_FN(SSL_SESSION_hash, SSL_SESSION *) +static IMPLEMENT_LHASH_COMP_FN(SSL_SESSION_cmp, SSL_SESSION *) + +SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) { - SSL_CTX *ret; + SSL_CTX *ret=NULL; if (meth == NULL) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_NULL_SSL_METHOD_PASSED); return(NULL); } - ret=(SSL_CTX *)Malloc(sizeof(SSL_CTX)); + + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) + { + SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); + goto err; + } + ret=(SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX)); if (ret == NULL) goto err; @@ -882,21 +1298,12 @@ SSL_METHOD *meth; /* We take the system default */ ret->session_timeout=meth->get_timeout(); - ret->new_session_cb=NULL; - ret->remove_session_cb=NULL; - ret->get_session_cb=NULL; - - ret->sess_connect=0; - ret->sess_connect_good=0; - ret->sess_accept=0; - ret->sess_accept_renegotiate=0; - ret->sess_connect_renegotiate=0; - ret->sess_accept_good=0; - ret->sess_miss=0; - ret->sess_timeout=0; - ret->sess_cache_full=0; - ret->sess_hit=0; - ret->sess_cb_hit=0; + ret->new_session_cb=0; + ret->remove_session_cb=0; + ret->get_session_cb=0; + ret->generate_session_id=0; + + memset((char *)&ret->stats,0,sizeof(ret->stats)); ret->references=1; ret->quiet_shutdown=0; @@ -909,19 +1316,26 @@ SSL_METHOD *meth; ret->info_callback=NULL; - ret->app_verify_callback=NULL; + ret->app_verify_callback=0; ret->app_verify_arg=NULL; - ret->default_read_ahead=0; - ret->default_verify_mode=SSL_VERIFY_NONE; + ret->max_cert_list=SSL_MAX_CERT_LIST_DEFAULT; + ret->read_ahead=0; + ret->msg_callback=0; + ret->msg_callback_arg=NULL; + ret->verify_mode=SSL_VERIFY_NONE; + ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */ + ret->sid_ctx_length=0; ret->default_verify_callback=NULL; - if ((ret->default_cert=ssl_cert_new()) == NULL) + if ((ret->cert=ssl_cert_new()) == NULL) goto err; - ret->default_passwd_callback=NULL; - ret->client_cert_cb=NULL; + ret->default_passwd_callback=0; + ret->default_passwd_callback_userdata=NULL; + ret->client_cert_cb=0; - ret->sessions=lh_new(SSL_SESSION_hash,SSL_SESSION_cmp); + ret->sessions=lh_new(LHASH_HASH_FN(SSL_SESSION_hash), + LHASH_COMP_FN(SSL_SESSION_cmp)); if (ret->sessions == NULL) goto err; ret->cert_store=X509_STORE_new(); if (ret->cert_store == NULL) goto err; @@ -929,7 +1343,8 @@ SSL_METHOD *meth; ssl_create_cipher_list(ret->method, &ret->cipher_list,&ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST); - if ((ret->cipher_list == NULL) || (sk_num(ret->cipher_list) <= 0)) + if (ret->cipher_list == NULL + || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_LIBRARY_HAS_NO_CIPHERS); goto err2; @@ -951,10 +1366,13 @@ SSL_METHOD *meth; goto err2; } - if ((ret->client_CA=sk_new_null()) == NULL) + if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL) goto err; - CRYPTO_new_ex_data(ssl_ctx_meth,(char *)ret,&ret->ex_data); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); + + ret->extra_certs=NULL; + ret->comp_methods=SSL_COMP_get_compression_methods(); return(ret); err: @@ -964,8 +1382,12 @@ err2: return(NULL); } -void SSL_CTX_free(a) -SSL_CTX *a; +#if 0 +static void SSL_COMP_free(SSL_COMP *comp) + { OPENSSL_free(comp); } +#endif + +void SSL_CTX_free(SSL_CTX *a) { int i; @@ -983,7 +1405,7 @@ SSL_CTX *a; abort(); /* ok */ } #endif - CRYPTO_free_ex_data(ssl_ctx_meth,(char *)a,&a->ex_data); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); if (a->sessions != NULL) { @@ -993,96 +1415,105 @@ SSL_CTX *a; if (a->cert_store != NULL) X509_STORE_free(a->cert_store); if (a->cipher_list != NULL) - sk_free(a->cipher_list); + sk_SSL_CIPHER_free(a->cipher_list); if (a->cipher_list_by_id != NULL) - sk_free(a->cipher_list_by_id); - if (a->default_cert != NULL) - ssl_cert_free(a->default_cert); + sk_SSL_CIPHER_free(a->cipher_list_by_id); + if (a->cert != NULL) + ssl_cert_free(a->cert); if (a->client_CA != NULL) - sk_pop_free(a->client_CA,X509_NAME_free); - Free((char *)a); + sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free); + if (a->extra_certs != NULL) + sk_X509_pop_free(a->extra_certs,X509_free); +#if 0 /* This should never be done, since it removes a global database */ + if (a->comp_methods != NULL) + sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free); +#else + a->comp_methods = NULL; +#endif + OPENSSL_free(a); } -void SSL_CTX_set_default_passwd_cb(ctx,cb) -SSL_CTX *ctx; -int (*cb)(); +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { ctx->default_passwd_callback=cb; } -void SSL_CTX_set_cert_verify_cb(ctx,cb,arg) -SSL_CTX *ctx; -int (*cb)(); -char *arg; +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u) + { + ctx->default_passwd_callback_userdata=u; + } + +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg) { ctx->app_verify_callback=cb; ctx->app_verify_arg=arg; } -void SSL_CTX_set_verify(ctx,mode,cb) -SSL_CTX *ctx; -int mode; -int (*cb)(); +void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *)) { - ctx->default_verify_mode=mode; + ctx->verify_mode=mode; ctx->default_verify_callback=cb; - /* This needs cleaning up EAY EAY EAY */ - X509_STORE_set_verify_cb_func(ctx->cert_store,cb); } -void ssl_set_cert_masks(c) -CERT *c; +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) + { + ctx->verify_depth=depth; + } + +void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher) { CERT_PKEY *cpk; int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign; int rsa_enc_export,dh_rsa_export,dh_dsa_export; - int rsa_tmp_export,dh_tmp_export; + int rsa_tmp_export,dh_tmp_export,kl; unsigned long mask,emask; - if ((c == NULL) || (c->valid)) return; + if (c == NULL) return; -#ifndef NO_RSA - rsa_tmp=((c->rsa_tmp != NULL) || (c->rsa_tmp_cb != NULL))?1:0; - rsa_tmp_export=((c->rsa_tmp_cb != NULL) || - (rsa_tmp && (RSA_size(c->rsa_tmp)*8 <= 512)))?1:0; + kl=SSL_C_EXPORT_PKEYLENGTH(cipher); + +#ifndef OPENSSL_NO_RSA + rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL); + rsa_tmp_export=(c->rsa_tmp_cb != NULL || + (rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl)); #else rsa_tmp=rsa_tmp_export=0; #endif -#ifndef NO_DH - dh_tmp=((c->dh_tmp != NULL) || (c->dh_tmp_cb != NULL))?1:0; - dh_tmp_export=((c->dh_tmp_cb != NULL) || - (dh_tmp && (DH_size(c->dh_tmp)*8 <= 512)))?1:0; +#ifndef OPENSSL_NO_DH + dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL); + dh_tmp_export=(c->dh_tmp_cb != NULL || + (dh_tmp && DH_size(c->dh_tmp)*8 <= kl)); #else dh_tmp=dh_tmp_export=0; #endif cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]); - rsa_enc= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; - rsa_enc_export=(rsa_enc && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0; + rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL); + rsa_enc_export=(rsa_enc && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]); - rsa_sign=((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + rsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); cpk= &(c->pkeys[SSL_PKEY_DSA_SIGN]); - dsa_sign=((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; + dsa_sign=(cpk->x509 != NULL && cpk->privatekey != NULL); cpk= &(c->pkeys[SSL_PKEY_DH_RSA]); - dh_rsa= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; - dh_rsa_export=(dh_rsa && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0; + dh_rsa= (cpk->x509 != NULL && cpk->privatekey != NULL); + dh_rsa_export=(dh_rsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); cpk= &(c->pkeys[SSL_PKEY_DH_DSA]); /* FIX THIS EAY EAY EAY */ - dh_dsa= ((cpk->x509 != NULL) && (cpk->privatekey != NULL))?1:0; - dh_dsa_export=(dh_dsa && (EVP_PKEY_size(cpk->privatekey)*8 <= 512))?1:0; + dh_dsa= (cpk->x509 != NULL && cpk->privatekey != NULL); + dh_dsa_export=(dh_dsa && EVP_PKEY_size(cpk->privatekey)*8 <= kl); mask=0; emask=0; #ifdef CIPHER_DEBUG - printf("rt=%d dht=%d re=%d rs=%d ds=%d dhr=%d dhd=%d\n", - rsa_tmp,dh_tmp, - rsa_enc,rsa_sign,dsa_sign,dh_rsa,dh_dsa); + printf("rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n", + rsa_tmp,rsa_tmp_export,dh_tmp, + rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa); #endif if (rsa_enc || (rsa_tmp && rsa_sign)) mask|=SSL_kRSA; - if (rsa_enc_export || (rsa_tmp_export && rsa_sign)) + if (rsa_enc_export || (rsa_tmp_export && (rsa_sign || rsa_enc))) emask|=SSL_kRSA; #if 0 @@ -1119,9 +1550,12 @@ CERT *c; emask|=SSL_aDSS; } -#ifdef SSL_ALLOW_ADH mask|=SSL_aNULL; emask|=SSL_aNULL; + +#ifndef OPENSSL_NO_KRB5 + mask|=SSL_kKRB5|SSL_aKRB5; + emask|=SSL_kKRB5|SSL_aKRB5; #endif c->mask=mask; @@ -1130,18 +1564,17 @@ CERT *c; } /* THIS NEEDS CLEANING UP */ -X509 *ssl_get_server_send_cert(s) -SSL *s; +X509 *ssl_get_server_send_cert(SSL *s) { unsigned long alg,mask,kalg; CERT *c; - int i,export; + int i,is_export; c=s->cert; - ssl_set_cert_masks(c); + ssl_set_cert_masks(c, s->s3->tmp.new_cipher); alg=s->s3->tmp.new_cipher->algorithms; - export=(alg & SSL_EXPORT)?1:0; - mask=(export)?c->export_mask:c->mask; + is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); + mask=is_export?c->export_mask:c->mask; kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK); if (kalg & SSL_kDHr) @@ -1157,18 +1590,21 @@ SSL *s; else i=SSL_PKEY_RSA_ENC; } + else if (kalg & SSL_aKRB5) + { + /* VRS something else here? */ + return(NULL); + } else /* if (kalg & SSL_aNULL) */ { - SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR); return(NULL); } if (c->pkeys[i].x509 == NULL) return(NULL); return(c->pkeys[i].x509); } -EVP_PKEY *ssl_get_sign_pkey(s,cipher) -SSL *s; -SSL_CIPHER *cipher; +EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher) { unsigned long alg; CERT *c; @@ -1190,14 +1626,12 @@ SSL_CIPHER *cipher; } else /* if (alg & SSL_aNULL) */ { - SSLerr(SSL_F_SSL_GET_SIGN_PKEY,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR); return(NULL); } } -void ssl_update_cache(s,mode) -SSL *s; -int mode; +void ssl_update_cache(SSL *s,int mode) { int i; @@ -1205,9 +1639,10 @@ int mode; * and it would be rather hard to do anyway :-) */ if (s->session->session_id_length == 0) return; - if ((s->ctx->session_cache_mode & mode) - && (!s->hit) - && SSL_CTX_add_session(s->ctx,s->session) + i=s->ctx->session_cache_mode; + if ((i & mode) && (!s->hit) + && ((i & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) + || SSL_CTX_add_session(s->ctx,s->session)) && (s->ctx->new_session_cb != NULL)) { CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION); @@ -1216,28 +1651,24 @@ int mode; } /* auto flush every 255 connections */ - i=s->ctx->session_cache_mode; if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { if ( (((mode & SSL_SESS_CACHE_CLIENT) - ?s->ctx->sess_connect_good - :s->ctx->sess_accept_good) & 0xff) == 0xff) + ?s->ctx->stats.sess_connect_good + :s->ctx->stats.sess_accept_good) & 0xff) == 0xff) { SSL_CTX_flush_sessions(s->ctx,time(NULL)); } } } -SSL_METHOD *SSL_get_ssl_method(s) -SSL *s; +SSL_METHOD *SSL_get_ssl_method(SSL *s) { return(s->method); } -int SSL_set_ssl_method(s,meth) -SSL *s; -SSL_METHOD *meth; +int SSL_set_ssl_method(SSL *s,SSL_METHOD *meth) { int conn= -1; int ret=1; @@ -1264,17 +1695,23 @@ SSL_METHOD *meth; return(ret); } -int SSL_get_error(s,i) -SSL *s; -int i; +int SSL_get_error(SSL *s,int i) { int reason; + unsigned long l; BIO *bio; if (i > 0) return(SSL_ERROR_NONE); - if (ERR_peek_error() != 0) - return(SSL_ERROR_SSL); + /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake + * etc, where we do encode the error */ + if ((l=ERR_peek_error()) != 0) + { + if (ERR_GET_LIB(l) == ERR_LIB_SYS) + return(SSL_ERROR_SYSCALL); + else + return(SSL_ERROR_SSL); + } if ((i < 0) && SSL_want_read(s)) { @@ -1282,12 +1719,23 @@ int i; if (BIO_should_read(bio)) return(SSL_ERROR_WANT_READ); else if (BIO_should_write(bio)) + /* This one doesn't make too much sense ... We never try + * to write to the rbio, and an application program where + * rbio and wbio are separate couldn't even know what it + * should wait for. + * However if we ever set s->rwstate incorrectly + * (so that we have SSL_want_read(s) instead of + * SSL_want_write(s)) and rbio and wbio *are* the same, + * this test works around that bug; so it might be safer + * to keep it. */ return(SSL_ERROR_WANT_WRITE); else if (BIO_should_io_special(bio)) { reason=BIO_get_retry_reason(bio); if (reason == BIO_RR_CONNECT) return(SSL_ERROR_WANT_CONNECT); + else if (reason == BIO_RR_ACCEPT) + return(SSL_ERROR_WANT_ACCEPT); else return(SSL_ERROR_SYSCALL); /* unknown */ } @@ -1299,12 +1747,15 @@ int i; if (BIO_should_write(bio)) return(SSL_ERROR_WANT_WRITE); else if (BIO_should_read(bio)) + /* See above (SSL_want_read(s) with BIO_should_write(bio)) */ return(SSL_ERROR_WANT_READ); else if (BIO_should_io_special(bio)) { reason=BIO_get_retry_reason(bio); if (reason == BIO_RR_CONNECT) return(SSL_ERROR_WANT_CONNECT); + else if (reason == BIO_RR_ACCEPT) + return(SSL_ERROR_WANT_ACCEPT); else return(SSL_ERROR_SYSCALL); } @@ -1331,8 +1782,7 @@ int i; return(SSL_ERROR_SYSCALL); } -int SSL_do_handshake(s) -SSL *s; +int SSL_do_handshake(SSL *s) { int ret=1; @@ -1341,7 +1791,9 @@ SSL *s; SSLerr(SSL_F_SSL_DO_HANDSHAKE,SSL_R_CONNECTION_TYPE_NOT_SET); return(-1); } - if (s->s3->renegotiate) ssl3_renegotiate_check(s); + + s->method->ssl_renegotiate_check(s); + if (SSL_in_init(s) || SSL_in_before(s)) { ret=s->handshake_func(s); @@ -1351,9 +1803,9 @@ SSL *s; /* For the next 2 functions, SSL_clear() sets shutdown and so * one of these calls will reset it */ -void SSL_set_accept_state(s) -SSL *s; +void SSL_set_accept_state(SSL *s) { + s->server=1; s->shutdown=0; s->state=SSL_ST_ACCEPT|SSL_ST_BEFORE; s->handshake_func=s->method->ssl_accept; @@ -1361,9 +1813,9 @@ SSL *s; ssl_clear_cipher_ctx(s); } -void SSL_set_connect_state(s) -SSL *s; +void SSL_set_connect_state(SSL *s) { + s->server=0; s->shutdown=0; s->state=SSL_ST_CONNECT|SSL_ST_BEFORE; s->handshake_func=s->method->ssl_connect; @@ -1371,22 +1823,19 @@ SSL *s; ssl_clear_cipher_ctx(s); } -int ssl_undefined_function(s) -SSL *s; +int ssl_undefined_function(SSL *s) { SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return(0); } -SSL_METHOD *ssl_bad_method(ver) -int ver; +SSL_METHOD *ssl_bad_method(int ver) { SSLerr(SSL_F_SSL_BAD_METHOD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return(NULL); } -char *SSL_get_version(s) -SSL *s; +const char *SSL_get_version(SSL *s) { if (s->version == TLS1_VERSION) return("TLSv1"); @@ -1398,30 +1847,67 @@ SSL *s; return("unknown"); } -SSL *SSL_dup(s) -SSL *s; - { - STACK *sk; +SSL *SSL_dup(SSL *s) + { + STACK_OF(X509_NAME) *sk; X509_NAME *xn; - SSL *ret; + SSL *ret; int i; - if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL) return(NULL); - - /* This copies version, session-id, SSL_METHOD and 'cert' */ - SSL_copy_session_id(ret,s); + if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL) + return(NULL); + + ret->version = s->version; + ret->type = s->type; + ret->method = s->method; + + if (s->session != NULL) + { + /* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */ + SSL_copy_session_id(ret,s); + } + else + { + /* No session has been established yet, so we have to expect + * that s->cert or ret->cert will be changed later -- + * they should not both point to the same object, + * and thus we can't use SSL_copy_session_id. */ + ret->method = s->method; + ret->method->ssl_new(ret); + + if (s->cert != NULL) + { + if (ret->cert != NULL) + { + ssl_cert_free(ret->cert); + } + ret->cert = ssl_cert_dup(s->cert); + if (ret->cert == NULL) + goto err; + } + + SSL_set_session_id_context(ret, + s->sid_ctx, s->sid_ctx_length); + } + + ret->options=s->options; + ret->mode=s->mode; + SSL_set_max_cert_list(ret,SSL_get_max_cert_list(s)); SSL_set_read_ahead(ret,SSL_get_read_ahead(s)); + ret->msg_callback = s->msg_callback; + ret->msg_callback_arg = s->msg_callback_arg; SSL_set_verify(ret,SSL_get_verify_mode(s), SSL_get_verify_callback(s)); + SSL_set_verify_depth(ret,SSL_get_verify_depth(s)); + ret->generate_session_id = s->generate_session_id; SSL_set_info_callback(ret,SSL_get_info_callback(s)); ret->debug=s->debug; - ret->options=s->options; /* copy app data, a little dangerous perhaps */ - if (!CRYPTO_dup_ex_data(ssl_meth,&ret->ex_data,&s->ex_data)) + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data)) goto err; /* setup rbio, and wbio */ @@ -1440,27 +1926,40 @@ SSL *s; else ret->wbio=ret->rbio; } + ret->rwstate = s->rwstate; + ret->in_handshake = s->in_handshake; + ret->handshake_func = s->handshake_func; + ret->server = s->server; + ret->new_session = s->new_session; + ret->quiet_shutdown = s->quiet_shutdown; + ret->shutdown=s->shutdown; + ret->state=s->state; /* SSL_dup does not really work at any state, though */ + ret->rstate=s->rstate; + ret->init_num = 0; /* would have to copy ret->init_buf, ret->init_msg, ret->init_num, ret->init_off */ + ret->hit=s->hit; + ret->purpose=s->purpose; + ret->trust=s->trust; /* dup the cipher_list and cipher_list_by_id stacks */ if (s->cipher_list != NULL) { - if ((ret->cipher_list=sk_dup(s->cipher_list)) == NULL) + if ((ret->cipher_list=sk_SSL_CIPHER_dup(s->cipher_list)) == NULL) goto err; } if (s->cipher_list_by_id != NULL) - if ((ret->cipher_list_by_id=sk_dup(s->cipher_list_by_id)) + if ((ret->cipher_list_by_id=sk_SSL_CIPHER_dup(s->cipher_list_by_id)) == NULL) goto err; /* Dup the client_CA list */ if (s->client_CA != NULL) { - if ((sk=sk_dup(s->client_CA)) == NULL) goto err; + if ((sk=sk_X509_NAME_dup(s->client_CA)) == NULL) goto err; ret->client_CA=sk; - for (i=0; ishutdown=s->shutdown; - ret->state=s->state; - ret->handshake_func=s->handshake_func; - if (0) { err: @@ -1481,26 +1976,34 @@ err: return(ret); } -void ssl_clear_cipher_ctx(s) -SSL *s; +void ssl_clear_cipher_ctx(SSL *s) { - if (s->enc_read_ctx != NULL) - { - EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); - Free(s->enc_read_ctx); - s->enc_read_ctx=NULL; - } - if (s->enc_write_ctx != NULL) - { - EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); - Free(s->enc_write_ctx); - s->enc_write_ctx=NULL; - } + if (s->enc_read_ctx != NULL) + { + EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); + OPENSSL_free(s->enc_read_ctx); + s->enc_read_ctx=NULL; + } + if (s->enc_write_ctx != NULL) + { + EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); + OPENSSL_free(s->enc_write_ctx); + s->enc_write_ctx=NULL; + } + if (s->expand != NULL) + { + COMP_CTX_free(s->expand); + s->expand=NULL; + } + if (s->compress != NULL) + { + COMP_CTX_free(s->compress); + s->compress=NULL; + } } /* Fix this function so that it takes an optional type parameter */ -X509 *SSL_get_certificate(s) -SSL *s; +X509 *SSL_get_certificate(SSL *s) { if (s->cert != NULL) return(s->cert->key->x509); @@ -1509,8 +2012,7 @@ SSL *s; } /* Fix this function so that it takes an optional type parameter */ -EVP_PKEY *SSL_get_privatekey(s) -SSL *s; +EVP_PKEY *SSL_get_privatekey(SSL *s) { if (s->cert != NULL) return(s->cert->key->privatekey); @@ -1518,17 +2020,14 @@ SSL *s; return(NULL); } -SSL_CIPHER *SSL_get_current_cipher(s) -SSL *s; +SSL_CIPHER *SSL_get_current_cipher(SSL *s) { - if ((s->session != NULL) && (s->session->cipher != NULL)) - return(s->session->cipher); - return(NULL); + if ((s->session != NULL) && (s->session->cipher != NULL)) + return(s->session->cipher); + return(NULL); } -int ssl_init_wbio_buffer(s,push) -SSL *s; -int push; +int ssl_init_wbio_buffer(SSL *s,int push) { BIO *bbio; @@ -1544,7 +2043,7 @@ int push; if (s->bbio == s->wbio) s->wbio=BIO_pop(s->wbio); } - BIO_reset(bbio); + (void)BIO_reset(bbio); /* if (!BIO_set_write_buffer_size(bbio,16*1024)) */ if (!BIO_set_read_buffer_size(bbio,1)) { @@ -1563,159 +2062,230 @@ int push; } return(1); } + +void ssl_free_wbio_buffer(SSL *s) + { + if (s->bbio == NULL) return; + + if (s->bbio == s->wbio) + { + /* remove buffering */ + s->wbio=BIO_pop(s->wbio); +#ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */ + assert(s->wbio != NULL); +#endif + } + BIO_free(s->bbio); + s->bbio=NULL; + } -void SSL_CTX_set_quiet_shutdown(ctx,mode) -SSL_CTX *ctx; -int mode; +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode) { ctx->quiet_shutdown=mode; } -int SSL_CTX_get_quiet_shutdown(ctx) -SSL_CTX *ctx; +int SSL_CTX_get_quiet_shutdown(SSL_CTX *ctx) { return(ctx->quiet_shutdown); } -void SSL_set_quiet_shutdown(s,mode) -SSL *s; -int mode; +void SSL_set_quiet_shutdown(SSL *s,int mode) { s->quiet_shutdown=mode; } -int SSL_get_quiet_shutdown(s) -SSL *s; +int SSL_get_quiet_shutdown(SSL *s) { return(s->quiet_shutdown); } -void SSL_set_shutdown(s,mode) -SSL *s; -int mode; +void SSL_set_shutdown(SSL *s,int mode) { s->shutdown=mode; } -int SSL_get_shutdown(s) -SSL *s; +int SSL_get_shutdown(SSL *s) { return(s->shutdown); } -int SSL_version(s) -SSL *s; +int SSL_version(SSL *s) { return(s->version); } -SSL_CTX *SSL_get_SSL_CTX(ssl) -SSL *ssl; +SSL_CTX *SSL_get_SSL_CTX(SSL *ssl) { return(ssl->ctx); } -int SSL_CTX_set_default_verify_paths(ctx) -SSL_CTX *ctx; +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) { return(X509_STORE_set_default_paths(ctx->cert_store)); } -int SSL_CTX_load_verify_locations(ctx,CAfile,CApath) -SSL_CTX *ctx; -char *CAfile; -char *CApath; +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath) { return(X509_STORE_load_locations(ctx->cert_store,CAfile,CApath)); } +#endif -void SSL_set_info_callback(ssl,cb) -SSL *ssl; -void (*cb)(); +void SSL_set_info_callback(SSL *ssl, + void (*cb)(const SSL *ssl,int type,int val)) { ssl->info_callback=cb; } -void (*SSL_get_info_callback(ssl))() -SSL *ssl; +void (*SSL_get_info_callback(SSL *ssl))(const SSL *ssl,int type,int val) { - return(ssl->info_callback); + return ssl->info_callback; } -int SSL_state(ssl) -SSL *ssl; +int SSL_state(SSL *ssl) { return(ssl->state); } -void SSL_set_verify_result(ssl,arg) -SSL *ssl; -long arg; +void SSL_set_verify_result(SSL *ssl,long arg) { ssl->verify_result=arg; } -long SSL_get_verify_result(ssl) -SSL *ssl; +long SSL_get_verify_result(SSL *ssl) { return(ssl->verify_result); } -int SSL_get_ex_new_index(argl,argp,new_func,dup_func,free_func) -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*free_func)(); - { - ssl_meth_num++; - return(CRYPTO_get_ex_new_index(ssl_meth_num-1, - &ssl_meth,argl,argp,new_func,dup_func,free_func)); - } +int SSL_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, + new_func, dup_func, free_func); + } -int SSL_set_ex_data(s,idx,arg) -SSL *s; -int idx; -char *arg; +int SSL_set_ex_data(SSL *s,int idx,void *arg) { return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); } -char *SSL_get_ex_data(s,idx) -SSL *s; -int idx; +void *SSL_get_ex_data(SSL *s,int idx) { return(CRYPTO_get_ex_data(&s->ex_data,idx)); } -int SSL_CTX_get_ex_new_index(argl,argp,new_func,dup_func,free_func) -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*free_func)(); - { - ssl_ctx_meth_num++; - return(CRYPTO_get_ex_new_index(ssl_ctx_meth_num-1, - &ssl_ctx_meth,argl,argp,new_func,dup_func,free_func)); - } +int SSL_CTX_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, + new_func, dup_func, free_func); + } -int SSL_CTX_set_ex_data(s,idx,arg) -SSL_CTX *s; -int idx; -char *arg; +int SSL_CTX_set_ex_data(SSL_CTX *s,int idx,void *arg) { return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); } -char *SSL_CTX_get_ex_data(s,idx) -SSL_CTX *s; -int idx; +void *SSL_CTX_get_ex_data(SSL_CTX *s,int idx) { return(CRYPTO_get_ex_data(&s->ex_data,idx)); } -#if defined(_WINDLL) && defined(WIN16) +int ssl_ok(SSL *s) + { + return(1); + } + +X509_STORE *SSL_CTX_get_cert_store(SSL_CTX *ctx) + { + return(ctx->cert_store); + } + +void SSL_CTX_set_cert_store(SSL_CTX *ctx,X509_STORE *store) + { + if (ctx->cert_store != NULL) + X509_STORE_free(ctx->cert_store); + ctx->cert_store=store; + } + +int SSL_want(SSL *s) + { + return(s->rwstate); + } + +/*! + * \brief Set the callback for generating temporary RSA keys. + * \param ctx the SSL context. + * \param cb the callback + */ + +#ifndef OPENSSL_NO_RSA +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,RSA *(*cb)(SSL *ssl, + int is_export, + int keylength)) + { + SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,(void (*)())cb); + } + +void SSL_set_tmp_rsa_callback(SSL *ssl,RSA *(*cb)(SSL *ssl, + int is_export, + int keylength)) + { + SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_RSA_CB,(void (*)())cb); + } +#endif + +#ifdef DOXYGEN +/*! + * \brief The RSA temporary key callback function. + * \param ssl the SSL session. + * \param is_export \c TRUE if the temp RSA key is for an export ciphersuite. + * \param keylength if \c is_export is \c TRUE, then \c keylength is the size + * of the required key in bits. + * \return the temporary RSA key. + * \sa SSL_CTX_set_tmp_rsa_callback, SSL_set_tmp_rsa_callback + */ + +RSA *cb(SSL *ssl,int is_export,int keylength) + {} +#endif + +/*! + * \brief Set the callback for generating temporary DH keys. + * \param ctx the SSL context. + * \param dh the callback + */ + +#ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export, + int keylength)) + { + SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)())dh); + } + +void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export, + int keylength)) + { + SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)())dh); + } +#endif + + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) + { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)())cb); + } +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) + { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)())cb); + } + + + +#if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16) #include "../crypto/bio/bss_file.c" #endif +IMPLEMENT_STACK_OF(SSL_CIPHER) +IMPLEMENT_STACK_OF(SSL_COMP) diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index b29517081b..17e9bef832 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -55,6 +55,59 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2001 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_SSL_LOCL_H #define HEADER_SSL_LOCL_H @@ -65,15 +118,23 @@ #include "e_os.h" -#include "buffer.h" -#include "bio.h" -#include "crypto.h" -#include "evp.h" -#include "stack.h" -#include "x509.h" -#include "err.h" -#include "ssl.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_BUILD_SHLIBSSL +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +#endif +#define PKCS1_CHECK #define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ l|=(((unsigned long)(*((c)++)))<< 8), \ @@ -126,18 +187,18 @@ } \ } -#define n2s(c,s) (s =((unsigned int)(*((c)++)))<< 8, \ - s|=((unsigned int)(*((c)++)))) -#define s2n(s,c) (*((c)++)=(unsigned char)(((s)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((s) )&0xff)) +#define n2s(c,s) ((s=(((unsigned int)(c[0]))<< 8)| \ + (((unsigned int)(c[1])) )),c+=2) +#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ + c[1]=(unsigned char)(((s) )&0xff)),c+=2) -#define n2l3(c,l) (l =((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))) +#define n2l3(c,l) ((l =(((unsigned long)(c[0]))<<16)| \ + (((unsigned long)(c[1]))<< 8)| \ + (((unsigned long)(c[2])) )),c+=3) -#define l2n3(l,c) (*((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) +#define l2n3(l,c) ((c[0]=(unsigned char)(((l)>>16)&0xff), \ + c[1]=(unsigned char)(((l)>> 8)&0xff), \ + c[2]=(unsigned char)(((l) )&0xff)),c+=3) /* LOCAL STUFF */ @@ -153,60 +214,128 @@ #define DEC32(a) ((a)=((a)-1)&0xffffffffL) #define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */ -#define SSL_MKEY_MASK 0x0000001FL +/* + * Define the Bitmasks for SSL_CIPHER.algorithms. + * This bits are used packed as dense as possible. If new methods/ciphers + * etc will be added, the bits a likely to change, so this information + * is for internal library use only, even though SSL_CIPHER.algorithms + * can be publicly accessed. + * Use the according functions for cipher management instead. + * + * The bit mask handling in the selection and sorting scheme in + * ssl_create_cipher_list() has only limited capabilities, reflecting + * that the different entities within are mutually exclusive: + * ONLY ONE BIT PER MASK CAN BE SET AT A TIME. + */ +#define SSL_MKEY_MASK 0x0000003FL #define SSL_kRSA 0x00000001L /* RSA key exchange */ #define SSL_kDHr 0x00000002L /* DH cert RSA CA cert */ #define SSL_kDHd 0x00000004L /* DH cert DSA CA cert */ #define SSL_kFZA 0x00000008L #define SSL_kEDH 0x00000010L /* tmp DH key no DH cert */ +#define SSL_kKRB5 0x00000020L /* Kerberos5 key exchange */ #define SSL_EDH (SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL)) -#define SSL_AUTH_MASK 0x000003e0L -#define SSL_aRSA 0x00000020L /* Authenticate with RSA */ -#define SSL_aDSS 0x00000040L /* Authenticate with DSS */ +#define SSL_AUTH_MASK 0x00000FC0L +#define SSL_aRSA 0x00000040L /* Authenticate with RSA */ +#define SSL_aDSS 0x00000080L /* Authenticate with DSS */ #define SSL_DSS SSL_aDSS -#define SSL_aFZA 0x00000080L -#define SSL_aNULL 0x00000100L /* no Authenticate, ADH */ -#define SSL_aDH 0x00000200L /* no Authenticate, ADH */ +#define SSL_aFZA 0x00000100L +#define SSL_aNULL 0x00000200L /* no Authenticate, ADH */ +#define SSL_aDH 0x00000400L /* no Authenticate, ADH */ +#define SSL_aKRB5 0x00000800L /* Authenticate with KRB5 */ #define SSL_NULL (SSL_eNULL) #define SSL_ADH (SSL_kEDH|SSL_aNULL) #define SSL_RSA (SSL_kRSA|SSL_aRSA) #define SSL_DH (SSL_kDHr|SSL_kDHd|SSL_kEDH) #define SSL_FZA (SSL_aFZA|SSL_kFZA|SSL_eFZA) - -#define SSL_ENC_MASK 0x0001Fc00L -#define SSL_DES 0x00000400L -#define SSL_3DES 0x00000800L -#define SSL_RC4 0x00001000L -#define SSL_RC2 0x00002000L -#define SSL_IDEA 0x00004000L -#define SSL_eFZA 0x00008000L -#define SSL_eNULL 0x00010000L - -#define SSL_MAC_MASK 0x00060000L -#define SSL_MD5 0x00020000L -#define SSL_SHA1 0x00040000L +#define SSL_KRB5 (SSL_kKRB5|SSL_aKRB5) + +#define SSL_ENC_MASK 0x0087F000L +#define SSL_DES 0x00001000L +#define SSL_3DES 0x00002000L +#define SSL_RC4 0x00004000L +#define SSL_RC2 0x00008000L +#define SSL_IDEA 0x00010000L +#define SSL_eFZA 0x00020000L +#define SSL_eNULL 0x00040000L +#define SSL_AES 0x00800000L + +#define SSL_MAC_MASK 0x00180000L +#define SSL_MD5 0x00080000L +#define SSL_SHA1 0x00100000L #define SSL_SHA (SSL_SHA1) -#define SSL_EXP_MASK 0x00300000L -#define SSL_EXP 0x00100000L -#define SSL_NOT_EXP 0x00200000L -#define SSL_EXPORT SSL_EXP +#define SSL_SSL_MASK 0x00600000L +#define SSL_SSLV2 0x00200000L +#define SSL_SSLV3 0x00400000L +#define SSL_TLSV1 SSL_SSLV3 /* for now */ -#define SSL_SSL_MASK 0x00c00000L -#define SSL_SSLV2 0x00400000L -#define SSL_SSLV3 0x00800000L +/* we have used 007fffff - 9 bits left to go */ + +/* + * Export and cipher strength information. For each cipher we have to decide + * whether it is exportable or not. This information is likely to change + * over time, since the export control rules are no static technical issue. + * + * Independent of the export flag the cipher strength is sorted into classes. + * SSL_EXP40 was denoting the 40bit US export limit of past times, which now + * is at 56bit (SSL_EXP56). If the exportable cipher class is going to change + * again (eg. to 64bit) the use of "SSL_EXP*" becomes blurred even more, + * since SSL_EXP64 could be similar to SSL_LOW. + * For this reason SSL_MICRO and SSL_MINI macros are included to widen the + * namespace of SSL_LOW-SSL_HIGH to lower values. As development of speed + * and ciphers goes, another extension to SSL_SUPER and/or SSL_ULTRA would + * be possible. + */ +#define SSL_EXP_MASK 0x00000003L +#define SSL_NOT_EXP 0x00000001L +#define SSL_EXPORT 0x00000002L + +#define SSL_STRONG_MASK 0x0000007cL +#define SSL_EXP40 0x00000004L +#define SSL_MICRO (SSL_EXP40) +#define SSL_EXP56 0x00000008L +#define SSL_MINI (SSL_EXP56) +#define SSL_LOW 0x00000010L +#define SSL_MEDIUM 0x00000020L +#define SSL_HIGH 0x00000040L + +/* we have used 0000007f - 25 bits left to go */ + +/* + * Macros to check the export status and cipher strength for export ciphers. + * Even though the macros for EXPORT and EXPORT40/56 have similar names, + * their meaning is different: + * *_EXPORT macros check the 'exportable' status. + * *_EXPORT40/56 macros are used to check whether a certain cipher strength + * is given. + * Since the SSL_IS_EXPORT* and SSL_EXPORT* macros depend on the correct + * algorithm structure element to be passed (algorithms, algo_strength) and no + * typechecking can be done as they are all of type unsigned long, their + * direct usage is discouraged. + * Use the SSL_C_* macros instead. + */ +#define SSL_IS_EXPORT(a) ((a)&SSL_EXPORT) +#define SSL_IS_EXPORT56(a) ((a)&SSL_EXP56) +#define SSL_IS_EXPORT40(a) ((a)&SSL_EXP40) +#define SSL_C_IS_EXPORT(c) SSL_IS_EXPORT((c)->algo_strength) +#define SSL_C_IS_EXPORT56(c) SSL_IS_EXPORT56((c)->algo_strength) +#define SSL_C_IS_EXPORT40(c) SSL_IS_EXPORT40((c)->algo_strength) + +#define SSL_EXPORT_KEYLENGTH(a,s) (SSL_IS_EXPORT40(s) ? 5 : \ + ((a)&SSL_ENC_MASK) == SSL_DES ? 8 : 7) +#define SSL_EXPORT_PKEYLENGTH(a) (SSL_IS_EXPORT40(a) ? 512 : 1024) +#define SSL_C_EXPORT_KEYLENGTH(c) SSL_EXPORT_KEYLENGTH((c)->algorithms, \ + (c)->algo_strength) +#define SSL_C_EXPORT_PKEYLENGTH(c) SSL_EXPORT_PKEYLENGTH((c)->algo_strength) -#define SSL_STRONG_MASK 0x07000000L -#define SSL_LOW 0x01000000L -#define SSL_MEDIUM 0x02000000L -#define SSL_HIGH 0x04000000L -/* we have used 0fffffff - 4 bits left to go */ #define SSL_ALL 0xffffffffL #define SSL_ALL_CIPHERS (SSL_MKEY_MASK|SSL_AUTH_MASK|SSL_ENC_MASK|\ - SSL_MAC_MASK|SSL_EXP_MASK) + SSL_MAC_MASK) +#define SSL_ALL_STRENGTHS (SSL_EXP_MASK|SSL_STRONG_MASK) /* Mostly for SSLv3 */ #define SSL_PKEY_RSA_ENC 0 @@ -233,44 +362,59 @@ typedef struct cert_pkey_st { X509 *x509; -/* EVP_PKEY *publickey; *//* when extracted */ EVP_PKEY *privatekey; } CERT_PKEY; typedef struct cert_st { - int cert_type; - -#ifdef undef - X509 *x509; - EVP_PKEY *publickey; /* when extracted */ - EVP_PKEY *privatekey; - - pkeys[SSL_PKEY_RSA_ENC].x509 -/* pkeys[SSL_PKEY_RSA_ENC].publickey */ - pkeys[SSL_PKEY_RSA_ENC].privatekey -#endif - /* Current active set */ - CERT_PKEY *key; - + CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array + * Probably it would make more sense to store + * an index, not a pointer. */ + /* The following masks are for the key and auth * algorithms that are supported by the certs below */ int valid; unsigned long mask; unsigned long export_mask; - +#ifndef OPENSSL_NO_RSA RSA *rsa_tmp; + RSA *(*rsa_tmp_cb)(SSL *ssl,int is_export,int keysize); +#endif +#ifndef OPENSSL_NO_DH DH *dh_tmp; - RSA *(*rsa_tmp_cb)(); - DH *(*dh_tmp_cb)(); - CERT_PKEY pkeys[SSL_PKEY_NUM]; + DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize); +#endif - STACK *cert_chain; + CERT_PKEY pkeys[SSL_PKEY_NUM]; - int references; + int references; /* >1 only if SSL_copy_session_id is used */ } CERT; + +typedef struct sess_cert_st + { + STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */ + + /* The 'peer_...' members are used only by clients. */ + int peer_cert_type; + + CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */ + CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; + /* Obviously we don't have the private keys of these, + * so maybe we shouldn't even use the CERT_PKEY type here. */ + +#ifndef OPENSSL_NO_RSA + RSA *peer_rsa_tmp; /* not used for SSL 2 */ +#endif +#ifndef OPENSSL_NO_DH + DH *peer_dh_tmp; /* not used for SSL 2 */ +#endif + + int references; /* actually always 1 at the moment */ + } SESS_CERT; + + /*#define MAC_DEBUG */ /*#define ERR_DEBUG */ @@ -282,12 +426,7 @@ typedef struct cert_st /*#define RSA_DEBUG */ /*#define IDEA_DEBUG */ -#ifndef NOPROTO #define FP_ICC (int (*)(const void *,const void *)) -#else -#define FP_ICC -#endif - #define ssl_put_cipher_by_char(ssl,ciph,ptr) \ ((ssl)->method->put_cipher_by_char((ciph),(ptr))) #define ssl_get_cipher_by_char(ssl,ptr) \ @@ -295,29 +434,41 @@ typedef struct cert_st /* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff * It is a bit of a mess of functions, but hell, think of it as - * an opaque strucute :-) */ + * an opaque structure :-) */ typedef struct ssl3_enc_method { - int (*enc)(); - int (*mac)(); - int (*setup_key_block)(); - int (*generate_master_secret)(); - int (*change_cipher_state)(); - int (*final_finish_mac)(); + int (*enc)(SSL *, int); + int (*mac)(SSL *, unsigned char *, int); + int (*setup_key_block)(SSL *); + int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int); + int (*change_cipher_state)(SSL *, int); + int (*final_finish_mac)(SSL *, EVP_MD_CTX *, EVP_MD_CTX *, const char *, int, unsigned char *); int finish_mac_length; - int (*cert_verify_mac)(); - unsigned char client_finished[20]; - int client_finished_len; - unsigned char server_finished[20]; - int server_finished_len; - int (*alert_value)(); + int (*cert_verify_mac)(SSL *, EVP_MD_CTX *, unsigned char *); + const char *client_finished_label; + int client_finished_label_len; + const char *server_finished_label; + int server_finished_label_len; + int (*alert_value)(int); } SSL3_ENC_METHOD; -extern SSL3_ENC_METHOD ssl3_undef_enc_method; -extern SSL_CIPHER ssl2_ciphers[]; -extern SSL_CIPHER ssl3_ciphers[]; +/* Used for holding the relevant compression methods loaded into SSL_CTX */ +typedef struct ssl3_comp_st + { + int comp_id; /* The identifier byte for this compression type */ + char *name; /* Text name used for the compression type */ + COMP_METHOD *method; /* The method :-) */ + } SSL3_COMP; + +OPENSSL_EXTERN SSL3_ENC_METHOD ssl3_undef_enc_method; +OPENSSL_EXTERN SSL_CIPHER ssl2_ciphers[]; +OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[]; + +#ifdef OPENSSL_SYS_VMS +#undef SSL_COMP_get_compression_methods +#define SSL_COMP_get_compression_methods SSL_COMP_get_compress_methods +#endif -#ifndef NOPROTO SSL_METHOD *ssl_bad_method(int ver); SSL_METHOD *sslv2_base_method(void); @@ -327,33 +478,42 @@ SSL_METHOD *sslv3_base_method(void); void ssl_clear_cipher_ctx(SSL *s); int ssl_clear_bad_session(SSL *s); CERT *ssl_cert_new(void); +CERT *ssl_cert_dup(CERT *cert); +int ssl_cert_inst(CERT **o); void ssl_cert_free(CERT *c); -int ssl_set_cert_type(CERT *c, int type); +SESS_CERT *ssl_sess_cert_new(void); +void ssl_sess_cert_free(SESS_CERT *sc); +int ssl_set_peer_cert_type(SESS_CERT *c, int type); int ssl_get_new_session(SSL *s, int session); int ssl_get_prev_session(SSL *s, unsigned char *session,int len); -int ssl_cipher_id_cmp(SSL_CIPHER *a,SSL_CIPHER *b); -int ssl_cipher_ptr_id_cmp(SSL_CIPHER **ap,SSL_CIPHER **bp); -STACK *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,STACK **skp); -int ssl_cipher_list_to_bytes(SSL *s,STACK *sk,unsigned char *p); -STACK *ssl_create_cipher_list(SSL_METHOD *meth,STACK **pref, - STACK **sorted,char *str); +int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b); +int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap, + const SSL_CIPHER * const *bp); +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num, + STACK_OF(SSL_CIPHER) **skp); +int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p); +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, + STACK_OF(SSL_CIPHER) **pref, + STACK_OF(SSL_CIPHER) **sorted, + const char *rule_str); void ssl_update_cache(SSL *s, int mode); -int ssl_cipher_get_evp(SSL_CIPHER *c, EVP_CIPHER **enc, EVP_MD **md); -int ssl_verify_cert_chain(SSL *s,STACK *sk); +int ssl_cipher_get_evp(SSL_SESSION *s,const EVP_CIPHER **enc,const EVP_MD **md, + SSL_COMP **comp); +int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); int ssl_undefined_function(SSL *s); X509 *ssl_get_server_send_cert(SSL *); EVP_PKEY *ssl_get_sign_pkey(SSL *,SSL_CIPHER *); int ssl_cert_type(X509 *x,EVP_PKEY *pkey); -void ssl_set_cert_masks(CERT *c); -STACK *ssl_get_ciphers_by_id(SSL *s); +void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher); +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); int ssl_verify_alarm_type(long type); int ssl2_enc_init(SSL *s, int client); void ssl2_generate_key_material(SSL *s); void ssl2_enc(SSL *s,int send_data); void ssl2_mac(SSL *s,unsigned char *mac,int send_data); -SSL_CIPHER *ssl2_get_cipher_by_char(unsigned char *p); -int ssl2_put_cipher_by_char(SSL_CIPHER *c,unsigned char *p); +SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p); +int ssl2_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p); int ssl2_part_read(SSL *s, unsigned long f, int i); int ssl2_do_write(SSL *s); int ssl2_set_certificate(SSL *s, int type, int len, unsigned char *data); @@ -365,17 +525,19 @@ int ssl2_new(SSL *s); void ssl2_free(SSL *s); int ssl2_accept(SSL *s); int ssl2_connect(SSL *s); -int ssl2_read(SSL *s, char *buf, int len); -int ssl2_peek(SSL *s, char *buf, int len); -int ssl2_write(SSL *s, char *buf, int len); +int ssl2_read(SSL *s, void *buf, int len); +int ssl2_peek(SSL *s, void *buf, int len); +int ssl2_write(SSL *s, const void *buf, int len); int ssl2_shutdown(SSL *s); void ssl2_clear(SSL *s); -long ssl2_ctrl(SSL *s,int cmd, long larg, char *parg); -long ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, char *parg); +long ssl2_ctrl(SSL *s,int cmd, long larg, void *parg); +long ssl2_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg); +long ssl2_callback_ctrl(SSL *s,int cmd, void (*fp)()); +long ssl2_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)()); int ssl2_pending(SSL *s); -SSL_CIPHER *ssl3_get_cipher_by_char(unsigned char *p); -int ssl3_put_cipher_by_char(SSL_CIPHER *c,unsigned char *p); +SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); +int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p); void ssl3_init_finished_mac(SSL *s); int ssl3_send_server_certificate(SSL *s); int ssl3_get_finished(SSL *s,int state_a,int state_b); @@ -389,35 +551,37 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, int len); int ssl3_get_req_cert_type(SSL *s,unsigned char *p); long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok); -int ssl3_send_finished(SSL *s, int a, int b, unsigned char *sender,int slen); +int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen); int ssl3_num_ciphers(void); SSL_CIPHER *ssl3_get_cipher(unsigned int u); int ssl3_renegotiate(SSL *ssl); int ssl3_renegotiate_check(SSL *ssl); int ssl3_dispatch_alert(SSL *s); -int ssl3_read_bytes(SSL *s, int type, char *buf, int len); -int ssl3_part_read(SSL *s, int i); -int ssl3_write_bytes(SSL *s, int type, char *buf, int len); -int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *ctx1,EVP_MD_CTX *ctx2, - unsigned char *sender, int slen,unsigned char *p); +int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); +int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); +int ssl3_final_finish_mac(SSL *s, EVP_MD_CTX *ctx1, EVP_MD_CTX *ctx2, + const char *sender, int slen,unsigned char *p); int ssl3_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p); -void ssl3_finish_mac(SSL *s, unsigned char *buf, int len); +void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len); int ssl3_enc(SSL *s, int send_data); int ssl3_mac(SSL *ssl, unsigned char *md, int send_data); unsigned long ssl3_output_cert_chain(SSL *s, X509 *x); -SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK *have,STACK *pref); +SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt, + STACK_OF(SSL_CIPHER) *srvr); int ssl3_setup_buffers(SSL *s); int ssl3_new(SSL *s); void ssl3_free(SSL *s); int ssl3_accept(SSL *s); int ssl3_connect(SSL *s); -int ssl3_read(SSL *s, char *buf, int len); -int ssl3_peek(SSL *s,char *buf, int len); -int ssl3_write(SSL *s, char *buf, int len); +int ssl3_read(SSL *s, void *buf, int len); +int ssl3_peek(SSL *s, void *buf, int len); +int ssl3_write(SSL *s, const void *buf, int len); int ssl3_shutdown(SSL *s); void ssl3_clear(SSL *s); -long ssl3_ctrl(SSL *s,int cmd, long larg, char *parg); -long ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, char *parg); +long ssl3_ctrl(SSL *s,int cmd, long larg, void *parg); +long ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg); +long ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)()); +long ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)()); int ssl3_pending(SSL *s); int ssl23_accept(SSL *s); @@ -428,131 +592,28 @@ int ssl23_write_bytes(SSL *s); int tls1_new(SSL *s); void tls1_free(SSL *s); void tls1_clear(SSL *s); -long tls1_ctrl(SSL *s,int cmd, long larg, char *parg); +long tls1_ctrl(SSL *s,int cmd, long larg, void *parg); +long tls1_callback_ctrl(SSL *s,int cmd, void (*fp)()); SSL_METHOD *tlsv1_base_method(void ); - int ssl_init_wbio_buffer(SSL *s, int push); +void ssl_free_wbio_buffer(SSL *s); int tls1_change_cipher_state(SSL *s, int which); int tls1_setup_key_block(SSL *s); int tls1_enc(SSL *s, int snd); int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx, - unsigned char *str, int slen, unsigned char *p); + const char *str, int slen, unsigned char *p); int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in, unsigned char *p); int tls1_mac(SSL *ssl, unsigned char *md, int snd); int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, int len); int tls1_alert_code(int code); int ssl3_alert_code(int code); +int ssl_ok(SSL *s); +SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); -#else - -SSL_METHOD *ssl_bad_method(); -SSL_METHOD *sslv2_base_method(); -SSL_METHOD *sslv23_base_method(); -SSL_METHOD *sslv3_base_method(); - -void ssl_clear_cipher_ctx(); -int ssl_clear_bad_session(); -CERT *ssl_cert_new(); -void ssl_cert_free(); -int ssl_set_cert_type(); -int ssl_get_new_session(); -int ssl_get_prev_session(); -int ssl_cipher_id_cmp(); -int ssl_cipher_ptr_id_cmp(); -STACK *ssl_bytes_to_cipher_list(); -int ssl_cipher_list_to_bytes(); -STACK *ssl_create_cipher_list(); -void ssl_update_cache(); -int ssl_session_get_ciphers(); -int ssl_verify_cert_chain(); -int ssl_undefined_function(); -X509 *ssl_get_server_send_cert(); -EVP_PKEY *ssl_get_sign_pkey(); -int ssl_cert_type(); -void ssl_set_cert_masks(); -STACK *ssl_get_ciphers_by_id(); -int ssl_verify_alarm_type(); - -int ssl2_enc_init(); -void ssl2_generate_key_material(); -void ssl2_enc(); -void ssl2_mac(); -SSL_CIPHER *ssl2_get_cipher_by_char(); -int ssl2_put_cipher_by_char(); -int ssl2_part_read(); -int ssl2_do_write(); -int ssl2_set_certificate(); -void ssl2_return_error(); -void ssl2_write_error(); -int ssl2_num_ciphers(); -SSL_CIPHER *ssl2_get_cipher(); -int ssl2_new(); -void ssl2_free(); -int ssl2_accept(); -int ssl2_connect(); -int ssl2_read(); -int ssl2_peek(); -int ssl2_write(); -int ssl2_shutdown(); -void ssl2_clear(); -long ssl2_ctrl(); -long ssl2_ctx_ctrl(); -int ssl2_pending(); - -SSL_CIPHER *ssl3_get_cipher_by_char(); -int ssl3_put_cipher_by_char(); -void ssl3_init_finished_mac(); -int ssl3_send_server_certificate(); -int ssl3_get_finished(); -int ssl3_setup_key_block(); -int ssl3_send_change_cipher_spec(); -int ssl3_change_cipher_state(); -void ssl3_cleanup_key_block(); -int ssl3_do_write(); -void ssl3_send_alert(); -int ssl3_generate_master_secret(); -int ssl3_get_req_cert_type(); -long ssl3_get_message(); -int ssl3_send_finished(); -int ssl3_num_ciphers(); -SSL_CIPHER *ssl3_get_cipher(); -int ssl3_renegotiate(); -int ssl3_renegotiate_check(); -int ssl3_dispatch_alert(); -int ssl3_read_bytes(); -int ssl3_part_read(); -int ssl3_write_bytes(); -int ssl3_final_finish_mac(); -void ssl3_finish_mac(); -int ssl3_enc(); -int ssl3_mac(); -unsigned long ssl3_output_cert_chain(); -SSL_CIPHER *ssl3_choose_cipher(); -int ssl3_setup_buffers(); -int ssl3_new(); -void ssl3_free(); -int ssl3_accept(); -int ssl3_connect(); -int ssl3_read(); -int ssl3_peek(); -int ssl3_write(); -int ssl3_shutdown(); -void ssl3_clear(); -long ssl3_ctrl(); -long ssl3_ctx_ctrl(); -int ssl3_pending(); - -int ssl23_accept(); -int ssl23_connect(); -int ssl23_read_bytes(); -int ssl23_write_bytes(); - -int ssl_init_wbio_buffer(); - -#endif #endif diff --git a/src/lib/libssl/ssl_rsa.c b/src/lib/libssl/ssl_rsa.c index 140475e5fb..1cf8e20934 100644 --- a/src/lib/libssl/ssl_rsa.c +++ b/src/lib/libssl/ssl_rsa.c @@ -57,53 +57,32 @@ */ #include -#include "bio.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" -#include "pem.h" +#include +#include +#include +#include +#include #include "ssl_locl.h" -#ifndef NOPROTO static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); -#else -static int ssl_set_cert(); -static int ssl_set_pkey(); -#endif - -int SSL_use_certificate(ssl, x) -SSL *ssl; -X509 *x; +int SSL_use_certificate(SSL *ssl, X509 *x) { - CERT *c; - if (x == NULL) { SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); return(0); } - if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert)) + if (!ssl_cert_inst(&ssl->cert)) { - c=ssl_cert_new(); - if (c == NULL) - { - SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); - return(0); - } - if (ssl->cert != NULL) ssl_cert_free(ssl->cert); - ssl->cert=c; + SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); + return(0); } - c=ssl->cert; - - return(ssl_set_cert(c,x)); + return(ssl_set_cert(ssl->cert,x)); } -#ifndef NO_STDIO -int SSL_use_certificate_file(ssl, file, type) -SSL *ssl; -char *file; -int type; +#ifndef OPENSSL_NO_STDIO +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) { int j; BIO *in; @@ -130,7 +109,7 @@ int type; else if (type == SSL_FILETYPE_PEM) { j=ERR_R_PEM_LIB; - x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback); + x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); } else { @@ -152,10 +131,7 @@ end: } #endif -int SSL_use_certificate_ASN1(ssl, len, d) -SSL *ssl; -int len; -unsigned char *d; +int SSL_use_certificate_ASN1(SSL *ssl, unsigned char *d, int len) { X509 *x; int ret; @@ -172,12 +148,9 @@ unsigned char *d; return(ret); } -#ifndef NO_RSA -int SSL_use_RSAPrivateKey(ssl, rsa) -SSL *ssl; -RSA *rsa; +#ifndef OPENSSL_NO_RSA +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { - CERT *c; EVP_PKEY *pkey; int ret; @@ -186,37 +159,27 @@ RSA *rsa; SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); return(0); } - - if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert)) - { - c=ssl_cert_new(); - if (c == NULL) - { - SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); - return(0); - } - if (ssl->cert != NULL) ssl_cert_free(ssl->cert); - ssl->cert=c; + if (!ssl_cert_inst(&ssl->cert)) + { + SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); } - c=ssl->cert; if ((pkey=EVP_PKEY_new()) == NULL) { SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); return(0); } - CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + RSA_up_ref(rsa); EVP_PKEY_assign_RSA(pkey,rsa); - ret=ssl_set_pkey(c,pkey); + ret=ssl_set_pkey(ssl->cert,pkey); EVP_PKEY_free(pkey); return(ret); } #endif -static int ssl_set_pkey(c,pkey) -CERT *c; -EVP_PKEY *pkey; +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i,ok=0,bad=0; @@ -229,7 +192,13 @@ EVP_PKEY *pkey; if (c->pkeys[i].x509 != NULL) { -#ifndef NO_RSA + EVP_PKEY *pktmp; + pktmp = X509_get_pubkey(c->pkeys[i].x509); + EVP_PKEY_copy_parameters(pktmp,pkey); + EVP_PKEY_free(pktmp); + ERR_clear_error(); + +#ifndef OPENSSL_NO_RSA /* Don't check the public/private key, this is mostly * for smart cards. */ if ((pkey->type == EVP_PKEY_RSA) && @@ -282,12 +251,9 @@ EVP_PKEY *pkey; return(1); } -#ifndef NO_RSA -#ifndef NO_STDIO -int SSL_use_RSAPrivateKey_file(ssl, file, type) -SSL *ssl; -char *file; -int type; +#ifndef OPENSSL_NO_RSA +#ifndef OPENSSL_NO_STDIO +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) { int j,ret=0; BIO *in; @@ -314,7 +280,7 @@ int type; { j=ERR_R_PEM_LIB; rsa=PEM_read_bio_RSAPrivateKey(in,NULL, - ssl->ctx->default_passwd_callback); + ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); } else { @@ -334,13 +300,10 @@ end: } #endif -int SSL_use_RSAPrivateKey_ASN1(ssl,d,len) -SSL *ssl; -unsigned char *d; -long len; +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len) { int ret; - unsigned char *p; + const unsigned char *p; RSA *rsa; p=d; @@ -354,13 +317,10 @@ long len; RSA_free(rsa); return(ret); } -#endif /* !NO_RSA */ +#endif /* !OPENSSL_NO_RSA */ -int SSL_use_PrivateKey(ssl, pkey) -SSL *ssl; -EVP_PKEY *pkey; +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { - CERT *c; int ret; if (pkey == NULL) @@ -368,29 +328,17 @@ EVP_PKEY *pkey; SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); return(0); } - - if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert)) - { - c=ssl_cert_new(); - if (c == NULL) - { - SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); - return(0); - } - if (ssl->cert != NULL) ssl_cert_free(ssl->cert); - ssl->cert=c; + if (!ssl_cert_inst(&ssl->cert)) + { + SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); } - c=ssl->cert; - - ret=ssl_set_pkey(c,pkey); + ret=ssl_set_pkey(ssl->cert,pkey); return(ret); } -#ifndef NO_STDIO -int SSL_use_PrivateKey_file(ssl, file, type) -SSL *ssl; -char *file; -int type; +#ifndef OPENSSL_NO_STDIO +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) { int j,ret=0; BIO *in; @@ -412,7 +360,7 @@ int type; { j=ERR_R_PEM_LIB; pkey=PEM_read_bio_PrivateKey(in,NULL, - ssl->ctx->default_passwd_callback); + ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); } else { @@ -432,11 +380,7 @@ end: } #endif -int SSL_use_PrivateKey_ASN1(type,ssl,d,len) -int type; -SSL *ssl; -unsigned char *d; -long len; +int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, unsigned char *d, long len) { int ret; unsigned char *p; @@ -454,36 +398,22 @@ long len; return(ret); } -int SSL_CTX_use_certificate(ctx, x) -SSL_CTX *ctx; -X509 *x; +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { - CERT *c; - if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); return(0); } - - if (ctx->default_cert == NULL) + if (!ssl_cert_inst(&ctx->cert)) { - c=ssl_cert_new(); - if (c == NULL) - { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); - return(0); - } - ctx->default_cert=c; + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); + return(0); } - c=ctx->default_cert; - - return(ssl_set_cert(c,x)); + return(ssl_set_cert(ctx->cert, x)); } -static int ssl_set_cert(c,x) -CERT *c; -X509 *x; +static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY *pkey; int i,ok=0,bad=0; @@ -499,10 +429,24 @@ X509 *x; if (i < 0) { SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE); + EVP_PKEY_free(pkey); return(0); } if (c->pkeys[i].privatekey != NULL) + { + EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey); + ERR_clear_error(); + +#ifndef OPENSSL_NO_RSA + /* Don't check the public/private key, this is mostly + * for smart cards. */ + if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && + (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & + RSA_METHOD_FLAG_NO_CHECK)) + ok=1; + else +#endif { if (!X509_check_private_key(x,c->pkeys[i].privatekey)) { @@ -527,10 +471,12 @@ X509 *x; } else ok=1; + } /* OPENSSL_NO_RSA */ } else ok=1; + EVP_PKEY_free(pkey); if (bad) { EVP_PKEY_free(c->pkeys[i].privatekey); @@ -547,11 +493,8 @@ X509 *x; return(1); } -#ifndef NO_STDIO -int SSL_CTX_use_certificate_file(ctx, file, type) -SSL_CTX *ctx; -char *file; -int type; +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) { int j; BIO *in; @@ -578,7 +521,7 @@ int type; else if (type == SSL_FILETYPE_PEM) { j=ERR_R_PEM_LIB; - x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback); + x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); } else { @@ -600,10 +543,7 @@ end: } #endif -int SSL_CTX_use_certificate_ASN1(ctx, len, d) -SSL_CTX *ctx; -int len; -unsigned char *d; +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d) { X509 *x; int ret; @@ -620,13 +560,10 @@ unsigned char *d; return(ret); } -#ifndef NO_RSA -int SSL_CTX_use_RSAPrivateKey(ctx, rsa) -SSL_CTX *ctx; -RSA *rsa; +#ifndef OPENSSL_NO_RSA +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { int ret; - CERT *c; EVP_PKEY *pkey; if (rsa == NULL) @@ -634,37 +571,27 @@ RSA *rsa; SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); return(0); } - if (ctx->default_cert == NULL) + if (!ssl_cert_inst(&ctx->cert)) { - c=ssl_cert_new(); - if (c == NULL) - { - SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); - return(0); - } - ctx->default_cert=c; + SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); } - c=ctx->default_cert; - if ((pkey=EVP_PKEY_new()) == NULL) { SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); return(0); } - CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA); + RSA_up_ref(rsa); EVP_PKEY_assign_RSA(pkey,rsa); - ret=ssl_set_pkey(c,pkey); + ret=ssl_set_pkey(ctx->cert, pkey); EVP_PKEY_free(pkey); return(ret); } -#ifndef NO_STDIO -int SSL_CTX_use_RSAPrivateKey_file(ctx, file, type) -SSL_CTX *ctx; -char *file; -int type; +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) { int j,ret=0; BIO *in; @@ -691,7 +618,7 @@ int type; { j=ERR_R_PEM_LIB; rsa=PEM_read_bio_RSAPrivateKey(in,NULL, - ctx->default_passwd_callback); + ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); } else { @@ -711,13 +638,10 @@ end: } #endif -int SSL_CTX_use_RSAPrivateKey_ASN1(ctx,d,len) -SSL_CTX *ctx; -unsigned char *d; -long len; +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len) { int ret; - unsigned char *p; + const unsigned char *p; RSA *rsa; p=d; @@ -731,40 +655,25 @@ long len; RSA_free(rsa); return(ret); } -#endif /* !NO_RSA */ +#endif /* !OPENSSL_NO_RSA */ -int SSL_CTX_use_PrivateKey(ctx, pkey) -SSL_CTX *ctx; -EVP_PKEY *pkey; +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { - CERT *c; - if (pkey == NULL) { SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); return(0); } - - if (ctx->default_cert == NULL) + if (!ssl_cert_inst(&ctx->cert)) { - c=ssl_cert_new(); - if (c == NULL) - { - SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); - return(0); - } - ctx->default_cert=c; + SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); + return(0); } - c=ctx->default_cert; - - return(ssl_set_pkey(c,pkey)); + return(ssl_set_pkey(ctx->cert,pkey)); } -#ifndef NO_STDIO -int SSL_CTX_use_PrivateKey_file(ctx, file, type) -SSL_CTX *ctx; -char *file; -int type; +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) { int j,ret=0; BIO *in; @@ -786,7 +695,7 @@ int type; { j=ERR_R_PEM_LIB; pkey=PEM_read_bio_PrivateKey(in,NULL, - ctx->default_passwd_callback); + ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); } else { @@ -806,11 +715,8 @@ end: } #endif -int SSL_CTX_use_PrivateKey_ASN1(type,ctx,d,len) -int type; -SSL_CTX *ctx; -unsigned char *d; -long len; +int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, unsigned char *d, + long len) { int ret; unsigned char *p; @@ -829,3 +735,81 @@ long len; } +#ifndef OPENSSL_NO_STDIO +/* Read a file that contains our certificate in "PEM" format, + * possibly followed by a sequence of CA certificates that should be + * sent to the peer in the Certificate message. + */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) + { + BIO *in; + int ret=0; + X509 *x=NULL; + + in=BIO_new(BIO_s_file_internal()); + if (in == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in,file) <= 0) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_SYS_LIB); + goto end; + } + + x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); + if (x == NULL) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB); + goto end; + } + + ret=SSL_CTX_use_certificate(ctx,x); + if (ERR_peek_error() != 0) + ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ + if (ret) + { + /* If we could set up our certificate, now proceed to + * the CA certificates. + */ + X509 *ca; + int r; + unsigned long err; + + if (ctx->extra_certs != NULL) + { + sk_X509_pop_free(ctx->extra_certs, X509_free); + ctx->extra_certs = NULL; + } + + while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata)) + != NULL) + { + r = SSL_CTX_add_extra_chain_cert(ctx, ca); + if (!r) + { + X509_free(ca); + ret = 0; + goto end; + } + /* Note that we must not free r if it was successfully + * added to the chain (while we must free the main + * certificate, since its reference count is increased + * by SSL_CTX_use_certificate). */ + } + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) + (void)ERR_get_error(); + else + ret = 0; /* some real error */ + } + +end: + if (x != NULL) X509_free(x); + if (in != NULL) BIO_free(in); + return(ret); + } +#endif diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 8212600e40..6424f775e2 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c @@ -57,60 +57,57 @@ */ #include -#include "lhash.h" -#include "rand.h" +#include +#include #include "ssl_locl.h" -#ifndef NOPROTO static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s); -#else -static void SSL_SESSION_list_remove(); -static void SSL_SESSION_list_add(); -#endif - -static ssl_session_num=0; -static STACK *ssl_session_meth=NULL; +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); -SSL_SESSION *SSL_get_session(ssl) -SSL *ssl; +SSL_SESSION *SSL_get_session(SSL *ssl) +/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ { return(ssl->session); } -int SSL_SESSION_get_ex_new_index(argl,argp,new_func,dup_func,free_func) -long argl; -char *argp; -int (*new_func)(); -int (*dup_func)(); -void (*free_func)(); - { - ssl_session_num++; - return(CRYPTO_get_ex_new_index(ssl_session_num-1, - &ssl_session_meth, - argl,argp,new_func,dup_func,free_func)); - } - -int SSL_SESSION_set_ex_data(s,idx,arg) -SSL_SESSION *s; -int idx; -char *arg; +SSL_SESSION *SSL_get1_session(SSL *ssl) +/* variant of SSL_get_session: caller really gets something */ + { + SSL_SESSION *sess; + /* Need to lock this all up rather than just use CRYPTO_add so that + * somebody doesn't free ssl->session between when we check it's + * non-null and when we up the reference count. */ + CRYPTO_r_lock(CRYPTO_LOCK_SSL_SESSION); + sess = ssl->session; + if(sess) + sess->references++; + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_SESSION); + return(sess); + } + +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, + new_func, dup_func, free_func); + } + +int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) { return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); } -char *SSL_SESSION_get_ex_data(s,idx) -SSL_SESSION *s; -int idx; +void *SSL_SESSION_get_ex_data(SSL_SESSION *s, int idx) { return(CRYPTO_get_ex_data(&s->ex_data,idx)); } -SSL_SESSION *SSL_SESSION_new() +SSL_SESSION *SSL_SESSION_new(void) { SSL_SESSION *ss; - ss=(SSL_SESSION *)Malloc(sizeof(SSL_SESSION)); + ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); if (ss == NULL) { SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE); @@ -118,26 +115,64 @@ SSL_SESSION *SSL_SESSION_new() } memset(ss,0,sizeof(SSL_SESSION)); + ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ ss->references=1; ss->timeout=60*5+4; /* 5 minute timeout by default */ ss->time=time(NULL); ss->prev=NULL; ss->next=NULL; - CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data); + ss->compress_meth=0; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); return(ss); } -int ssl_get_new_session(s, session) -SSL *s; -int session; +/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 + * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly + * until we have no conflict is going to complete in one iteration pretty much + * "most" of the time (btw: understatement). So, if it takes us 10 iterations + * and we still can't avoid a conflict - well that's a reasonable point to call + * it quits. Either the RAND code is broken or someone is trying to open roughly + * very close to 2^128 (or 2^256) SSL sessions to our server. How you might + * store that many sessions is perhaps a more interesting question ... */ + +#define MAX_SESS_ID_ATTEMPTS 10 +static int def_generate_session_id(const SSL *ssl, unsigned char *id, + unsigned int *id_len) +{ + unsigned int retry = 0; + do + RAND_pseudo_bytes(id, *id_len); + while(SSL_has_matching_session_id(ssl, id, *id_len) && + (++retry < MAX_SESS_ID_ATTEMPTS)); + if(retry < MAX_SESS_ID_ATTEMPTS) + return 1; + /* else - woops a session_id match */ + /* XXX We should also check the external cache -- + * but the probability of a collision is negligible, and + * we could not prevent the concurrent creation of sessions + * with identical IDs since we currently don't have means + * to atomically check whether a session ID already exists + * and make a reservation for it if it does not + * (this problem applies to the internal cache as well). + */ + return 0; +} + +int ssl_get_new_session(SSL *s, int session) { + /* This gets used by clients and servers. */ + + unsigned int tmp; SSL_SESSION *ss=NULL; + GEN_SESSION_CB cb = def_generate_session_id; if ((ss=SSL_SESSION_new()) == NULL) return(0); /* If the context has a default timeout, use it */ - if (s->ctx->session_timeout != 0) + if (s->ctx->session_timeout == 0) ss->timeout=SSL_get_default_timeout(s); + else + ss->timeout=s->ctx->session_timeout; if (s->session != NULL) { @@ -147,7 +182,7 @@ int session; if (session) { - if (s->version == SSL2_CLIENT_VERSION) + if (s->version == SSL2_VERSION) { ss->ssl_version=SSL2_VERSION; ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH; @@ -168,18 +203,46 @@ int session; SSL_SESSION_free(ss); return(0); } - - for (;;) + /* Choose which callback will set the session ID */ + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + if(s->generate_session_id) + cb = s->generate_session_id; + else if(s->ctx->generate_session_id) + cb = s->ctx->generate_session_id; + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + /* Choose a session ID */ + tmp = ss->session_id_length; + if(!cb(s, ss->session_id, &tmp)) + { + /* The callback failed */ + SSLerr(SSL_F_SSL_GET_NEW_SESSION, + SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); + SSL_SESSION_free(ss); + return(0); + } + /* Don't allow the callback to set the session length to zero. + * nor set it higher than it was. */ + if(!tmp || (tmp > ss->session_id_length)) + { + /* The callback set an illegal length */ + SSLerr(SSL_F_SSL_GET_NEW_SESSION, + SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); + SSL_SESSION_free(ss); + return(0); + } + /* If the session length was shrunk and we're SSLv2, pad it */ + if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION)) + memset(ss->session_id + tmp, 0, ss->session_id_length - tmp); + else + ss->session_id_length = tmp; + /* Finally, check for a conflict */ + if(SSL_has_matching_session_id(s, ss->session_id, + ss->session_id_length)) { - SSL_SESSION *r; - - RAND_bytes(ss->session_id,ss->session_id_length); - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions, - (char *)ss); - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - if (r == NULL) break; - /* else - woops a session_id match */ + SSLerr(SSL_F_SSL_GET_NEW_SESSION, + SSL_R_SSL_SESSION_ID_CONFLICT); + SSL_SESSION_free(ss); + return(0); } } else @@ -187,58 +250,100 @@ int session; ss->session_id_length=0; } + memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); + ss->sid_ctx_length=s->sid_ctx_length; s->session=ss; ss->ssl_version=s->version; + ss->verify_result = X509_V_OK; return(1); } -int ssl_get_prev_session(s,session_id,len) -SSL *s; -unsigned char *session_id; -int len; +int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len) { + /* This is used only by servers. */ + SSL_SESSION *ret=NULL,data; + int fatal = 0; - /* conn_init();*/ data.ssl_version=s->version; data.session_id_length=len; if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) - return(0); - memcpy(data.session_id,session_id,len);; + goto err; + memcpy(data.session_id,session_id,len); if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) { CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data); + ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data); + if (ret != NULL) + /* don't allow other threads to steal it: */ + CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); } if (ret == NULL) { int copy=1; - - s->ctx->sess_miss++; + + s->ctx->stats.sess_miss++; ret=NULL; - if ((s->ctx->get_session_cb != NULL) && - ((ret=s->ctx->get_session_cb(s,session_id,len,©)) - != NULL)) + if (s->ctx->get_session_cb != NULL + && (ret=s->ctx->get_session_cb(s,session_id,len,©)) + != NULL) { - s->ctx->sess_cb_hit++; + s->ctx->stats.sess_cb_hit++; + + /* Increment reference count now if the session callback + * asks us to do so (note that if the session structures + * returned by the callback are shared between threads, + * it must handle the reference count itself [i.e. copy == 0], + * or things won't be thread-safe). */ + if (copy) + CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); /* The following should not return 1, otherwise, * things are very strange */ SSL_CTX_add_session(s->ctx,ret); - /* auto free it */ - if (!copy) - SSL_SESSION_free(ret); } - if (ret == NULL) return(0); + if (ret == NULL) + goto err; + } + + /* Now ret is non-NULL, and we own one of its reference counts. */ + + if((s->verify_mode&SSL_VERIFY_PEER) + && (!s->sid_ctx_length || ret->sid_ctx_length != s->sid_ctx_length + || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))) + { + /* We've found the session named by the client, but we don't + * want to use it in this context. */ + + if (s->sid_ctx_length == 0) + { + /* application should have used SSL[_CTX]_set_session_id_context + * -- we could tolerate this and just pretend we never heard + * of this session, but then applications could effectively + * disable the session cache by accident without anyone noticing */ + + SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); + fatal = 1; + goto err; + } + else + { +#if 0 /* The client cannot always know when a session is not appropriate, + * so we shouldn't generate an error message. */ + + SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); +#endif + goto err; /* treat like cache miss */ + } } if (ret->cipher == NULL) { - char buf[5],*p; + unsigned char buf[5],*p; unsigned long l; p=buf; @@ -249,25 +354,28 @@ int len; else ret->cipher=ssl_get_cipher_by_char(s,&(buf[1])); if (ret->cipher == NULL) - return(0); + goto err; } + +#if 0 /* This is way too late. */ + /* If a thread got the session, then 'swaped', and another got - * it and then due to a time-out decided to 'Free' it we could + * it and then due to a time-out decided to 'OPENSSL_free' it we could * be in trouble. So I'll increment it now, then double decrement * later - am I speaking rubbish?. */ CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); +#endif if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */ { - s->ctx->sess_timeout++; + s->ctx->stats.sess_timeout++; /* remove it from the cache */ SSL_CTX_remove_session(s->ctx,ret); - SSL_SESSION_free(ret); /* again to actually Free it */ - return(0); + goto err; } - s->ctx->sess_hit++; + s->ctx->stats.sess_hit++; /* ret->time=time(NULL); */ /* rezero timeout? */ /* again, just leave the session @@ -276,37 +384,64 @@ int len; if (s->session != NULL) SSL_SESSION_free(s->session); s->session=ret; + s->verify_result = s->session->verify_result; return(1); + + err: + if (ret != NULL) + SSL_SESSION_free(ret); + if (fatal) + return -1; + else + return 0; } -int SSL_CTX_add_session(ctx,c) -SSL_CTX *ctx; -SSL_SESSION *c; +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { int ret=0; SSL_SESSION *s; - /* conn_init(); */ + /* add just 1 reference count for the SSL_CTX's session cache + * even though it has two ways of access: each session is in a + * doubly linked list and an lhash */ CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); + /* if session c is in already in cache, we take back the increment later */ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c); + s=(SSL_SESSION *)lh_insert(ctx->sessions,c); - /* Put on the end of the queue unless it is already in the cache */ + /* s != NULL iff we already had a session with the given PID. + * In this case, s == c should hold (then we did not really modify + * ctx->sessions), or we're in trouble. */ + if (s != NULL && s != c) + { + /* We *are* in trouble ... */ + SSL_SESSION_list_remove(ctx,s); + SSL_SESSION_free(s); + /* ... so pretend the other session did not exist in cache + * (we cannot handle two SSL_SESSION structures with identical + * session ID in the same cache, which could happen e.g. when + * two threads concurrently obtain the same session from an external + * cache) */ + s = NULL; + } + + /* Put at the head of the queue unless it is already in the cache */ if (s == NULL) SSL_SESSION_list_add(ctx,c); - /* If the same session if is being 're-added', Free the old - * one when the last person stops using it. - * This will also work if it is alread in the cache. - * The references will go up and then down :-) */ if (s != NULL) { - SSL_SESSION_free(s); + /* existing cache entry -- decrement previously incremented reference + * count because it already takes into account the cache */ + + SSL_SESSION_free(s); /* s == c */ ret=0; } else { + /* new cache entry -- remove old ones if cache has become too large */ + ret=1; if (SSL_CTX_sess_get_cache_size(ctx) > 0) @@ -314,11 +449,11 @@ SSL_SESSION *c; while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { - if (!SSL_CTX_remove_session(ctx, - ctx->session_cache_tail)) + if (!remove_session_lock(ctx, + ctx->session_cache_tail, 0)) break; else - ctx->sess_cache_full++; + ctx->stats.sess_cache_full++; } } } @@ -326,24 +461,27 @@ SSL_SESSION *c; return(ret); } -int SSL_CTX_remove_session(ctx,c) -SSL_CTX *ctx; -SSL_SESSION *c; +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) +{ + return remove_session_lock(ctx, c, 1); +} + +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) { SSL_SESSION *r; int ret=0; if ((c != NULL) && (c->session_id_length != 0)) { - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c); - if (r != NULL) + if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + if ((r = (SSL_SESSION *)lh_retrieve(ctx->sessions,c)) == c) { ret=1; + r=(SSL_SESSION *)lh_delete(ctx->sessions,c); SSL_SESSION_list_remove(ctx,c); } - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); if (ret) { @@ -358,11 +496,13 @@ SSL_SESSION *c; return(ret); } -void SSL_SESSION_free(ss) -SSL_SESSION *ss; +void SSL_SESSION_free(SSL_SESSION *ss) { int i; + if(ss == NULL) + return; + i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); #ifdef REF_PRINT REF_PRINT("SSL_SESSION",ss); @@ -376,21 +516,19 @@ SSL_SESSION *ss; } #endif - CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH); memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH); memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH); - if (ss->cert != NULL) ssl_cert_free(ss->cert); + if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); if (ss->peer != NULL) X509_free(ss->peer); - if (ss->ciphers != NULL) sk_free(ss->ciphers); + if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers); memset(ss,0,sizeof(*ss)); - Free(ss); + OPENSSL_free(ss); } -int SSL_set_session(s, session) -SSL *s; -SSL_SESSION *session; +int SSL_set_session(SSL *s, SSL_SESSION *session) { int ret=0; SSL_METHOD *meth; @@ -410,14 +548,29 @@ SSL_SESSION *session; { if (!SSL_set_ssl_method(s,meth)) return(0); - session->timeout=SSL_get_default_timeout(s); + if (s->ctx->session_timeout == 0) + session->timeout=SSL_get_default_timeout(s); + else + session->timeout=s->ctx->session_timeout; } +#ifndef OPENSSL_NO_KRB5 + if (s->kssl_ctx && !s->kssl_ctx->client_princ && + session->krb5_client_princ_len > 0) + { + s->kssl_ctx->client_princ = (char *)malloc(session->krb5_client_princ_len + 1); + memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ, + session->krb5_client_princ_len); + s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0'; + } +#endif /* OPENSSL_NO_KRB5 */ + /* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/ CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION); if (s->session != NULL) SSL_SESSION_free(s->session); s->session=session; + s->verify_result = s->session->verify_result; /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/ ret=1; } @@ -428,42 +581,59 @@ SSL_SESSION *session; SSL_SESSION_free(s->session); s->session=NULL; } + + meth=s->ctx->method; + if (meth != s->method) + { + if (!SSL_set_ssl_method(s,meth)) + return(0); + } + ret=1; } return(ret); } -long SSL_SESSION_set_timeout(s,t) -SSL_SESSION *s; -long t; +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) { if (s == NULL) return(0); s->timeout=t; return(1); } -long SSL_SESSION_get_timeout(s) -SSL_SESSION *s; +long SSL_SESSION_get_timeout(SSL_SESSION *s) { if (s == NULL) return(0); return(s->timeout); } -long SSL_SESSION_get_time(s) -SSL_SESSION *s; +long SSL_SESSION_get_time(SSL_SESSION *s) { if (s == NULL) return(0); return(s->time); } -long SSL_SESSION_set_time(s,t) -SSL_SESSION *s; -long t; +long SSL_SESSION_set_time(SSL_SESSION *s, long t) { if (s == NULL) return(0); s->time=t; return(t); } +long SSL_CTX_set_timeout(SSL_CTX *s, long t) + { + long l; + if (s == NULL) return(0); + l=s->session_timeout; + s->session_timeout=t; + return(l); + } + +long SSL_CTX_get_timeout(SSL_CTX *s) + { + if (s == NULL) return(0); + return(s->session_timeout); + } + typedef struct timeout_param_st { SSL_CTX *ctx; @@ -471,15 +641,13 @@ typedef struct timeout_param_st LHASH *cache; } TIMEOUT_PARAM; -static void timeout(s,p) -SSL_SESSION *s; -TIMEOUT_PARAM *p; +static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p) { if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */ { /* The reason we don't call SSL_CTX_remove_session() is to * save on locking overhead */ - lh_delete(p->cache,(char *)s); + lh_delete(p->cache,s); SSL_SESSION_list_remove(p->ctx,s); s->not_resumable=1; if (p->ctx->remove_session_cb != NULL) @@ -488,27 +656,26 @@ TIMEOUT_PARAM *p; } } -void SSL_CTX_flush_sessions(s,t) -SSL_CTX *s; -long t; +static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION *, TIMEOUT_PARAM *) + +void SSL_CTX_flush_sessions(SSL_CTX *s, long t) { unsigned long i; TIMEOUT_PARAM tp; tp.ctx=s; - tp.cache=SSL_CTX_sessions(s); + tp.cache=s->sessions; if (tp.cache == NULL) return; tp.time=t; CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); i=tp.cache->down_load; tp.cache->down_load=0; - lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp); + lh_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout), &tp); tp.cache->down_load=i; CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); } -int ssl_clear_bad_session(s) -SSL *s; +int ssl_clear_bad_session(SSL *s) { if ( (s->session != NULL) && !(s->shutdown & SSL_SENT_SHUTDOWN) && @@ -522,9 +689,7 @@ SSL *s; } /* locked by SSL_CTX in the calling function */ -static void SSL_SESSION_list_remove(ctx,s) -SSL_CTX *ctx; -SSL_SESSION *s; +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) { if ((s->next == NULL) || (s->prev == NULL)) return; @@ -557,9 +722,7 @@ SSL_SESSION *s; s->prev=s->next=NULL; } -static void SSL_SESSION_list_add(ctx,s) -SSL_CTX *ctx; -SSL_SESSION *s; +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) { if ((s->next != NULL) && (s->prev != NULL)) SSL_SESSION_list_remove(ctx,s); diff --git a/src/lib/libssl/ssl_stat.c b/src/lib/libssl/ssl_stat.c index a1daf25dd4..b16d253081 100644 --- a/src/lib/libssl/ssl_stat.c +++ b/src/lib/libssl/ssl_stat.c @@ -59,23 +59,22 @@ #include #include "ssl_locl.h" -char *SSL_state_string_long(s) -SSL *s; +const char *SSL_state_string_long(const SSL *s) { - char *str; + const char *str; switch (s->state) { -case SSL_ST_BEFORE: str="before SSL initalisation"; break; -case SSL_ST_ACCEPT: str="before accept initalisation"; break; -case SSL_ST_CONNECT: str="before connect initalisation"; break; +case SSL_ST_BEFORE: str="before SSL initialization"; break; +case SSL_ST_ACCEPT: str="before accept initialization"; break; +case SSL_ST_CONNECT: str="before connect initialization"; break; case SSL_ST_OK: str="SSL negotiation finished successfully"; break; case SSL_ST_RENEGOTIATE: str="SSL renegotiate ciphers"; break; -case SSL_ST_BEFORE|SSL_ST_CONNECT: str="before/connect initalisation"; break; -case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initalisation"; break; -case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initalisation"; break; -case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initalisation"; break; -#ifndef NO_SSL2 +case SSL_ST_BEFORE|SSL_ST_CONNECT: str="before/connect initialization"; break; +case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initialization"; break; +case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initialization"; break; +case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initialization"; break; +#ifndef OPENSSL_NO_SSL2 case SSL2_ST_CLIENT_START_ENCRYPTION: str="SSLv2 client start encryption"; break; case SSL2_ST_SERVER_START_ENCRYPTION: str="SSLv2 server start encryption"; break; case SSL2_ST_SEND_CLIENT_HELLO_A: str="SSLv2 write client hello A"; break; @@ -116,7 +115,7 @@ case SSL2_ST_X509_GET_SERVER_CERTIFICATE: str="SSLv2 X509 read server certificat case SSL2_ST_X509_GET_CLIENT_CERTIFICATE: str="SSLv2 X509 read client certificate"; break; #endif -#ifndef NO_SSL3 +#ifndef OPENSSL_NO_SSL3 /* SSLv3 additions */ case SSL3_ST_CW_CLNT_HELLO_A: str="SSLv3 write client hello A"; break; case SSL3_ST_CW_CLNT_HELLO_B: str="SSLv3 write client hello B"; break; @@ -132,10 +131,12 @@ case SSL3_ST_CR_SRVR_DONE_A: str="SSLv3 read server done A"; break; case SSL3_ST_CR_SRVR_DONE_B: str="SSLv3 read server done B"; break; case SSL3_ST_CW_CERT_A: str="SSLv3 write client certificate A"; break; case SSL3_ST_CW_CERT_B: str="SSLv3 write client certificate B"; break; +case SSL3_ST_CW_CERT_C: str="SSLv3 write client certificate C"; break; +case SSL3_ST_CW_CERT_D: str="SSLv3 write client certificate D"; break; case SSL3_ST_CW_KEY_EXCH_A: str="SSLv3 write client key exchange A"; break; case SSL3_ST_CW_KEY_EXCH_B: str="SSLv3 write client key exchange B"; break; case SSL3_ST_CW_CERT_VRFY_A: str="SSLv3 write certificate verify A"; break; -case SSL3_ST_CW_CERT_VRFY_B: str="SSLv3 write certificate verify A"; break; +case SSL3_ST_CW_CERT_VRFY_B: str="SSLv3 write certificate verify B"; break; case SSL3_ST_CW_CHANGE_A: case SSL3_ST_SW_CHANGE_A: str="SSLv3 write change cipher spec A"; break; @@ -144,7 +145,7 @@ case SSL3_ST_SW_CHANGE_B: str="SSLv3 write change cipher spec B"; break; case SSL3_ST_CW_FINISHED_A: case SSL3_ST_SW_FINISHED_A: str="SSLv3 write finished A"; break; case SSL3_ST_CW_FINISHED_B: -case SSL3_ST_SW_FINISHED_B: str="SSLv3 write finished A"; break; +case SSL3_ST_SW_FINISHED_B: str="SSLv3 write finished B"; break; case SSL3_ST_CR_CHANGE_A: case SSL3_ST_SR_CHANGE_A: str="SSLv3 read change cipher spec A"; break; case SSL3_ST_CR_CHANGE_B: @@ -181,8 +182,8 @@ case SSL3_ST_SR_CERT_VRFY_A: str="SSLv3 read certificate verify A"; break; case SSL3_ST_SR_CERT_VRFY_B: str="SSLv3 read certificate verify B"; break; #endif -#if !defined(NO_SSL2) && !defined(NO_SSL3) -/* SSLv2/v3 compatablitity states */ +#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) +/* SSLv2/v3 compatibility states */ /* client */ case SSL23_ST_CW_CLNT_HELLO_A: str="SSLv2/v3 write client hello A"; break; case SSL23_ST_CW_CLNT_HELLO_B: str="SSLv2/v3 write client hello B"; break; @@ -198,10 +199,9 @@ default: str="unknown state"; break; return(str); } -char *SSL_rstate_string_long(s) -SSL *s; +const char *SSL_rstate_string_long(const SSL *s) { - char *str; + const char *str; switch (s->rstate) { @@ -213,10 +213,9 @@ SSL *s; return(str); } -char *SSL_state_string(s) -SSL *s; +const char *SSL_state_string(const SSL *s) { - char *str; + const char *str; switch (s->state) { @@ -224,7 +223,7 @@ case SSL_ST_BEFORE: str="PINIT "; break; case SSL_ST_ACCEPT: str="AINIT "; break; case SSL_ST_CONNECT: str="CINIT "; break; case SSL_ST_OK: str="SSLOK "; break; -#ifndef NO_SSL2 +#ifndef OPENSSL_NO_SSL2 case SSL2_ST_CLIENT_START_ENCRYPTION: str="2CSENC"; break; case SSL2_ST_SERVER_START_ENCRYPTION: str="2SSENC"; break; case SSL2_ST_SEND_CLIENT_HELLO_A: str="2SCH_A"; break; @@ -265,7 +264,7 @@ case SSL2_ST_X509_GET_SERVER_CERTIFICATE: str="2X9GSC"; break; case SSL2_ST_X509_GET_CLIENT_CERTIFICATE: str="2X9GCC"; break; #endif -#ifndef NO_SSL3 +#ifndef OPENSSL_NO_SSL3 /* SSLv3 additions */ case SSL3_ST_SW_FLUSH: case SSL3_ST_CW_FLUSH: str="3FLUSH"; break; @@ -283,6 +282,8 @@ case SSL3_ST_CR_SRVR_DONE_A: str="3RSD_A"; break; case SSL3_ST_CR_SRVR_DONE_B: str="3RSD_B"; break; case SSL3_ST_CW_CERT_A: str="3WCC_A"; break; case SSL3_ST_CW_CERT_B: str="3WCC_B"; break; +case SSL3_ST_CW_CERT_C: str="3WCC_C"; break; +case SSL3_ST_CW_CERT_D: str="3WCC_D"; break; case SSL3_ST_CW_KEY_EXCH_A: str="3WCKEA"; break; case SSL3_ST_CW_KEY_EXCH_B: str="3WCKEB"; break; case SSL3_ST_CW_CERT_VRFY_A: str="3WCV_A"; break; @@ -329,8 +330,8 @@ case SSL3_ST_SR_CERT_VRFY_A: str="3RCV_A"; break; case SSL3_ST_SR_CERT_VRFY_B: str="3RCV_B"; break; #endif -#if !defined(NO_SSL2) && !defined(NO_SSL3) -/* SSLv2/v3 compatablitity states */ +#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) +/* SSLv2/v3 compatibility states */ /* client */ case SSL23_ST_CW_CLNT_HELLO_A: str="23WCHA"; break; case SSL23_ST_CW_CLNT_HELLO_B: str="23WCHB"; break; @@ -346,8 +347,7 @@ default: str="UNKWN "; break; return(str); } -char *SSL_alert_type_string_long(value) -int value; +const char *SSL_alert_type_string_long(int value) { value>>=8; if (value == SSL3_AL_WARNING) @@ -358,8 +358,7 @@ int value; return("unknown"); } -char *SSL_alert_type_string(value) -int value; +const char *SSL_alert_type_string(int value) { value>>=8; if (value == SSL3_AL_WARNING) @@ -370,10 +369,9 @@ int value; return("U"); } -char *SSL_alert_desc_string(value) -int value; +const char *SSL_alert_desc_string(int value) { - char *str; + const char *str; switch (value & 0xff) { @@ -389,15 +387,26 @@ int value; case SSL3_AD_CERTIFICATE_EXPIRED: str="CE"; break; case SSL3_AD_CERTIFICATE_UNKNOWN: str="CU"; break; case SSL3_AD_ILLEGAL_PARAMETER: str="IP"; break; + case TLS1_AD_DECRYPTION_FAILED: str="DC"; break; + case TLS1_AD_RECORD_OVERFLOW: str="RO"; break; + case TLS1_AD_UNKNOWN_CA: str="CA"; break; + case TLS1_AD_ACCESS_DENIED: str="AD"; break; + case TLS1_AD_DECODE_ERROR: str="DE"; break; + case TLS1_AD_DECRYPT_ERROR: str="CY"; break; + case TLS1_AD_EXPORT_RESTRICTION: str="ER"; break; + case TLS1_AD_PROTOCOL_VERSION: str="PV"; break; + case TLS1_AD_INSUFFICIENT_SECURITY: str="IS"; break; + case TLS1_AD_INTERNAL_ERROR: str="IE"; break; + case TLS1_AD_USER_CANCELLED: str="US"; break; + case TLS1_AD_NO_RENEGOTIATION: str="NR"; break; default: str="UK"; break; } return(str); } -char *SSL_alert_desc_string_long(value) -int value; +const char *SSL_alert_desc_string_long(int value) { - char *str; + const char *str; switch (value & 0xff) { @@ -405,7 +414,7 @@ int value; str="close notify"; break; case SSL3_AD_UNEXPECTED_MESSAGE: - str="unexected_message"; + str="unexpected_message"; break; case SSL3_AD_BAD_RECORD_MAC: str="bad record mac"; @@ -432,20 +441,55 @@ int value; str="certificate expired"; break; case SSL3_AD_CERTIFICATE_UNKNOWN: - str="certifcate unknown"; + str="certificate unknown"; break; case SSL3_AD_ILLEGAL_PARAMETER: str="illegal parameter"; break; + case TLS1_AD_DECRYPTION_FAILED: + str="decryption failed"; + break; + case TLS1_AD_RECORD_OVERFLOW: + str="record overflow"; + break; + case TLS1_AD_UNKNOWN_CA: + str="unknown CA"; + break; + case TLS1_AD_ACCESS_DENIED: + str="access denied"; + break; + case TLS1_AD_DECODE_ERROR: + str="decode error"; + break; + case TLS1_AD_DECRYPT_ERROR: + str="decrypt error"; + break; + case TLS1_AD_EXPORT_RESTRICTION: + str="export restriction"; + break; + case TLS1_AD_PROTOCOL_VERSION: + str="protocol version"; + break; + case TLS1_AD_INSUFFICIENT_SECURITY: + str="insufficient security"; + break; + case TLS1_AD_INTERNAL_ERROR: + str="internal error"; + break; + case TLS1_AD_USER_CANCELLED: + str="user canceled"; + break; + case TLS1_AD_NO_RENEGOTIATION: + str="no renegotiation"; + break; default: str="unknown"; break; } return(str); } -char *SSL_rstate_string(s) -SSL *s; +const char *SSL_rstate_string(const SSL *s) { - char *str; + const char *str; switch (s->rstate) { diff --git a/src/lib/libssl/ssl_txt.c b/src/lib/libssl/ssl_txt.c index ce60e1a6dd..40b76b1b26 100644 --- a/src/lib/libssl/ssl_txt.c +++ b/src/lib/libssl/ssl_txt.c @@ -57,35 +57,31 @@ */ #include -#include "buffer.h" +#include #include "ssl_locl.h" -#ifndef NO_FP_API -int SSL_SESSION_print_fp(fp, x) -FILE *fp; -SSL_SESSION *x; - { - BIO *b; - int ret; +#ifndef OPENSSL_NO_FP_API +int SSL_SESSION_print_fp(FILE *fp, SSL_SESSION *x) + { + BIO *b; + int ret; - if ((b=BIO_new(BIO_s_file_internal())) == NULL) + if ((b=BIO_new(BIO_s_file_internal())) == NULL) { SSLerr(SSL_F_SSL_SESSION_PRINT_FP,ERR_R_BUF_LIB); - return(0); + return(0); } - BIO_set_fp(b,fp,BIO_NOCLOSE); - ret=SSL_SESSION_print(b,x); - BIO_free(b); - return(ret); - } + BIO_set_fp(b,fp,BIO_NOCLOSE); + ret=SSL_SESSION_print(b,x); + BIO_free(b); + return(ret); + } #endif -int SSL_SESSION_print(bp,x) -BIO *bp; -SSL_SESSION *x; +int SSL_SESSION_print(BIO *bp, SSL_SESSION *x) { - int i; - char str[128],*s; + unsigned int i; + char *s; if (x == NULL) goto err; if (BIO_puts(bp,"SSL-Session:\n") <= 0) goto err; @@ -97,30 +93,41 @@ SSL_SESSION *x; s="TLSv1"; else s="unknown"; - sprintf(str," Protocol : %s\n",s); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_printf(bp," Protocol : %s\n",s) <= 0) goto err; if (x->cipher == NULL) { if (((x->cipher_id) & 0xff000000) == 0x02000000) - sprintf(str," Cipher : %06lX\n",x->cipher_id&0xffffff); + { + if (BIO_printf(bp," Cipher : %06lX\n",x->cipher_id&0xffffff) <= 0) + goto err; + } else - sprintf(str," Cipher : %04lX\n",x->cipher_id&0xffff); + { + if (BIO_printf(bp," Cipher : %04lX\n",x->cipher_id&0xffff) <= 0) + goto err; + } } else - sprintf(str," Cipher : %s\n",(x->cipher == NULL)?"unknown":x->cipher->name); - if (BIO_puts(bp,str) <= 0) goto err; + { + if (BIO_printf(bp," Cipher : %s\n",((x->cipher == NULL)?"unknown":x->cipher->name)) <= 0) + goto err; + } if (BIO_puts(bp," Session-ID: ") <= 0) goto err; - for (i=0; i<(int)x->session_id_length; i++) + for (i=0; isession_id_length; i++) + { + if (BIO_printf(bp,"%02X",x->session_id[i]) <= 0) goto err; + } + if (BIO_puts(bp,"\n Session-ID-ctx: ") <= 0) goto err; + for (i=0; isid_ctx_length; i++) { - sprintf(str,"%02X",x->session_id[i]); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_printf(bp,"%02X",x->sid_ctx[i]) <= 0) + goto err; } if (BIO_puts(bp,"\n Master-Key: ") <= 0) goto err; - for (i=0; i<(int)x->master_key_length; i++) + for (i=0; i<(unsigned int)x->master_key_length; i++) { - sprintf(str,"%02X",x->master_key[i]); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_printf(bp,"%02X",x->master_key[i]) <= 0) goto err; } if (BIO_puts(bp,"\n Key-Arg : ") <= 0) goto err; if (x->key_arg_length == 0) @@ -128,22 +135,49 @@ SSL_SESSION *x; if (BIO_puts(bp,"None") <= 0) goto err; } else - for (i=0; i<(int)x->key_arg_length; i++) + for (i=0; ikey_arg_length; i++) { - sprintf(str,"%02X",x->key_arg[i]); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_printf(bp,"%02X",x->key_arg[i]) <= 0) goto err; } +#ifndef OPENSSL_NO_KRB5 + if (BIO_puts(bp,"\n Krb5 Principal: ") <= 0) goto err; + if (x->krb5_client_princ_len == 0) + { + if (BIO_puts(bp,"None") <= 0) goto err; + } + else + for (i=0; ikrb5_client_princ_len; i++) + { + if (BIO_printf(bp,"%02X",x->krb5_client_princ[i]) <= 0) goto err; + } +#endif /* OPENSSL_NO_KRB5 */ + if (x->compress_meth != 0) + { + SSL_COMP *comp; + + ssl_cipher_get_evp(x,NULL,NULL,&comp); + if (comp == NULL) + { + if (BIO_printf(bp,"\n Compression: %d",x->compress_meth) <= 0) goto err; + } + else + { + if (BIO_printf(bp,"\n Compression: %d (%s)", comp->id,comp->method->name) <= 0) goto err; + } + } if (x->time != 0L) { - sprintf(str,"\n Start Time: %ld",x->time); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_printf(bp, "\n Start Time: %ld",x->time) <= 0) goto err; } if (x->timeout != 0L) { - sprintf(str,"\n Timeout : %ld (sec)",x->timeout); - if (BIO_puts(bp,str) <= 0) goto err; + if (BIO_printf(bp, "\n Timeout : %ld (sec)",x->timeout) <= 0) goto err; } if (BIO_puts(bp,"\n") <= 0) goto err; + + if (BIO_puts(bp, " Verify return code: ") <= 0) goto err; + if (BIO_printf(bp, "%ld (%s)\n", x->verify_result, + X509_verify_cert_error_string(x->verify_result)) <= 0) goto err; return(1); err: diff --git a/src/lib/libssl/t1_clnt.c b/src/lib/libssl/t1_clnt.c index 986d2436e2..9745630a00 100644 --- a/src/lib/libssl/t1_clnt.c +++ b/src/lib/libssl/t1_clnt.c @@ -57,14 +57,14 @@ */ #include -#include "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" +#include +#include +#include +#include #include "ssl_locl.h" -static SSL_METHOD *tls1_get_client_method(ver) -int ver; +static SSL_METHOD *tls1_get_client_method(int ver); +static SSL_METHOD *tls1_get_client_method(int ver) { if (ver == TLS1_VERSION) return(TLSv1_client_method()); @@ -72,18 +72,18 @@ int ver; return(NULL); } -SSL_METHOD *TLSv1_client_method() +SSL_METHOD *TLSv1_client_method(void) { static int init=1; static SSL_METHOD TLSv1_client_data; if (init) { - init=0; memcpy((char *)&TLSv1_client_data,(char *)tlsv1_base_method(), sizeof(SSL_METHOD)); TLSv1_client_data.ssl_connect=ssl3_connect; TLSv1_client_data.get_ssl_method=tls1_get_client_method; + init=0; } return(&TLSv1_client_data); } diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c index fbdd3bffb5..b80525f3ba 100644 --- a/src/lib/libssl/t1_enc.c +++ b/src/lib/libssl/t1_enc.c @@ -55,20 +55,70 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2002 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 "evp.h" -#include "hmac.h" +#include +#include +#include #include "ssl_locl.h" +#include -static void tls1_P_hash(md,sec,sec_len,seed,seed_len,out,olen) -EVP_MD *md; -unsigned char *sec; -int sec_len; -unsigned char *seed; -int seed_len; -unsigned char *out; -int olen; +static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec, + int sec_len, unsigned char *seed, int seed_len, + unsigned char *out, int olen) { int chunk,n; unsigned int j; @@ -79,16 +129,20 @@ int olen; chunk=EVP_MD_size(md); - HMAC_Init(&ctx,sec,sec_len,md); + HMAC_CTX_init(&ctx); + HMAC_CTX_init(&ctx_tmp); + HMAC_Init_ex(&ctx,sec,sec_len,md, NULL); + HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL); HMAC_Update(&ctx,seed,seed_len); HMAC_Final(&ctx,A1,&A1_len); n=0; for (;;) { - HMAC_Init(&ctx,NULL,0,NULL); /* re-init */ + HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */ + HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */ HMAC_Update(&ctx,A1,A1_len); - memcpy(&ctx_tmp,&ctx,sizeof(ctx)); /* Copy for A2 */ /* not needed for last one */ + HMAC_Update(&ctx_tmp,A1,A1_len); HMAC_Update(&ctx,seed,seed_len); if (olen > chunk) @@ -105,24 +159,18 @@ int olen; break; } } - HMAC_cleanup(&ctx); - HMAC_cleanup(&ctx_tmp); + HMAC_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&ctx_tmp); memset(A1,0,sizeof(A1)); } -static void tls1_PRF(md5,sha1,label,label_len,sec,slen,out1,out2,olen) -EVP_MD *md5; -EVP_MD *sha1; -unsigned char *label; -int label_len; -unsigned char *sec; -int slen; -unsigned char *out1; -unsigned char *out2; -int olen; +static void tls1_PRF(const EVP_MD *md5, const EVP_MD *sha1, + unsigned char *label, int label_len, + const unsigned char *sec, int slen, unsigned char *out1, + unsigned char *out2, int olen) { int len,i; - unsigned char *S1,*S2; + const unsigned char *S1,*S2; len=slen/2; S1=sec; @@ -137,10 +185,8 @@ int olen; out1[i]^=out2[i]; } -static void tls1_generate_key_block(s,km,tmp,num) -SSL *s; -unsigned char *km,*tmp; -int num; +static void tls1_generate_key_block(SSL *s, unsigned char *km, + unsigned char *tmp, int num) { unsigned char *p; unsigned char buf[SSL3_RANDOM_SIZE*2+ @@ -155,15 +201,25 @@ int num; memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); p+=SSL3_RANDOM_SIZE; - tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf, - s->session->master_key,s->session->master_key_length, - km,tmp,num); + tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf), + s->session->master_key,s->session->master_key_length, + km,tmp,num); +#ifdef KSSL_DEBUG + printf("tls1_generate_key_block() ==> %d byte master_key =\n\t", + s->session->master_key_length); + { + int i; + for (i=0; i < s->session->master_key_length; i++) + { + printf("%02X", s->session->master_key[i]); + } + printf("\n"); } +#endif /* KSSL_DEBUG */ } -int tls1_change_cipher_state(s,which) -SSL *s; -int which; +int tls1_change_cipher_state(SSL *s, int which) { + static const unsigned char empty[]=""; unsigned char *p,*key_block,*mac_secret; unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+ SSL3_RANDOM_SIZE*2]; @@ -174,47 +230,103 @@ int which; unsigned char *ms,*key,*iv,*er1,*er2; int client_write; EVP_CIPHER_CTX *dd; - EVP_CIPHER *c; - SSL_COMPRESSION *comp; - EVP_MD *m; - int exp,n,i,j,k,exp_label_len; + const EVP_CIPHER *c; + const SSL_COMP *comp; + const EVP_MD *m; + int is_export,n,i,j,k,exp_label_len,cl; + int reuse_dd = 0; - exp=(s->s3->tmp.new_cipher->algorithms & SSL_EXPORT)?1:0; + is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); c=s->s3->tmp.new_sym_enc; m=s->s3->tmp.new_hash; comp=s->s3->tmp.new_compression; key_block=s->s3->tmp.key_block; +#ifdef KSSL_DEBUG + printf("tls1_change_cipher_state(which= %d) w/\n", which); + printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms, + comp); + printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); + printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", + c->nid,c->block_size,c->key_len,c->iv_len); + printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); + { + int i; + for (i=0; is3->tmp.key_block_length; i++) + printf("%02x", key_block[i]); printf("\n"); + } +#endif /* KSSL_DEBUG */ + if (which & SSL3_CC_READ) { - if ((s->enc_read_ctx == NULL) && - ((s->enc_read_ctx=(EVP_CIPHER_CTX *) - Malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) + if (s->enc_read_ctx != NULL) + reuse_dd = 1; + else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) goto err; dd= s->enc_read_ctx; s->read_hash=m; - s->read_compression=comp; + if (s->expand != NULL) + { + COMP_CTX_free(s->expand); + s->expand=NULL; + } + if (comp != NULL) + { + s->expand=COMP_CTX_new(comp->method); + if (s->expand == NULL) + { + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); + goto err2; + } + if (s->s3->rrec.comp == NULL) + s->s3->rrec.comp=(unsigned char *) + OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); + if (s->s3->rrec.comp == NULL) + goto err; + } memset(&(s->s3->read_sequence[0]),0,8); mac_secret= &(s->s3->read_mac_secret[0]); } else { + if (s->enc_write_ctx != NULL) + reuse_dd = 1; + else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) + goto err; if ((s->enc_write_ctx == NULL) && ((s->enc_write_ctx=(EVP_CIPHER_CTX *) - Malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) + OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)) goto err; dd= s->enc_write_ctx; s->write_hash=m; - s->write_compression=comp; + if (s->compress != NULL) + { + COMP_CTX_free(s->compress); + s->compress=NULL; + } + if (comp != NULL) + { + s->compress=COMP_CTX_new(comp->method); + if (s->compress == NULL) + { + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); + goto err2; + } + } memset(&(s->s3->write_sequence[0]),0,8); mac_secret= &(s->s3->write_mac_secret[0]); } + if (reuse_dd) + EVP_CIPHER_CTX_cleanup(dd); EVP_CIPHER_CTX_init(dd); p=s->s3->tmp.key_block; i=EVP_MD_size(m); - j=(exp)?5:EVP_CIPHER_key_length(c); + cl=EVP_CIPHER_key_length(c); + j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? + cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; + /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ k=EVP_CIPHER_iv_length(c); er1= &(s->s3->client_random[0]); er2= &(s->s3->server_random[0]); @@ -241,7 +353,7 @@ int which; if (n > s->s3->tmp.key_block_length) { - SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_INTERNAL_ERROR); + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); goto err2; } @@ -250,7 +362,7 @@ int which; printf("which = %04X\nmac key=",which); { int z; for (z=0; zctx->md5,s->ctx->sha1,buf,p-buf,empty,0, + iv1,iv2,k*2); if (client_write) iv=iv1; else @@ -286,8 +398,18 @@ printf("which = %04X\nmac key=",which); } s->session->key_arg_length=0; +#ifdef KSSL_DEBUG + { + int i; + printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); + printf("\tkey= "); for (i=0; ikey_len; i++) printf("%02x", key[i]); + printf("\n"); + printf("\t iv= "); for (i=0; iiv_len; i++) printf("%02x", iv[i]); + printf("\n"); + } +#endif /* KSSL_DEBUG */ - EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE)); + EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); #ifdef TLS_DEBUG printf("which = %04X\nkey=",which); { int z; for (z=0; zs3->tmp.key_block_length != 0) return(1); - if (!ssl_cipher_get_evp(s->session->cipher,&c,&hash)) + if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp)) { SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return(0); @@ -327,16 +453,14 @@ SSL *s; s->s3->tmp.new_sym_enc=c; s->s3->tmp.new_hash=hash; - exp=(s->session->cipher->algorithms & SSL_EXPORT)?1:0; - num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c); num*=2; ssl3_cleanup_key_block(s); - if ((p1=(unsigned char *)Malloc(num)) == NULL) + if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL) goto err; - if ((p2=(unsigned char *)Malloc(num)) == NULL) + if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL) goto err; s->s3->tmp.key_block_length=num; @@ -353,28 +477,33 @@ printf("pre-master\n"); #endif tls1_generate_key_block(s,p1,p2,num); memset(p2,0,num); - Free(p2); + OPENSSL_free(p2); #ifdef TLS_DEBUG printf("\nkey block\n"); { int z; for (z=0; zs3->need_empty_fragments = 1; +#ifndef NO_RC4 + if ((s->session->cipher != NULL) && ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4)) + s->s3->need_empty_fragments = 0; +#endif + return(1); err: SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); return(0); } -int tls1_enc(s,send) -SSL *s; -int send; +int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,ii,j,k,n=0; - EVP_CIPHER *enc; - SSL_COMPRESSION *comp; + const EVP_CIPHER *enc; if (send) { @@ -383,12 +512,9 @@ int send; ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) - { enc=NULL; comp=NULL; } + enc=NULL; else - { enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); - comp=s->write_compression; - } } else { @@ -397,18 +523,19 @@ int send; ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) - { enc=NULL; comp=NULL; } + enc=NULL; else - { enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); - comp=s->read_compression; - } } +#ifdef KSSL_DEBUG + printf("tls1_enc(%d)\n", send); +#endif /* KSSL_DEBUG */ + if ((s->session == NULL) || (ds == NULL) || - ((enc == NULL) && (comp == NULL))) + (enc == NULL)) { - memcpy(rec->data,rec->input,rec->length); + memmove(rec->data,rec->input,rec->length); rec->input=rec->data; } else @@ -435,11 +562,48 @@ int send; rec->length+=i; } +#ifdef KSSL_DEBUG + { + unsigned long ui; + printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", + ds,rec->data,rec->input,l); + printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", + ds->buf_len, ds->cipher->key_len, + DES_KEY_SZ, DES_SCHEDULE_SZ, + ds->cipher->iv_len); + printf("\t\tIV: "); + for (i=0; icipher->iv_len; i++) printf("%02X", ds->iv[i]); + printf("\n"); + printf("\trec->input="); + for (ui=0; uiinput[ui]); + printf("\n"); + } +#endif /* KSSL_DEBUG */ + + if (!send) + { + if (l == 0 || l%bs != 0) + { + SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); + return 0; + } + } + EVP_Cipher(ds,rec->data,rec->input,l); +#ifdef KSSL_DEBUG + { + unsigned long i; + printf("\trec->data="); + for (i=0; idata[i]); printf("\n"); + } +#endif /* KSSL_DEBUG */ + if ((bs != 1) && !send) { - ii=i=rec->data[l-1]; + ii=i=rec->data[l-1]; /* padding_length */ i++; if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) { @@ -450,19 +614,22 @@ int send; if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) i--; } + /* TLS 1.0 does not bound the number of padding bytes by the block size. + * All of them must have value 'padding_length'. */ if (i > (int)rec->length) { - SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); - return(0); + /* Incorrect padding. SSLerr() and ssl3_alert are done + * by caller: we don't want to reveal whether this is + * a decryption error or a MAC verification failure + * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ + return -1; } for (j=(int)(l-i); j<(int)l; j++) { if (rec->data[j] != ii) { - SSLerr(SSL_F_TLS1_ENC,SSL_R_DECRYPTION_FAILED); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); - return(0); + /* Incorrect padding */ + return -1; } } rec->length-=i; @@ -471,25 +638,20 @@ int send; return(1); } -int tls1_cert_verify_mac(s,in_ctx,out) -SSL *s; -EVP_MD_CTX *in_ctx; -unsigned char *out; +int tls1_cert_verify_mac(SSL *s, EVP_MD_CTX *in_ctx, unsigned char *out) { unsigned int ret; EVP_MD_CTX ctx; - memcpy(&ctx,in_ctx,sizeof(EVP_MD_CTX)); - EVP_DigestFinal(&ctx,out,&ret); + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_copy_ex(&ctx,in_ctx); + EVP_DigestFinal_ex(&ctx,out,&ret); + EVP_MD_CTX_cleanup(&ctx); return((int)ret); } -int tls1_final_finish_mac(s,in1_ctx,in2_ctx,str,slen,out) -SSL *s; -EVP_MD_CTX *in1_ctx,*in2_ctx; -unsigned char *str; -int slen; -unsigned char *out; +int tls1_final_finish_mac(SSL *s, EVP_MD_CTX *in1_ctx, EVP_MD_CTX *in2_ctx, + const char *str, int slen, unsigned char *out) { unsigned int i; EVP_MD_CTX ctx; @@ -500,29 +662,27 @@ unsigned char *out; memcpy(q,str,slen); q+=slen; - memcpy(&ctx,in1_ctx,sizeof(EVP_MD_CTX)); - EVP_DigestFinal(&ctx,q,&i); + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_copy_ex(&ctx,in1_ctx); + EVP_DigestFinal_ex(&ctx,q,&i); q+=i; - memcpy(&ctx,in2_ctx,sizeof(EVP_MD_CTX)); - EVP_DigestFinal(&ctx,q,&i); + EVP_MD_CTX_copy_ex(&ctx,in2_ctx); + EVP_DigestFinal_ex(&ctx,q,&i); q+=i; - tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,q-buf, + tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(q-buf), s->session->master_key,s->session->master_key_length, out,buf2,12); - memset(&ctx,0,sizeof(EVP_MD_CTX)); + EVP_MD_CTX_cleanup(&ctx); return((int)12); } -int tls1_mac(ssl,md,send) -SSL *ssl; -unsigned char *md; -int send; +int tls1_mac(SSL *ssl, unsigned char *md, int send) { SSL3_RECORD *rec; unsigned char *mac_sec,*seq; - EVP_MD *hash; + const EVP_MD *hash; unsigned int md_size; int i; HMAC_CTX hmac; @@ -552,41 +712,47 @@ int send; buf[4]=rec->length&0xff; /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ - HMAC_Init(&hmac,mac_sec,EVP_MD_size(hash),hash); + HMAC_CTX_init(&hmac); + HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL); HMAC_Update(&hmac,seq,8); HMAC_Update(&hmac,buf,5); HMAC_Update(&hmac,rec->input,rec->length); HMAC_Final(&hmac,md,&md_size); + HMAC_CTX_cleanup(&hmac); #ifdef TLS_DEBUG printf("sec="); -{int z; for (z=0; zlength; z++) printf("%02X ",buf[z]); printf("\n"); } #endif for (i=7; i>=0; i--) - if (++seq[i]) break; + { + ++seq[i]; + if (seq[i] != 0) break; + } #ifdef TLS_DEBUG -{int z; for (z=0; zctx->md5,s->ctx->sha1, buf,TLS_MD_MASTER_SECRET_CONST_SIZE+SSL3_RANDOM_SIZE*2,p,len, s->session->master_key,buff,SSL3_MASTER_SECRET_SIZE); +#ifdef KSSL_DEBUG + printf ("tls1_generate_master_secret() complete\n"); +#endif /* KSSL_DEBUG */ return(SSL3_MASTER_SECRET_SIZE); } -int tls1_alert_code(code) -int code; +int tls1_alert_code(int code) { switch (code) { @@ -623,11 +791,11 @@ int code; case SSL_AD_ACCESS_DENIED: return(TLS1_AD_ACCESS_DENIED); case SSL_AD_DECODE_ERROR: return(TLS1_AD_DECODE_ERROR); case SSL_AD_DECRYPT_ERROR: return(TLS1_AD_DECRYPT_ERROR); - case SSL_AD_EXPORT_RESTRICION: return(TLS1_AD_EXPORT_RESTRICION); + case SSL_AD_EXPORT_RESTRICTION: return(TLS1_AD_EXPORT_RESTRICTION); case SSL_AD_PROTOCOL_VERSION: return(TLS1_AD_PROTOCOL_VERSION); case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY); case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR); - case SSL_AD_USER_CANCLED: return(TLS1_AD_USER_CANCLED); + case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED); case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION); default: return(-1); } diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c index f9fbfa414c..ca6c03d5af 100644 --- a/src/lib/libssl/t1_lib.c +++ b/src/lib/libssl/t1_lib.c @@ -57,16 +57,12 @@ */ #include -#include "objects.h" +#include #include "ssl_locl.h" -char *tls1_version_str="TLSv1 part of SSLeay 0.9.0b 29-Jun-1998"; +const char *tls1_version_str="TLSv1" OPENSSL_VERSION_PTEXT; -#ifndef NO_PROTO static long tls1_default_timeout(void); -#else -static long tls1_default_timeout(); -#endif static SSL3_ENC_METHOD TLSv1_enc_data={ tls1_enc, @@ -94,6 +90,7 @@ static SSL_METHOD TLSv1_data= { ssl3_write, ssl3_shutdown, ssl3_renegotiate, + ssl3_renegotiate_check, ssl3_ctrl, ssl3_ctx_ctrl, ssl3_get_cipher_by_char, @@ -104,47 +101,48 @@ static SSL_METHOD TLSv1_data= { ssl_bad_method, tls1_default_timeout, &TLSv1_enc_data, + ssl_undefined_function, + ssl3_callback_ctrl, + ssl3_ctx_callback_ctrl, }; -static long tls1_default_timeout() +static long tls1_default_timeout(void) { /* 2 hours, the 24 hours mentioned in the TLSv1 spec * is way too long for http, the cache would over fill */ return(60*60*2); } -SSL_METHOD *tlsv1_base_method() +SSL_METHOD *tlsv1_base_method(void) { return(&TLSv1_data); } -int tls1_new(s) -SSL *s; +int tls1_new(SSL *s) { if (!ssl3_new(s)) return(0); s->method->ssl_clear(s); return(1); } -void tls1_free(s) -SSL *s; +void tls1_free(SSL *s) { ssl3_free(s); } -void tls1_clear(s) -SSL *s; +void tls1_clear(SSL *s) { ssl3_clear(s); s->version=TLS1_VERSION; } #if 0 -long tls1_ctrl(s,cmd,larg,parg) -SSL *s; -int cmd; -long larg; -char *parg; +long tls1_ctrl(SSL *s, int cmd, long larg, char *parg) + { + return(0); + } + +long tls1_callback_ctrl(SSL *s, int cmd, void *(*fp)()) { return(0); } diff --git a/src/lib/libssl/t1_meth.c b/src/lib/libssl/t1_meth.c index 512c2078e7..9bb36a7d1c 100644 --- a/src/lib/libssl/t1_meth.c +++ b/src/lib/libssl/t1_meth.c @@ -57,11 +57,11 @@ */ #include -#include "objects.h" +#include #include "ssl_locl.h" -static SSL_METHOD *tls1_get_method(ver) -int ver; +static SSL_METHOD *tls1_get_method(int ver); +static SSL_METHOD *tls1_get_method(int ver) { if (ver == TLS1_VERSION) return(TLSv1_method()); @@ -69,19 +69,19 @@ int ver; return(NULL); } -SSL_METHOD *TLSv1_method() +SSL_METHOD *TLSv1_method(void) { static int init=1; static SSL_METHOD TLSv1_data; if (init) { - init=0; memcpy((char *)&TLSv1_data,(char *)tlsv1_base_method(), sizeof(SSL_METHOD)); TLSv1_data.ssl_connect=ssl3_connect; TLSv1_data.ssl_accept=ssl3_accept; TLSv1_data.get_ssl_method=tls1_get_method; + init=0; } return(&TLSv1_data); } diff --git a/src/lib/libssl/t1_srvr.c b/src/lib/libssl/t1_srvr.c index 8cf0addcd9..996b7ca8e2 100644 --- a/src/lib/libssl/t1_srvr.c +++ b/src/lib/libssl/t1_srvr.c @@ -57,15 +57,15 @@ */ #include -#include "buffer.h" -#include "rand.h" -#include "objects.h" -#include "evp.h" -#include "x509.h" +#include +#include +#include +#include +#include #include "ssl_locl.h" -static SSL_METHOD *tls1_get_server_method(ver) -int ver; +static SSL_METHOD *tls1_get_server_method(int ver); +static SSL_METHOD *tls1_get_server_method(int ver) { if (ver == TLS1_VERSION) return(TLSv1_server_method()); @@ -73,18 +73,18 @@ int ver; return(NULL); } -SSL_METHOD *TLSv1_server_method() +SSL_METHOD *TLSv1_server_method(void) { static int init=1; static SSL_METHOD TLSv1_server_data; if (init) { - init=0; memcpy((char *)&TLSv1_server_data,(char *)tlsv1_base_method(), sizeof(SSL_METHOD)); TLSv1_server_data.ssl_accept=ssl3_accept; TLSv1_server_data.get_ssl_method=tls1_get_server_method; + init=0; } return(&TLSv1_server_data); } diff --git a/src/lib/libssl/test/methtest.c b/src/lib/libssl/test/methtest.c index 630d29dc91..06ccb3b310 100644 --- a/src/lib/libssl/test/methtest.c +++ b/src/lib/libssl/test/methtest.c @@ -58,10 +58,10 @@ #include #include -#include "rsa.h" -#include "x509.h" +#include +#include #include "meth.h" -#include "err.h" +#include int main(argc,argv) int argc; diff --git a/src/lib/libssl/test/tcrl b/src/lib/libssl/test/tcrl index 859fba452f..acaf8f3c47 100644 --- a/src/lib/libssl/test/tcrl +++ b/src/lib/libssl/test/tcrl @@ -3,7 +3,7 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay crl' +cmd='../apps/openssl crl' if [ "$1"x != "x" ]; then t=$1 diff --git a/src/lib/libssl/test/testca b/src/lib/libssl/test/testca index a28402f9ca..88c186b6ab 100644 --- a/src/lib/libssl/test/testca +++ b/src/lib/libssl/test/testca @@ -23,7 +23,7 @@ if [ $? != 0 ]; then fi -SSLEAY_CONFIG="-config ../apps/ssleay.cnf" +SSLEAY_CONFIG="-config ../apps/openssl.cnf" export SSLEAY_CONFIG $SH ../apps/CA.sh -sign <$test; @@ -27,15 +27,7 @@ else /bin/rm $test.cipher $test.clear fi -for i in rc4 \ - des-cfb des-ede-cfb des-ede3-cfb \ - des-ofb des-ede-ofb des-ede3-ofb \ - des-ecb des-ede des-ede3 desx \ - des-cbc des-ede-cbc des-ede3-cbc \ - idea-ecb idea-cfb idea-ofb idea-cbc \ - rc2-ecb rc2-cfb rc2-ofb rc2-cbc \ - bf-ecb bf-cfb bf-ofb bf-cbc rc4 \ - cast5-ecb cast5-cfb cast5-ofb cast5-cbc +for i in `$cmd list-cipher-commands` do echo $i $cmd $i -bufsize 113 -e -k test < $test > $test.$i.cipher diff --git a/src/lib/libssl/test/testgen b/src/lib/libssl/test/testgen index 12a4ca4cea..6a4b6b9221 100644 --- a/src/lib/libssl/test/testgen +++ b/src/lib/libssl/test/testgen @@ -11,17 +11,25 @@ export PATH echo "generating certificate request" -echo "There should be a 2 sequences of .'s and some +'s." -echo "There should not be more that at most 80 per line" +echo "string to make the random number generator think it has entropy" >> ./.rnd + +if ../apps/openssl no-rsa; then + req_new='-newkey dsa:../apps/dsa512.pem' +else + req_new='-new' + echo "There should be a 2 sequences of .'s and some +'s." + echo "There should not be more that at most 80 per line" +fi + echo "This could take some time." -../apps/ssleay req -config test.cnf -new -out testreq.pem +../apps/openssl req -config test.cnf $req_new -out testreq.pem if [ $? != 0 ]; then echo problems creating request exit 1 fi -../apps/ssleay req -verify -in testreq.pem -noout +../apps/openssl req -config test.cnf -verify -in testreq.pem -noout if [ $? != 0 ]; then echo signature on req is wrong exit 1 diff --git a/src/lib/libssl/test/testp7.pem b/src/lib/libssl/test/testp7.pem index b3b6dba830..e5b7866c31 100644 --- a/src/lib/libssl/test/testp7.pem +++ b/src/lib/libssl/test/testp7.pem @@ -1,46 +1,46 @@ -----BEGIN PKCS7----- -MIAGCSqGSIb3DQEHAqCAMIIIBwIBATEAMIAGCSqGSIb3DQEHAQAAoIIGPDCCBHIw -ggQcoAMCAQICEHkvjiX1iVGQMenF9HgIjI8wDQYJKoZIhvcNAQEEBQAwYjERMA8G -A1UEBxMISW50ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQL -EytWZXJpU2lnbiBDbGFzcyAxIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyMB4X -DTk2MDcxOTAwMDAwMFoXDTk3MDMzMDIzNTk1OVowgdUxETAPBgNVBAcTCEludGVy -bmV0MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE0MDIGA1UECxMrVmVyaVNpZ24g -Q2xhc3MgMSBDQSAtIEluZGl2aWR1YWwgU3Vic2NyaWJlcjEoMCYGA1UECxMfRGln -aXRhbCBJRCBDbGFzcyAxIC0gU01JTUUgVGVzdDFHMEUGA1UECxM+d3d3LnZlcmlz -aWduLmNvbS9yZXBvc2l0b3J5L0NQUy0xLjAgSW5jLiBieSBSZWYuLExJQUIuTFRE -KGMpOTYwWzANBgkqhkiG9w0BAQEFAANKADBHAkAOy7xxCAIkOfuIA2LyRpxgKlDO -Rl8htdXYhF5iBGUx1GYaK6KF+bK/CCI0l4j2OfWGFBUrwGoWqxTNcWgTfMzRAgMB -AAGjggI5MIICNTAJBgNVHRMEAjAAMIICJgYDVR0DBIICHTCCAhkwggIVMIICEQYL -YIZIAYb4RQEHAQEwggIAFoIBq1RoaXMgY2VydGlmaWNhdGUgaW5jb3Jwb3JhdGVz -IGJ5IHJlZmVyZW5jZSwgYW5kIGl0cyB1c2UgaXMgc3RyaWN0bHkgc3ViamVjdCB0 -bywgdGhlIFZlcmlTaWduIENlcnRpZmljYXRpb24gUHJhY3RpY2UgU3RhdGVtZW50 -IChDUFMpLCBhdmFpbGFibGUgYXQ6IGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9D -UFMtMS4wOyBieSBFLW1haWwgYXQgQ1BTLXJlcXVlc3RzQHZlcmlzaWduLmNvbTsg -b3IgYnkgbWFpbCBhdCBWZXJpU2lnbiwgSW5jLiwgMjU5MyBDb2FzdCBBdmUuLCBN -b3VudGFpbiBWaWV3LCBDQSA5NDA0MyBVU0EgVGVsLiArMSAoNDE1KSA5NjEtODgz -MCBDb3B5cmlnaHQgKGMpIDE5OTYgVmVyaVNpZ24sIEluYy4gIEFsbCBSaWdodHMg -UmVzZXJ2ZWQuIENFUlRBSU4gV0FSUkFOVElFUyBESVNDTEFJTUVEIGFuZCBMSUFC -SUxJVFkgTElNSVRFRC6gDgYMYIZIAYb4RQEHAQEBoQ4GDGCGSAGG+EUBBwEBAjAv -MC0WK2h0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9yZXBvc2l0b3J5L0NQUy0xLgMw -DQYJKoZIhvcNAQEEBQADQQDAmA7km/3iJWEsWN9Z2WU2gmZAknx45WnDKHxMa3Bf -gNsh6BLk/ngkJKjNKTDR13XVHqEPUY1flbjATZputw1GMIIBwjCCAWygAwIBAgIQ -fAmE6tW5ERSQWDneu3KfSTANBgkqhkiG9w0BAQIFADA+MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xFjAUBgNVBAsTDVRFU1QgUm9vdCBQQ0Ew -HhcNOTYwNzE3MDAwMDAwWhcNOTcwNzE3MjM1OTU5WjBiMREwDwYDVQQHEwhJbnRl -cm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNDAyBgNVBAsTK1ZlcmlTaWdu -IENsYXNzIDEgQ0EgLSBJbmRpdmlkdWFsIFN1YnNjcmliZXIwXDANBgkqhkiG9w0B -AQEFAANLADBIAkEA7Fc6zYJw4WwCWa1ni3fYNbzGSQNluuw990024GusjLfhEk1h -MsIUukTT/n8yxoO7rYp4x+LS+tHF2tBtuxg7CwIDAQABoyIwIDALBgNVHQ8EBAMC -AQYwEQYJYIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBAgUAA0EAFKem0cJGg9nd -TAbP5o1HIEyNn11ZlvLU5v1Hejs1MKQt72IMm4jjgOH+pjguXW8lB6yzrK4oVOO2 -UNCaNQ1H26GCAa0wgeYwgZEwDQYJKoZIhvcNAQECBQAwYjERMA8GA1UEBxMISW50 +MIIIGAYJKoZIhvcNAQcCoIIICTCCCAUCAQExADALBgkqhkiG9w0BBwGgggY8MIIE +cjCCBBygAwIBAgIQeS+OJfWJUZAx6cX0eAiMjzANBgkqhkiG9w0BAQQFADBiMREw +DwYDVQQHEwhJbnRlcm5ldDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNDAyBgNV +BAsTK1ZlcmlTaWduIENsYXNzIDEgQ0EgLSBJbmRpdmlkdWFsIFN1YnNjcmliZXIw +HhcNOTYwNzE5MDAwMDAwWhcNOTcwMzMwMjM1OTU5WjCB1TERMA8GA1UEBxMISW50 ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytWZXJpU2ln -biBDbGFzcyAxIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyFw05NjA3MTcxNzU5 -MjlaFw05NzA3MTgwMDAwMDBaMA0GCSqGSIb3DQEBAgUAA0EAubVWYTsWsQmste9f -+UgMw8BkjDlM25fwQLrCfmmnLxjewey10kSROypUaJLb+r4oRALc0fG9XfZsaiiI -gotQHjCBwTBtMA0GCSqGSIb3DQEBAgUAMD4xCzAJBgNVBAYTAlVTMRcwFQYDVQQK -Ew5WZXJpU2lnbiwgSW5jLjEWMBQGA1UECxMNVEVTVCBSb290IFBDQRcNOTYwNzE3 -MTc0NDA5WhcNOTgwNzE3MDAwMDAwWjANBgkqhkiG9w0BAQIFAANBAHitA0/xAukC -jHzeh1AMT/l2oC68N+yFb+aJPHBBMxc6gG2MaKjBNwb5hcXUllMlExONA3ju10f7 -owIq3s3wx10xAAAAAAA= +biBDbGFzcyAxIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyMSgwJgYDVQQLEx9E +aWdpdGFsIElEIENsYXNzIDEgLSBTTUlNRSBUZXN0MUcwRQYDVQQLEz53d3cudmVy +aXNpZ24uY29tL3JlcG9zaXRvcnkvQ1BTLTEuMCBJbmMuIGJ5IFJlZi4sTElBQi5M +VEQoYyk5NjBbMA0GCSqGSIb3DQEBAQUAA0oAMEcCQA7LvHEIAiQ5+4gDYvJGnGAq +UM5GXyG11diEXmIEZTHUZhorooX5sr8IIjSXiPY59YYUFSvAaharFM1xaBN8zNEC +AwEAAaOCAjkwggI1MAkGA1UdEwQCMAAwggImBgNVHQMEggIdMIICGTCCAhUwggIR +BgtghkgBhvhFAQcBATCCAgAWggGrVGhpcyBjZXJ0aWZpY2F0ZSBpbmNvcnBvcmF0 +ZXMgYnkgcmVmZXJlbmNlLCBhbmQgaXRzIHVzZSBpcyBzdHJpY3RseSBzdWJqZWN0 +IHRvLCB0aGUgVmVyaVNpZ24gQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1l +bnQgKENQUyksIGF2YWlsYWJsZSBhdDogaHR0cHM6Ly93d3cudmVyaXNpZ24uY29t +L0NQUy0xLjA7IGJ5IEUtbWFpbCBhdCBDUFMtcmVxdWVzdHNAdmVyaXNpZ24uY29t +OyBvciBieSBtYWlsIGF0IFZlcmlTaWduLCBJbmMuLCAyNTkzIENvYXN0IEF2ZS4s +IE1vdW50YWluIFZpZXcsIENBIDk0MDQzIFVTQSBUZWwuICsxICg0MTUpIDk2MS04 +ODMwIENvcHlyaWdodCAoYykgMTk5NiBWZXJpU2lnbiwgSW5jLiAgQWxsIFJpZ2h0 +cyBSZXNlcnZlZC4gQ0VSVEFJTiBXQVJSQU5USUVTIERJU0NMQUlNRUQgYW5kIExJ +QUJJTElUWSBMSU1JVEVELqAOBgxghkgBhvhFAQcBAQGhDgYMYIZIAYb4RQEHAQEC +MC8wLRYraHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvQ1BTLTEu +AzANBgkqhkiG9w0BAQQFAANBAMCYDuSb/eIlYSxY31nZZTaCZkCSfHjlacMofExr +cF+A2yHoEuT+eCQkqM0pMNHXddUeoQ9RjV+VuMBNmm63DUYwggHCMIIBbKADAgEC +AhB8CYTq1bkRFJBYOd67cp9JMA0GCSqGSIb3DQEBAgUAMD4xCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEWMBQGA1UECxMNVEVTVCBSb290IFBD +QTAeFw05NjA3MTcwMDAwMDBaFw05NzA3MTcyMzU5NTlaMGIxETAPBgNVBAcTCElu +dGVybmV0MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE0MDIGA1UECxMrVmVyaVNp +Z24gQ2xhc3MgMSBDQSAtIEluZGl2aWR1YWwgU3Vic2NyaWJlcjBcMA0GCSqGSIb3 +DQEBAQUAA0sAMEgCQQDsVzrNgnDhbAJZrWeLd9g1vMZJA2W67D33TTbga6yMt+ES +TWEywhS6RNP+fzLGg7utinjH4tL60cXa0G27GDsLAgMBAAGjIjAgMAsGA1UdDwQE +AwIBBjARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcNAQECBQADQQAUp6bRwkaD +2d1MBs/mjUcgTI2fXVmW8tTm/Ud6OzUwpC3vYgybiOOA4f6mOC5dbyUHrLOsrihU +47ZQ0Jo1DUfboYIBrTCBwTBtMA0GCSqGSIb3DQEBAgUAMD4xCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEWMBQGA1UECxMNVEVTVCBSb290IFBD +QRcNOTYwNzE3MTc0NDA5WhcNOTgwNzE3MDAwMDAwWjANBgkqhkiG9w0BAQIFAANB +AHitA0/xAukCjHzeh1AMT/l2oC68N+yFb+aJPHBBMxc6gG2MaKjBNwb5hcXUllMl +ExONA3ju10f7owIq3s3wx10wgeYwgZEwDQYJKoZIhvcNAQECBQAwYjERMA8GA1UE +BxMISW50ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytW +ZXJpU2lnbiBDbGFzcyAxIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyFw05NjA3 +MTcxNzU5MjlaFw05NzA3MTgwMDAwMDBaMA0GCSqGSIb3DQEBAgUAA0EAubVWYTsW +sQmste9f+UgMw8BkjDlM25fwQLrCfmmnLxjewey10kSROypUaJLb+r4oRALc0fG9 +XfZsaiiIgotQHjEA -----END PKCS7----- diff --git a/src/lib/libssl/test/testsid.pem b/src/lib/libssl/test/testsid.pem index cd8617be2e..7ffd008f66 100644 --- a/src/lib/libssl/test/testsid.pem +++ b/src/lib/libssl/test/testsid.pem @@ -1,5 +1,5 @@ -----BEGIN SSL SESSION PARAMETERS----- -MIIBxwIBAQIBAgQDAQCABBCi11xa5qkOP8xrr02K/NQCBBBkIYQZM0Bt95W0EHNV +MIIB1gIBAQIBAgQDAQCABBCi11xa5qkOP8xrr02K/NQCBBBkIYQZM0Bt95W0EHNV bA58oQYCBDIBr7WiBAICASyjggGGMIIBgjCCASwCAQMwDQYJKoZIhvcNAQEEBQAw ODELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3Jz YSB0ZXN0IENBMB4XDTk1MTAwOTIzMzEzNFoXDTk4MDcwNTIzMzEzNFowYDELMAkG @@ -8,5 +8,5 @@ LjELMAkGA1UECxMCQ1MxGzAZBgNVBAMTElNTTGVheSBkZW1vIGNsaWVudDBcMA0G CSqGSIb3DQEBAQUAA0sAMEgCQQC4pcXEL1lgVA+B5Q3TcuW/O3LZHoA73IYm8oFD TezgCDhL2RTMn+seKWF36UtJKRIOBU9jZHCVVd0Me5ls6BEjAgMBAAEwDQYJKoZI hvcNAQEEBQADQQBoIpOcwUY1qlVF7j3ROSGvUsbvByOBFmYWkIBgsCqR+9qo1A7L -CrWF5i8LWt/vLwAHaxWNx2YuBJMFyuK81fTv +CrWF5i8LWt/vLwAHaxWNx2YuBJMFyuK81fTvpA0EC3Rlc3Rjb250ZXh0 -----END SSL SESSION PARAMETERS----- diff --git a/src/lib/libssl/test/testss b/src/lib/libssl/test/testss index a5aecf4694..8d3557f356 100644 --- a/src/lib/libssl/test/testss +++ b/src/lib/libssl/test/testss @@ -1,9 +1,10 @@ #!/bin/sh -digest='-mdc2' -reqcmd="../apps/ssleay req" -x509cmd="../apps/ssleay x509 $digest" -verifycmd="../apps/ssleay verify" +digest='-md5' +reqcmd="../apps/openssl req" +x509cmd="../apps/openssl x509 $digest" +verifycmd="../apps/openssl verify" +dummycnf="../apps/openssl.cnf" CAkey="keyCA.ss" CAcert="certCA.ss" @@ -18,7 +19,16 @@ Ucert="certU.ss" echo echo "make a certificate request using 'req'" -$reqcmd -config $CAconf -out $CAreq -keyout $CAkey -new #>err.ss + +echo "string to make the random number generator think it has entropy" >> ./.rnd + +if ../apps/openssl no-rsa; then + req_new='-newkey dsa:../apps/dsa512.pem' +else + req_new='-new' +fi + +$reqcmd -config $CAconf -out $CAreq -keyout $CAkey $req_new #>err.ss if [ $? != 0 ]; then echo "error using 'req' to generate a certificate request" exit 1 @@ -39,13 +49,13 @@ if [ $? != 0 ]; then exit 1 fi -$reqcmd -verify -in $CAreq -noout +$reqcmd -config $dummycnf -verify -in $CAreq -noout if [ $? != 0 ]; then echo first generated request is invalid exit 1 fi -$reqcmd -verify -in $CAreq2 -noout +$reqcmd -config $dummycnf -verify -in $CAreq2 -noout if [ $? != 0 ]; then echo second generated request is invalid exit 1 @@ -59,7 +69,7 @@ fi echo echo "make another certificate request using 'req'" -$reqcmd -config $Uconf -out $Ureq -keyout $Ukey -new >err.ss +$reqcmd -config $Uconf -out $Ureq -keyout $Ukey $req_new >err.ss if [ $? != 0 ]; then echo "error using 'req' to generate a certificate request" exit 1 diff --git a/src/lib/libssl/test/testssl b/src/lib/libssl/test/testssl index f115adb8e1..ba5e41c861 100644 --- a/src/lib/libssl/test/testssl +++ b/src/lib/libssl/test/testssl @@ -1,40 +1,137 @@ #!/bin/sh +if [ "$1" = "" ]; then + key=../apps/server.pem +else + key="$1" +fi +if [ "$2" = "" ]; then + cert=../apps/server.pem +else + cert="$2" +fi +ssltest="./ssltest -key $key -cert $cert -c_key $key -c_cert $cert" + +if ../apps/openssl x509 -in $cert -text -noout | fgrep 'DSA Public Key' >/dev/null; then + dsa_cert=YES +else + dsa_cert=NO +fi + +if [ "$3" = "" ]; then + CA="-CApath ../certs" +else + CA="-CAfile $3" +fi + +if [ "$4" = "" ]; then + extra="" +else + extra="$4" +fi + +############################################################################# + echo test sslv2 -./ssltest -ssl2 || exit 1 +$ssltest -ssl2 $extra || exit 1 echo test sslv2 with server authentication -./ssltest -ssl2 -server_auth -CApath ../certs || exit 1 +$ssltest -ssl2 -server_auth $CA $extra || exit 1 -echo test sslv2 with client authentication -./ssltest -ssl2 -client_auth -CApath ../certs || exit 1 +if [ $dsa_cert = NO ]; then + echo test sslv2 with client authentication + $ssltest -ssl2 -client_auth $CA $extra || exit 1 -echo test sslv2 with both client and server authentication -./ssltest -ssl2 -server_auth -client_auth -CApath ../certs || exit 1 + echo test sslv2 with both client and server authentication + $ssltest -ssl2 -server_auth -client_auth $CA $extra || exit 1 +fi echo test sslv3 -./ssltest -ssl3 || exit 1 +$ssltest -ssl3 $extra || exit 1 echo test sslv3 with server authentication -./ssltest -ssl3 -server_auth -CApath ../certs || exit 1 +$ssltest -ssl3 -server_auth $CA $extra || exit 1 echo test sslv3 with client authentication -./ssltest -ssl3 -client_auth -CApath ../certs || exit 1 +$ssltest -ssl3 -client_auth $CA $extra || exit 1 echo test sslv3 with both client and server authentication -./ssltest -ssl3 -server_auth -client_auth -CApath ../certs || exit 1 +$ssltest -ssl3 -server_auth -client_auth $CA $extra || exit 1 echo test sslv2/sslv3 -./ssltest || exit 1 +$ssltest $extra || exit 1 echo test sslv2/sslv3 with server authentication -./ssltest -server_auth -CApath ../certs || exit 1 +$ssltest -server_auth $CA $extra || exit 1 echo test sslv2/sslv3 with client authentication -./ssltest -client_auth -CApath ../certs || exit 1 +$ssltest -client_auth $CA $extra || exit 1 echo test sslv2/sslv3 with both client and server authentication -./ssltest -server_auth -client_auth -CApath ../certs || exit 1 +$ssltest -server_auth -client_auth $CA $extra || exit 1 -exit 0 +echo test sslv2 via BIO pair +$ssltest -bio_pair -ssl2 $extra || exit 1 + +echo test sslv2 with server authentication via BIO pair +$ssltest -bio_pair -ssl2 -server_auth $CA $extra || exit 1 + +if [ $dsa_cert = NO ]; then + echo test sslv2 with client authentication via BIO pair + $ssltest -bio_pair -ssl2 -client_auth $CA $extra || exit 1 + + echo test sslv2 with both client and server authentication via BIO pair + $ssltest -bio_pair -ssl2 -server_auth -client_auth $CA $extra || exit 1 +fi + +echo test sslv3 via BIO pair +$ssltest -bio_pair -ssl3 $extra || exit 1 + +echo test sslv3 with server authentication via BIO pair +$ssltest -bio_pair -ssl3 -server_auth $CA $extra || exit 1 + +echo test sslv3 with client authentication via BIO pair +$ssltest -bio_pair -ssl3 -client_auth $CA $extra || exit 1 + +echo test sslv3 with both client and server authentication via BIO pair +$ssltest -bio_pair -ssl3 -server_auth -client_auth $CA $extra || exit 1 +echo test sslv2/sslv3 via BIO pair +$ssltest $extra || exit 1 + +if [ $dsa_cert = NO ]; then + echo test sslv2/sslv3 w/o DHE via BIO pair + $ssltest -bio_pair -no_dhe $extra || exit 1 +fi + +echo test sslv2/sslv3 with 1024bit DHE via BIO pair +$ssltest -bio_pair -dhe1024dsa -v $extra || exit 1 + +echo test sslv2/sslv3 with server authentication +$ssltest -bio_pair -server_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with client authentication via BIO pair +$ssltest -bio_pair -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication via BIO pair +$ssltest -bio_pair -server_auth -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication via BIO pair and app verify +$ssltest -bio_pair -server_auth -client_auth -app_verify $CA $extra || exit 1 + +############################################################################# + +echo test tls1 with 1024bit anonymous DH, multiple handshakes +$ssltest -v -bio_pair -tls1 -cipher ADH -dhe1024dsa -num 10 -f -time $extra || exit 1 + +if ../apps/openssl no-rsa; then + echo skipping RSA tests +else + echo test tls1 with 1024bit RSA, no DHE, multiple handshakes + ./ssltest -v -bio_pair -tls1 -cert ../apps/server2.pem -no_dhe -num 10 -f -time $extra || exit 1 + + echo test tls1 with 1024bit RSA, 1024bit DHE, multiple handshakes + ./ssltest -v -bio_pair -tls1 -cert ../apps/server2.pem -dhe1024dsa -num 10 -f -time $extra || exit 1 +fi + +exit 0 diff --git a/src/lib/libssl/test/tpkcs7 b/src/lib/libssl/test/tpkcs7 index ea1f005dac..15bbba42c0 100644 --- a/src/lib/libssl/test/tpkcs7 +++ b/src/lib/libssl/test/tpkcs7 @@ -3,7 +3,7 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay pkcs7' +cmd='../apps/openssl pkcs7' if [ "$1"x != "x" ]; then t=$1 diff --git a/src/lib/libssl/test/tpkcs7d b/src/lib/libssl/test/tpkcs7d index c8f18fb09c..46e5aa2bd6 100644 --- a/src/lib/libssl/test/tpkcs7d +++ b/src/lib/libssl/test/tpkcs7d @@ -3,7 +3,7 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay pkcs7' +cmd='../apps/openssl pkcs7' if [ "$1"x != "x" ]; then t=$1 @@ -11,7 +11,7 @@ else t=pkcs7-1.pem fi -echo testing pkcs7 conversions +echo "testing pkcs7 conversions (2)" cp $t fff.p echo "p -> d" diff --git a/src/lib/libssl/test/treq b/src/lib/libssl/test/treq index e5f1d8cc41..9f5eb7eea5 100644 --- a/src/lib/libssl/test/treq +++ b/src/lib/libssl/test/treq @@ -3,7 +3,7 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay req' +cmd='../apps/openssl req -config ../apps/openssl.cnf' if [ "$1"x != "x" ]; then t=$1 @@ -11,6 +11,11 @@ else t=testreq.pem fi +if $cmd -in $t -inform p -noout -text | fgrep 'Unknown Public Key'; then + echo "skipping req conversion test for $t" + exit 0 +fi + echo testing req conversions cp $t fff.p diff --git a/src/lib/libssl/test/trsa b/src/lib/libssl/test/trsa index e5b8fe0448..bd6c07650a 100644 --- a/src/lib/libssl/test/trsa +++ b/src/lib/libssl/test/trsa @@ -3,7 +3,12 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay rsa' +if ../apps/openssl no-rsa; then + echo skipping rsa conversion test + exit 0 +fi + +cmd='../apps/openssl rsa' if [ "$1"x != "x" ]; then t=$1 diff --git a/src/lib/libssl/test/tsid b/src/lib/libssl/test/tsid index 8c7e9b1387..9e0854516c 100644 --- a/src/lib/libssl/test/tsid +++ b/src/lib/libssl/test/tsid @@ -3,7 +3,7 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay sess_id' +cmd='../apps/openssl sess_id' if [ "$1"x != "x" ]; then t=$1 diff --git a/src/lib/libssl/test/tx509 b/src/lib/libssl/test/tx509 index f8d1f82cdd..35169f3a43 100644 --- a/src/lib/libssl/test/tx509 +++ b/src/lib/libssl/test/tx509 @@ -3,7 +3,7 @@ PATH=../apps:$PATH export PATH -cmd='../apps/ssleay x509' +cmd='../apps/openssl x509' if [ "$1"x != "x" ]; then t=$1 diff --git a/src/lib/libssl/tls1.h b/src/lib/libssl/tls1.h index 60978613ef..88ec5fb527 100644 --- a/src/lib/libssl/tls1.h +++ b/src/lib/libssl/tls1.h @@ -59,12 +59,14 @@ #ifndef HEADER_TLS1_H #define HEADER_TLS1_H -#include "buffer.h" +#include #ifdef __cplusplus extern "C" { #endif +#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 1 + #define TLS1_VERSION 0x0301 #define TLS1_VERSION_MAJOR 0x03 #define TLS1_VERSION_MINOR 0x01 @@ -75,13 +77,71 @@ extern "C" { #define TLS1_AD_ACCESS_DENIED 49 /* fatal */ #define TLS1_AD_DECODE_ERROR 50 /* fatal */ #define TLS1_AD_DECRYPT_ERROR 51 -#define TLS1_AD_EXPORT_RESTRICION 60 /* fatal */ +#define TLS1_AD_EXPORT_RESTRICTION 60 /* fatal */ #define TLS1_AD_PROTOCOL_VERSION 70 /* fatal */ #define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */ #define TLS1_AD_INTERNAL_ERROR 80 /* fatal */ -#define TLS1_AD_USER_CANCLED 90 +#define TLS1_AD_USER_CANCELLED 90 #define TLS1_AD_NO_RENEGOTIATION 100 +/* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt + * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see + * s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably + * shouldn't. */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060 +#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061 +#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063 +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065 +#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066 + + /* AES ciphersuites from draft ietf-tls-ciphersuite-03.txt */ + +#define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +#define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 + +#define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +#define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +/* XXX + * Inconsistency alert: + * The OpenSSL names of ciphers with ephemeral DH here include the string + * "DHE", while elsewhere it has always been "EDH". + * (The alias for the list of all such ciphers also is "EDH".) + * The specifications speak of "EDH"; maybe we should allow both forms + * for everything. */ +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DHE-DSS-DES-CBC-SHA" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA" +#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + /* AES ciphersuites from draft-ietf-tls-ciphersuite-06.txt */ +#define TLS1_TXT_RSA_WITH_AES_128_SHA "AESdraft128-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AESdraft128-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AESdraft128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AESdraft128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AESdraft128-SHA" +#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AESdraft128-SHA" + +#define TLS1_TXT_RSA_WITH_AES_256_SHA "AESdraft256-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AESdraft256-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AESdraft256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AESdraft256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AESdraft256-SHA" +#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AESdraft256-SHA" + + #define TLS_CT_RSA_SIGN 1 #define TLS_CT_DSS_SIGN 2 #define TLS_CT_RSA_FIXED_DH 3 @@ -108,6 +168,25 @@ extern "C" { #define TLS_MD_MASTER_SECRET_CONST "master secret" #define TLS_MD_MASTER_SECRET_CONST_SIZE 13 +#ifdef CHARSET_EBCDIC +#undef TLS_MD_CLIENT_FINISH_CONST +#define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64" /*client finished*/ +#undef TLS_MD_SERVER_FINISH_CONST +#define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64" /*server finished*/ +#undef TLS_MD_SERVER_WRITE_KEY_CONST +#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*server write key*/ +#undef TLS_MD_KEY_EXPANSION_CONST +#define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e" /*key expansion*/ +#undef TLS_MD_CLIENT_WRITE_KEY_CONST +#define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*client write key*/ +#undef TLS_MD_SERVER_WRITE_KEY_CONST +#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*server write key*/ +#undef TLS_MD_IV_BLOCK_CONST +#define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b" /*IV block*/ +#undef TLS_MD_MASTER_SECRET_CONST +#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3-55-g6feb From 715a204e4615e4a70a466fcb383a9a57cad5e6b8 Mon Sep 17 00:00:00 2001 From: markus <> Date: Thu, 5 Sep 2002 22:44:52 +0000 Subject: import openssl-0.9.7-beta3 --- src/lib/libcrypto/aes/aes_locl.h | 3 - src/lib/libcrypto/asn1/a_strex.c | 11 +- src/lib/libcrypto/asn1/asn1.h | 1 + src/lib/libcrypto/asn1/asn1_lib.c | 11 +- src/lib/libcrypto/asn1/n_pkey.c | 4 + src/lib/libcrypto/asn1/t_pkey.c | 88 ++++++++++----- src/lib/libcrypto/bio/b_sock.c | 4 + src/lib/libcrypto/bio/bio.h | 3 + src/lib/libcrypto/bio/bio_err.c | 1 + src/lib/libcrypto/bio/bss_file.c | 6 ++ src/lib/libcrypto/bn/bn_lib.c | 6 ++ src/lib/libcrypto/bn/bn_mul.c | 2 +- src/lib/libcrypto/conf/conf.h | 8 +- src/lib/libcrypto/conf/conf_def.c | 3 +- src/lib/libcrypto/conf/conf_lib.c | 5 +- src/lib/libcrypto/conf/conf_mod.c | 2 +- src/lib/libcrypto/cryptlib.c | 8 ++ src/lib/libcrypto/cryptlib.h | 8 ++ src/lib/libcrypto/doc/DH_get_ex_new_index.pod | 2 +- src/lib/libcrypto/doc/EVP_DigestInit.pod | 11 +- src/lib/libcrypto/doc/EVP_EncryptInit.pod | 5 + src/lib/libcrypto/doc/EVP_SignInit.pod | 4 +- src/lib/libcrypto/doc/EVP_VerifyInit.pod | 2 +- src/lib/libcrypto/doc/RSA_check_key.pod | 32 +++++- src/lib/libcrypto/doc/rsa.pod | 2 +- src/lib/libcrypto/engine/eng_cnf.c | 2 +- src/lib/libcrypto/engine/eng_dyn.c | 24 ++++- src/lib/libcrypto/engine/eng_fat.c | 2 +- src/lib/libcrypto/err/err.c | 1 + src/lib/libcrypto/err/err.h | 1 + src/lib/libcrypto/evp/c_all.c | 2 + src/lib/libcrypto/evp/evp.h | 56 ++++++++++ src/lib/libcrypto/evp/evp_pbe.c | 2 +- src/lib/libcrypto/evp/p5_crpt.c | 2 +- src/lib/libcrypto/evp/p5_crpt2.c | 2 +- src/lib/libcrypto/objects/obj_dat.c | 2 +- src/lib/libcrypto/objects/obj_mac.num | 138 ++++++++++++++++++++++++ src/lib/libcrypto/objects/objects.txt | 148 ++++++++++++++++++++++++++ src/lib/libcrypto/opensslv.h | 4 +- src/lib/libcrypto/pem/pem2.h | 2 + src/lib/libcrypto/pem/pem_pkey.c | 1 + src/lib/libcrypto/perlasm/x86asm.pl | 6 ++ src/lib/libcrypto/pkcs12/pkcs12.h | 4 +- src/lib/libcrypto/rand/rand.h | 5 + src/lib/libcrypto/rsa/rsa.h | 3 + src/lib/libcrypto/ui/ui_openssl.c | 2 +- src/lib/libcrypto/ui/ui_util.c | 7 +- src/lib/libcrypto/x509v3/ext_dat.h | 4 +- src/lib/libcrypto/x509v3/v3_info.c | 1 + src/lib/libssl/s23_clnt.c | 2 +- src/lib/libssl/s23_pkt.c | 2 +- src/lib/libssl/s23_srvr.c | 2 +- src/lib/libssl/s3_both.c | 2 +- src/lib/libssl/s3_clnt.c | 15 ++- src/lib/libssl/s3_lib.c | 8 +- src/lib/libssl/s3_pkt.c | 2 +- src/lib/libssl/s3_srvr.c | 20 +++- src/lib/libssl/ssl.h | 46 ++++++-- src/lib/libssl/ssl_asn1.c | 4 +- src/lib/libssl/ssl_ciph.c | 15 +-- src/lib/libssl/ssl_err.c | 4 +- src/lib/libssl/ssl_lib.c | 4 +- src/lib/libssl/ssl_locl.h | 15 +-- src/lib/libssl/ssl_rsa.c | 2 +- src/lib/libssl/ssl_sess.c | 2 + src/lib/libssl/t1_clnt.c | 2 +- src/lib/libssl/t1_enc.c | 27 +++-- src/lib/libssl/t1_srvr.c | 2 +- src/lib/libssl/test/tcrl | 6 +- src/lib/libssl/test/testca | 6 +- src/lib/libssl/test/testgen | 6 +- src/lib/libssl/test/tpkcs7 | 6 +- src/lib/libssl/test/tpkcs7d | 6 +- src/lib/libssl/test/treq | 6 +- src/lib/libssl/test/trsa | 6 +- src/lib/libssl/test/tsid | 6 +- src/lib/libssl/test/tx509 | 6 +- src/lib/libssl/tls1.h | 31 +++--- 78 files changed, 765 insertions(+), 149 deletions(-) diff --git a/src/lib/libcrypto/aes/aes_locl.h b/src/lib/libcrypto/aes/aes_locl.h index 541d1d6e84..18fc2d0747 100644 --- a/src/lib/libcrypto/aes/aes_locl.h +++ b/src/lib/libcrypto/aes/aes_locl.h @@ -60,10 +60,7 @@ #include #include - -#if defined(__STDC__) || defined(OPENSSL_SYS_VMS) || defined(M_XENIX) || defined(OPENSSL_SYS_MSDOS) #include -#endif #ifdef _MSC_VER # define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) diff --git a/src/lib/libcrypto/asn1/a_strex.c b/src/lib/libcrypto/asn1/a_strex.c index 128aa7e772..8dab29dca1 100644 --- a/src/lib/libcrypto/asn1/a_strex.c +++ b/src/lib/libcrypto/asn1/a_strex.c @@ -77,8 +77,8 @@ /* Three IO functions for sending data to memory, a BIO and * and a FILE pointer. */ - -int send_mem_chars(void *arg, const void *buf, int len) +#if 0 /* never used */ +static int send_mem_chars(void *arg, const void *buf, int len) { unsigned char **out = arg; if(!out) return 1; @@ -86,15 +86,16 @@ int send_mem_chars(void *arg, const void *buf, int len) *out += len; return 1; } +#endif -int send_bio_chars(void *arg, const void *buf, int len) +static int send_bio_chars(void *arg, const void *buf, int len) { if(!arg) return 1; if(BIO_write(arg, buf, len) != len) return 0; return 1; } -int send_fp_chars(void *arg, const void *buf, int len) +static int send_fp_chars(void *arg, const void *buf, int len) { if(!arg) return 1; if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0; @@ -240,7 +241,7 @@ static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen * #01234 format. */ -int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str) +static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str) { /* Placing the ASN1_STRING in a temp ASN1_TYPE allows * the DER encoding to readily obtained diff --git a/src/lib/libcrypto/asn1/asn1.h b/src/lib/libcrypto/asn1/asn1.h index 0d1713f8dd..dbb30f4f22 100644 --- a/src/lib/libcrypto/asn1/asn1.h +++ b/src/lib/libcrypto/asn1/asn1.h @@ -773,6 +773,7 @@ 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); DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING) DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) DECLARE_ASN1_FUNCTIONS(ASN1_NULL) DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) diff --git a/src/lib/libcrypto/asn1/asn1_lib.c b/src/lib/libcrypto/asn1/asn1_lib.c index 830ff2af3c..422685a3b4 100644 --- a/src/lib/libcrypto/asn1/asn1_lib.c +++ b/src/lib/libcrypto/asn1/asn1_lib.c @@ -59,6 +59,7 @@ #include #include "cryptlib.h" #include +#include static int asn1_get_length(unsigned char **pp,int *inf,long *rl,int max); static void asn1_put_length(unsigned char **pp, int length); @@ -123,15 +124,13 @@ int ASN1_get_object(unsigned char **pp, long *plength, int *ptag, int *pclass, (int)(omax+ *pp)); #endif -#if 0 - if ((p+ *plength) > (omax+ *pp)) + if (*plength > (omax - (*pp - p))) { ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG); /* Set this so that even if things are not long enough * the values are set correctly */ ret|=0x80; } -#endif *pp=p; return(ret|inf); err: @@ -158,6 +157,8 @@ static int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) i= *p&0x7f; if (*(p++) & 0x80) { + if (i > sizeof(long)) + return 0; if (max-- == 0) return(0); while (i-- > 0) { @@ -169,6 +170,8 @@ static int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) else ret=i; } + if (ret < 0) + return 0; *pp=p; *rl=ret; return(1); @@ -406,7 +409,7 @@ int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b) void asn1_add_error(unsigned char *address, int offset) { - char buf1[16],buf2[16]; + char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1]; sprintf(buf1,"%lu",(unsigned long)address); sprintf(buf2,"%d",offset); diff --git a/src/lib/libcrypto/asn1/n_pkey.c b/src/lib/libcrypto/asn1/n_pkey.c index 49f80fffd2..9146ee02c9 100644 --- a/src/lib/libcrypto/asn1/n_pkey.c +++ b/src/lib/libcrypto/asn1/n_pkey.c @@ -92,6 +92,8 @@ ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = { ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG) } ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY) +DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY) IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) ASN1_SEQUENCE(NETSCAPE_PKEY) = { @@ -100,6 +102,8 @@ ASN1_SEQUENCE(NETSCAPE_PKEY) = { ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING) } ASN1_SEQUENCE_END(NETSCAPE_PKEY) +DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY) IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, diff --git a/src/lib/libcrypto/asn1/t_pkey.c b/src/lib/libcrypto/asn1/t_pkey.c index 8060115202..2d46914cb1 100644 --- a/src/lib/libcrypto/asn1/t_pkey.c +++ b/src/lib/libcrypto/asn1/t_pkey.c @@ -96,10 +96,34 @@ int RSA_print(BIO *bp, const RSA *x, int off) char str[128]; const char *s; unsigned char *m=NULL; - int i,ret=0; + int ret=0; + size_t buf_len=0, i; - i=RSA_size(x); - m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); + if (x->n) + buf_len = (size_t)BN_num_bytes(x->n); + if (x->e) + if (buf_len < (i = (size_t)BN_num_bytes(x->e))) + buf_len = i; + if (x->d) + if (buf_len < (i = (size_t)BN_num_bytes(x->d))) + buf_len = i; + if (x->p) + if (buf_len < (i = (size_t)BN_num_bytes(x->p))) + buf_len = i; + if (x->q) + if (buf_len < (i = (size_t)BN_num_bytes(x->q))) + buf_len = i; + if (x->dmp1) + if (buf_len < (i = (size_t)BN_num_bytes(x->dmp1))) + buf_len = i; + if (x->dmq1) + if (buf_len < (i = (size_t)BN_num_bytes(x->dmq1))) + buf_len = i; + if (x->iqmp) + if (buf_len < (i = (size_t)BN_num_bytes(x->iqmp))) + buf_len = i; + + m=(unsigned char *)OPENSSL_malloc(buf_len+10); if (m == NULL) { RSAerr(RSA_F_RSA_PRINT,ERR_R_MALLOC_FAILURE); @@ -161,22 +185,25 @@ int DSA_print(BIO *bp, const DSA *x, int off) { char str[128]; unsigned char *m=NULL; - int i,ret=0; - BIGNUM *bn=NULL; + int ret=0; + size_t buf_len=0,i; - if (x->p != NULL) - bn=x->p; - else if (x->priv_key != NULL) - bn=x->priv_key; - else if (x->pub_key != NULL) - bn=x->pub_key; - - /* larger than needed but what the hell :-) */ - if (bn != NULL) - i=BN_num_bytes(bn)*2; - else - i=256; - m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); + if (x->p) + buf_len = (size_t)BN_num_bytes(x->p); + if (x->q) + if (buf_len < (i = (size_t)BN_num_bytes(x->q))) + buf_len = i; + if (x->g) + if (buf_len < (i = (size_t)BN_num_bytes(x->g))) + buf_len = i; + if (x->priv_key) + if (buf_len < (i = (size_t)BN_num_bytes(x->priv_key))) + buf_len = i; + if (x->pub_key) + if (buf_len < (i = (size_t)BN_num_bytes(x->pub_key))) + buf_len = i; + + m=(unsigned char *)OPENSSL_malloc(buf_len+10); if (m == NULL) { DSAerr(DSA_F_DSA_PRINT,ERR_R_MALLOC_FAILURE); @@ -281,10 +308,15 @@ int DHparams_print_fp(FILE *fp, const DH *x) int DHparams_print(BIO *bp, const DH *x) { unsigned char *m=NULL; - int reason=ERR_R_BUF_LIB,i,ret=0; + int reason=ERR_R_BUF_LIB,ret=0; + size_t buf_len=0, i; - i=BN_num_bytes(x->p); - m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); + if (x->p) + buf_len = (size_t)BN_num_bytes(x->p); + if (x->g) + if (buf_len < (i = (size_t)BN_num_bytes(x->g))) + buf_len = i; + m=(unsigned char *)OPENSSL_malloc(buf_len+10); if (m == NULL) { reason=ERR_R_MALLOC_FAILURE; @@ -334,10 +366,18 @@ int DSAparams_print_fp(FILE *fp, const DSA *x) int DSAparams_print(BIO *bp, const DSA *x) { unsigned char *m=NULL; - int reason=ERR_R_BUF_LIB,i,ret=0; + int reason=ERR_R_BUF_LIB,ret=0; + size_t buf_len=0,i; - i=BN_num_bytes(x->p); - m=(unsigned char *)OPENSSL_malloc((unsigned int)i+10); + if (x->p) + buf_len = (size_t)BN_num_bytes(x->p); + if (x->q) + if (buf_len < (i = (size_t)BN_num_bytes(x->q))) + buf_len = i; + if (x->g) + if (buf_len < (i = (size_t)BN_num_bytes(x->g))) + buf_len = i; + m=(unsigned char *)OPENSSL_malloc(buf_len+10); if (m == NULL) { reason=ERR_R_MALLOC_FAILURE; diff --git a/src/lib/libcrypto/bio/b_sock.c b/src/lib/libcrypto/bio/b_sock.c index dcaef68ea7..45bd7c47e8 100644 --- a/src/lib/libcrypto/bio/b_sock.c +++ b/src/lib/libcrypto/bio/b_sock.c @@ -484,7 +484,11 @@ int BIO_socket_ioctl(int fd, long type, unsigned long *arg) { int i; +#ifdef __DJGPP__ + i=ioctlsocket(fd,type,(char *)arg); +#else i=ioctlsocket(fd,type,arg); +#endif /* __DJGPP__ */ if (i < 0) SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); return(i); diff --git a/src/lib/libcrypto/bio/bio.h b/src/lib/libcrypto/bio/bio.h index b122c7069d..c5caf253c9 100644 --- a/src/lib/libcrypto/bio/bio.h +++ b/src/lib/libcrypto/bio/bio.h @@ -554,7 +554,9 @@ BIO_METHOD *BIO_s_socket(void); BIO_METHOD *BIO_s_connect(void); BIO_METHOD *BIO_s_accept(void); BIO_METHOD *BIO_s_fd(void); +#ifndef OPENSSL_SYS_OS2 BIO_METHOD *BIO_s_log(void); +#endif BIO_METHOD *BIO_s_bio(void); BIO_METHOD *BIO_s_null(void); BIO_METHOD *BIO_f_null(void); @@ -647,6 +649,7 @@ void ERR_load_BIO_strings(void); #define BIO_F_CONN_CTRL 127 #define BIO_F_CONN_STATE 115 #define BIO_F_FILE_CTRL 116 +#define BIO_F_FILE_READ 130 #define BIO_F_LINEBUFFER_CTRL 129 #define BIO_F_MEM_READ 128 #define BIO_F_MEM_WRITE 117 diff --git a/src/lib/libcrypto/bio/bio_err.c b/src/lib/libcrypto/bio/bio_err.c index 99ca3cd0da..68a119d895 100644 --- a/src/lib/libcrypto/bio/bio_err.c +++ b/src/lib/libcrypto/bio/bio_err.c @@ -91,6 +91,7 @@ static ERR_STRING_DATA BIO_str_functs[]= {ERR_PACK(0,BIO_F_CONN_CTRL,0), "CONN_CTRL"}, {ERR_PACK(0,BIO_F_CONN_STATE,0), "CONN_STATE"}, {ERR_PACK(0,BIO_F_FILE_CTRL,0), "FILE_CTRL"}, +{ERR_PACK(0,BIO_F_FILE_READ,0), "FILE_READ"}, {ERR_PACK(0,BIO_F_LINEBUFFER_CTRL,0), "LINEBUFFER_CTRL"}, {ERR_PACK(0,BIO_F_MEM_READ,0), "MEM_READ"}, {ERR_PACK(0,BIO_F_MEM_WRITE,0), "MEM_WRITE"}, diff --git a/src/lib/libcrypto/bio/bss_file.c b/src/lib/libcrypto/bio/bss_file.c index 8b3ff278d9..826b361fa2 100644 --- a/src/lib/libcrypto/bio/bss_file.c +++ b/src/lib/libcrypto/bio/bss_file.c @@ -162,6 +162,12 @@ static int MS_CALLBACK file_read(BIO *b, char *out, int outl) if (b->init && (out != NULL)) { ret=fread(out,1,(int)outl,(FILE *)b->ptr); + if(ret == 0 && ferror((FILE *)b->ptr)) + { + SYSerr(SYS_F_FREAD,get_last_sys_error()); + BIOerr(BIO_F_FILE_READ,ERR_R_SYS_LIB); + ret=-1; + } } return(ret); } diff --git a/src/lib/libcrypto/bn/bn_lib.c b/src/lib/libcrypto/bn/bn_lib.c index a016cb7f53..8abe095af2 100644 --- a/src/lib/libcrypto/bn/bn_lib.c +++ b/src/lib/libcrypto/bn/bn_lib.c @@ -397,6 +397,12 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, int words) { BIGNUM *r = NULL; + /* This function does not work if + * words <= b->dmax && top < words + * because BN_dup() does not preserve 'dmax'! + * (But bn_dup_expand() is not used anywhere yet.) + */ + if (words > b->dmax) { BN_ULONG *a = bn_expand_internal(b, words); diff --git a/src/lib/libcrypto/bn/bn_mul.c b/src/lib/libcrypto/bn/bn_mul.c index fd598b8b3d..b03458d002 100644 --- a/src/lib/libcrypto/bn/bn_mul.c +++ b/src/lib/libcrypto/bn/bn_mul.c @@ -66,7 +66,7 @@ #include "cryptlib.h" #include "bn_lcl.h" -#if defined(OPENSSL_NO_ASM) || !(defined(__i386) || defined(__i386__))/* Assembler implementation exists only for x86 */ +#if defined(OPENSSL_NO_ASM) || !(defined(__i386) || defined(__i386__)) || defined(__DJGPP__) /* Assembler implementation exists only for x86 */ /* Here follows specialised variants of bn_add_words() and bn_sub_words(). They have the property performing operations on arrays of different sizes. The sizes of those arrays is expressed through diff --git a/src/lib/libcrypto/conf/conf.h b/src/lib/libcrypto/conf/conf.h index 3c03fb19c0..f4671442ab 100644 --- a/src/lib/libcrypto/conf/conf.h +++ b/src/lib/libcrypto/conf/conf.h @@ -129,6 +129,7 @@ int CONF_dump_fp(LHASH *conf, FILE *out); int CONF_dump_bio(LHASH *conf, BIO *out); void OPENSSL_config(const char *config_name); +void OPENSSL_no_config(void); /* New conf code. The semantics are different from the functions above. If that wasn't the case, the above functions would have been replaced */ @@ -141,10 +142,10 @@ struct conf_st }; CONF *NCONF_new(CONF_METHOD *meth); -CONF_METHOD *NCONF_default(); -CONF_METHOD *NCONF_WIN32(); +CONF_METHOD *NCONF_default(void); +CONF_METHOD *NCONF_WIN32(void); #if 0 /* Just to give you an idea of what I have in mind */ -CONF_METHOD *NCONF_XML(); +CONF_METHOD *NCONF_XML(void); #endif void NCONF_free(CONF *conf); void NCONF_free_data(CONF *conf); @@ -176,6 +177,7 @@ int CONF_modules_load_file(const char *filename, const char *appname, unsigned long flags); void CONF_modules_unload(int all); void CONF_modules_finish(void); +void CONF_modules_free(void); int CONF_module_add(const char *name, conf_init_func *ifunc, conf_finish_func *ffunc); diff --git a/src/lib/libcrypto/conf/conf_def.c b/src/lib/libcrypto/conf/conf_def.c index 31f2766246..5e194de60e 100644 --- a/src/lib/libcrypto/conf/conf_def.c +++ b/src/lib/libcrypto/conf/conf_def.c @@ -67,6 +67,7 @@ #include "conf_def.h" #include #include +#include "cryptlib.h" static char *eat_ws(CONF *conf, char *p); static char *eat_alpha_numeric(CONF *conf, char *p); @@ -208,12 +209,12 @@ static int def_load(CONF *conf, const char *name, long *line) static int def_load_bio(CONF *conf, BIO *in, long *line) { #define BUFSIZE 512 - char btmp[16]; int bufnum=0,i,ii; BUF_MEM *buff=NULL; char *s,*p,*end; int again,n; long eline=0; + char btmp[DECIMAL_SIZE(eline)+1]; CONF_VALUE *v=NULL,*tv; CONF_VALUE *sv=NULL; char *section=NULL,*buf; diff --git a/src/lib/libcrypto/conf/conf_lib.c b/src/lib/libcrypto/conf/conf_lib.c index 7998f34c7b..6a3cf109dd 100644 --- a/src/lib/libcrypto/conf/conf_lib.c +++ b/src/lib/libcrypto/conf/conf_lib.c @@ -382,8 +382,9 @@ int NCONF_dump_bio(const CONF *conf, BIO *out) return conf->meth->dump(conf, out); } + /* This function should be avoided */ -#undef NCONF_get_number +#if 0 long NCONF_get_number(CONF *conf,char *group,char *name) { int status; @@ -397,4 +398,4 @@ long NCONF_get_number(CONF *conf,char *group,char *name) } return ret; } - +#endif diff --git a/src/lib/libcrypto/conf/conf_mod.c b/src/lib/libcrypto/conf/conf_mod.c index f92babc2e2..edcc08921c 100644 --- a/src/lib/libcrypto/conf/conf_mod.c +++ b/src/lib/libcrypto/conf/conf_mod.c @@ -230,7 +230,7 @@ static int module_run(const CONF *cnf, char *name, char *value, { if (!(flags & CONF_MFLAGS_SILENT)) { - char rcode[10]; + char rcode[DECIMAL_SIZE(ret)+1]; CONFerr(CONF_F_CONF_MODULES_LOAD, CONF_R_MODULE_INITIALIZATION_ERROR); sprintf(rcode, "%-8d", ret); ERR_add_error_data(6, "module=", name, ", value=", value, ", retcode=", rcode); diff --git a/src/lib/libcrypto/cryptlib.c b/src/lib/libcrypto/cryptlib.c index 612b3b93b4..d301b376f7 100644 --- a/src/lib/libcrypto/cryptlib.c +++ b/src/lib/libcrypto/cryptlib.c @@ -492,3 +492,11 @@ BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, #endif #endif + +void OpenSSLDie(const char *file,int line,const char *assertion) + { + fprintf(stderr,"%s(%d): OpenSSL internal error, assertion failed: %s\n", + file,line,assertion); + abort(); + } + diff --git a/src/lib/libcrypto/cryptlib.h b/src/lib/libcrypto/cryptlib.h index a0489e57fc..985a6d377c 100644 --- a/src/lib/libcrypto/cryptlib.h +++ b/src/lib/libcrypto/cryptlib.h @@ -89,6 +89,14 @@ extern "C" { #define X509_CERT_DIR_EVP "SSL_CERT_DIR" #define X509_CERT_FILE_EVP "SSL_CERT_FILE" +/* size of string represenations */ +#define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1) +#define HEX_SIZE(type) ((sizeof(type)*2) + +/* die if we have to */ +void OpenSSLDie(const char *file,int line,const char *assertion); +#define die(e) ((e) ? (void)0 : OpenSSLDie(__FILE__, __LINE__, #e)) + #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/doc/DH_get_ex_new_index.pod b/src/lib/libcrypto/doc/DH_get_ex_new_index.pod index 82e2548bcd..fa5eab2650 100644 --- a/src/lib/libcrypto/doc/DH_get_ex_new_index.pod +++ b/src/lib/libcrypto/doc/DH_get_ex_new_index.pod @@ -26,7 +26,7 @@ as described in L. =head1 SEE ALSO -L, L +L, L =head1 HISTORY diff --git a/src/lib/libcrypto/doc/EVP_DigestInit.pod b/src/lib/libcrypto/doc/EVP_DigestInit.pod index b3a61f1c5d..5901c39526 100644 --- a/src/lib/libcrypto/doc/EVP_DigestInit.pod +++ b/src/lib/libcrypto/doc/EVP_DigestInit.pod @@ -238,14 +238,19 @@ even though they are identical digests. L, L, L, L, L, L, -L, L +L, L =head1 HISTORY EVP_DigestInit(), EVP_DigestUpdate() and EVP_DigestFinal() are available in all versions of SSLeay and OpenSSL. -EVP_DigestInit_ex(), EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex() -were added in OpenSSL 0.9.7. +EVP_MD_CTX_init(), EVP_MD_CTX_create(), EVP_MD_CTX_copy_ex(), +EVP_MD_CTX_cleanup(), EVP_MD_CTX_destroy(), EVP_DigestInit_ex() +and EVP_DigestFinal_ex() were added in OpenSSL 0.9.7. + +EVP_md_null(), EVP_md2(), EVP_md5(), EVP_sha(), EVP_sha1(), +EVP_dss(), EVP_dss1(), EVP_mdc2() and EVP_ripemd160() were +changed to return truely const EVP_MD * in OpenSSL 0.9.7. =cut diff --git a/src/lib/libcrypto/doc/EVP_EncryptInit.pod b/src/lib/libcrypto/doc/EVP_EncryptInit.pod index 371b6a2287..75cceb1ca2 100644 --- a/src/lib/libcrypto/doc/EVP_EncryptInit.pod +++ b/src/lib/libcrypto/doc/EVP_EncryptInit.pod @@ -501,4 +501,9 @@ L =head1 HISTORY +EVP_CIPHER_CTX_init(), EVP_EncryptInit_ex(), EVP_EncryptFinal_ex(), +EVP_DecryptInit_ex(), EVP_DecryptFinal_ex(), EVP_CipherInit_ex(), +EVP_CipherFinal_ex() and EVP_CIPHER_CTX_set_padding() appeared in +OpenSSL 0.9.7. + =cut diff --git a/src/lib/libcrypto/doc/EVP_SignInit.pod b/src/lib/libcrypto/doc/EVP_SignInit.pod index 32e9d54809..b203c3a1c5 100644 --- a/src/lib/libcrypto/doc/EVP_SignInit.pod +++ b/src/lib/libcrypto/doc/EVP_SignInit.pod @@ -84,13 +84,13 @@ L, L, L, L, L, L, L, L, L, -L, L +L, L =head1 HISTORY EVP_SignInit(), EVP_SignUpdate() and EVP_SignFinal() are available in all versions of SSLeay and OpenSSL. -EVP_SignInit_ex() was added in OpenSSL 0.9.7 +EVP_SignInit_ex() was added in OpenSSL 0.9.7. =cut diff --git a/src/lib/libcrypto/doc/EVP_VerifyInit.pod b/src/lib/libcrypto/doc/EVP_VerifyInit.pod index 80c656fde8..b6afaedee5 100644 --- a/src/lib/libcrypto/doc/EVP_VerifyInit.pod +++ b/src/lib/libcrypto/doc/EVP_VerifyInit.pod @@ -74,7 +74,7 @@ L, L, L, L, L, L, L, L, L, -L, L +L, L =head1 HISTORY diff --git a/src/lib/libcrypto/doc/RSA_check_key.pod b/src/lib/libcrypto/doc/RSA_check_key.pod index 79fed753ad..3d824a07f5 100644 --- a/src/lib/libcrypto/doc/RSA_check_key.pod +++ b/src/lib/libcrypto/doc/RSA_check_key.pod @@ -18,7 +18,9 @@ in fact prime, and that B. It also checks that B, and that B, B and B are set correctly or are B. -The key's public components may not be B. +As such, this function can not be used with any arbitrary RSA key object, +even if it is otherwise fit for regular RSA operation. See B for more +information. =head1 RETURN VALUE @@ -28,12 +30,38 @@ RSA_check_key() returns 1 if B is a valid RSA key, and 0 otherwise. If the key is invalid or an error occurred, the reason code can be obtained using L. +=head1 NOTES + +This function does not work on RSA public keys that have only the modulus +and public exponent elements populated. It performs integrity checks on all +the RSA key material, so the RSA key structure must contain all the private +key data too. + +Unlike most other RSA functions, this function does B work +transparently with any underlying ENGINE implementation because it uses the +key data in the RSA structure directly. An ENGINE implementation can +override the way key data is stored and handled, and can even provide +support for HSM keys - in which case the RSA structure may contain B +key data at all! If the ENGINE in question is only being used for +acceleration or analysis purposes, then in all likelihood the RSA key data +is complete and untouched, but this can't be assumed in the general case. + +=head1 BUGS + +A method of verifying the RSA key using opaque RSA API functions might need +to be considered. Right now RSA_check_key() simply uses the RSA structure +elements directly, bypassing the RSA_METHOD table altogether (and +completely violating encapsulation and object-orientation in the process). +The best fix will probably be to introduce a "check_key()" handler to the +RSA_METHOD function table so that alternative implementations can also +provide their own verifiers. + =head1 SEE ALSO L, L =head1 HISTORY -RSA_check() appeared in OpenSSL 0.9.4. +RSA_check_key() appeared in OpenSSL 0.9.4. =cut diff --git a/src/lib/libcrypto/doc/rsa.pod b/src/lib/libcrypto/doc/rsa.pod index 09ad30cab1..2b93a12b65 100644 --- a/src/lib/libcrypto/doc/rsa.pod +++ b/src/lib/libcrypto/doc/rsa.pod @@ -110,7 +110,7 @@ L, L, L, L, L, -L, +L, L =cut diff --git a/src/lib/libcrypto/engine/eng_cnf.c b/src/lib/libcrypto/engine/eng_cnf.c index 8c0ae8a1ad..cdf670901a 100644 --- a/src/lib/libcrypto/engine/eng_cnf.c +++ b/src/lib/libcrypto/engine/eng_cnf.c @@ -92,7 +92,7 @@ static int int_engine_init(ENGINE *e) } -int int_engine_configure(char *name, char *value, const CONF *cnf) +static int int_engine_configure(char *name, char *value, const CONF *cnf) { int i; int ret = 0; diff --git a/src/lib/libcrypto/engine/eng_dyn.c b/src/lib/libcrypto/engine/eng_dyn.c index 4fefcc0cae..4139a16e76 100644 --- a/src/lib/libcrypto/engine/eng_dyn.c +++ b/src/lib/libcrypto/engine/eng_dyn.c @@ -157,6 +157,10 @@ static void dynamic_data_ctx_free_func(void *parent, void *ptr, dynamic_data_ctx *ctx = (dynamic_data_ctx *)ptr; if(ctx->dynamic_dso) DSO_free(ctx->dynamic_dso); + if(ctx->DYNAMIC_LIBNAME) + OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); + if(ctx->engine_id) + OPENSSL_free((void*)ctx->engine_id); OPENSSL_free(ctx); } } @@ -169,7 +173,7 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) { dynamic_data_ctx *c; c = OPENSSL_malloc(sizeof(dynamic_data_ctx)); - if(!ctx) + if(!c) { ENGINEerr(ENGINE_F_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); return 0; @@ -310,8 +314,13 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) /* a NULL 'p' or a string of zero-length is the same thing */ if(p && (strlen((const char *)p) < 1)) p = NULL; - ctx->DYNAMIC_LIBNAME = (const char *)p; - return 1; + if(ctx->DYNAMIC_LIBNAME) + OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); + if(p) + ctx->DYNAMIC_LIBNAME = BUF_strdup(p); + else + ctx->DYNAMIC_LIBNAME = NULL; + return (ctx->DYNAMIC_LIBNAME ? 1 : 0); case DYNAMIC_CMD_NO_VCHECK: ctx->no_vcheck = ((i == 0) ? 0 : 1); return 1; @@ -319,8 +328,13 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) /* a NULL 'p' or a string of zero-length is the same thing */ if(p && (strlen((const char *)p) < 1)) p = NULL; - ctx->engine_id = (const char *)p; - return 1; + if(ctx->engine_id) + OPENSSL_free((void*)ctx->engine_id); + if(p) + ctx->engine_id = BUF_strdup(p); + else + ctx->engine_id = NULL; + return (ctx->engine_id ? 1 : 0); case DYNAMIC_CMD_LIST_ADD: if((i < 0) || (i > 2)) { diff --git a/src/lib/libcrypto/engine/eng_fat.c b/src/lib/libcrypto/engine/eng_fat.c index d49aa7ed40..f7edb5ad32 100644 --- a/src/lib/libcrypto/engine/eng_fat.c +++ b/src/lib/libcrypto/engine/eng_fat.c @@ -84,7 +84,7 @@ int ENGINE_set_default(ENGINE *e, unsigned int flags) /* Set default algorithms using a string */ -int int_def_cb(const char *alg, int len, void *arg) +static int int_def_cb(const char *alg, int len, void *arg) { unsigned int *pflags = arg; if (!strncmp(alg, "ALL", len)) diff --git a/src/lib/libcrypto/err/err.c b/src/lib/libcrypto/err/err.c index 04773d65a6..5abe44e6d5 100644 --- a/src/lib/libcrypto/err/err.c +++ b/src/lib/libcrypto/err/err.c @@ -166,6 +166,7 @@ static ERR_STRING_DATA ERR_str_functs[]= {ERR_PACK(0,SYS_F_WSASTARTUP,0), "WSAstartup"}, #endif {ERR_PACK(0,SYS_F_OPENDIR,0), "opendir"}, + {ERR_PACK(0,SYS_F_FREAD,0), "fread"}, {0,NULL}, }; diff --git a/src/lib/libcrypto/err/err.h b/src/lib/libcrypto/err/err.h index cc9bb649ea..988ef81aa0 100644 --- a/src/lib/libcrypto/err/err.h +++ b/src/lib/libcrypto/err/err.h @@ -182,6 +182,7 @@ typedef struct err_state_st #define SYS_F_ACCEPT 8 #define SYS_F_WSASTARTUP 9 /* Winsock stuff */ #define SYS_F_OPENDIR 10 +#define SYS_F_FREAD 11 /* reasons */ diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c index 5ffd352ea0..2d3e57c4fa 100644 --- a/src/lib/libcrypto/evp/c_all.c +++ b/src/lib/libcrypto/evp/c_all.c @@ -60,12 +60,14 @@ #include "cryptlib.h" #include +#if 0 #undef OpenSSL_add_all_algorithms void OpenSSL_add_all_algorithms(void) { OPENSSL_add_all_algorithms_noconf(); } +#endif void OPENSSL_add_all_algorithms_noconf(void) { diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h index fb16de6852..45a25f968d 100644 --- a/src/lib/libcrypto/evp/evp.h +++ b/src/lib/libcrypto/evp/evp.h @@ -74,6 +74,48 @@ #ifndef OPENSSL_NO_BIO #include #endif +#ifndef OPENSSL_NO_MD2 +#include +#endif +#ifndef OPENSSL_NO_MD4 +#include +#endif +#ifndef OPENSSL_NO_MD5 +#include +#endif +#ifndef OPENSSL_NO_SHA +#include +#endif +#ifndef OPENSSL_NO_RIPEMD +#include +#endif +#ifndef OPENSSL_NO_DES +#include +#endif +#ifndef OPENSSL_NO_RC4 +#include +#endif +#ifndef OPENSSL_NO_RC2 +#include +#endif +#ifndef OPENSSL_NO_RC5 +#include +#endif +#ifndef OPENSSL_NO_BF +#include +#endif +#ifndef OPENSSL_NO_CAST +#include +#endif +#ifndef OPENSSL_NO_IDEA +#include +#endif +#ifndef OPENSSL_NO_MDC2 +#include +#endif +#ifndef OPENSSL_NO_AES +#include +#endif /* #define EVP_RC2_KEY_SIZE 16 @@ -91,6 +133,18 @@ /* Default PKCS#5 iteration count */ #define PKCS5_DEFAULT_ITER 2048 +#ifndef OPENSSL_NO_RSA +#include +#endif + +#ifndef OPENSSL_NO_DSA +#include +#endif + +#ifndef OPENSSL_NO_DH +#include +#endif + #include #define EVP_PK_RSA 0x0001 @@ -582,6 +636,8 @@ const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ const EVP_CIPHER *EVP_des_ecb(void); const EVP_CIPHER *EVP_des_ede(void); const EVP_CIPHER *EVP_des_ede3(void); +const EVP_CIPHER *EVP_des_ede_ecb(void); +const EVP_CIPHER *EVP_des_ede3_ecb(void); const EVP_CIPHER *EVP_des_cfb(void); const EVP_CIPHER *EVP_des_ede_cfb(void); const EVP_CIPHER *EVP_des_ede3_cfb(void); diff --git a/src/lib/libcrypto/evp/evp_pbe.c b/src/lib/libcrypto/evp/evp_pbe.c index 06afb9d152..bcd4d29f85 100644 --- a/src/lib/libcrypto/evp/evp_pbe.c +++ b/src/lib/libcrypto/evp/evp_pbe.c @@ -57,9 +57,9 @@ */ #include +#include "cryptlib.h" #include #include -#include "cryptlib.h" /* Password based encryption (PBE) functions */ diff --git a/src/lib/libcrypto/evp/p5_crpt.c b/src/lib/libcrypto/evp/p5_crpt.c index 113c60fedb..27a8286489 100644 --- a/src/lib/libcrypto/evp/p5_crpt.c +++ b/src/lib/libcrypto/evp/p5_crpt.c @@ -58,9 +58,9 @@ #include #include +#include "cryptlib.h" #include #include -#include "cryptlib.h" /* PKCS#5 v1.5 compatible PBE functions: see PKCS#5 v2.0 for more info. */ diff --git a/src/lib/libcrypto/evp/p5_crpt2.c b/src/lib/libcrypto/evp/p5_crpt2.c index 7881860b53..7485d6a278 100644 --- a/src/lib/libcrypto/evp/p5_crpt2.c +++ b/src/lib/libcrypto/evp/p5_crpt2.c @@ -58,10 +58,10 @@ #if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA) #include #include +#include "cryptlib.h" #include #include #include -#include "cryptlib.h" /* set this to print out info about the keygen algorithm */ /* #define DEBUG_PKCS5V2 */ diff --git a/src/lib/libcrypto/objects/obj_dat.c b/src/lib/libcrypto/objects/obj_dat.c index 3ff64bb8d1..02c3719f04 100644 --- a/src/lib/libcrypto/objects/obj_dat.c +++ b/src/lib/libcrypto/objects/obj_dat.c @@ -436,7 +436,7 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) unsigned long l; unsigned char *p; const char *s; - char tbuf[32]; + char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2]; if (buf_len <= 0) return(0); diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num index 02b39062fe..1486199661 100644 --- a/src/lib/libcrypto/objects/obj_mac.num +++ b/src/lib/libcrypto/objects/obj_mac.num @@ -507,3 +507,141 @@ mime_mhs_bodies 506 id_hex_partial_message 507 id_hex_multipart_message 508 generationQualifier 509 +pseudonym 510 +InternationalRA 511 +id_set 512 +set_ctype 513 +set_msgExt 514 +set_attr 515 +set_policy 516 +set_certExt 517 +set_brand 518 +setct_PANData 519 +setct_PANToken 520 +setct_PANOnly 521 +setct_OIData 522 +setct_PI 523 +setct_PIData 524 +setct_PIDataUnsigned 525 +setct_HODInput 526 +setct_AuthResBaggage 527 +setct_AuthRevReqBaggage 528 +setct_AuthRevResBaggage 529 +setct_CapTokenSeq 530 +setct_PInitResData 531 +setct_PI_TBS 532 +setct_PResData 533 +setct_AuthReqTBS 534 +setct_AuthResTBS 535 +setct_AuthResTBSX 536 +setct_AuthTokenTBS 537 +setct_CapTokenData 538 +setct_CapTokenTBS 539 +setct_AcqCardCodeMsg 540 +setct_AuthRevReqTBS 541 +setct_AuthRevResData 542 +setct_AuthRevResTBS 543 +setct_CapReqTBS 544 +setct_CapReqTBSX 545 +setct_CapResData 546 +setct_CapRevReqTBS 547 +setct_CapRevReqTBSX 548 +setct_CapRevResData 549 +setct_CredReqTBS 550 +setct_CredReqTBSX 551 +setct_CredResData 552 +setct_CredRevReqTBS 553 +setct_CredRevReqTBSX 554 +setct_CredRevResData 555 +setct_PCertReqData 556 +setct_PCertResTBS 557 +setct_BatchAdminReqData 558 +setct_BatchAdminResData 559 +setct_CardCInitResTBS 560 +setct_MeAqCInitResTBS 561 +setct_RegFormResTBS 562 +setct_CertReqData 563 +setct_CertReqTBS 564 +setct_CertResData 565 +setct_CertInqReqTBS 566 +setct_ErrorTBS 567 +setct_PIDualSignedTBE 568 +setct_PIUnsignedTBE 569 +setct_AuthReqTBE 570 +setct_AuthResTBE 571 +setct_AuthResTBEX 572 +setct_AuthTokenTBE 573 +setct_CapTokenTBE 574 +setct_CapTokenTBEX 575 +setct_AcqCardCodeMsgTBE 576 +setct_AuthRevReqTBE 577 +setct_AuthRevResTBE 578 +setct_AuthRevResTBEB 579 +setct_CapReqTBE 580 +setct_CapReqTBEX 581 +setct_CapResTBE 582 +setct_CapRevReqTBE 583 +setct_CapRevReqTBEX 584 +setct_CapRevResTBE 585 +setct_CredReqTBE 586 +setct_CredReqTBEX 587 +setct_CredResTBE 588 +setct_CredRevReqTBE 589 +setct_CredRevReqTBEX 590 +setct_CredRevResTBE 591 +setct_BatchAdminReqTBE 592 +setct_BatchAdminResTBE 593 +setct_RegFormReqTBE 594 +setct_CertReqTBE 595 +setct_CertReqTBEX 596 +setct_CertResTBE 597 +setct_CRLNotificationTBS 598 +setct_CRLNotificationResTBS 599 +setct_BCIDistributionTBS 600 +setext_genCrypt 601 +setext_miAuth 602 +setext_pinSecure 603 +setext_pinAny 604 +setext_track2 605 +setext_cv 606 +set_policy_root 607 +setCext_hashedRoot 608 +setCext_certType 609 +setCext_merchData 610 +setCext_cCertRequired 611 +setCext_tunneling 612 +setCext_setExt 613 +setCext_setQualf 614 +setCext_PGWYcapabilities 615 +setCext_TokenIdentifier 616 +setCext_Track2Data 617 +setCext_TokenType 618 +setCext_IssuerCapabilities 619 +setAttr_Cert 620 +setAttr_PGWYcap 621 +setAttr_TokenType 622 +setAttr_IssCap 623 +set_rootKeyThumb 624 +set_addPolicy 625 +setAttr_Token_EMV 626 +setAttr_Token_B0Prime 627 +setAttr_IssCap_CVM 628 +setAttr_IssCap_T2 629 +setAttr_IssCap_Sig 630 +setAttr_GenCryptgrm 631 +setAttr_T2Enc 632 +setAttr_T2cleartxt 633 +setAttr_TokICCsig 634 +setAttr_SecDevSig 635 +set_brand_IATA_ATA 636 +set_brand_Diners 637 +set_brand_AmericanExpress 638 +set_brand_JCB 639 +set_brand_Visa 640 +set_brand_MasterCard 641 +set_brand_Novus 642 +des_cdmf 643 +rsaOAEPEncryptionSET 644 +itu_t 645 +joint_iso_itu_t 646 +international_organizations 647 diff --git a/src/lib/libcrypto/objects/objects.txt b/src/lib/libcrypto/objects/objects.txt index 65d0b15629..71a4908485 100644 --- a/src/lib/libcrypto/objects/objects.txt +++ b/src/lib/libcrypto/objects/objects.txt @@ -542,6 +542,7 @@ X509 43 : : initials X509 44 : : generationQualifier X509 45 : : x500UniqueIdentifier X509 46 : dnQualifier : dnQualifier +X509 65 : : pseudonym X509 72 : role : role X500 8 : X500algorithms : directory services - algorithms @@ -762,3 +763,150 @@ pilotAttributeType 53 : : personalSignature pilotAttributeType 54 : : dITRedirect pilotAttributeType 55 : audio pilotAttributeType 56 : : documentPublisher + +2 23 42 : id-set : Secure Electronic Transactions + +id-set 0 : set-ctype : content types +id-set 1 : set-msgExt : message extensions +id-set 3 : set-attr +id-set 5 : set-policy +id-set 7 : set-certExt : certificate extensions +id-set 8 : set-brand + +set-ctype 0 : setct-PANData +set-ctype 1 : setct-PANToken +set-ctype 2 : setct-PANOnly +set-ctype 3 : setct-OIData +set-ctype 4 : setct-PI +set-ctype 5 : setct-PIData +set-ctype 6 : setct-PIDataUnsigned +set-ctype 7 : setct-HODInput +set-ctype 8 : setct-AuthResBaggage +set-ctype 9 : setct-AuthRevReqBaggage +set-ctype 10 : setct-AuthRevResBaggage +set-ctype 11 : setct-CapTokenSeq +set-ctype 12 : setct-PInitResData +set-ctype 13 : setct-PI-TBS +set-ctype 14 : setct-PResData +set-ctype 16 : setct-AuthReqTBS +set-ctype 17 : setct-AuthResTBS +set-ctype 18 : setct-AuthResTBSX +set-ctype 19 : setct-AuthTokenTBS +set-ctype 20 : setct-CapTokenData +set-ctype 21 : setct-CapTokenTBS +set-ctype 22 : setct-AcqCardCodeMsg +set-ctype 23 : setct-AuthRevReqTBS +set-ctype 24 : setct-AuthRevResData +set-ctype 25 : setct-AuthRevResTBS +set-ctype 26 : setct-CapReqTBS +set-ctype 27 : setct-CapReqTBSX +set-ctype 28 : setct-CapResData +set-ctype 29 : setct-CapRevReqTBS +set-ctype 30 : setct-CapRevReqTBSX +set-ctype 31 : setct-CapRevResData +set-ctype 32 : setct-CredReqTBS +set-ctype 33 : setct-CredReqTBSX +set-ctype 34 : setct-CredResData +set-ctype 35 : setct-CredRevReqTBS +set-ctype 36 : setct-CredRevReqTBSX +set-ctype 37 : setct-CredRevResData +set-ctype 38 : setct-PCertReqData +set-ctype 39 : setct-PCertResTBS +set-ctype 40 : setct-BatchAdminReqData +set-ctype 41 : setct-BatchAdminResData +set-ctype 42 : setct-CardCInitResTBS +set-ctype 43 : setct-MeAqCInitResTBS +set-ctype 44 : setct-RegFormResTBS +set-ctype 45 : setct-CertReqData +set-ctype 46 : setct-CertReqTBS +set-ctype 47 : setct-CertResData +set-ctype 48 : setct-CertInqReqTBS +set-ctype 49 : setct-ErrorTBS +set-ctype 50 : setct-PIDualSignedTBE +set-ctype 51 : setct-PIUnsignedTBE +set-ctype 52 : setct-AuthReqTBE +set-ctype 53 : setct-AuthResTBE +set-ctype 54 : setct-AuthResTBEX +set-ctype 55 : setct-AuthTokenTBE +set-ctype 56 : setct-CapTokenTBE +set-ctype 57 : setct-CapTokenTBEX +set-ctype 58 : setct-AcqCardCodeMsgTBE +set-ctype 59 : setct-AuthRevReqTBE +set-ctype 60 : setct-AuthRevResTBE +set-ctype 61 : setct-AuthRevResTBEB +set-ctype 62 : setct-CapReqTBE +set-ctype 63 : setct-CapReqTBEX +set-ctype 64 : setct-CapResTBE +set-ctype 65 : setct-CapRevReqTBE +set-ctype 66 : setct-CapRevReqTBEX +set-ctype 67 : setct-CapRevResTBE +set-ctype 68 : setct-CredReqTBE +set-ctype 69 : setct-CredReqTBEX +set-ctype 70 : setct-CredResTBE +set-ctype 71 : setct-CredRevReqTBE +set-ctype 72 : setct-CredRevReqTBEX +set-ctype 73 : setct-CredRevResTBE +set-ctype 74 : setct-BatchAdminReqTBE +set-ctype 75 : setct-BatchAdminResTBE +set-ctype 76 : setct-RegFormReqTBE +set-ctype 77 : setct-CertReqTBE +set-ctype 78 : setct-CertReqTBEX +set-ctype 79 : setct-CertResTBE +set-ctype 80 : setct-CRLNotificationTBS +set-ctype 81 : setct-CRLNotificationResTBS +set-ctype 82 : setct-BCIDistributionTBS + +set-msgExt 1 : setext-genCrypt : generic cryptogram +set-msgExt 3 : setext-miAuth : merchant initiated auth +set-msgExt 4 : setext-pinSecure +set-msgExt 5 : setext-pinAny +set-msgExt 7 : setext-track2 +set-msgExt 8 : setext-cv : additional verification + +set-policy 0 : set-policy-root + +set-certExt 0 : setCext-hashedRoot +set-certExt 1 : setCext-certType +set-certExt 2 : setCext-merchData +set-certExt 3 : setCext-cCertRequired +set-certExt 4 : setCext-tunneling +set-certExt 5 : setCext-setExt +set-certExt 6 : setCext-setQualf +set-certExt 7 : setCext-PGWYcapabilities +set-certExt 8 : setCext-TokenIdentifier +set-certExt 9 : setCext-Track2Data +set-certExt 10 : setCext-TokenType +set-certExt 11 : setCext-IssuerCapabilities + +set-attr 0 : setAttr-Cert +set-attr 1 : setAttr-PGWYcap : payment gateway capabilities +set-attr 2 : setAttr-TokenType +set-attr 3 : setAttr-IssCap : issuer capabilities + +setAttr-Cert 0 : set-rootKeyThumb +setAttr-Cert 1 : set-addPolicy + +setAttr-TokenType 1 : setAttr-Token-EMV +setAttr-TokenType 2 : setAttr-Token-B0Prime + +setAttr-IssCap 3 : setAttr-IssCap-CVM +setAttr-IssCap 4 : setAttr-IssCap-T2 +setAttr-IssCap 5 : setAttr-IssCap-Sig + +setAttr-IssCap-CVM 1 : setAttr-GenCryptgrm : generate cryptogram +setAttr-IssCap-T2 1 : setAttr-T2Enc : encrypted track 2 +setAttr-IssCap-T2 2 : setAttr-T2cleartxt : cleartext track 2 + +setAttr-IssCap-Sig 1 : setAttr-TokICCsig : ICC or token signature +setAttr-IssCap-Sig 2 : setAttr-SecDevSig : secure device signature + +set-brand 1 : set-brand-IATA-ATA +set-brand 30 : set-brand-Diners +set-brand 34 : set-brand-AmericanExpress +set-brand 35 : set-brand-JCB +set-brand 4 : set-brand-Visa +set-brand 5 : set-brand-MasterCard +set-brand 6011 : set-brand-Novus + +rsadsi 3 10 : DES-CDMF : des-cdmf +rsadsi 1 1 6 : rsaOAEPEncryptionSET diff --git a/src/lib/libcrypto/opensslv.h b/src/lib/libcrypto/opensslv.h index 0d23a02fb2..9689b49c5b 100644 --- a/src/lib/libcrypto/opensslv.h +++ b/src/lib/libcrypto/opensslv.h @@ -25,8 +25,8 @@ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -#define OPENSSL_VERSION_NUMBER 0x00907001L -#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.7-beta1 01 Jun 2002" +#define OPENSSL_VERSION_NUMBER 0x00907003L +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.7-beta3 30 Jul 2002" #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/src/lib/libcrypto/pem/pem2.h b/src/lib/libcrypto/pem/pem2.h index 4e484bcd82..f31790d69c 100644 --- a/src/lib/libcrypto/pem/pem2.h +++ b/src/lib/libcrypto/pem/pem2.h @@ -61,7 +61,9 @@ extern "C" { #endif +#ifndef HEADER_PEM_H void ERR_load_PEM_strings(void); +#endif #ifdef __cplusplus } diff --git a/src/lib/libcrypto/pem/pem_pkey.c b/src/lib/libcrypto/pem/pem_pkey.c index 270892d72b..d96ecf6940 100644 --- a/src/lib/libcrypto/pem/pem_pkey.c +++ b/src/lib/libcrypto/pem/pem_pkey.c @@ -85,6 +85,7 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, vo else if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); + if(!p8inf) goto p8err; ret = EVP_PKCS82PKEY(p8inf); PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm,PEM_STRING_PKCS8) == 0) { diff --git a/src/lib/libcrypto/perlasm/x86asm.pl b/src/lib/libcrypto/perlasm/x86asm.pl index 81c6e64e87..9a3d85b098 100644 --- a/src/lib/libcrypto/perlasm/x86asm.pl +++ b/src/lib/libcrypto/perlasm/x86asm.pl @@ -87,6 +87,12 @@ $tmp #ifdef OUT #define OK 1 #define ALIGN 4 +#if defined(__CYGWIN__) || defined(__DJGPP__) +#undef SIZE +#undef TYPE +#define SIZE(a,b) +#define TYPE(a,b) +#endif /* __CYGWIN || __DJGPP */ #endif #if defined(BSDI) && !defined(ELF) diff --git a/src/lib/libcrypto/pkcs12/pkcs12.h b/src/lib/libcrypto/pkcs12/pkcs12.h index 1786b6d4f3..dd338f266c 100644 --- a/src/lib/libcrypto/pkcs12/pkcs12.h +++ b/src/lib/libcrypto/pkcs12/pkcs12.h @@ -156,8 +156,8 @@ union { #define M_PKCS12_decrypt_skey PKCS12_decrypt_skey #define M_PKCS8_decrypt PKCS8_decrypt -#define M_PKCS12_bag_type(bag) OBJ_obj2nid(bag->type) -#define M_PKCS12_cert_bag_type(bag) OBJ_obj2nid(bag->value.bag->type) +#define M_PKCS12_bag_type(bg) OBJ_obj2nid((bg)->type) +#define M_PKCS12_cert_bag_type(bg) OBJ_obj2nid((bg)->value.bag->type) #define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type #define PKCS12_get_attr(bag, attr_nid) \ diff --git a/src/lib/libcrypto/rand/rand.h b/src/lib/libcrypto/rand/rand.h index e17aa7a9f7..66e39991ec 100644 --- a/src/lib/libcrypto/rand/rand.h +++ b/src/lib/libcrypto/rand/rand.h @@ -61,6 +61,11 @@ #include #include +#include + +#if defined(OPENSSL_SYS_WINDOWS) +#include +#endif #ifdef __cplusplus extern "C" { diff --git a/src/lib/libcrypto/rsa/rsa.h b/src/lib/libcrypto/rsa/rsa.h index 030a6c88e5..98b3bd7cc5 100644 --- a/src/lib/libcrypto/rsa/rsa.h +++ b/src/lib/libcrypto/rsa/rsa.h @@ -276,6 +276,9 @@ int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, int RSA_set_ex_data(RSA *r,int idx,void *arg); void *RSA_get_ex_data(const RSA *r, int idx); +RSA *RSAPublicKey_dup(RSA *rsa); +RSA *RSAPrivateKey_dup(RSA *rsa); + /* 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. diff --git a/src/lib/libcrypto/ui/ui_openssl.c b/src/lib/libcrypto/ui/ui_openssl.c index 4e12165410..2c2fbc0443 100644 --- a/src/lib/libcrypto/ui/ui_openssl.c +++ b/src/lib/libcrypto/ui/ui_openssl.c @@ -269,7 +269,7 @@ static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this w static long status; static unsigned short channel = 0; #else -#ifndef OPENSSL_SYS_MSDOS +#if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__) static TTY_STRUCT tty_orig,tty_new; #endif #endif diff --git a/src/lib/libcrypto/ui/ui_util.c b/src/lib/libcrypto/ui/ui_util.c index 7c6f7d3a73..f05573df33 100644 --- a/src/lib/libcrypto/ui/ui_util.c +++ b/src/lib/libcrypto/ui/ui_util.c @@ -71,12 +71,15 @@ int UI_UTIL_read_pw(char *buf,char *buff,int size,const char *prompt,int verify) int ok = 0; UI *ui; + if (size < 1) + return -1; + ui = UI_new(); if (ui) { - ok = UI_add_input_string(ui,prompt,0,buf,0,BUFSIZ-1); + ok = UI_add_input_string(ui,prompt,0,buf,0,size-1); if (ok == 0 && verify) - ok = UI_add_verify_string(ui,prompt,0,buff,0,BUFSIZ-1, + ok = UI_add_verify_string(ui,prompt,0,buff,0,size-1, buf); if (ok == 0) ok=UI_process(ui); diff --git a/src/lib/libcrypto/x509v3/ext_dat.h b/src/lib/libcrypto/x509v3/ext_dat.h index 586f116db5..2fb97d8925 100644 --- a/src/lib/libcrypto/x509v3/ext_dat.h +++ b/src/lib/libcrypto/x509v3/ext_dat.h @@ -99,8 +99,8 @@ static X509V3_EXT_METHOD *standard_exts[] = { &v3_ocsp_nocheck, &v3_ocsp_acutoff, &v3_ocsp_serviceloc, -&v3_crl_hold, -&v3_sinfo +&v3_sinfo, +&v3_crl_hold }; /* Number of standard extensions */ diff --git a/src/lib/libcrypto/x509v3/v3_info.c b/src/lib/libcrypto/x509v3/v3_info.c index 7f17f3231d..e1cf01a9b4 100644 --- a/src/lib/libcrypto/x509v3/v3_info.c +++ b/src/lib/libcrypto/x509v3/v3_info.c @@ -158,6 +158,7 @@ static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *metho objlen = ptmp - cnf->name; ctmp.name = ptmp + 1; ctmp.value = cnf->value; + GENERAL_NAME_free(acc->location); if(!(acc->location = v2i_GENERAL_NAME(method, ctx, &ctmp))) goto err; if(!(objtmp = OPENSSL_malloc(objlen + 1))) { diff --git a/src/lib/libssl/s23_clnt.c b/src/lib/libssl/s23_clnt.c index b2be8340fb..019e9aecee 100644 --- a/src/lib/libssl/s23_clnt.c +++ b/src/lib/libssl/s23_clnt.c @@ -57,11 +57,11 @@ */ #include +#include "ssl_locl.h" #include #include #include #include -#include "ssl_locl.h" static SSL_METHOD *ssl23_get_client_method(int ver); static int ssl23_client_hello(SSL *s); diff --git a/src/lib/libssl/s23_pkt.c b/src/lib/libssl/s23_pkt.c index f45e1ce3d8..4ca6a1b258 100644 --- a/src/lib/libssl/s23_pkt.c +++ b/src/lib/libssl/s23_pkt.c @@ -59,9 +59,9 @@ #include #include #define USE_SOCKETS +#include "ssl_locl.h" #include #include -#include "ssl_locl.h" int ssl23_write_bytes(SSL *s) { diff --git a/src/lib/libssl/s23_srvr.c b/src/lib/libssl/s23_srvr.c index 9e89cc7f9a..8743b61cbb 100644 --- a/src/lib/libssl/s23_srvr.c +++ b/src/lib/libssl/s23_srvr.c @@ -110,11 +110,11 @@ */ #include +#include "ssl_locl.h" #include #include #include #include -#include "ssl_locl.h" static SSL_METHOD *ssl23_get_server_method(int ver); int ssl23_get_client_hello(SSL *s); diff --git a/src/lib/libssl/s3_both.c b/src/lib/libssl/s3_both.c index 58a24cd883..8864366f59 100644 --- a/src/lib/libssl/s3_both.c +++ b/src/lib/libssl/s3_both.c @@ -112,12 +112,12 @@ #include #include #include +#include "ssl_locl.h" #include #include #include #include #include -#include "ssl_locl.h" /* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ int ssl3_do_write(SSL *s, int type) diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c index e5853ede95..2699b5863b 100644 --- a/src/lib/libssl/s3_clnt.c +++ b/src/lib/libssl/s3_clnt.c @@ -110,13 +110,14 @@ */ #include +#include "ssl_locl.h" +#include "kssl_lcl.h" #include #include #include #include -#include "ssl_locl.h" -#include "kssl_lcl.h" #include +#include "cryptlib.h" static SSL_METHOD *ssl3_get_client_method(int ver); static int ssl3_client_hello(SSL *s); @@ -545,6 +546,7 @@ static int ssl3_client_hello(SSL *s) *(p++)=i; if (i != 0) { + die(i <= sizeof s->session->session_id); memcpy(p,s->session->session_id,i); p+=i; } @@ -626,6 +628,14 @@ static int ssl3_get_server_hello(SSL *s) /* get the session-id */ j= *(p++); + if(j > sizeof s->session->session_id) + { + al=SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_SSL3_SESSION_ID_TOO_LONG); + goto f_err; + } + if ((j != 0) && (j != SSL3_SESSION_ID_SIZE)) { /* SSLref returns 16 :-( */ @@ -1588,6 +1598,7 @@ static int ssl3_send_client_key_exchange(SSL *s) SSL_MAX_MASTER_KEY_LENGTH); EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); outl += padl; + die(outl <= sizeof epms); EVP_CIPHER_CTX_cleanup(&ciph_ctx); /* KerberosWrapper.EncryptedPreMasterSecret */ diff --git a/src/lib/libssl/s3_lib.c b/src/lib/libssl/s3_lib.c index 686992406c..14b2f13ae2 100644 --- a/src/lib/libssl/s3_lib.c +++ b/src/lib/libssl/s3_lib.c @@ -129,7 +129,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ SSL3_TXT_RSA_NULL_MD5, SSL3_CK_RSA_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_MD5|SSL_SSLV3, - SSL_NOT_EXP, + SSL_NOT_EXP|SSL_STRONG_NONE, 0, 0, 0, @@ -142,7 +142,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ SSL3_TXT_RSA_NULL_SHA, SSL3_CK_RSA_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_SSLV3, - SSL_NOT_EXP, + SSL_NOT_EXP|SSL_STRONG_NONE, 0, 0, 0, @@ -490,7 +490,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ SSL3_TXT_FZA_DMS_NULL_SHA, SSL3_CK_FZA_DMS_NULL_SHA, SSL_kFZA|SSL_aFZA |SSL_eNULL |SSL_SHA1|SSL_SSLV3, - SSL_NOT_EXP, + SSL_NOT_EXP|SSL_STRONG_NONE, 0, 0, 0, @@ -504,7 +504,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ SSL3_TXT_FZA_DMS_FZA_SHA, SSL3_CK_FZA_DMS_FZA_SHA, SSL_kFZA|SSL_aFZA |SSL_eFZA |SSL_SHA1|SSL_SSLV3, - SSL_NOT_EXP, + SSL_NOT_EXP|SSL_STRONG_NONE, 0, 0, 0, diff --git a/src/lib/libssl/s3_pkt.c b/src/lib/libssl/s3_pkt.c index 43e8502b66..6ccea9aee5 100644 --- a/src/lib/libssl/s3_pkt.c +++ b/src/lib/libssl/s3_pkt.c @@ -112,9 +112,9 @@ #include #include #define USE_SOCKETS +#include "ssl_locl.h" #include #include -#include "ssl_locl.h" static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len, int create_empty_fragment); diff --git a/src/lib/libssl/s3_srvr.c b/src/lib/libssl/s3_srvr.c index 99b6a86983..782b57f57a 100644 --- a/src/lib/libssl/s3_srvr.c +++ b/src/lib/libssl/s3_srvr.c @@ -114,15 +114,16 @@ #include +#include "ssl_locl.h" +#include "kssl_lcl.h" #include #include #include #include #include #include -#include "ssl_locl.h" -#include "kssl_lcl.h" #include +#include "cryptlib.h" static SSL_METHOD *ssl3_get_server_method(int ver); static int ssl3_get_client_hello(SSL *s); @@ -964,6 +965,7 @@ static int ssl3_send_server_hello(SSL *s) s->session->session_id_length=0; sl=s->session->session_id_length; + die(sl <= sizeof s->session->session_id); *(p++)=sl; memcpy(p,s->session->session_id,sl); p+=sl; @@ -1559,8 +1561,8 @@ static int ssl3_get_client_key_exchange(SSL *s) EVP_CIPHER *enc = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH - + EVP_MAX_IV_LENGTH + 1]; - int padl, outl = sizeof(pms); + + EVP_MAX_BLOCK_LENGTH]; + int padl, outl; krb5_timestamp authtime = 0; krb5_ticket_times ttimes; @@ -1583,6 +1585,16 @@ static int ssl3_get_client_key_exchange(SSL *s) enc_pms.data = (char *)p; p+=enc_pms.length; + /* Note that the length is checked again below, + ** after decryption + */ + if(enc.pms_length > sizeof pms) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + if (n != enc_ticket.length + authenticator.length + enc_pms.length + 6) { diff --git a/src/lib/libssl/ssl.h b/src/lib/libssl/ssl.h index 833f761690..d9949e8eb2 100644 --- a/src/lib/libssl/ssl.h +++ b/src/lib/libssl/ssl.h @@ -253,7 +253,7 @@ extern "C" { #define SSL_TXT_RC4 "RC4" #define SSL_TXT_RC2 "RC2" #define SSL_TXT_IDEA "IDEA" -#define SSL_TXT_AES "AESdraft" /* AES ciphersuites are not yet official (thus excluded from 'ALL') */ +#define SSL_TXT_AES "AES" #define SSL_TXT_MD5 "MD5" #define SSL_TXT_SHA1 "SHA1" #define SSL_TXT_SHA "SHA" @@ -266,6 +266,23 @@ extern "C" { #define SSL_TXT_TLSV1 "TLSv1" #define SSL_TXT_ALL "ALL" +/* + * COMPLEMENTOF* definitions. These identifiers are used to (de-select) + * ciphers normally not being used. + * Example: "RC4" will activate all ciphers using RC4 including ciphers + * without authentication, which would normally disabled by DEFAULT (due + * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" + * will make sure that it is also disabled in the specific selection. + * COMPLEMENTOF* identifiers are portable between version, as adjustments + * to the default cipher setup will also be included here. + * + * COMPLEMENTOFDEFAULT does not experience the same special treatment that + * DEFAULT gets, as only selection is being done and no sorting as needed + * for DEFAULT. + */ +#define SSL_TXT_CMPALL "COMPLEMENTOFALL" +#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" + /* The following cipher list is used by default. * It also is substituted when an application-defined cipher list string * starts with 'DEFAULT'. */ @@ -429,6 +446,7 @@ typedef struct ssl_session_st struct ssl_session_st *prev,*next; } SSL_SESSION; + #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L @@ -439,6 +457,19 @@ typedef struct ssl_session_st #define SSL_OP_TLS_D5_BUG 0x00000100L #define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L +/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added + * in OpenSSL 0.9.6d. Usually (depending on the application protocol) + * the workaround is not needed. Unfortunately some broken SSL/TLS + * implementations cannot handle it at all, which is why we include + * it in SSL_OP_ALL. */ +#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L /* added in 0.9.6e */ + +/* SSL_OP_ALL: various bug workarounds that should be rather harmless. + * This used to be 0x000FFFFFL before 0.9.7. */ +#define SSL_OP_ALL 0x00000FFFL + +/* As server, disallow session resumption on renegotiation */ +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L /* If set, always create a new key when using tmp_dh parameters */ #define SSL_OP_SINGLE_DH_USE 0x00100000L /* Set to always use the tmp_rsa key when doing RSA operations, @@ -452,8 +483,10 @@ typedef struct ssl_session_st * (version 3.1) was announced in the client hello. Normally this is * forbidden to prevent version rollback attacks. */ #define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L -/* As server, disallow session resumption on renegotiation */ -#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x01000000L + +#define SSL_OP_NO_SSLv2 0x01000000L +#define SSL_OP_NO_SSLv3 0x02000000L +#define SSL_OP_NO_TLSv1 0x04000000L /* The next flag deliberately changes the ciphertest, this is a check * for the PKCS#1 attack */ @@ -461,11 +494,7 @@ typedef struct ssl_session_st #define SSL_OP_PKCS1_CHECK_2 0x10000000L #define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L -#define SSL_OP_ALL 0x000FFFFFL -#define SSL_OP_NO_SSLv2 0x01000000L -#define SSL_OP_NO_SSLv3 0x02000000L -#define SSL_OP_NO_TLSv1 0x04000000L /* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success * when just a single record has been written): */ @@ -479,6 +508,7 @@ typedef struct ssl_session_st * is blocking: */ #define SSL_MODE_AUTO_RETRY 0x00000004L + /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, * they cannot be used to clear bits. */ @@ -1637,6 +1667,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_INVALID_COMMAND 280 #define SSL_R_INVALID_PURPOSE 278 #define SSL_R_INVALID_TRUST 279 +#define SSL_R_KEY_ARG_TOO_LONG 1112 #define SSL_R_KRB5 1104 #define SSL_R_KRB5_C_CC_PRINC 1094 #define SSL_R_KRB5_C_GET_CRED 1095 @@ -1716,6 +1747,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_SHORT_READ 219 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 +#define SSL_R_SSL3_SESSION_ID_TOO_LONG 1113 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 diff --git a/src/lib/libssl/ssl_asn1.c b/src/lib/libssl/ssl_asn1.c index c5eeeb6bc5..1638c6b525 100644 --- a/src/lib/libssl/ssl_asn1.c +++ b/src/lib/libssl/ssl_asn1.c @@ -58,10 +58,11 @@ #include #include +#include "ssl_locl.h" #include #include #include -#include "ssl_locl.h" +#include "cryptlib.h" typedef struct ssl_session_asn1_st { @@ -296,6 +297,7 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, os.length=i; ret->session_id_length=os.length; + die(os.length <= sizeof ret->session_id); memcpy(ret->session_id,os.data,os.length); M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING); diff --git a/src/lib/libssl/ssl_ciph.c b/src/lib/libssl/ssl_ciph.c index cdd8dde128..37f58886a6 100644 --- a/src/lib/libssl/ssl_ciph.c +++ b/src/lib/libssl/ssl_ciph.c @@ -100,9 +100,10 @@ typedef struct cipher_order_st } CIPHER_ORDER; static const SSL_CIPHER cipher_aliases[]={ - /* Don't include eNULL unless specifically enabled. - * Similarly, don't include AES in ALL because these ciphers are not yet official. */ - {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL & ~SSL_AES, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL}, /* must be first */ + /* Don't include eNULL unless specifically enabled. */ + {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL}, /* must be first */ + {0,SSL_TXT_CMPALL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0}, /* COMPLEMENT OF ALL */ + {0,SSL_TXT_CMPDEF,0,SSL_ADH, 0,0,0,0,SSL_AUTH_MASK,0}, {0,SSL_TXT_kKRB5,0,SSL_kKRB5,0,0,0,0,SSL_MKEY_MASK,0}, /* VRS Kerberos5 */ {0,SSL_TXT_kRSA,0,SSL_kRSA, 0,0,0,0,SSL_MKEY_MASK,0}, {0,SSL_TXT_kDHr,0,SSL_kDHr, 0,0,0,0,SSL_MKEY_MASK,0}, @@ -999,10 +1000,10 @@ char *SSL_CIPHER_description(SSL_CIPHER *cipher, char *buf, int len) case SSL_AES: switch(cipher->strength_bits) { - case 128: enc="AESdraft(128)"; break; - case 192: enc="AESdraft(192)"; break; - case 256: enc="AESdraft(256)"; break; - default: enc="AESdraft(?""?""?)"; break; + case 128: enc="AES(128)"; break; + case 192: enc="AES(192)"; break; + case 256: enc="AES(256)"; break; + default: enc="AES(?""?""?)"; break; } break; default: diff --git a/src/lib/libssl/ssl_err.c b/src/lib/libssl/ssl_err.c index c32c4ef6e9..0cad32c855 100644 --- a/src/lib/libssl/ssl_err.c +++ b/src/lib/libssl/ssl_err.c @@ -1,6 +1,6 @@ /* ssl/ssl_err.c */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2002 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 @@ -275,6 +275,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_INVALID_COMMAND ,"invalid command"}, {SSL_R_INVALID_PURPOSE ,"invalid purpose"}, {SSL_R_INVALID_TRUST ,"invalid trust"}, +{SSL_R_KEY_ARG_TOO_LONG ,"key arg too long"}, {SSL_R_KRB5 ,"krb5"}, {SSL_R_KRB5_C_CC_PRINC ,"krb5 client cc principal (no tkt?)"}, {SSL_R_KRB5_C_GET_CRED ,"krb5 client get cred"}, @@ -354,6 +355,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_SHORT_READ ,"short read"}, {SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE,"signature for non signing certificate"}, {SSL_R_SSL23_DOING_SESSION_ID_REUSE ,"ssl23 doing session id reuse"}, +{SSL_R_SSL3_SESSION_ID_TOO_LONG ,"ssl3 session id too long"}, {SSL_R_SSL3_SESSION_ID_TOO_SHORT ,"ssl3 session id too short"}, {SSL_R_SSLV3_ALERT_BAD_CERTIFICATE ,"sslv3 alert bad certificate"}, {SSL_R_SSLV3_ALERT_BAD_RECORD_MAC ,"sslv3 alert bad record mac"}, diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index df307a80c5..ab172aeaec 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c @@ -116,11 +116,11 @@ # include #endif #include +#include "ssl_locl.h" +#include "kssl_lcl.h" #include #include #include -#include "ssl_locl.h" -#include "kssl_lcl.h" const char *SSL_version_str=OPENSSL_VERSION_TEXT; diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 17e9bef832..fe4ac839cf 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -293,16 +293,17 @@ #define SSL_NOT_EXP 0x00000001L #define SSL_EXPORT 0x00000002L -#define SSL_STRONG_MASK 0x0000007cL -#define SSL_EXP40 0x00000004L +#define SSL_STRONG_MASK 0x000000fcL +#define SSL_STRONG_NONE 0x00000004L +#define SSL_EXP40 0x00000008L #define SSL_MICRO (SSL_EXP40) -#define SSL_EXP56 0x00000008L +#define SSL_EXP56 0x00000010L #define SSL_MINI (SSL_EXP56) -#define SSL_LOW 0x00000010L -#define SSL_MEDIUM 0x00000020L -#define SSL_HIGH 0x00000040L +#define SSL_LOW 0x00000020L +#define SSL_MEDIUM 0x00000040L +#define SSL_HIGH 0x00000080L -/* we have used 0000007f - 25 bits left to go */ +/* we have used 000000ff - 24 bits left to go */ /* * Macros to check the export status and cipher strength for export ciphers. diff --git a/src/lib/libssl/ssl_rsa.c b/src/lib/libssl/ssl_rsa.c index 1cf8e20934..03828b6632 100644 --- a/src/lib/libssl/ssl_rsa.c +++ b/src/lib/libssl/ssl_rsa.c @@ -57,12 +57,12 @@ */ #include +#include "ssl_locl.h" #include #include #include #include #include -#include "ssl_locl.h" static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 6424f775e2..8bfc382bb6 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c @@ -60,6 +60,7 @@ #include #include #include "ssl_locl.h" +#include "cryptlib.h" static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s); @@ -250,6 +251,7 @@ int ssl_get_new_session(SSL *s, int session) ss->session_id_length=0; } + die(s->sid_ctx_length <= sizeof ss->sid_ctx); memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); ss->sid_ctx_length=s->sid_ctx_length; s->session=ss; diff --git a/src/lib/libssl/t1_clnt.c b/src/lib/libssl/t1_clnt.c index 9745630a00..9ad518f9f4 100644 --- a/src/lib/libssl/t1_clnt.c +++ b/src/lib/libssl/t1_clnt.c @@ -57,11 +57,11 @@ */ #include +#include "ssl_locl.h" #include #include #include #include -#include "ssl_locl.h" static SSL_METHOD *tls1_get_client_method(int ver); static SSL_METHOD *tls1_get_client_method(int ver) diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c index b80525f3ba..5290bf6665 100644 --- a/src/lib/libssl/t1_enc.c +++ b/src/lib/libssl/t1_enc.c @@ -110,10 +110,10 @@ */ #include +#include "ssl_locl.h" #include #include #include -#include "ssl_locl.h" #include static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec, @@ -483,14 +483,25 @@ printf("\nkey block\n"); { int z; for (z=0; zs3->need_empty_fragments = 1; -#ifndef NO_RC4 - if ((s->session->cipher != NULL) && ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4)) - s->s3->need_empty_fragments = 0; + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) + { + /* enable vulnerability countermeasure for CBC ciphers with + * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) + */ + s->s3->need_empty_fragments = 1; + + if (s->session->cipher != NULL) + { + if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_eNULL) + s->s3->need_empty_fragments = 0; + +#ifndef OPENSSL_NO_RC4 + if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4) + s->s3->need_empty_fragments = 0; #endif - + } + } + return(1); err: SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE); diff --git a/src/lib/libssl/t1_srvr.c b/src/lib/libssl/t1_srvr.c index 996b7ca8e2..6e765e587f 100644 --- a/src/lib/libssl/t1_srvr.c +++ b/src/lib/libssl/t1_srvr.c @@ -57,12 +57,12 @@ */ #include +#include "ssl_locl.h" #include #include #include #include #include -#include "ssl_locl.h" static SSL_METHOD *tls1_get_server_method(int ver); static SSL_METHOD *tls1_get_server_method(int ver) diff --git a/src/lib/libssl/test/tcrl b/src/lib/libssl/test/tcrl index acaf8f3c47..f71ef7a863 100644 --- a/src/lib/libssl/test/tcrl +++ b/src/lib/libssl/test/tcrl @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH cmd='../apps/openssl crl' diff --git a/src/lib/libssl/test/testca b/src/lib/libssl/test/testca index 88c186b6ab..8215ebb5d1 100644 --- a/src/lib/libssl/test/testca +++ b/src/lib/libssl/test/testca @@ -1,7 +1,11 @@ #!/bin/sh SH="/bin/sh" -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=./apps\;../apps\;$PATH +else + PATH=../apps:$PATH +fi export SH PATH SSLEAY_CONFIG="-config CAss.cnf" diff --git a/src/lib/libssl/test/testgen b/src/lib/libssl/test/testgen index 6a4b6b9221..55c496f4bc 100644 --- a/src/lib/libssl/test/testgen +++ b/src/lib/libssl/test/testgen @@ -6,7 +6,11 @@ CA=../certs/testca.pem /bin/rm -f $T.1 $T.2 $T.key -PATH=../apps:$PATH; +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH; +else + PATH=../apps:$PATH; +fi export PATH echo "generating certificate request" diff --git a/src/lib/libssl/test/tpkcs7 b/src/lib/libssl/test/tpkcs7 index 15bbba42c0..cf3bd9fadb 100644 --- a/src/lib/libssl/test/tpkcs7 +++ b/src/lib/libssl/test/tpkcs7 @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH cmd='../apps/openssl pkcs7' diff --git a/src/lib/libssl/test/tpkcs7d b/src/lib/libssl/test/tpkcs7d index 46e5aa2bd6..18f9311b06 100644 --- a/src/lib/libssl/test/tpkcs7d +++ b/src/lib/libssl/test/tpkcs7d @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH cmd='../apps/openssl pkcs7' diff --git a/src/lib/libssl/test/treq b/src/lib/libssl/test/treq index 9f5eb7eea5..47a8273cde 100644 --- a/src/lib/libssl/test/treq +++ b/src/lib/libssl/test/treq @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH cmd='../apps/openssl req -config ../apps/openssl.cnf' diff --git a/src/lib/libssl/test/trsa b/src/lib/libssl/test/trsa index bd6c07650a..413e2ec0a0 100644 --- a/src/lib/libssl/test/trsa +++ b/src/lib/libssl/test/trsa @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH if ../apps/openssl no-rsa; then diff --git a/src/lib/libssl/test/tsid b/src/lib/libssl/test/tsid index 9e0854516c..40a1dfa97c 100644 --- a/src/lib/libssl/test/tsid +++ b/src/lib/libssl/test/tsid @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH cmd='../apps/openssl sess_id' diff --git a/src/lib/libssl/test/tx509 b/src/lib/libssl/test/tx509 index 35169f3a43..d380963abc 100644 --- a/src/lib/libssl/test/tx509 +++ b/src/lib/libssl/test/tx509 @@ -1,6 +1,10 @@ #!/bin/sh -PATH=../apps:$PATH +if test "$OSTYPE" = msdosdjgpp; then + PATH=../apps\;$PATH +else + PATH=../apps:$PATH +fi export PATH cmd='../apps/openssl x509' diff --git a/src/lib/libssl/tls1.h b/src/lib/libssl/tls1.h index 88ec5fb527..38838ea9a5 100644 --- a/src/lib/libssl/tls1.h +++ b/src/lib/libssl/tls1.h @@ -96,7 +96,7 @@ extern "C" { #define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065 #define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066 - /* AES ciphersuites from draft ietf-tls-ciphersuite-03.txt */ +/* AES ciphersuites from RFC3268 */ #define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F #define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 @@ -126,20 +126,21 @@ extern "C" { #define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA" #define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA" #define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" - /* AES ciphersuites from draft-ietf-tls-ciphersuite-06.txt */ -#define TLS1_TXT_RSA_WITH_AES_128_SHA "AESdraft128-SHA" -#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AESdraft128-SHA" -#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AESdraft128-SHA" -#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AESdraft128-SHA" -#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AESdraft128-SHA" -#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AESdraft128-SHA" - -#define TLS1_TXT_RSA_WITH_AES_256_SHA "AESdraft256-SHA" -#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AESdraft256-SHA" -#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AESdraft256-SHA" -#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AESdraft256-SHA" -#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AESdraft256-SHA" -#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AESdraft256-SHA" + +/* AES ciphersuites from RFC3268 */ +#define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +#define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" #define TLS_CT_RSA_SIGN 1 -- cgit v1.2.3-55-g6feb From 31392c89d1135cf2a416f97295f6d21681b3fbc4 Mon Sep 17 00:00:00 2001 From: markus <> Date: Thu, 12 Sep 2002 20:53:05 +0000 Subject: import openssl-0.9.7-stable-SNAP-20020911 (without idea) --- src/lib/libcrypto/asn1/a_bitstr.c | 6 + src/lib/libcrypto/asn1/a_strex.c | 4 +- src/lib/libcrypto/asn1/asn1_lib.c | 9 +- src/lib/libcrypto/asn1/t_req.c | 260 ++++++----- src/lib/libcrypto/asn1/tasn_dec.c | 6 +- src/lib/libcrypto/bio/b_print.c | 2 +- src/lib/libcrypto/bn/bn.h | 2 +- src/lib/libcrypto/cryptlib.c | 8 - src/lib/libcrypto/cryptlib.h | 4 - src/lib/libcrypto/des/ecb_enc.c | 1 + src/lib/libcrypto/des/set_key.c | 2 +- src/lib/libcrypto/doc/DH_set_method.pod | 102 ++-- src/lib/libcrypto/doc/DSA_dup_DH.pod | 2 +- src/lib/libcrypto/doc/DSA_new.pod | 3 +- src/lib/libcrypto/doc/DSA_set_method.pod | 91 ++-- src/lib/libcrypto/doc/DSA_size.pod | 2 +- src/lib/libcrypto/doc/EVP_SealInit.pod | 2 + src/lib/libcrypto/doc/RAND_set_rand_method.pod | 44 +- src/lib/libcrypto/doc/RSA_new.pod | 6 +- src/lib/libcrypto/doc/RSA_set_method.pod | 127 +++-- src/lib/libcrypto/doc/RSA_size.pod | 2 +- src/lib/libcrypto/doc/dh.pod | 31 +- src/lib/libcrypto/doc/dsa.pod | 41 +- src/lib/libcrypto/doc/engine.pod | 621 +++++++++++++++++++++++++ src/lib/libcrypto/doc/evp.pod | 10 +- src/lib/libcrypto/doc/rsa.pod | 31 +- src/lib/libcrypto/evp/evp_locl.h | 12 +- src/lib/libcrypto/objects/obj_dat.c | 2 +- src/lib/libcrypto/pem/pem_lib.c | 7 +- src/lib/libcrypto/pkcs12/p12_asn.c | 6 +- src/lib/libcrypto/pkcs7/pk7_lib.c | 7 + src/lib/libcrypto/x509/x509.h | 2 + src/lib/libssl/doc/openssl.txt | 2 +- src/lib/libssl/s3_clnt.c | 12 +- src/lib/libssl/s3_srvr.c | 8 +- src/lib/libssl/ssl.h | 6 + src/lib/libssl/ssl_asn1.c | 5 +- src/lib/libssl/ssl_err.c | 6 + src/lib/libssl/ssl_lib.c | 17 +- src/lib/libssl/ssl_locl.h | 2 +- src/lib/libssl/ssl_sess.c | 7 +- 41 files changed, 1189 insertions(+), 331 deletions(-) create mode 100644 src/lib/libcrypto/doc/engine.pod diff --git a/src/lib/libcrypto/asn1/a_bitstr.c b/src/lib/libcrypto/asn1/a_bitstr.c index ed0bdfbde1..e0265f69d2 100644 --- a/src/lib/libcrypto/asn1/a_bitstr.c +++ b/src/lib/libcrypto/asn1/a_bitstr.c @@ -120,6 +120,12 @@ ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, unsigned char **pp, unsigned char *p,*s; int i; + if (len < 1) + { + i=ASN1_R_STRING_TOO_SHORT; + goto err; + } + if ((a == NULL) || ((*a) == NULL)) { if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL); diff --git a/src/lib/libcrypto/asn1/a_strex.c b/src/lib/libcrypto/asn1/a_strex.c index 8dab29dca1..7ddb7662f1 100644 --- a/src/lib/libcrypto/asn1/a_strex.c +++ b/src/lib/libcrypto/asn1/a_strex.c @@ -544,7 +544,7 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) { ASN1_STRING stmp, *str = &stmp; int mbflag, type, ret; - if(!*out || !in) return -1; + if(!in) return -1; type = in->type; if((type < 0) || (type > 30)) return -1; mbflag = tag2nbyte[type]; @@ -553,6 +553,6 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) stmp.data = NULL; ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING); if(ret < 0) return ret; - if(out) *out = stmp.data; + *out = stmp.data; return stmp.length; } diff --git a/src/lib/libcrypto/asn1/asn1_lib.c b/src/lib/libcrypto/asn1/asn1_lib.c index 422685a3b4..0638870ab7 100644 --- a/src/lib/libcrypto/asn1/asn1_lib.c +++ b/src/lib/libcrypto/asn1/asn1_lib.c @@ -57,6 +57,7 @@ */ #include +#include #include "cryptlib.h" #include #include @@ -124,7 +125,7 @@ int ASN1_get_object(unsigned char **pp, long *plength, int *ptag, int *pclass, (int)(omax+ *pp)); #endif - if (*plength > (omax - (*pp - p))) + if (*plength > (omax - (p - *pp))) { ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG); /* Set this so that even if things are not long enough @@ -141,7 +142,7 @@ err: static int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) { unsigned char *p= *pp; - long ret=0; + unsigned long ret=0; int i; if (max-- < 1) return(0); @@ -170,10 +171,10 @@ static int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) else ret=i; } - if (ret < 0) + if (ret > LONG_MAX) return 0; *pp=p; - *rl=ret; + *rl=(long)ret; return(1); } diff --git a/src/lib/libcrypto/asn1/t_req.c b/src/lib/libcrypto/asn1/t_req.c index 848c29a2dd..739f272ecf 100644 --- a/src/lib/libcrypto/asn1/t_req.c +++ b/src/lib/libcrypto/asn1/t_req.c @@ -82,7 +82,7 @@ int X509_REQ_print_fp(FILE *fp, X509_REQ *x) } #endif -int X509_REQ_print(BIO *bp, X509_REQ *x) +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { unsigned long l; int i; @@ -92,143 +92,185 @@ int X509_REQ_print(BIO *bp, X509_REQ *x) STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(X509_EXTENSION) *exts; char str[128]; + char mlch = ' '; + int nmindent = 0; + + if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mlch = '\n'; + nmindent = 12; + } + + if(nmflags == X509_FLAG_COMPAT) + nmindent = 16; + ri=x->req_info; - sprintf(str,"Certificate Request:\n"); - if (BIO_puts(bp,str) <= 0) goto err; - sprintf(str,"%4sData:\n",""); - if (BIO_puts(bp,str) <= 0) goto err; - - neg=(ri->version->type == V_ASN1_NEG_INTEGER)?"-":""; - l=0; - for (i=0; iversion->length; i++) - { l<<=8; l+=ri->version->data[i]; } - sprintf(str,"%8sVersion: %s%lu (%s0x%lx)\n","",neg,l,neg,l); - if (BIO_puts(bp,str) <= 0) goto err; - sprintf(str,"%8sSubject: ",""); - if (BIO_puts(bp,str) <= 0) goto err; - - X509_NAME_print(bp,ri->subject,16); - sprintf(str,"\n%8sSubject Public Key Info:\n",""); - if (BIO_puts(bp,str) <= 0) goto err; - i=OBJ_obj2nid(ri->pubkey->algor->algorithm); - sprintf(str,"%12sPublic Key Algorithm: %s\n","", - (i == NID_undef)?"UNKNOWN":OBJ_nid2ln(i)); - if (BIO_puts(bp,str) <= 0) goto err; - - pkey=X509_REQ_get_pubkey(x); -#ifndef OPENSSL_NO_RSA - if (pkey != NULL && pkey->type == EVP_PKEY_RSA) + if(!(cflag & X509_FLAG_NO_HEADER)) { - BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", - BN_num_bits(pkey->pkey.rsa->n)); - RSA_print(bp,pkey->pkey.rsa,16); + if (BIO_write(bp,"Certificate Request:\n",21) <= 0) goto err; + if (BIO_write(bp," Data:\n",10) <= 0) goto err; } - else -#endif -#ifndef OPENSSL_NO_DSA - if (pkey != NULL && pkey->type == EVP_PKEY_DSA) + if(!(cflag & X509_FLAG_NO_VERSION)) { - BIO_printf(bp,"%12sDSA Public Key:\n",""); - DSA_print(bp,pkey->pkey.dsa,16); + neg=(ri->version->type == V_ASN1_NEG_INTEGER)?"-":""; + l=0; + for (i=0; iversion->length; i++) + { l<<=8; l+=ri->version->data[i]; } + sprintf(str,"%8sVersion: %s%lu (%s0x%lx)\n","",neg,l,neg,l); + if (BIO_puts(bp,str) <= 0) goto err; } - else -#endif - BIO_printf(bp,"%12sUnknown Public Key:\n",""); + if(!(cflag & X509_FLAG_NO_SUBJECT)) + { + if (BIO_printf(bp," Subject:%c",mlch) <= 0) goto err; + if (X509_NAME_print_ex(bp,ri->subject,nmindent, nmflags) < 0) goto err; + if (BIO_write(bp,"\n",1) <= 0) goto err; + } + if(!(cflag & X509_FLAG_NO_PUBKEY)) + { + if (BIO_write(bp," Subject Public Key Info:\n",33) <= 0) + goto err; + if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; - if (pkey != NULL) - EVP_PKEY_free(pkey); + pkey=X509_REQ_get_pubkey(x); + if (pkey == NULL) + { + BIO_printf(bp,"%12sUnable to load Public Key\n",""); + ERR_print_errors(bp); + } + else +#ifndef OPENSSL_NO_RSA + if (pkey->type == EVP_PKEY_RSA) + { + BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", + BN_num_bits(pkey->pkey.rsa->n)); + RSA_print(bp,pkey->pkey.rsa,16); + } + else +#endif +#ifndef OPENSSL_NO_DSA + if (pkey->type == EVP_PKEY_DSA) + { + BIO_printf(bp,"%12sDSA Public Key:\n",""); + DSA_print(bp,pkey->pkey.dsa,16); + } + else +#endif + BIO_printf(bp,"%12sUnknown Public Key:\n",""); - /* may not be */ - sprintf(str,"%8sAttributes:\n",""); - if (BIO_puts(bp,str) <= 0) goto err; + EVP_PKEY_free(pkey); + } - sk=x->req_info->attributes; - if (sk_X509_ATTRIBUTE_num(sk) == 0) + if(!(cflag & X509_FLAG_NO_ATTRIBUTES)) { - sprintf(str,"%12sa0:00\n",""); + /* may not be */ + sprintf(str,"%8sAttributes:\n",""); if (BIO_puts(bp,str) <= 0) goto err; - } - else - { - for (i=0; ireq_info->attributes; + if (sk_X509_ATTRIBUTE_num(sk) == 0) { - ASN1_TYPE *at; - X509_ATTRIBUTE *a; - ASN1_BIT_STRING *bs=NULL; - ASN1_TYPE *t; - int j,type=0,count=1,ii=0; - - a=sk_X509_ATTRIBUTE_value(sk,i); - if(X509_REQ_extension_nid(OBJ_obj2nid(a->object))) - continue; - sprintf(str,"%12s",""); + sprintf(str,"%12sa0:00\n",""); if (BIO_puts(bp,str) <= 0) goto err; - if ((j=i2a_ASN1_OBJECT(bp,a->object)) > 0) + } + else { - if (a->single) + for (i=0; ivalue.single; - type=t->type; - bs=t->value.bit_string; - } - else + ASN1_TYPE *at; + X509_ATTRIBUTE *a; + ASN1_BIT_STRING *bs=NULL; + ASN1_TYPE *t; + int j,type=0,count=1,ii=0; + + a=sk_X509_ATTRIBUTE_value(sk,i); + if(X509_REQ_extension_nid(OBJ_obj2nid(a->object))) + continue; + sprintf(str,"%12s",""); + if (BIO_puts(bp,str) <= 0) goto err; + if ((j=i2a_ASN1_OBJECT(bp,a->object)) > 0) { - ii=0; - count=sk_ASN1_TYPE_num(a->value.set); + if (a->single) + { + t=a->value.single; + type=t->type; + bs=t->value.bit_string; + } + else + { + ii=0; + count=sk_ASN1_TYPE_num(a->value.set); get_next: - at=sk_ASN1_TYPE_value(a->value.set,ii); - type=at->type; - bs=at->value.asn1_string; + at=sk_ASN1_TYPE_value(a->value.set,ii); + type=at->type; + bs=at->value.asn1_string; + } + } + for (j=25-j; j>0; j--) + if (BIO_write(bp," ",1) != 1) goto err; + if (BIO_puts(bp,":") <= 0) goto err; + if ( (type == V_ASN1_PRINTABLESTRING) || + (type == V_ASN1_T61STRING) || + (type == V_ASN1_IA5STRING)) + { + if (BIO_write(bp,(char *)bs->data,bs->length) + != bs->length) + goto err; + BIO_puts(bp,"\n"); + } + else + { + BIO_puts(bp,"unable to print attribute\n"); + } + if (++ii < count) goto get_next; } } - for (j=25-j; j>0; j--) - if (BIO_write(bp," ",1) != 1) goto err; - if (BIO_puts(bp,":") <= 0) goto err; - if ( (type == V_ASN1_PRINTABLESTRING) || - (type == V_ASN1_T61STRING) || - (type == V_ASN1_IA5STRING)) + } + if(!(cflag & X509_FLAG_NO_ATTRIBUTES)) + { + exts = X509_REQ_get_extensions(x); + if(exts) + { + BIO_printf(bp,"%8sRequested Extensions:\n",""); + for (i=0; idata,bs->length) - != bs->length) + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + int j; + ex=sk_X509_EXTENSION_value(exts, i); + if (BIO_printf(bp,"%12s","") <= 0) goto err; + obj=X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bp,obj); + j=X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp,": %s\n",j?"critical":"","") <= 0) goto err; - BIO_puts(bp,"\n"); - } - else - { - BIO_puts(bp,"unable to print attribute\n"); + if(!X509V3_EXT_print(bp, ex, 0, 16)) + { + BIO_printf(bp, "%16s", ""); + M_ASN1_OCTET_STRING_print(bp,ex->value); + } + if (BIO_write(bp,"\n",1) <= 0) goto err; } - if (++ii < count) goto get_next; + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } } - exts = X509_REQ_get_extensions(x); - if(exts) { - BIO_printf(bp,"%8sRequested Extensions:\n",""); - for (i=0; ivalue); - } - if (BIO_write(bp,"\n",1) <= 0) goto err; + if(!(cflag & X509_FLAG_NO_SIGDUMP)) + { + if(!X509_signature_print(bp, x->sig_alg, x->signature)) goto err; } - sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); - } - - if(!X509_signature_print(bp, x->sig_alg, x->signature)) goto err; return(1); err: X509err(X509_F_X509_REQ_PRINT,ERR_R_BUF_LIB); return(0); } + +int X509_REQ_print(BIO *bp, X509_REQ *x) + { + return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); + } diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 0fc1f421e2..f87c08793a 100644 --- a/src/lib/libcrypto/asn1/tasn_dec.c +++ b/src/lib/libcrypto/asn1/tasn_dec.c @@ -913,10 +913,10 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *i ctx->ptag = ptag; ctx->hdrlen = p - q; ctx->valid = 1; - /* If definite length, length + header can't exceed total - * amount of data available. + /* If definite length, and no error, length + + * header can't exceed total amount of data available. */ - if(!(i & 1) && ((plen + ctx->hdrlen) > len)) { + if(!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); asn1_tlc_clear(ctx); return 0; diff --git a/src/lib/libcrypto/bio/b_print.c b/src/lib/libcrypto/bio/b_print.c index 3ce1290772..80c9cb69db 100644 --- a/src/lib/libcrypto/bio/b_print.c +++ b/src/lib/libcrypto/bio/b_print.c @@ -109,7 +109,7 @@ * o ... (for OpenSSL) */ -#if HAVE_LONG_DOUBLE +#ifdef HAVE_LONG_DOUBLE #define LDOUBLE long double #else #define LDOUBLE double diff --git a/src/lib/libcrypto/bn/bn.h b/src/lib/libcrypto/bn/bn.h index 1eaf879553..b40682f831 100644 --- a/src/lib/libcrypto/bn/bn.h +++ b/src/lib/libcrypto/bn/bn.h @@ -430,7 +430,7 @@ int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b, int BN_from_montgomery(BIGNUM *r,const 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); +int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,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); diff --git a/src/lib/libcrypto/cryptlib.c b/src/lib/libcrypto/cryptlib.c index d301b376f7..612b3b93b4 100644 --- a/src/lib/libcrypto/cryptlib.c +++ b/src/lib/libcrypto/cryptlib.c @@ -492,11 +492,3 @@ BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, #endif #endif - -void OpenSSLDie(const char *file,int line,const char *assertion) - { - fprintf(stderr,"%s(%d): OpenSSL internal error, assertion failed: %s\n", - file,line,assertion); - abort(); - } - diff --git a/src/lib/libcrypto/cryptlib.h b/src/lib/libcrypto/cryptlib.h index 985a6d377c..88e4ae509f 100644 --- a/src/lib/libcrypto/cryptlib.h +++ b/src/lib/libcrypto/cryptlib.h @@ -93,10 +93,6 @@ extern "C" { #define DECIMAL_SIZE(type) ((sizeof(type)*8+2)/3+1) #define HEX_SIZE(type) ((sizeof(type)*2) -/* die if we have to */ -void OpenSSLDie(const char *file,int line,const char *assertion); -#define die(e) ((e) ? (void)0 : OpenSSLDie(__FILE__, __LINE__, #e)) - #ifdef __cplusplus } #endif diff --git a/src/lib/libcrypto/des/ecb_enc.c b/src/lib/libcrypto/des/ecb_enc.c index 4650f2fa0f..1b70f68806 100644 --- a/src/lib/libcrypto/des/ecb_enc.c +++ b/src/lib/libcrypto/des/ecb_enc.c @@ -57,6 +57,7 @@ */ #include "des_locl.h" +#include "des_ver.h" #include "spr.h" #include diff --git a/src/lib/libcrypto/des/set_key.c b/src/lib/libcrypto/des/set_key.c index 683916e71b..143008ed9c 100644 --- a/src/lib/libcrypto/des/set_key.c +++ b/src/lib/libcrypto/des/set_key.c @@ -342,7 +342,7 @@ void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule) register DES_LONG *k; register int i; -#if OPENBSD_DEV_CRYPTO +#ifdef OPENBSD_DEV_CRYPTO memcpy(schedule->key,key,sizeof schedule->key); schedule->session=NULL; #endif diff --git a/src/lib/libcrypto/doc/DH_set_method.pod b/src/lib/libcrypto/doc/DH_set_method.pod index d990bf8786..73261fc467 100644 --- a/src/lib/libcrypto/doc/DH_set_method.pod +++ b/src/lib/libcrypto/doc/DH_set_method.pod @@ -2,7 +2,7 @@ =head1 NAME -DH_set_default_openssl_method, DH_get_default_openssl_method, +DH_set_default_method, DH_get_default_method, DH_set_method, DH_new_method, DH_OpenSSL - select DH method =head1 SYNOPSIS @@ -10,45 +10,47 @@ DH_set_method, DH_new_method, DH_OpenSSL - select DH method #include #include - void DH_set_default_openssl_method(DH_METHOD *meth); + void DH_set_default_method(const DH_METHOD *meth); - DH_METHOD *DH_get_default_openssl_method(void); + const DH_METHOD *DH_get_default_method(void); - int DH_set_method(DH *dh, ENGINE *engine); + int DH_set_method(DH *dh, const DH_METHOD *meth); DH *DH_new_method(ENGINE *engine); - DH_METHOD *DH_OpenSSL(void); + const DH_METHOD *DH_OpenSSL(void); =head1 DESCRIPTION A B specifies the functions that OpenSSL uses for Diffie-Hellman operations. By modifying the method, alternative implementations -such as hardware accelerators may be used. - -Initially, the default is to use the OpenSSL internal implementation. -DH_OpenSSL() returns a pointer to that method. - -DH_set_default_openssl_method() makes B the default method for all DH -structures created later. B This is true only whilst the default engine -for Diffie-Hellman operations remains as "openssl". ENGINEs provide an -encapsulation for implementations of one or more algorithms, and all the DH -functions mentioned here operate within the scope of the default -"openssl" engine. - -DH_get_default_openssl_method() returns a pointer to the current default -method for the "openssl" engine. - -DH_set_method() selects B as the engine that will be responsible for -all operations using the structure B. If this function completes successfully, -then the B structure will have its own functional reference of B, so -the caller should remember to free their own reference to B when they are -finished with it. NB: An ENGINE's DH_METHOD can be retrieved (or set) by -ENGINE_get_DH() or ENGINE_set_DH(). - -DH_new_method() allocates and initializes a DH structure so that -B will be used for the DH operations. If B is NULL, -the default engine for Diffie-Hellman opertaions is used. +such as hardware accelerators may be used. IMPORTANT: See the NOTES section for +important information about how these DH API functions are affected by the use +of B API calls. + +Initially, the default DH_METHOD is the OpenSSL internal implementation, as +returned by DH_OpenSSL(). + +DH_set_default_method() makes B the default method for all DH +structures created later. B: This is true only whilst no ENGINE has been set +as a default for DH, so this function is no longer recommended. + +DH_get_default_method() returns a pointer to the current default DH_METHOD. +However, the meaningfulness of this result is dependant on whether the ENGINE +API is being used, so this function is no longer recommended. + +DH_set_method() selects B to perform all operations using the key B. +This will replace the DH_METHOD used by the DH key and if the previous method +was supplied by an ENGINE, the handle to that ENGINE will be released during the +change. It is possible to have DH keys that only work with certain DH_METHOD +implementations (eg. from an ENGINE module that supports embedded +hardware-protected keys), and in such cases attempting to change the DH_METHOD +for the key can have unexpected results. + +DH_new_method() allocates and initializes a DH structure so that B will +be used for the DH operations. If B is NULL, the default ENGINE for DH +operations is used, and if no default ENGINE is set, the DH_METHOD controlled by +DH_set_default_method() is used. =head1 THE DH_METHOD STRUCTURE @@ -82,17 +84,28 @@ the default engine for Diffie-Hellman opertaions is used. =head1 RETURN VALUES -DH_OpenSSL() and DH_get_default_openssl_method() return pointers to the -respective Bs. +DH_OpenSSL() and DH_get_default_method() return pointers to the respective +Bs. + +DH_set_default_method() returns no value. + +DH_set_method() returns non-zero if the provided B was successfully set as +the method for B (including unloading the ENGINE handle if the previous +method was supplied by an ENGINE). -DH_set_default_openssl_method() returns no value. +DH_new_method() returns NULL and sets an error code that can be obtained by +L if the allocation fails. Otherwise it +returns a pointer to the newly allocated structure. -DH_set_method() returns non-zero if the ENGINE associated with B -was successfully changed to B. +=head1 NOTES -DH_new_method() returns NULL and sets an error code that can be -obtained by L if the allocation fails. -Otherwise it returns a pointer to the newly allocated structure. +As of version 0.9.7, DH_METHOD implementations are grouped together with other +algorithmic APIs (eg. RSA_METHOD, EVP_CIPHER, etc) in B modules. If a +default ENGINE is specified for DH functionality using an ENGINE API function, +that will override any DH defaults set using the DH API (ie. +DH_set_default_method()). For this reason, the ENGINE API is the recommended way +to control default implementations for use in DH and other cryptographic +algorithms. =head1 SEE ALSO @@ -103,9 +116,14 @@ L, L DH_set_default_method(), DH_get_default_method(), DH_set_method(), DH_new_method() and DH_OpenSSL() were added in OpenSSL 0.9.4. -DH_set_default_openssl_method() and DH_get_default_openssl_method() -replaced DH_set_default_method() and DH_get_default_method() respectively, -and DH_set_method() and DH_new_method() were altered to use Bs -rather than Bs during development of OpenSSL 0.9.6. +DH_set_default_openssl_method() and DH_get_default_openssl_method() replaced +DH_set_default_method() and DH_get_default_method() respectively, and +DH_set_method() and DH_new_method() were altered to use Bs rather than +Bs during development of the engine version of OpenSSL 0.9.6. For +0.9.7, the handling of defaults in the ENGINE API was restructured so that this +change was reversed, and behaviour of the other functions resembled more closely +the previous behaviour. The behaviour of defaults in the ENGINE API now +transparently overrides the behaviour of defaults in the DH API without +requiring changing these function prototypes. =cut diff --git a/src/lib/libcrypto/doc/DSA_dup_DH.pod b/src/lib/libcrypto/doc/DSA_dup_DH.pod index 29cb1075d1..fdfe125ab0 100644 --- a/src/lib/libcrypto/doc/DSA_dup_DH.pod +++ b/src/lib/libcrypto/doc/DSA_dup_DH.pod @@ -8,7 +8,7 @@ DSA_dup_DH - create a DH structure out of DSA structure #include - DH * DSA_dup_DH(DSA *r); + DH * DSA_dup_DH(const DSA *r); =head1 DESCRIPTION diff --git a/src/lib/libcrypto/doc/DSA_new.pod b/src/lib/libcrypto/doc/DSA_new.pod index 7dde54445b..546146d9de 100644 --- a/src/lib/libcrypto/doc/DSA_new.pod +++ b/src/lib/libcrypto/doc/DSA_new.pod @@ -14,7 +14,8 @@ DSA_new, DSA_free - allocate and free DSA objects =head1 DESCRIPTION -DSA_new() allocates and initializes a B structure. +DSA_new() allocates and initializes a B structure. It is equivalent to +calling DSA_new_method(NULL). DSA_free() frees the B structure and its components. The values are erased before the memory is returned to the system. diff --git a/src/lib/libcrypto/doc/DSA_set_method.pod b/src/lib/libcrypto/doc/DSA_set_method.pod index 36a1052d27..bc3cfb1f0a 100644 --- a/src/lib/libcrypto/doc/DSA_set_method.pod +++ b/src/lib/libcrypto/doc/DSA_set_method.pod @@ -2,7 +2,7 @@ =head1 NAME -DSA_set_default_openssl_method, DSA_get_default_openssl_method, +DSA_set_default_method, DSA_get_default_method, DSA_set_method, DSA_new_method, DSA_OpenSSL - select DSA method =head1 SYNOPSIS @@ -10,11 +10,11 @@ DSA_set_method, DSA_new_method, DSA_OpenSSL - select DSA method #include #include - void DSA_set_default_openssl_method(DSA_METHOD *meth); + void DSA_set_default_method(const DSA_METHOD *meth); - DSA_METHOD *DSA_get_default_openssl_method(void); + const DSA_METHOD *DSA_get_default_method(void); - int DSA_set_method(DSA *dsa, ENGINE *engine); + int DSA_set_method(DSA *dsa, const DSA_METHOD *meth); DSA *DSA_new_method(ENGINE *engine); @@ -24,26 +24,35 @@ DSA_set_method, DSA_new_method, DSA_OpenSSL - select DSA method A B specifies the functions that OpenSSL uses for DSA operations. By modifying the method, alternative implementations -such as hardware accelerators may be used. - -Initially, the default is to use the OpenSSL internal implementation. -DSA_OpenSSL() returns a pointer to that method. - -DSA_set_default_openssl_method() makes B the default method for -all DSA structures created later. B This is true only whilst the -default engine for DSA operations remains as "openssl". ENGINEs -provide an encapsulation for implementations of one or more algorithms at a -time, and all the DSA functions mentioned here operate within the scope -of the default "openssl" engine. - -DSA_get_default_openssl_method() returns a pointer to the current default -method for the "openssl" engine. - -DSA_set_method() selects B for all operations using the structure B. - -DSA_new_method() allocates and initializes a DSA structure so that -B will be used for the DSA operations. If B is NULL, -the default engine for DSA operations is used. +such as hardware accelerators may be used. IMPORTANT: See the NOTES section for +important information about how these DSA API functions are affected by the use +of B API calls. + +Initially, the default DSA_METHOD is the OpenSSL internal implementation, +as returned by DSA_OpenSSL(). + +DSA_set_default_method() makes B the default method for all DSA +structures created later. B: This is true only whilst no ENGINE has +been set as a default for DSA, so this function is no longer recommended. + +DSA_get_default_method() returns a pointer to the current default +DSA_METHOD. However, the meaningfulness of this result is dependant on +whether the ENGINE API is being used, so this function is no longer +recommended. + +DSA_set_method() selects B to perform all operations using the key +B. This will replace the DSA_METHOD used by the DSA key and if the +previous method was supplied by an ENGINE, the handle to that ENGINE will +be released during the change. It is possible to have DSA keys that only +work with certain DSA_METHOD implementations (eg. from an ENGINE module +that supports embedded hardware-protected keys), and in such cases +attempting to change the DSA_METHOD for the key can have unexpected +results. + +DSA_new_method() allocates and initializes a DSA structure so that B +will be used for the DSA operations. If B is NULL, the default engine +for DSA operations is used, and if no default ENGINE is set, the DSA_METHOD +controlled by DSA_set_default_method() is used. =head1 THE DSA_METHOD STRUCTURE @@ -89,18 +98,29 @@ struct =head1 RETURN VALUES -DSA_OpenSSL() and DSA_get_default_openssl_method() return pointers to the -respective Bs. +DSA_OpenSSL() and DSA_get_default_method() return pointers to the respective +Bs. -DSA_set_default_openssl_method() returns no value. +DSA_set_default_method() returns no value. -DSA_set_method() returns non-zero if the ENGINE associated with B -was successfully changed to B. +DSA_set_method() returns non-zero if the provided B was successfully set as +the method for B (including unloading the ENGINE handle if the previous +method was supplied by an ENGINE). DSA_new_method() returns NULL and sets an error code that can be obtained by L if the allocation fails. Otherwise it returns a pointer to the newly allocated structure. +=head1 NOTES + +As of version 0.9.7, DSA_METHOD implementations are grouped together with other +algorithmic APIs (eg. RSA_METHOD, EVP_CIPHER, etc) in B modules. If a +default ENGINE is specified for DSA functionality using an ENGINE API function, +that will override any DSA defaults set using the DSA API (ie. +DSA_set_default_method()). For this reason, the ENGINE API is the recommended way +to control default implementations for use in DSA and other cryptographic +algorithms. + =head1 SEE ALSO L, L @@ -110,9 +130,14 @@ L, L DSA_set_default_method(), DSA_get_default_method(), DSA_set_method(), DSA_new_method() and DSA_OpenSSL() were added in OpenSSL 0.9.4. -DSA_set_default_openssl_method() and DSA_get_default_openssl_method() -replaced DSA_set_default_method() and DSA_get_default_method() respectively, -and DSA_set_method() and DSA_new_method() were altered to use Bs -rather than Bs during development of OpenSSL 0.9.6. +DSA_set_default_openssl_method() and DSA_get_default_openssl_method() replaced +DSA_set_default_method() and DSA_get_default_method() respectively, and +DSA_set_method() and DSA_new_method() were altered to use Bs rather than +Bs during development of the engine version of OpenSSL 0.9.6. For +0.9.7, the handling of defaults in the ENGINE API was restructured so that this +change was reversed, and behaviour of the other functions resembled more closely +the previous behaviour. The behaviour of defaults in the ENGINE API now +transparently overrides the behaviour of defaults in the DSA API without +requiring changing these function prototypes. =cut diff --git a/src/lib/libcrypto/doc/DSA_size.pod b/src/lib/libcrypto/doc/DSA_size.pod index 23b6320a4d..ba4f650361 100644 --- a/src/lib/libcrypto/doc/DSA_size.pod +++ b/src/lib/libcrypto/doc/DSA_size.pod @@ -8,7 +8,7 @@ DSA_size - get DSA signature size #include - int DSA_size(DSA *dsa); + int DSA_size(const DSA *dsa); =head1 DESCRIPTION diff --git a/src/lib/libcrypto/doc/EVP_SealInit.pod b/src/lib/libcrypto/doc/EVP_SealInit.pod index 0451eb648a..25ef07f7c7 100644 --- a/src/lib/libcrypto/doc/EVP_SealInit.pod +++ b/src/lib/libcrypto/doc/EVP_SealInit.pod @@ -73,4 +73,6 @@ L =head1 HISTORY +EVP_SealFinal() did not return a value before OpenSSL 0.9.7. + =cut diff --git a/src/lib/libcrypto/doc/RAND_set_rand_method.pod b/src/lib/libcrypto/doc/RAND_set_rand_method.pod index 464eba416d..c9bb6d9f27 100644 --- a/src/lib/libcrypto/doc/RAND_set_rand_method.pod +++ b/src/lib/libcrypto/doc/RAND_set_rand_method.pod @@ -8,22 +8,30 @@ RAND_set_rand_method, RAND_get_rand_method, RAND_SSLeay - select RAND method #include - void RAND_set_rand_method(RAND_METHOD *meth); + void RAND_set_rand_method(const RAND_METHOD *meth); - RAND_METHOD *RAND_get_rand_method(void); + const RAND_METHOD *RAND_get_rand_method(void); RAND_METHOD *RAND_SSLeay(void); =head1 DESCRIPTION -A B specifies the functions that OpenSSL uses for random -number generation. By modifying the method, alternative -implementations such as hardware RNGs may be used. Initially, the -default is to use the OpenSSL internal implementation. RAND_SSLeay() -returns a pointer to that method. +A B specifies the functions that OpenSSL uses for random number +generation. By modifying the method, alternative implementations such as +hardware RNGs may be used. IMPORTANT: See the NOTES section for important +information about how these RAND API functions are affected by the use of +B API calls. -RAND_set_rand_method() sets the RAND method to B. -RAND_get_rand_method() returns a pointer to the current method. +Initially, the default RAND_METHOD is the OpenSSL internal implementation, as +returned by RAND_SSLeay(). + +RAND_set_default_method() makes B the method for PRNG use. B: This is +true only whilst no ENGINE has been set as a default for RAND, so this function +is no longer recommended. + +RAND_get_default_method() returns a pointer to the current RAND_METHOD. +However, the meaningfulness of this result is dependant on whether the ENGINE +API is being used, so this function is no longer recommended. =head1 THE RAND_METHOD STRUCTURE @@ -47,13 +55,29 @@ Each component may be NULL if the function is not implemented. RAND_set_rand_method() returns no value. RAND_get_rand_method() and RAND_SSLeay() return pointers to the respective methods. +=head1 NOTES + +As of version 0.9.7, RAND_METHOD implementations are grouped together with other +algorithmic APIs (eg. RSA_METHOD, EVP_CIPHER, etc) in B modules. If a +default ENGINE is specified for RAND functionality using an ENGINE API function, +that will override any RAND defaults set using the RAND API (ie. +RAND_set_rand_method()). For this reason, the ENGINE API is the recommended way +to control default implementations for use in RAND and other cryptographic +algorithms. + =head1 SEE ALSO -L +L, L =head1 HISTORY RAND_set_rand_method(), RAND_get_rand_method() and RAND_SSLeay() are available in all versions of OpenSSL. +In the engine version of version 0.9.6, RAND_set_rand_method() was altered to +take an ENGINE pointer as its argument. As of version 0.9.7, that has been +reverted as the ENGINE API transparently overrides RAND defaults if used, +otherwise RAND API functions work as before. RAND_set_rand_engine() was also +introduced in version 0.9.7. + =cut diff --git a/src/lib/libcrypto/doc/RSA_new.pod b/src/lib/libcrypto/doc/RSA_new.pod index f16490ea6a..f0d996c40f 100644 --- a/src/lib/libcrypto/doc/RSA_new.pod +++ b/src/lib/libcrypto/doc/RSA_new.pod @@ -14,7 +14,8 @@ RSA_new, RSA_free - allocate and free RSA objects =head1 DESCRIPTION -RSA_new() allocates and initializes an B structure. +RSA_new() allocates and initializes an B structure. It is equivalent to +calling RSA_new_method(NULL). RSA_free() frees the B structure and its components. The key is erased before the memory is returned to the system. @@ -29,7 +30,8 @@ RSA_free() returns no value. =head1 SEE ALSO -L, L, L +L, L, L, +L =head1 HISTORY diff --git a/src/lib/libcrypto/doc/RSA_set_method.pod b/src/lib/libcrypto/doc/RSA_set_method.pod index 14917dd35f..0687c2242a 100644 --- a/src/lib/libcrypto/doc/RSA_set_method.pod +++ b/src/lib/libcrypto/doc/RSA_set_method.pod @@ -11,52 +11,64 @@ RSA_null_method, RSA_flags, RSA_new_method - select RSA method #include #include - void RSA_set_default_openssl_method(RSA_METHOD *meth); + void RSA_set_default_method(const RSA_METHOD *meth); - RSA_METHOD *RSA_get_default_openssl_method(void); + RSA_METHOD *RSA_get_default_method(void); - int RSA_set_method(RSA *rsa, ENGINE *engine); + int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); - RSA_METHOD *RSA_get_method(RSA *rsa); + RSA_METHOD *RSA_get_method(const RSA *rsa); RSA_METHOD *RSA_PKCS1_SSLeay(void); RSA_METHOD *RSA_null_method(void); - int RSA_flags(RSA *rsa); + int RSA_flags(const RSA *rsa); RSA *RSA_new_method(ENGINE *engine); =head1 DESCRIPTION An B specifies the functions that OpenSSL uses for RSA -operations. By modifying the method, alternative implementations -such as hardware accelerators may be used. - -Initially, the default is to use the OpenSSL internal implementation. -RSA_PKCS1_SSLeay() returns a pointer to that method. - -RSA_set_default_openssl_method() makes B the default method for all B -structures created later. B This is true only whilst the default engine -for RSA operations remains as "openssl". ENGINEs provide an -encapsulation for implementations of one or more algorithms at a time, and all -the RSA functions mentioned here operate within the scope of the default -"openssl" engine. - -RSA_get_default_openssl_method() returns a pointer to the current default -method for the "openssl" engine. - -RSA_set_method() selects B for all operations using the key -B. - -RSA_get_method() returns a pointer to the RSA_METHOD from the currently -selected ENGINE for B. - -RSA_flags() returns the B that are set for B's current method. +operations. By modifying the method, alternative implementations such as +hardware accelerators may be used. IMPORTANT: See the NOTES section for +important information about how these RSA API functions are affected by the +use of B API calls. + +Initially, the default RSA_METHOD is the OpenSSL internal implementation, +as returned by RSA_PKCS1_SSLeay(). + +RSA_set_default_method() makes B the default method for all RSA +structures created later. B: This is true only whilst no ENGINE has +been set as a default for RSA, so this function is no longer recommended. + +RSA_get_default_method() returns a pointer to the current default +RSA_METHOD. However, the meaningfulness of this result is dependant on +whether the ENGINE API is being used, so this function is no longer +recommended. + +RSA_set_method() selects B to perform all operations using the key +B. This will replace the RSA_METHOD used by the RSA key and if the +previous method was supplied by an ENGINE, the handle to that ENGINE will +be released during the change. It is possible to have RSA keys that only +work with certain RSA_METHOD implementations (eg. from an ENGINE module +that supports embedded hardware-protected keys), and in such cases +attempting to change the RSA_METHOD for the key can have unexpected +results. + +RSA_get_method() returns a pointer to the RSA_METHOD being used by B. +This method may or may not be supplied by an ENGINE implementation, but if +it is, the return value can only be guaranteed to be valid as long as the +RSA key itself is valid and does not have its implementation changed by +RSA_set_method(). + +RSA_flags() returns the B that are set for B's current +RSA_METHOD. See the BUGS section. RSA_new_method() allocates and initializes an RSA structure so that -B will be used for the RSA operations. If B is NULL, -the default engine for RSA operations is used. +B will be used for the RSA operations. If B is NULL, the +default ENGINE for RSA operations is used, and if no default ENGINE is set, +the RSA_METHOD controlled by RSA_set_default_method() is used. =head1 THE RSA_METHOD STRUCTURE @@ -121,22 +133,45 @@ the default engine for RSA operations is used. =head1 RETURN VALUES -RSA_PKCS1_SSLeay(), RSA_PKCS1_null_method(), RSA_get_default_openssl_method() +RSA_PKCS1_SSLeay(), RSA_PKCS1_null_method(), RSA_get_default_method() and RSA_get_method() return pointers to the respective RSA_METHODs. -RSA_set_default_openssl_method() returns no value. +RSA_set_default_method() returns no value. -RSA_set_method() selects B as the engine that will be responsible for -all operations using the structure B. If this function completes successfully, -then the B structure will have its own functional reference of B, so -the caller should remember to free their own reference to B when they are -finished with it. NB: An ENGINE's RSA_METHOD can be retrieved (or set) by -ENGINE_get_RSA() or ENGINE_set_RSA(). +RSA_set_method() returns a pointer to the old RSA_METHOD implementation +that was replaced. However, this return value should probably be ignored +because if it was supplied by an ENGINE, the pointer could be invalidated +at any time if the ENGINE is unloaded (in fact it could be unloaded as a +result of the RSA_set_method() function releasing its handle to the +ENGINE). For this reason, the return type may be replaced with a B +declaration in a future release. -RSA_new_method() returns NULL and sets an error code that can be -obtained by L if the allocation fails. Otherwise +RSA_new_method() returns NULL and sets an error code that can be obtained +by L if the allocation fails. Otherwise it returns a pointer to the newly allocated structure. +=head1 NOTES + +As of version 0.9.7, RSA_METHOD implementations are grouped together with +other algorithmic APIs (eg. DSA_METHOD, EVP_CIPHER, etc) into B +modules. If a default ENGINE is specified for RSA functionality using an +ENGINE API function, that will override any RSA defaults set using the RSA +API (ie. RSA_set_default_method()). For this reason, the ENGINE API is the +recommended way to control default implementations for use in RSA and other +cryptographic algorithms. + +=head1 BUGS + +The behaviour of RSA_flags() is a mis-feature that is left as-is for now +to avoid creating compatibility problems. RSA functionality, such as the +encryption functions, are controlled by the B value in the RSA key +itself, not by the B value in the RSA_METHOD attached to the RSA key +(which is what this function returns). If the flags element of an RSA key +is changed, the changes will be honoured by RSA functionality but will not +be reflected in the return value of the RSA_flags() function - in effect +RSA_flags() behaves more like an RSA_default_flags() function (which does +not currently exist). + =head1 SEE ALSO L, L @@ -149,8 +184,14 @@ well as the rsa_sign and rsa_verify components of RSA_METHOD were added in OpenSSL 0.9.4. RSA_set_default_openssl_method() and RSA_get_default_openssl_method() -replaced RSA_set_default_method() and RSA_get_default_method() respectively, -and RSA_set_method() and RSA_new_method() were altered to use Bs -rather than Bs during development of OpenSSL 0.9.6. +replaced RSA_set_default_method() and RSA_get_default_method() +respectively, and RSA_set_method() and RSA_new_method() were altered to use +Bs rather than Bs during development of the engine +version of OpenSSL 0.9.6. For 0.9.7, the handling of defaults in the ENGINE +API was restructured so that this change was reversed, and behaviour of the +other functions resembled more closely the previous behaviour. The +behaviour of defaults in the ENGINE API now transparently overrides the +behaviour of defaults in the RSA API without requiring changing these +function prototypes. =cut diff --git a/src/lib/libcrypto/doc/RSA_size.pod b/src/lib/libcrypto/doc/RSA_size.pod index b36b4d58d5..5b7f835f95 100644 --- a/src/lib/libcrypto/doc/RSA_size.pod +++ b/src/lib/libcrypto/doc/RSA_size.pod @@ -8,7 +8,7 @@ RSA_size - get RSA modulus size #include - int RSA_size(RSA *rsa); + int RSA_size(const RSA *rsa); =head1 DESCRIPTION diff --git a/src/lib/libcrypto/doc/dh.pod b/src/lib/libcrypto/doc/dh.pod index b4be4be405..c3ccd06207 100644 --- a/src/lib/libcrypto/doc/dh.pod +++ b/src/lib/libcrypto/doc/dh.pod @@ -12,20 +12,20 @@ dh - Diffie-Hellman key agreement DH * DH_new(void); void DH_free(DH *dh); - int DH_size(DH *dh); + int DH_size(const DH *dh); 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_check(const DH *dh, int *codes); int DH_generate_key(DH *dh); int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh); - void DH_set_default_openssl_method(DH_METHOD *meth); - DH_METHOD *DH_get_default_openssl_method(void); - int DH_set_method(DH *dh, ENGINE *engine); + void DH_set_default_method(const DH_METHOD *meth); + const DH_METHOD *DH_get_default_method(void); + int DH_set_method(DH *dh, const DH_METHOD *meth); DH *DH_new_method(ENGINE *engine); - DH_METHOD *DH_OpenSSL(void); + const DH_METHOD *DH_OpenSSL(void); int DH_get_ex_new_index(long argl, char *argp, int (*new_func)(), int (*dup_func)(), void (*free_func)()); @@ -33,10 +33,10 @@ dh - Diffie-Hellman key agreement char *DH_get_ex_data(DH *d, int idx); DH * d2i_DHparams(DH **a, unsigned char **pp, long length); - int i2d_DHparams(DH *a, unsigned char **pp); + int i2d_DHparams(const DH *a, unsigned char **pp); - int DHparams_print_fp(FILE *fp, DH *x); - int DHparams_print(BIO *bp, DH *x); + int DHparams_print_fp(FILE *fp, const DH *x); + int DHparams_print(BIO *bp, const DH *x); =head1 DESCRIPTION @@ -57,11 +57,20 @@ The B structure consists of several BIGNUM components. }; DH +Note that DH keys may use non-standard B implementations, +either directly or by the use of B modules. In some cases (eg. an +ENGINE providing support for hardware-embedded keys), these BIGNUM values +will not be used by the implementation or may be used for alternative data +storage. For this reason, applications should generally avoid using DH +structure elements directly and instead use API functions to query or +modify keys. + =head1 SEE ALSO L, L, L, L, -L, L, L, -L, L, +L, L, L, +L, L, +L, L, L, L, L diff --git a/src/lib/libcrypto/doc/dsa.pod b/src/lib/libcrypto/doc/dsa.pod index 82d7fb77cd..da07d2b930 100644 --- a/src/lib/libcrypto/doc/dsa.pod +++ b/src/lib/libcrypto/doc/dsa.pod @@ -12,13 +12,13 @@ dsa - Digital Signature Algorithm DSA * DSA_new(void); void DSA_free(DSA *dsa); - int DSA_size(DSA *dsa); + int DSA_size(const DSA *dsa); 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); - DH * DSA_dup_DH(DSA *r); + DH * DSA_dup_DH(const DSA *r); int DSA_generate_key(DSA *dsa); @@ -27,13 +27,13 @@ dsa - Digital Signature Algorithm int DSA_sign_setup(DSA *dsa, BN_CTX *ctx, BIGNUM **kinvp, BIGNUM **rp); int DSA_verify(int dummy, const unsigned char *dgst, int len, - unsigned char *sigbuf, int siglen, DSA *dsa); + const unsigned char *sigbuf, int siglen, DSA *dsa); - void DSA_set_default_openssl_method(DSA_METHOD *meth); - DSA_METHOD *DSA_get_default_openssl_method(void); - int DSA_set_method(DSA *dsa, ENGINE *engine); + void DSA_set_default_method(const DSA_METHOD *meth); + const DSA_METHOD *DSA_get_default_method(void); + int DSA_set_method(DSA *dsa, const DSA_METHOD *meth); DSA *DSA_new_method(ENGINE *engine); - DSA_METHOD *DSA_OpenSSL(void); + const DSA_METHOD *DSA_OpenSSL(void); int DSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), int (*dup_func)(), void (*free_func)()); @@ -42,7 +42,7 @@ dsa - Digital Signature Algorithm DSA_SIG *DSA_SIG_new(void); void DSA_SIG_free(DSA_SIG *a); - int i2d_DSA_SIG(DSA_SIG *a, unsigned char **pp); + int i2d_DSA_SIG(const 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); @@ -52,14 +52,14 @@ dsa - Digital Signature Algorithm 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); - int i2d_DSAPublicKey(DSA *a, unsigned char **pp); - int i2d_DSAPrivateKey(DSA *a, unsigned char **pp); - int i2d_DSAparams(DSA *a,unsigned char **pp); + int i2d_DSAPublicKey(const DSA *a, unsigned char **pp); + int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); + int i2d_DSAparams(const DSA *a,unsigned char **pp); - int DSAparams_print(BIO *bp, DSA *x); - int DSAparams_print_fp(FILE *fp, DSA *x); - int DSA_print(BIO *bp, DSA *x, int off); - int DSA_print_fp(FILE *bp, DSA *x, int off); + int DSAparams_print(BIO *bp, const DSA *x); + int DSAparams_print_fp(FILE *fp, const DSA *x); + int DSA_print(BIO *bp, const DSA *x, int off); + int DSA_print_fp(FILE *bp, const DSA *x, int off); =head1 DESCRIPTION @@ -85,6 +85,14 @@ The B structure consists of several BIGNUM components. In public keys, B is NULL. +Note that DSA keys may use non-standard B implementations, +either directly or by the use of B modules. In some cases (eg. an +ENGINE providing support for hardware-embedded keys), these BIGNUM values +will not be used by the implementation or may be used for alternative data +storage. For this reason, applications should generally avoid using DSA +structure elements directly and instead use API functions to query or +modify keys. + =head1 CONFORMING TO US Federal Information Processing Standard FIPS 186 (Digital Signature @@ -93,7 +101,8 @@ Standard, DSS), ANSI X9.30 =head1 SEE ALSO L, L, L, L, -L, L, L, +L, L, L, +L, L, L, L, diff --git a/src/lib/libcrypto/doc/engine.pod b/src/lib/libcrypto/doc/engine.pod new file mode 100644 index 0000000000..61e0264bb7 --- /dev/null +++ b/src/lib/libcrypto/doc/engine.pod @@ -0,0 +1,621 @@ +=pod + +=head1 NAME + +engine - ENGINE cryptographic module support + +=head1 SYNOPSIS + + #include + + ENGINE *ENGINE_get_first(void); + ENGINE *ENGINE_get_last(void); + ENGINE *ENGINE_get_next(ENGINE *e); + ENGINE *ENGINE_get_prev(ENGINE *e); + + int ENGINE_add(ENGINE *e); + int ENGINE_remove(ENGINE *e); + + ENGINE *ENGINE_by_id(const char *id); + + int ENGINE_init(ENGINE *e); + int ENGINE_finish(ENGINE *e); + + void ENGINE_load_openssl(void); + void ENGINE_load_dynamic(void); + void ENGINE_load_cswift(void); + void ENGINE_load_chil(void); + void ENGINE_load_atalla(void); + void ENGINE_load_nuron(void); + void ENGINE_load_ubsec(void); + void ENGINE_load_aep(void); + void ENGINE_load_sureware(void); + void ENGINE_load_4758cca(void); + void ENGINE_load_openbsd_dev_crypto(void); + void ENGINE_load_builtin_engines(void); + + void ENGINE_cleanup(void); + + ENGINE *ENGINE_get_default_RSA(void); + ENGINE *ENGINE_get_default_DSA(void); + ENGINE *ENGINE_get_default_DH(void); + ENGINE *ENGINE_get_default_RAND(void); + ENGINE *ENGINE_get_cipher_engine(int nid); + ENGINE *ENGINE_get_digest_engine(int nid); + + int ENGINE_set_default_RSA(ENGINE *e); + int ENGINE_set_default_DSA(ENGINE *e); + int ENGINE_set_default_DH(ENGINE *e); + int ENGINE_set_default_RAND(ENGINE *e); + int ENGINE_set_default_ciphers(ENGINE *e); + int ENGINE_set_default_digests(ENGINE *e); + int ENGINE_set_default_string(ENGINE *e, const char *list); + + int ENGINE_set_default(ENGINE *e, unsigned int flags); + + unsigned int ENGINE_get_table_flags(void); + void ENGINE_set_table_flags(unsigned int flags); + + int ENGINE_register_RSA(ENGINE *e); + void ENGINE_unregister_RSA(ENGINE *e); + void ENGINE_register_all_RSA(void); + int ENGINE_register_DSA(ENGINE *e); + void ENGINE_unregister_DSA(ENGINE *e); + void ENGINE_register_all_DSA(void); + int ENGINE_register_DH(ENGINE *e); + void ENGINE_unregister_DH(ENGINE *e); + void ENGINE_register_all_DH(void); + int ENGINE_register_RAND(ENGINE *e); + void ENGINE_unregister_RAND(ENGINE *e); + void ENGINE_register_all_RAND(void); + int ENGINE_register_ciphers(ENGINE *e); + void ENGINE_unregister_ciphers(ENGINE *e); + void ENGINE_register_all_ciphers(void); + int ENGINE_register_digests(ENGINE *e); + void ENGINE_unregister_digests(ENGINE *e); + void ENGINE_register_all_digests(void); + int ENGINE_register_complete(ENGINE *e); + int ENGINE_register_all_complete(void); + + int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); + int ENGINE_cmd_is_executable(ENGINE *e, int cmd); + int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f)(), int cmd_optional); + int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional); + + int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); + void *ENGINE_get_ex_data(const ENGINE *e, int idx); + + int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + + ENGINE *ENGINE_new(void); + int ENGINE_free(ENGINE *e); + + int ENGINE_set_id(ENGINE *e, const char *id); + int ENGINE_set_name(ENGINE *e, const char *name); + int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth); + int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth); + int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth); + int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth); + int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f); + int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); + int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); + int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); + int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f); + int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f); + int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f); + int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f); + int ENGINE_set_flags(ENGINE *e, int flags); + int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); + + const char *ENGINE_get_id(const ENGINE *e); + const char *ENGINE_get_name(const ENGINE *e); + const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e); + const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e); + const DH_METHOD *ENGINE_get_DH(const ENGINE *e); + const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); + ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e); + ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e); + ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e); + ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e); + ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); + ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); + ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e); + ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e); + const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid); + const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid); + int ENGINE_get_flags(const ENGINE *e); + const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); + + EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); + EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); + + void ENGINE_add_conf_module(void); + +=head1 DESCRIPTION + +These functions create, manipulate, and use cryptographic modules in the +form of B objects. These objects act as containers for +implementations of cryptographic algorithms, and support a +reference-counted mechanism to allow them to be dynamically loaded in and +out of the running application. + +The cryptographic functionality that can be provided by an B +implementation includes the following abstractions; + + RSA_METHOD - for providing alternative RSA implementations + DSA_METHOD, DH_METHOD, RAND_METHOD - alternative DSA, DH, and RAND + EVP_CIPHER - potentially multiple cipher algorithms (indexed by 'nid') + EVP_DIGEST - potentially multiple hash algorithms (indexed by 'nid') + key-loading - loading public and/or private EVP_PKEY keys + +=head2 Reference counting and handles + +Due to the modular nature of the ENGINE API, pointers to ENGINEs need to be +treated as handles - ie. not only as pointers, but also as references to +the underlying ENGINE object. Ie. you should obtain a new reference when +making copies of an ENGINE pointer if the copies will be used (and +released) independantly. + +ENGINE objects have two levels of reference-counting to match the way in +which the objects are used. At the most basic level, each ENGINE pointer is +inherently a B reference - you need a structural reference +simply to refer to the pointer value at all, as this kind of reference is +your guarantee that the structure can not be deallocated until you release +your reference. + +However, a structural reference provides no guarantee that the ENGINE has +been initiliased to be usable to perform any of its cryptographic +implementations - and indeed it's quite possible that most ENGINEs will not +initialised at all on standard setups, as ENGINEs are typically used to +support specialised hardware. To use an ENGINE's functionality, you need a +B reference. This kind of reference can be considered a +specialised form of structural reference, because each functional reference +implicitly contains a structural reference as well - however to avoid +difficult-to-find programming bugs, it is recommended to treat the two +kinds of reference independantly. If you have a functional reference to an +ENGINE, you have a guarantee that the ENGINE has been initialised ready to +perform cryptographic operations and will not be uninitialised or cleaned +up until after you have released your reference. + +We will discuss the two kinds of reference separately, including how to +tell which one you are dealing with at any given point in time (after all +they are both simply (ENGINE *) pointers, the difference is in the way they +are used). + +=head3 Structural references + +This basic type of reference is typically used for creating new ENGINEs +dynamically, iterating across OpenSSL's internal linked-list of loaded +ENGINEs, reading information about an ENGINE, etc. Essentially a structural +reference is sufficient if you only need to query or manipulate the data of +an ENGINE implementation rather than use its functionality. + +The ENGINE_new() function returns a structural reference to a new (empty) +ENGINE object. Other than that, structural references come from return +values to various ENGINE API functions such as; ENGINE_by_id(), +ENGINE_get_first(), ENGINE_get_last(), ENGINE_get_next(), +ENGINE_get_prev(). All structural references should be released by a +corresponding to call to the ENGINE_free() function - the ENGINE object +itself will only actually be cleaned up and deallocated when the last +structural reference is released. + +It should also be noted that many ENGINE API function calls that accept a +structural reference will internally obtain another reference - typically +this happens whenever the supplied ENGINE will be needed by OpenSSL after +the function has returned. Eg. the function to add a new ENGINE to +OpenSSL's internal list is ENGINE_add() - if this function returns success, +then OpenSSL will have stored a new structural reference internally so the +caller is still responsible for freeing their own reference with +ENGINE_free() when they are finished with it. In a similar way, some +functions will automatically release the structural reference passed to it +if part of the function's job is to do so. Eg. the ENGINE_get_next() and +ENGINE_get_prev() functions are used for iterating across the internal +ENGINE list - they will return a new structural reference to the next (or +previous) ENGINE in the list or NULL if at the end (or beginning) of the +list, but in either case the structural reference passed to the function is +released on behalf of the caller. + +To clarify a particular function's handling of references, one should +always consult that function's documentation "man" page, or failing that +the openssl/engine.h header file includes some hints. + +=head3 Functional references + +As mentioned, functional references exist when the cryptographic +functionality of an ENGINE is required to be available. A functional +reference can be obtained in one of two ways; from an existing structural +reference to the required ENGINE, or by asking OpenSSL for the default +operational ENGINE for a given cryptographic purpose. + +To obtain a functional reference from an existing structural reference, +call the ENGINE_init() function. This returns zero if the ENGINE was not +already operational and couldn't be successfully initialised (eg. lack of +system drivers, no special hardware attached, etc), otherwise it will +return non-zero to indicate that the ENGINE is now operational and will +have allocated a new B reference to the ENGINE. In this case, +the supplied ENGINE pointer is, from the point of the view of the caller, +both a structural reference and a functional reference - so if the caller +intends to use it as a functional reference it should free the structural +reference with ENGINE_free() first. If the caller wishes to use it only as +a structural reference (eg. if the ENGINE_init() call was simply to test if +the ENGINE seems available/online), then it should free the functional +reference; all functional references are released by the ENGINE_finish() +function. + +The second way to get a functional reference is by asking OpenSSL for a +default implementation for a given task, eg. by ENGINE_get_default_RSA(), +ENGINE_get_default_cipher_engine(), etc. These are discussed in the next +section, though they are not usually required by application programmers as +they are used automatically when creating and using the relevant +algorithm-specific types in OpenSSL, such as RSA, DSA, EVP_CIPHER_CTX, etc. + +=head2 Default implementations + +For each supported abstraction, the ENGINE code maintains an internal table +of state to control which implementations are available for a given +abstraction and which should be used by default. These implementations are +registered in the tables separated-out by an 'nid' index, because +abstractions like EVP_CIPHER and EVP_DIGEST support many distinct +algorithms and modes - ENGINEs will support different numbers and +combinations of these. In the case of other abstractions like RSA, DSA, +etc, there is only one "algorithm" so all implementations implicitly +register using the same 'nid' index. ENGINEs can be B into +these tables to make themselves available for use automatically by the +various abstractions, eg. RSA. For illustrative purposes, we continue with +the RSA example, though all comments apply similarly to the other +abstractions (they each get their own table and linkage to the +corresponding section of openssl code). + +When a new RSA key is being created, ie. in RSA_new_method(), a +"get_default" call will be made to the ENGINE subsystem to process the RSA +state table and return a functional reference to an initialised ENGINE +whose RSA_METHOD should be used. If no ENGINE should (or can) be used, it +will return NULL and the RSA key will operate with a NULL ENGINE handle by +using the conventional RSA implementation in OpenSSL (and will from then on +behave the way it used to before the ENGINE API existed - for details see +L). + +Each state table has a flag to note whether it has processed this +"get_default" query since the table was last modified, because to process +this question it must iterate across all the registered ENGINEs in the +table trying to initialise each of them in turn, in case one of them is +operational. If it returns a functional reference to an ENGINE, it will +also cache another reference to speed up processing future queries (without +needing to iterate across the table). Likewise, it will cache a NULL +response if no ENGINE was available so that future queries won't repeat the +same iteration unless the state table changes. This behaviour can also be +changed; if the ENGINE_TABLE_FLAG_NOINIT flag is set (using +ENGINE_set_table_flags()), no attempted initialisations will take place, +instead the only way for the state table to return a non-NULL ENGINE to the +"get_default" query will be if one is expressly set in the table. Eg. +ENGINE_set_default_RSA() does the same job as ENGINE_register_RSA() except +that it also sets the state table's cached response for the "get_default" +query. + +In the case of abstractions like EVP_CIPHER, where implementations are +indexed by 'nid', these flags and cached-responses are distinct for each +'nid' value. + +It is worth illustrating the difference between "registration" of ENGINEs +into these per-algorithm state tables and using the alternative +"set_default" functions. The latter handles both "registration" and also +setting the cached "default" ENGINE in each relevant state table - so +registered ENGINEs will only have a chance to be initialised for use as a +default if a default ENGINE wasn't already set for the same state table. +Eg. if ENGINE X supports cipher nids {A,B} and RSA, ENGINE Y supports +ciphers {A} and DSA, and the following code is executed; + + ENGINE_register_complete(X); + ENGINE_set_default(Y, ENGINE_METHOD_ALL); + e1 = ENGINE_get_default_RSA(); + e2 = ENGINE_get_cipher_engine(A); + e3 = ENGINE_get_cipher_engine(B); + e4 = ENGINE_get_default_DSA(); + e5 = ENGINE_get_cipher_engine(C); + +The results would be as follows; + + assert(e1 == X); + assert(e2 == Y); + assert(e3 == X); + assert(e4 == Y); + assert(e5 == NULL); + +=head2 Application requirements + +This section will explain the basic things an application programmer should +support to make the most useful elements of the ENGINE functionality +available to the user. The first thing to consider is whether the +programmer wishes to make alternative ENGINE modules available to the +application and user. OpenSSL maintains an internal linked list of +"visible" ENGINEs from which it has to operate - at start-up, this list is +empty and in fact if an application does not call any ENGINE API calls and +it uses static linking against openssl, then the resulting application +binary will not contain any alternative ENGINE code at all. So the first +consideration is whether any/all available ENGINE implementations should be +made visible to OpenSSL - this is controlled by calling the various "load" +functions, eg. + + /* Make the "dynamic" ENGINE available */ + void ENGINE_load_dynamic(void); + /* Make the CryptoSwift hardware acceleration support available */ + void ENGINE_load_cswift(void); + /* Make support for nCipher's "CHIL" hardware available */ + void ENGINE_load_chil(void); + ... + /* Make ALL ENGINE implementations bundled with OpenSSL available */ + void ENGINE_load_builtin_engines(void); + +Having called any of these functions, ENGINE objects would have been +dynamically allocated and populated with these implementations and linked +into OpenSSL's internal linked list. At this point it is important to +mention an important API function; + + void ENGINE_cleanup(void); + +If no ENGINE API functions are called at all in an application, then there +are no inherent memory leaks to worry about from the ENGINE functionality, +however if any ENGINEs are "load"ed, even if they are never registered or +used, it is necessary to use the ENGINE_cleanup() function to +correspondingly cleanup before program exit, if the caller wishes to avoid +memory leaks. This mechanism uses an internal callback registration table +so that any ENGINE API functionality that knows it requires cleanup can +register its cleanup details to be called during ENGINE_cleanup(). This +approach allows ENGINE_cleanup() to clean up after any ENGINE functionality +at all that your program uses, yet doesn't automatically create linker +dependencies to all possible ENGINE functionality - only the cleanup +callbacks required by the functionality you do use will be required by the +linker. + +The fact that ENGINEs are made visible to OpenSSL (and thus are linked into +the program and loaded into memory at run-time) does not mean they are +"registered" or called into use by OpenSSL automatically - that behaviour +is something for the application to have control over. Some applications +will want to allow the user to specify exactly which ENGINE they want used +if any is to be used at all. Others may prefer to load all support and have +OpenSSL automatically use at run-time any ENGINE that is able to +successfully initialise - ie. to assume that this corresponds to +acceleration hardware attached to the machine or some such thing. There are +probably numerous other ways in which applications may prefer to handle +things, so we will simply illustrate the consequences as they apply to a +couple of simple cases and leave developers to consider these and the +source code to openssl's builtin utilities as guides. + +=head3 Using a specific ENGINE implementation + +Here we'll assume an application has been configured by its user or admin +to want to use the "ACME" ENGINE if it is available in the version of +OpenSSL the application was compiled with. If it is available, it should be +used by default for all RSA, DSA, and symmetric cipher operation, otherwise +OpenSSL should use its builtin software as per usual. The following code +illustrates how to approach this; + + ENGINE *e; + const char *engine_id = "ACME"; + ENGINE_load_builtin_engines(); + e = ENGINE_by_id(engine_id); + if(!e) + /* the engine isn't available */ + return; + if(!ENGINE_init(e)) { + /* the engine couldn't initialise, release 'e' */ + ENGINE_free(e); + return; + } + if(!ENGINE_set_default_RSA(e)) + /* This should only happen when 'e' can't initialise, but the previous + * statement suggests it did. */ + abort(); + ENGINE_set_default_DSA(e); + ENGINE_set_default_ciphers(e); + /* Release the functional reference from ENGINE_init() */ + ENGINE_finish(e); + /* Release the structural reference from ENGINE_by_id() */ + ENGINE_free(e); + +=head3 Automatically using builtin ENGINE implementations + +Here we'll assume we want to load and register all ENGINE implementations +bundled with OpenSSL, such that for any cryptographic algorithm required by +OpenSSL - if there is an ENGINE that implements it and can be initialise, +it should be used. The following code illustrates how this can work; + + /* Load all bundled ENGINEs into memory and make them visible */ + ENGINE_load_builtin_engines(); + /* Register all of them for every algorithm they collectively implement */ + ENGINE_register_all_complete(); + +That's all that's required. Eg. the next time OpenSSL tries to set up an +RSA key, any bundled ENGINEs that implement RSA_METHOD will be passed to +ENGINE_init() and if any of those succeed, that ENGINE will be set as the +default for use with RSA from then on. + +=head2 Advanced configuration support + +There is a mechanism supported by the ENGINE framework that allows each +ENGINE implementation to define an arbitrary set of configuration +"commands" and expose them to OpenSSL and any applications based on +OpenSSL. This mechanism is entirely based on the use of name-value pairs +and and assumes ASCII input (no unicode or UTF for now!), so it is ideal if +applications want to provide a transparent way for users to provide +arbitrary configuration "directives" directly to such ENGINEs. It is also +possible for the application to dynamically interrogate the loaded ENGINE +implementations for the names, descriptions, and input flags of their +available "control commands", providing a more flexible configuration +scheme. However, if the user is expected to know which ENGINE device he/she +is using (in the case of specialised hardware, this goes without saying) +then applications may not need to concern themselves with discovering the +supported control commands and simply prefer to allow settings to passed +into ENGINEs exactly as they are provided by the user. + +Before illustrating how control commands work, it is worth mentioning what +they are typically used for. Broadly speaking there are two uses for +control commands; the first is to provide the necessary details to the +implementation (which may know nothing at all specific to the host system) +so that it can be initialised for use. This could include the path to any +driver or config files it needs to load, required network addresses, +smart-card identifiers, passwords to initialise password-protected devices, +logging information, etc etc. This class of commands typically needs to be +passed to an ENGINE B attempting to initialise it, ie. before +calling ENGINE_init(). The other class of commands consist of settings or +operations that tweak certain behaviour or cause certain operations to take +place, and these commands may work either before or after ENGINE_init(), or +in same cases both. ENGINE implementations should provide indications of +this in the descriptions attached to builtin control commands and/or in +external product documentation. + +=head3 Issuing control commands to an ENGINE + +Let's illustrate by example; a function for which the caller supplies the +name of the ENGINE it wishes to use, a table of string-pairs for use before +initialisation, and another table for use after initialisation. Note that +the string-pairs used for control commands consist of a command "name" +followed by the command "parameter" - the parameter could be NULL in some +cases but the name can not. This function should initialise the ENGINE +(issuing the "pre" commands beforehand and the "post" commands afterwards) +and set it as the default for everything except RAND and then return a +boolean success or failure. + + int generic_load_engine_fn(const char *engine_id, + const char **pre_cmds, int pre_num, + const char **post_cmds, int post_num) + { + ENGINE *e = ENGINE_by_id(engine_id); + if(!e) return 0; + while(pre_num--) { + if(!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) { + fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id, + pre_cmds[0], pre_cmds[1] ? pre_cmds[1] : "(NULL)"); + ENGINE_free(e); + return 0; + } + pre_cmds += 2; + } + if(!ENGINE_init(e)) { + fprintf(stderr, "Failed initialisation\n"); + ENGINE_free(e); + return 0; + } + /* ENGINE_init() returned a functional reference, so free the structural + * reference from ENGINE_by_id(). */ + ENGINE_free(e); + while(post_num--) { + if(!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) { + fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id, + post_cmds[0], post_cmds[1] ? post_cmds[1] : "(NULL)"); + ENGINE_finish(e); + return 0; + } + post_cmds += 2; + } + ENGINE_set_default(e, ENGINE_METHOD_ALL & ~ENGINE_METHOD_RAND); + /* Success */ + return 1; + } + +Note that ENGINE_ctrl_cmd_string() accepts a boolean argument that can +relax the semantics of the function - if set non-zero it will only return +failure if the ENGINE supported the given command name but failed while +executing it, if the ENGINE doesn't support the command name it will simply +return success without doing anything. In this case we assume the user is +only supplying commands specific to the given ENGINE so we set this to +FALSE. + +=head3 Discovering supported control commands + +It is possible to discover at run-time the names, numerical-ids, descriptions +and input parameters of the control commands supported from a structural +reference to any ENGINE. It is first important to note that some control +commands are defined by OpenSSL itself and it will intercept and handle these +control commands on behalf of the ENGINE, ie. the ENGINE's ctrl() handler is not +used for the control command. openssl/engine.h defines a symbol, +ENGINE_CMD_BASE, that all control commands implemented by ENGINEs from. Any +command value lower than this symbol is considered a "generic" command is +handled directly by the OpenSSL core routines. + +It is using these "core" control commands that one can discover the the control +commands implemented by a given ENGINE, specifically the commands; + + #define ENGINE_HAS_CTRL_FUNCTION 10 + #define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 + #define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 + #define ENGINE_CTRL_GET_CMD_FROM_NAME 13 + #define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 + #define ENGINE_CTRL_GET_NAME_FROM_CMD 15 + #define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 + #define ENGINE_CTRL_GET_DESC_FROM_CMD 17 + #define ENGINE_CTRL_GET_CMD_FLAGS 18 + +Whilst these commands are automatically processed by the OpenSSL framework code, +they use various properties exposed by each ENGINE by which to process these +queries. An ENGINE has 3 properties it exposes that can affect this behaviour; +it can supply a ctrl() handler, it can specify ENGINE_FLAGS_MANUAL_CMD_CTRL in +the ENGINE's flags, and it can expose an array of control command descriptions. +If an ENGINE specifies the ENGINE_FLAGS_MANUAL_CMD_CTRL flag, then it will +simply pass all these "core" control commands directly to the ENGINE's ctrl() +handler (and thus, it must have supplied one), so it is up to the ENGINE to +reply to these "discovery" commands itself. If that flag is not set, then the +OpenSSL framework code will work with the following rules; + + if no ctrl() handler supplied; + ENGINE_HAS_CTRL_FUNCTION returns FALSE (zero), + all other commands fail. + if a ctrl() handler was supplied but no array of control commands; + ENGINE_HAS_CTRL_FUNCTION returns TRUE, + all other commands fail. + if a ctrl() handler and array of control commands was supplied; + ENGINE_HAS_CTRL_FUNCTION returns TRUE, + all other commands proceed processing ... + +If the ENGINE's array of control commands is empty then all other commands will +fail, otherwise; ENGINE_CTRL_GET_FIRST_CMD_TYPE returns the identifier of +the first command supported by the ENGINE, ENGINE_GET_NEXT_CMD_TYPE takes the +identifier of a command supported by the ENGINE and returns the next command +identifier or fails if there are no more, ENGINE_CMD_FROM_NAME takes a string +name for a command and returns the corresponding identifier or fails if no such +command name exists, and the remaining commands take a command identifier and +return properties of the corresponding commands. All except +ENGINE_CTRL_GET_FLAGS return the string length of a command name or description, +or populate a supplied character buffer with a copy of the command name or +description. ENGINE_CTRL_GET_FLAGS returns a bitwise-OR'd mask of the following +possible values; + + #define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 + #define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 + #define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 + #define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 + +If the ENGINE_CMD_FLAG_INTERNAL flag is set, then any other flags are purely +informational to the caller - this flag will prevent the command being usable +for any higher-level ENGINE functions such as ENGINE_ctrl_cmd_string(). +"INTERNAL" commands are not intended to be exposed to text-based configuration +by applications, administrations, users, etc. These can support arbitrary +operations via ENGINE_ctrl(), including passing to and/or from the control +commands data of any arbitrary type. These commands are supported in the +discovery mechanisms simply to allow applications determinie if an ENGINE +supports certain specific commands it might want to use (eg. application "foo" +might query various ENGINEs to see if they implement "FOO_GET_VENDOR_LOGO_GIF" - +and ENGINE could therefore decide whether or not to support this "foo"-specific +extension). + +=head2 Future developments + +The ENGINE API and internal architecture is currently being reviewed. Slated for +possible release in 0.9.8 is support for transparent loading of "dynamic" +ENGINEs (built as self-contained shared-libraries). This would allow ENGINE +implementations to be provided independantly of OpenSSL libraries and/or +OpenSSL-based applications, and would also remove any requirement for +applications to explicitly use the "dynamic" ENGINE to bind to shared-library +implementations. + +=head1 SEE ALSO + +L, L, L, L, +L + +=cut diff --git a/src/lib/libcrypto/doc/evp.pod b/src/lib/libcrypto/doc/evp.pod index edf47dbde6..b3ca14314f 100644 --- a/src/lib/libcrypto/doc/evp.pod +++ b/src/lib/libcrypto/doc/evp.pod @@ -24,6 +24,13 @@ functions. The BI<...> functions provide message digests. Algorithms are loaded with OpenSSL_add_all_algorithms(3). +All the symmetric algorithms (ciphers) and digests can be replaced by ENGINE +modules providing alternative implementations. If ENGINE implementations of +ciphers or digests are registered as defaults, then the various EVP functions +will automatically use those implementations automatically in preference to +built in software implementations. For more information, consult the engine(3) +man page. + =head1 SEE ALSO L, @@ -32,6 +39,7 @@ L, L, L, L, -L +L, +L =cut diff --git a/src/lib/libcrypto/doc/rsa.pod b/src/lib/libcrypto/doc/rsa.pod index 2b93a12b65..45ac53ffc1 100644 --- a/src/lib/libcrypto/doc/rsa.pod +++ b/src/lib/libcrypto/doc/rsa.pod @@ -16,13 +16,17 @@ rsa - RSA public key cryptosystem unsigned char *to, RSA *rsa, int padding); int RSA_private_decrypt(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_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); - int RSA_size(RSA *rsa); + int RSA_size(const RSA *rsa); RSA *RSA_generate_key(int num, unsigned long e, void (*callback)(int,int,void *), void *cb_arg); @@ -32,13 +36,13 @@ rsa - RSA public key cryptosystem int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); void RSA_blinding_off(RSA *rsa); - void RSA_set_default_openssl_method(RSA_METHOD *meth); - RSA_METHOD *RSA_get_default_openssl_method(void); - int RSA_set_method(RSA *rsa, ENGINE *engine); - RSA_METHOD *RSA_get_method(RSA *rsa); + void RSA_set_default_method(const RSA_METHOD *meth); + const RSA_METHOD *RSA_get_default_method(void); + int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); + const RSA_METHOD *RSA_get_method(const RSA *rsa); RSA_METHOD *RSA_PKCS1_SSLeay(void); RSA_METHOD *RSA_null_method(void); - int RSA_flags(RSA *rsa); + int RSA_flags(const RSA *rsa); RSA *RSA_new_method(ENGINE *engine); int RSA_print(BIO *bp, RSA *x, int offset); @@ -49,11 +53,6 @@ rsa - RSA public key cryptosystem int RSA_set_ex_data(RSA *r,int idx,char *arg); char *RSA_get_ex_data(RSA *r, int idx); - 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_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa); @@ -90,6 +89,14 @@ B

, B, B, B and B may be B in private keys, but the RSA operations are much faster when these values are available. +Note that RSA keys may use non-standard B implementations, +either directly or by the use of B modules. In some cases (eg. an +ENGINE providing support for hardware-embedded keys), these BIGNUM values +will not be used by the implementation or may be used for alternative data +storage. For this reason, applications should generally avoid using RSA +structure elements directly and instead use API functions to query or +modify keys. + =head1 CONFORMING TO SSL, PKCS #1 v2.0 @@ -101,7 +108,7 @@ RSA was covered by a US patent which expired in September 2000. =head1 SEE ALSO L, L, L, L, -L, L, +L, L, L, L, L, L, L, diff --git a/src/lib/libcrypto/evp/evp_locl.h b/src/lib/libcrypto/evp/evp_locl.h index 7b088b4848..4d81a3bf4c 100644 --- a/src/lib/libcrypto/evp/evp_locl.h +++ b/src/lib/libcrypto/evp/evp_locl.h @@ -124,17 +124,17 @@ const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; } BLOCK_CIPHER_def1(cname, cbc, cbc, CBC, kstruct, nid, block_size, key_len, \ iv_len, flags, init_key, cleanup, set_asn1, get_asn1, ctrl) -#define BLOCK_CIPHER_def_cfb(cname, kstruct, nid, block_size, key_len, \ +#define BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, \ iv_len, cbits, flags, init_key, cleanup, \ set_asn1, get_asn1, ctrl) \ -BLOCK_CIPHER_def1(cname, cfb##cbits, cfb, CFB, kstruct, nid, block_size, \ +BLOCK_CIPHER_def1(cname, cfb##cbits, cfb, CFB, kstruct, nid, 1, \ key_len, iv_len, flags, init_key, cleanup, set_asn1, \ get_asn1, ctrl) -#define BLOCK_CIPHER_def_ofb(cname, kstruct, nid, block_size, key_len, \ +#define BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, \ iv_len, cbits, flags, init_key, cleanup, \ set_asn1, get_asn1, ctrl) \ -BLOCK_CIPHER_def1(cname, ofb##cbits, ofb, OFB, kstruct, nid, block_size, \ +BLOCK_CIPHER_def1(cname, ofb##cbits, ofb, OFB, kstruct, nid, 1, \ key_len, iv_len, flags, init_key, cleanup, set_asn1, \ get_asn1, ctrl) @@ -149,9 +149,9 @@ BLOCK_CIPHER_def1(cname, ecb, ecb, ECB, kstruct, nid, block_size, key_len, \ init_key, cleanup, set_asn1, get_asn1, ctrl) \ BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, iv_len, flags, \ init_key, cleanup, set_asn1, get_asn1, ctrl) \ -BLOCK_CIPHER_def_cfb(cname, kstruct, nid, block_size, key_len, iv_len, cbits, \ +BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, iv_len, cbits, \ flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \ -BLOCK_CIPHER_def_ofb(cname, kstruct, nid, block_size, key_len, iv_len, cbits, \ +BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, iv_len, cbits, \ flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \ BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, iv_len, flags, \ init_key, cleanup, set_asn1, get_asn1, ctrl) diff --git a/src/lib/libcrypto/objects/obj_dat.c b/src/lib/libcrypto/objects/obj_dat.c index 02c3719f04..ce779dc1b5 100644 --- a/src/lib/libcrypto/objects/obj_dat.c +++ b/src/lib/libcrypto/objects/obj_dat.c @@ -425,7 +425,7 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) a2d_ASN1_OBJECT(p,i,s,-1); p=buf; - op=d2i_ASN1_OBJECT(NULL,&p,i); + op=d2i_ASN1_OBJECT(NULL,&p,j); OPENSSL_free(buf); return op; } diff --git a/src/lib/libcrypto/pem/pem_lib.c b/src/lib/libcrypto/pem/pem_lib.c index 18b751a91a..a8db6ffbf5 100644 --- a/src/lib/libcrypto/pem/pem_lib.c +++ b/src/lib/libcrypto/pem/pem_lib.c @@ -366,8 +366,11 @@ err: memset(iv,0,sizeof(iv)); memset((char *)&ctx,0,sizeof(ctx)); memset(buf,0,PEM_BUFSIZE); - memset(data,0,(unsigned int)dsize); - OPENSSL_free(data); + if (data != NULL) + { + memset(data,0,(unsigned int)dsize); + OPENSSL_free(data); + } return(ret); } diff --git a/src/lib/libcrypto/pkcs12/p12_asn.c b/src/lib/libcrypto/pkcs12/p12_asn.c index c327bdba03..a3739fee1a 100644 --- a/src/lib/libcrypto/pkcs12/p12_asn.c +++ b/src/lib/libcrypto/pkcs12/p12_asn.c @@ -83,8 +83,8 @@ ASN1_ADB_TEMPLATE(bag_default) = ASN1_EXP(PKCS12_BAGS, value.other, ASN1_ANY, 0) ASN1_ADB(PKCS12_BAGS) = { ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.x509cert, ASN1_OCTET_STRING, 0)), - ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.x509crl, ASN1_OCTET_STRING, 0)), - ADB_ENTRY(NID_x509Certificate, ASN1_EXP(PKCS12_BAGS, value.sdsicert, ASN1_IA5STRING, 0)), + ADB_ENTRY(NID_x509Crl, ASN1_EXP(PKCS12_BAGS, value.x509crl, ASN1_OCTET_STRING, 0)), + ADB_ENTRY(NID_sdsiCertificate, ASN1_EXP(PKCS12_BAGS, value.sdsicert, ASN1_IA5STRING, 0)), } ASN1_ADB_END(PKCS12_BAGS, 0, type, 0, &bag_default_tt, NULL); ASN1_SEQUENCE(PKCS12_BAGS) = { @@ -98,7 +98,7 @@ ASN1_ADB_TEMPLATE(safebag_default) = ASN1_EXP(PKCS12_SAFEBAG, value.other, ASN1_ ASN1_ADB(PKCS12_SAFEBAG) = { ADB_ENTRY(NID_keyBag, ASN1_EXP(PKCS12_SAFEBAG, value.keybag, PKCS8_PRIV_KEY_INFO, 0)), - ADB_ENTRY(NID_pkcs8ShroudedKeyBag, ASN1_EXP(PKCS12_SAFEBAG, value.keybag, X509_SIG, 0)), + ADB_ENTRY(NID_pkcs8ShroudedKeyBag, ASN1_EXP(PKCS12_SAFEBAG, value.shkeybag, X509_SIG, 0)), ADB_ENTRY(NID_safeContentsBag, ASN1_EXP_SET_OF(PKCS12_SAFEBAG, value.safes, PKCS12_SAFEBAG, 0)), ADB_ENTRY(NID_certBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)), ADB_ENTRY(NID_crlBag, ASN1_EXP(PKCS12_SAFEBAG, value.bag, PKCS12_BAGS, 0)), diff --git a/src/lib/libcrypto/pkcs7/pk7_lib.c b/src/lib/libcrypto/pkcs7/pk7_lib.c index c00ed6833a..985b07245c 100644 --- a/src/lib/libcrypto/pkcs7/pk7_lib.c +++ b/src/lib/libcrypto/pkcs7/pk7_lib.c @@ -74,6 +74,13 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) if (nid == NID_pkcs7_signed) { ret=p7->detached=(int)larg; + if (ret && PKCS7_type_is_data(p7->d.sign->contents)) + { + ASN1_OCTET_STRING *os; + os=p7->d.sign->contents->d.data; + ASN1_OCTET_STRING_free(os); + p7->d.sign->contents->d.data = NULL; + } } else { diff --git a/src/lib/libcrypto/x509/x509.h b/src/lib/libcrypto/x509/x509.h index c75aa0c717..7095440d36 100644 --- a/src/lib/libcrypto/x509/x509.h +++ b/src/lib/libcrypto/x509/x509.h @@ -331,6 +331,7 @@ DECLARE_STACK_OF(X509_TRUST) #define X509_FLAG_NO_EXTENSIONS (1L << 8) #define X509_FLAG_NO_SIGDUMP (1L << 9) #define X509_FLAG_NO_AUX (1L << 10) +#define X509_FLAG_NO_ATTRIBUTES (1L << 11) /* Flags specific to X509_NAME_print_ex() */ @@ -1015,6 +1016,7 @@ int X509_print(BIO *bp,X509 *x); int X509_ocspid_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_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag); int X509_REQ_print(BIO *bp,X509_REQ *req); #endif diff --git a/src/lib/libssl/doc/openssl.txt b/src/lib/libssl/doc/openssl.txt index 5da519e7e4..432a17b66c 100644 --- a/src/lib/libssl/doc/openssl.txt +++ b/src/lib/libssl/doc/openssl.txt @@ -344,7 +344,7 @@ the extension. Examples: -subjectAltName=email:copy,email:my@other.address,URL:http://my.url.here/ +subjectAltName=email:copy,email:my@other.address,URI:http://my.url.here/ subjectAltName=email:my@other.address,RID:1.2.3.4 Issuer Alternative Name. diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c index 2699b5863b..2b58482484 100644 --- a/src/lib/libssl/s3_clnt.c +++ b/src/lib/libssl/s3_clnt.c @@ -546,7 +546,11 @@ static int ssl3_client_hello(SSL *s) *(p++)=i; if (i != 0) { - die(i <= sizeof s->session->session_id); + if (i > sizeof s->session->session_id) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } memcpy(p,s->session->session_id,i); p+=i; } @@ -1598,7 +1602,11 @@ static int ssl3_send_client_key_exchange(SSL *s) SSL_MAX_MASTER_KEY_LENGTH); EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); outl += padl; - die(outl <= sizeof epms); + if (outl > sizeof epms) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } EVP_CIPHER_CTX_cleanup(&ciph_ctx); /* KerberosWrapper.EncryptedPreMasterSecret */ diff --git a/src/lib/libssl/s3_srvr.c b/src/lib/libssl/s3_srvr.c index 782b57f57a..20d716fb1b 100644 --- a/src/lib/libssl/s3_srvr.c +++ b/src/lib/libssl/s3_srvr.c @@ -965,7 +965,11 @@ static int ssl3_send_server_hello(SSL *s) s->session->session_id_length=0; sl=s->session->session_id_length; - die(sl <= sizeof s->session->session_id); + if (sl > sizeof s->session->session_id) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + return -1; + } *(p++)=sl; memcpy(p,s->session->session_id,sl); p+=sl; @@ -1588,7 +1592,7 @@ static int ssl3_get_client_key_exchange(SSL *s) /* Note that the length is checked again below, ** after decryption */ - if(enc.pms_length > sizeof pms) + if(enc_pms.length > sizeof pms) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); diff --git a/src/lib/libssl/ssl.h b/src/lib/libssl/ssl.h index d9949e8eb2..e9d1e896d7 100644 --- a/src/lib/libssl/ssl.h +++ b/src/lib/libssl/ssl.h @@ -1462,6 +1462,7 @@ void ERR_load_SSL_strings(void); /* Function codes. */ #define SSL_F_CLIENT_CERTIFICATE 100 +#define SSL_F_CLIENT_FINISHED 238 #define SSL_F_CLIENT_HELLO 101 #define SSL_F_CLIENT_MASTER_KEY 102 #define SSL_F_D2I_SSL_SESSION 103 @@ -1475,7 +1476,9 @@ void ERR_load_SSL_strings(void); #define SSL_F_I2D_SSL_SESSION 111 #define SSL_F_READ_N 112 #define SSL_F_REQUEST_CERTIFICATE 113 +#define SSL_F_SERVER_FINISH 239 #define SSL_F_SERVER_HELLO 114 +#define SSL_F_SERVER_VERIFY 240 #define SSL_F_SSL23_ACCEPT 115 #define SSL_F_SSL23_CLIENT_HELLO 116 #define SSL_F_SSL23_CONNECT 117 @@ -1487,6 +1490,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL2_ACCEPT 122 #define SSL_F_SSL2_CONNECT 123 #define SSL_F_SSL2_ENC_INIT 124 +#define SSL_F_SSL2_GENERATE_KEY_MATERIAL 241 #define SSL_F_SSL2_PEEK 234 #define SSL_F_SSL2_READ 125 #define SSL_F_SSL2_READ_INTERNAL 236 @@ -1523,6 +1527,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152 #define SSL_F_SSL3_SEND_CLIENT_VERIFY 153 #define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154 +#define SSL_F_SSL3_SEND_SERVER_HELLO 242 #define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155 #define SSL_F_SSL3_SETUP_BUFFERS 156 #define SSL_F_SSL3_SETUP_KEY_BLOCK 157 @@ -1747,6 +1752,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_SHORT_READ 219 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 +#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 1114 #define SSL_R_SSL3_SESSION_ID_TOO_LONG 1113 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 diff --git a/src/lib/libssl/ssl_asn1.c b/src/lib/libssl/ssl_asn1.c index 1638c6b525..3723fc2e37 100644 --- a/src/lib/libssl/ssl_asn1.c +++ b/src/lib/libssl/ssl_asn1.c @@ -294,10 +294,11 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, i=SSL2_MAX_SSL_SESSION_ID_LENGTH; if (os.length > i) - os.length=i; + os.length = i; + if (os.length > sizeof ret->session_id) /* can't happen */ + os.length = sizeof ret->session_id; ret->session_id_length=os.length; - die(os.length <= sizeof ret->session_id); memcpy(ret->session_id,os.data,os.length); M_ASN1_D2I_get(osp,d2i_ASN1_OCTET_STRING); diff --git a/src/lib/libssl/ssl_err.c b/src/lib/libssl/ssl_err.c index 0cad32c855..7067a745f3 100644 --- a/src/lib/libssl/ssl_err.c +++ b/src/lib/libssl/ssl_err.c @@ -67,6 +67,7 @@ static ERR_STRING_DATA SSL_str_functs[]= { {ERR_PACK(0,SSL_F_CLIENT_CERTIFICATE,0), "CLIENT_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_CLIENT_FINISHED,0), "CLIENT_FINISHED"}, {ERR_PACK(0,SSL_F_CLIENT_HELLO,0), "CLIENT_HELLO"}, {ERR_PACK(0,SSL_F_CLIENT_MASTER_KEY,0), "CLIENT_MASTER_KEY"}, {ERR_PACK(0,SSL_F_D2I_SSL_SESSION,0), "d2i_SSL_SESSION"}, @@ -80,7 +81,9 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_I2D_SSL_SESSION,0), "i2d_SSL_SESSION"}, {ERR_PACK(0,SSL_F_READ_N,0), "READ_N"}, {ERR_PACK(0,SSL_F_REQUEST_CERTIFICATE,0), "REQUEST_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SERVER_FINISH,0), "SERVER_FINISH"}, {ERR_PACK(0,SSL_F_SERVER_HELLO,0), "SERVER_HELLO"}, +{ERR_PACK(0,SSL_F_SERVER_VERIFY,0), "SERVER_VERIFY"}, {ERR_PACK(0,SSL_F_SSL23_ACCEPT,0), "SSL23_ACCEPT"}, {ERR_PACK(0,SSL_F_SSL23_CLIENT_HELLO,0), "SSL23_CLIENT_HELLO"}, {ERR_PACK(0,SSL_F_SSL23_CONNECT,0), "SSL23_CONNECT"}, @@ -92,6 +95,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL2_ACCEPT,0), "SSL2_ACCEPT"}, {ERR_PACK(0,SSL_F_SSL2_CONNECT,0), "SSL2_CONNECT"}, {ERR_PACK(0,SSL_F_SSL2_ENC_INIT,0), "SSL2_ENC_INIT"}, +{ERR_PACK(0,SSL_F_SSL2_GENERATE_KEY_MATERIAL,0), "SSL2_GENERATE_KEY_MATERIAL"}, {ERR_PACK(0,SSL_F_SSL2_PEEK,0), "SSL2_PEEK"}, {ERR_PACK(0,SSL_F_SSL2_READ,0), "SSL2_READ"}, {ERR_PACK(0,SSL_F_SSL2_READ_INTERNAL,0), "SSL2_READ_INTERNAL"}, @@ -128,6 +132,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,0), "SSL3_SEND_CLIENT_KEY_EXCHANGE"}, {ERR_PACK(0,SSL_F_SSL3_SEND_CLIENT_VERIFY,0), "SSL3_SEND_CLIENT_VERIFY"}, {ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_CERTIFICATE,0), "SSL3_SEND_SERVER_CERTIFICATE"}, +{ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_HELLO,0), "SSL3_SEND_SERVER_HELLO"}, {ERR_PACK(0,SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,0), "SSL3_SEND_SERVER_KEY_EXCHANGE"}, {ERR_PACK(0,SSL_F_SSL3_SETUP_BUFFERS,0), "SSL3_SETUP_BUFFERS"}, {ERR_PACK(0,SSL_F_SSL3_SETUP_KEY_BLOCK,0), "SSL3_SETUP_KEY_BLOCK"}, @@ -355,6 +360,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_SHORT_READ ,"short read"}, {SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE,"signature for non signing certificate"}, {SSL_R_SSL23_DOING_SESSION_ID_REUSE ,"ssl23 doing session id reuse"}, +{SSL_R_SSL2_CONNECTION_ID_TOO_LONG ,"ssl2 connection id too long"}, {SSL_R_SSL3_SESSION_ID_TOO_LONG ,"ssl3 session id too long"}, {SSL_R_SSL3_SESSION_ID_TOO_SHORT ,"ssl3 session id too short"}, {SSL_R_SSLV3_ALERT_BAD_CERTIFICATE ,"sslv3 alert bad certificate"}, diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index ab172aeaec..4bc4ce5b3a 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c @@ -1405,13 +1405,24 @@ void SSL_CTX_free(SSL_CTX *a) abort(); /* ok */ } #endif - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); + /* + * Free internal session cache. However: the remove_cb() may reference + * the ex_data of SSL_CTX, thus the ex_data store can only be removed + * after the sessions were flushed. + * As the ex_data handling routines might also touch the session cache, + * the most secure solution seems to be: empty (flush) the cache, then + * free ex_data, then finally free the cache. + * (See ticket [openssl.org #212].) + */ if (a->sessions != NULL) - { SSL_CTX_flush_sessions(a,0); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); + + if (a->sessions != NULL) lh_free(a->sessions); - } + if (a->cert_store != NULL) X509_STORE_free(a->cert_store); if (a->cipher_list != NULL) diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index fe4ac839cf..dd6c7a7323 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -510,7 +510,7 @@ STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); int ssl_verify_alarm_type(long type); int ssl2_enc_init(SSL *s, int client); -void ssl2_generate_key_material(SSL *s); +int ssl2_generate_key_material(SSL *s); void ssl2_enc(SSL *s,int send_data); void ssl2_mac(SSL *s,unsigned char *mac,int send_data); SSL_CIPHER *ssl2_get_cipher_by_char(const unsigned char *p); diff --git a/src/lib/libssl/ssl_sess.c b/src/lib/libssl/ssl_sess.c index 8bfc382bb6..ca1a7427be 100644 --- a/src/lib/libssl/ssl_sess.c +++ b/src/lib/libssl/ssl_sess.c @@ -251,7 +251,12 @@ int ssl_get_new_session(SSL *s, int session) ss->session_id_length=0; } - die(s->sid_ctx_length <= sizeof ss->sid_ctx); + if (s->sid_ctx_length > sizeof ss->sid_ctx) + { + SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); ss->sid_ctx_length=s->sid_ctx_length; s->session=ss; -- cgit v1.2.3-55-g6feb