diff --git a/crypto/bn/asm/ia64.S b/crypto/bn/asm/ia64.S new file mode 100644 index 000000000..ae5606631 --- /dev/null +++ b/crypto/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 +#include +#include "cryptlib.h" +#include +#include + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_UBSEC + +#ifdef FLAT_INC +#include "hw_ubsec.h" +#else +#include "vendor_defns/hw_ubsec.h" +#endif + +static int ubsec_destroy(ENGINE *e); +static int ubsec_init(ENGINE *e); +static int ubsec_finish(ENGINE *e); +static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); +static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dp, + const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx); +#ifndef OPENSSL_NO_RSA +static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa); +#endif +static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +#ifndef OPENSSL_NO_DSA +#if NOT_USED +static int ubsec_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 ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +#endif +static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); +static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); +#endif +#ifndef OPENSSL_NO_DH +static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh); +static int ubsec_dh_generate_key(DH *dh); +#endif + +#if NOT_USED +static int ubsec_rand_bytes(unsigned char *buf, int num); +static int ubsec_rand_status(void); +#endif + +#define UBSEC_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = { + {UBSEC_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'ubsec' shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} + }; + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD ubsec_rsa = + { + "UBSEC RSA method", + NULL, + NULL, + NULL, + NULL, + ubsec_rsa_mod_exp, + ubsec_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD ubsec_dsa = + { + "UBSEC DSA method", + ubsec_dsa_do_sign, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + ubsec_dsa_verify, /* dsa_do_verify */ + NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */ + NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */ + NULL, /* init */ + NULL, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; +#endif + +#ifndef OPENSSL_NO_DH +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD ubsec_dh = + { + "UBSEC DH method", + ubsec_dh_generate_key, + ubsec_dh_compute_key, + ubsec_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; +#endif + +#ifndef OPENSSL_NO_ERR +/* Error function codes for use in ubsec operation */ +#define UBSEC_F_UBSEC_INIT 100 +#define UBSEC_F_UBSEC_FINISH 101 +#define UBSEC_F_UBSEC_CTRL 102 +#define UBSEC_F_UBSEC_MOD_EXP 103 +#define UBSEC_F_UBSEC_RSA_MOD_EXP 104 +#define UBSEC_F_UBSEC_RSA_MOD_EXP_CRT 105 +#define UBSEC_F_UBSEC_DSA_SIGN 106 +#define UBSEC_F_UBSEC_DSA_VERIFY 107 +/* Error reason codes */ +#define UBSEC_R_ALREADY_LOADED 108 +#define UBSEC_R_DSO_FAILURE 109 +#define UBSEC_R_UNIT_FAILURE 110 +#define UBSEC_R_NOT_LOADED 111 +#define UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED 112 +#define UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL 113 +#define UBSEC_R_BN_EXPAND_FAIL 114 +#define UBSEC_R_REQUEST_FAILED 115 +#define UBSEC_R_MISSING_KEY_COMPONENTS 116 +static ERR_STRING_DATA ubsec_str_functs[] = + { + /* This first element is changed to match the dynamic 'lib' number */ +{ERR_PACK(0,0,0), "ubsec engine code"}, +{ERR_PACK(0,UBSEC_F_UBSEC_INIT,0), "ubsec_init"}, +{ERR_PACK(0,UBSEC_F_UBSEC_FINISH,0), "ubsec_finish"}, +{ERR_PACK(0,UBSEC_F_UBSEC_CTRL,0), "ubsec_ctrl"}, +{ERR_PACK(0,UBSEC_F_UBSEC_MOD_EXP,0), "ubsec_mod_exp"}, +{ERR_PACK(0,UBSEC_F_UBSEC_RSA_MOD_EXP,0), "ubsec_rsa_mod_exp"}, +{ERR_PACK(0,UBSEC_F_UBSEC_RSA_MOD_EXP_CRT,0), "ubsec_rsa_mod_exp_crt"}, +{ERR_PACK(0,UBSEC_F_UBSEC_DSA_SIGN,0), "ubsec_dsa_sign"}, +{ERR_PACK(0,UBSEC_F_UBSEC_DSA_VERIFY,0), "ubsec_dsa_verify"}, +/* Error reason codes */ +{UBSEC_R_ALREADY_LOADED ,"already loaded"}, +{UBSEC_R_DSO_FAILURE ,"DSO failure"}, +{UBSEC_R_UNIT_FAILURE ,"unit failure"}, +{UBSEC_R_NOT_LOADED ,"not loaded"}, +{UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"}, +{UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL ,"size too large or too small"}, +{UBSEC_R_BN_EXPAND_FAIL ,"bn_expand fail"}, +{UBSEC_R_REQUEST_FAILED ,"request failed"}, +{UBSEC_R_MISSING_KEY_COMPONENTS ,"missing key components"}, +{0,NULL} + }; +/* The library number we obtain dynamically from the ERR code */ +static int ubsec_err_lib = -1; +#define UBSECerr(f,r) ERR_PUT_error(ubsec_err_lib,(f),(r),__FILE__,__LINE__) +static void ubsec_load_error_strings(void) + { + if(ubsec_err_lib < 0) + { + if((ubsec_err_lib = ERR_get_next_error_library()) <= 0) + return; + ubsec_str_functs[0].error = ERR_PACK(ubsec_err_lib,0,0); + ERR_load_strings(ubsec_err_lib, ubsec_str_functs); + } + } +static void ubsec_unload_error_strings(void) + { + if(ubsec_err_lib >= 0) + { + ERR_unload_strings(ubsec_err_lib, ubsec_str_functs); + ubsec_err_lib = -1; + } + } +#else +#define UBSECerr(f,r) /* NOP */ +static void ubsec_load_error_strings(void) { } /* NOP */ +static void ubsec_unload_error_strings(void) { } /* NOP */ +#endif + +/* Constants used when creating the ENGINE */ +static const char *engine_ubsec_id = "ubsec"; +static const char *engine_ubsec_name = "UBSEC hardware engine support"; + +/* This internal function is used by ENGINE_ubsec() and possibly by the + * "dynamic" ENGINE support too */ +static int bind_helper(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *meth1; +#endif +#ifndef OPENSSL_NO_DH +#ifndef HAVE_UBSEC_DH + const DH_METHOD *meth3; +#endif /* HAVE_UBSEC_DH */ +#endif + if(!ENGINE_set_id(e, engine_ubsec_id) || + !ENGINE_set_name(e, engine_ubsec_name) || +#ifndef OPENSSL_NO_RSA + !ENGINE_set_RSA(e, &ubsec_rsa) || +#endif +#ifndef OPENSSL_NO_DSA + !ENGINE_set_DSA(e, &ubsec_dsa) || +#endif +#ifndef OPENSSL_NO_DH + !ENGINE_set_DH(e, &ubsec_dh) || +#endif + !ENGINE_set_destroy_function(e, ubsec_destroy) || + !ENGINE_set_init_function(e, ubsec_init) || + !ENGINE_set_finish_function(e, ubsec_finish) || + !ENGINE_set_ctrl_function(e, ubsec_ctrl) || + !ENGINE_set_cmd_defns(e, ubsec_cmd_defns)) + return 0; + +#ifndef OPENSSL_NO_RSA + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the Broadcom-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1 = RSA_PKCS1_SSLeay(); + ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc; + ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec; + ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc; + ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec; +#endif + +#ifndef OPENSSL_NO_DH +#ifndef HAVE_UBSEC_DH + /* Much the same for Diffie-Hellman */ + meth3 = DH_OpenSSL(); + ubsec_dh.generate_key = meth3->generate_key; + ubsec_dh.compute_key = meth3->compute_key; +#endif /* HAVE_UBSEC_DH */ +#endif + + /* Ensure the ubsec error handling is set up */ + ubsec_load_error_strings(); + return 1; + } + +static ENGINE *engine_ubsec(void) + { + ENGINE *ret = ENGINE_new(); + if(!ret) + return NULL; + if(!bind_helper(ret)) + { + ENGINE_free(ret); + return NULL; + } + return ret; + } + +void ENGINE_load_ubsec(void) + { + /* Copied from eng_[openssl|dyn].c */ + ENGINE *toadd = engine_ubsec(); + if(!toadd) return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); + } + +/* This is a process-global DSO handle used for loading and unloading + * the UBSEC library. NB: This is only set (or unset) during an + * init() or finish() call (reference counts permitting) and they're + * operating with global locks, so this should be thread-safe + * implicitly. */ + +static DSO *ubsec_dso = NULL; + +/* These are the function pointers that are (un)set when the library has + * successfully (un)loaded. */ + +static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL; +static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL; +static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL; +static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL; +#ifndef OPENSSL_NO_DH +static t_UBSEC_diffie_hellman_generate_ioctl + *p_UBSEC_diffie_hellman_generate_ioctl = NULL; +static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL; +#endif +/* #ifndef OPENSSL_NO_RSA */ +static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL; +static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; +/* #endif */ +#ifndef OPENSSL_NO_DSA +static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL; +static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL; +#endif +static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL; +static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL; + +/* + * These are the static string constants for the DSO file name and the function + * symbol names to bind to. + */ + +static const char *UBSEC_LIBNAME = "ubsec"; +static const char *UBSEC_F1 = "ubsec_bytes_to_bits"; +static const char *UBSEC_F2 = "ubsec_bits_to_bytes"; +static const char *UBSEC_F3 = "ubsec_open"; +static const char *UBSEC_F4 = "ubsec_close"; +#ifndef OPENSSL_NO_DH +static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl"; +static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl"; +#endif +/* #ifndef OPENSSL_NO_RSA */ +static const char *UBSEC_F7 = "rsa_mod_exp_ioctl"; +static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl"; +/* #endif */ +#ifndef OPENSSL_NO_DSA +static const char *UBSEC_F9 = "dsa_sign_ioctl"; +static const char *UBSEC_F10 = "dsa_verify_ioctl"; +#endif +static const char *UBSEC_F11 = "math_accelerate_ioctl"; +static const char *UBSEC_F12 = "rng_ioctl"; + +/* Destructor (complements the "ENGINE_ubsec()" constructor) */ +static int ubsec_destroy(ENGINE *e) + { + ubsec_unload_error_strings(); + return 1; + } + +/* (de)initialisation functions. */ +static int ubsec_init(ENGINE *e) + { + t_UBSEC_ubsec_bytes_to_bits *p1; + t_UBSEC_ubsec_bits_to_bytes *p2; + t_UBSEC_ubsec_open *p3; + t_UBSEC_ubsec_close *p4; +#ifndef OPENSSL_NO_DH + t_UBSEC_diffie_hellman_generate_ioctl *p5; + t_UBSEC_diffie_hellman_agree_ioctl *p6; +#endif +/* #ifndef OPENSSL_NO_RSA */ + t_UBSEC_rsa_mod_exp_ioctl *p7; + t_UBSEC_rsa_mod_exp_crt_ioctl *p8; +/* #endif */ +#ifndef OPENSSL_NO_DSA + t_UBSEC_dsa_sign_ioctl *p9; + t_UBSEC_dsa_verify_ioctl *p10; +#endif + t_UBSEC_math_accelerate_ioctl *p11; + t_UBSEC_rng_ioctl *p12; + int fd = 0; + + if(ubsec_dso != NULL) + { + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED); + goto err; + } + /* + * Attempt to load libubsec.so/ubsec.dll/whatever. + */ + ubsec_dso = DSO_load(NULL, UBSEC_LIBNAME, NULL, 0); + if(ubsec_dso == NULL) + { + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); + goto err; + } + + if ( + !(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) || + !(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) || + !(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) || + !(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) || +#ifndef OPENSSL_NO_DH + !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) + DSO_bind_func(ubsec_dso, UBSEC_F5)) || + !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) + DSO_bind_func(ubsec_dso, UBSEC_F6)) || +#endif +/* #ifndef OPENSSL_NO_RSA */ + !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) || + !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) || +/* #endif */ +#ifndef OPENSSL_NO_DSA + !(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) || + !(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) || +#endif + !(p11 = (t_UBSEC_math_accelerate_ioctl *) + DSO_bind_func(ubsec_dso, UBSEC_F11)) || + !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12))) + { + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); + goto err; + } + + /* Copy the pointers */ + p_UBSEC_ubsec_bytes_to_bits = p1; + p_UBSEC_ubsec_bits_to_bytes = p2; + p_UBSEC_ubsec_open = p3; + p_UBSEC_ubsec_close = p4; +#ifndef OPENSSL_NO_DH + p_UBSEC_diffie_hellman_generate_ioctl = p5; + p_UBSEC_diffie_hellman_agree_ioctl = p6; +#endif +#ifndef OPENSSL_NO_RSA + p_UBSEC_rsa_mod_exp_ioctl = p7; + p_UBSEC_rsa_mod_exp_crt_ioctl = p8; +#endif +#ifndef OPENSSL_NO_DSA + p_UBSEC_dsa_sign_ioctl = p9; + p_UBSEC_dsa_verify_ioctl = p10; +#endif + p_UBSEC_math_accelerate_ioctl = p11; + p_UBSEC_rng_ioctl = p12; + + /* Perform an open to see if there's actually any unit running. */ + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) + { + p_UBSEC_ubsec_close(fd); + return 1; + } + else + { + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); + } + +err: + if(ubsec_dso) + DSO_free(ubsec_dso); + p_UBSEC_ubsec_bytes_to_bits = NULL; + p_UBSEC_ubsec_bits_to_bytes = NULL; + p_UBSEC_ubsec_open = NULL; + p_UBSEC_ubsec_close = NULL; +#ifndef OPENSSL_NO_DH + p_UBSEC_diffie_hellman_generate_ioctl = NULL; + p_UBSEC_diffie_hellman_agree_ioctl = NULL; +#endif +#ifndef OPENSSL_NO_RSA + p_UBSEC_rsa_mod_exp_ioctl = NULL; + p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; +#endif +#ifndef OPENSSL_NO_DSA + p_UBSEC_dsa_sign_ioctl = NULL; + p_UBSEC_dsa_verify_ioctl = NULL; +#endif + p_UBSEC_math_accelerate_ioctl = NULL; + p_UBSEC_rng_ioctl = NULL; + + return 0; + } + +static int ubsec_finish(ENGINE *e) + { + if(ubsec_dso == NULL) + { + UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED); + return 0; + } + if(!DSO_free(ubsec_dso)) + { + UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE); + return 0; + } + ubsec_dso = NULL; + p_UBSEC_ubsec_bytes_to_bits = NULL; + p_UBSEC_ubsec_bits_to_bytes = NULL; + p_UBSEC_ubsec_open = NULL; + p_UBSEC_ubsec_close = NULL; +#ifndef OPENSSL_NO_DH + p_UBSEC_diffie_hellman_generate_ioctl = NULL; + p_UBSEC_diffie_hellman_agree_ioctl = NULL; +#endif +#ifndef OPENSSL_NO_RSA + p_UBSEC_rsa_mod_exp_ioctl = NULL; + p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; +#endif +#ifndef OPENSSL_NO_DSA + p_UBSEC_dsa_sign_ioctl = NULL; + p_UBSEC_dsa_verify_ioctl = NULL; +#endif + p_UBSEC_math_accelerate_ioctl = NULL; + p_UBSEC_rng_ioctl = NULL; + return 1; + } + +static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialised = ((ubsec_dso == NULL) ? 0 : 1); + switch(cmd) + { + case UBSEC_CMD_SO_PATH: + if(p == NULL) + { + UBSECerr(UBSEC_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(initialised) + { + UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_ALREADY_LOADED); + return 0; + } + UBSEC_LIBNAME = (const char *)p; + return 1; + default: + break; + } + UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; + } + +static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) + { + int y_len = 0; + int fd; + + if(ubsec_dso == NULL) + { + UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED); + return 0; + } + + /* Check if hardware can't handle this argument. */ + y_len = BN_num_bits(m); + if (y_len > 1024) { + UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); + return 0; + } + + if(!bn_wexpand(r, m->top)) + { + UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL); + return 0; + } + memset(r->d, 0, BN_num_bytes(m)); + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { + fd = 0; + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); + return 0; + } + + if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a), + (unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, + BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0) + { + UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED); + return 0; + } + + p_UBSEC_ubsec_close(fd); + + r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2; + return 1; + } + +#ifndef OPENSSL_NO_RSA +static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) + { + BN_CTX *ctx; + int to_return = 0; + + if((ctx = BN_CTX_new()) == NULL) + goto err; + + if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) + { + UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS); + goto err; + } + + /* + * Do in software if argument is too large for hardware. + */ + if ((BN_num_bits(rsa->p)+BN_num_bits(rsa->q)) > 1024) { + const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); + to_return = (*meth->rsa_mod_exp)(r0, I, rsa); + } else { + to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, + rsa->dmq1, rsa->iqmp, ctx); + } +err: + if(ctx) + BN_CTX_free(ctx); + return to_return; + } +#endif + +static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dp, + const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx) + { + int y_len, + m_len, + fd; + + m_len = BN_num_bytes(p) + BN_num_bytes(q) + 1; + y_len = BN_num_bits(p) + BN_num_bits(q); + + /* Check if hardware can't handle this argument. */ + if (y_len > 1024) { + UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); + return 0; + } + + if (!bn_wexpand(r, p->top + q->top + 1)) { + UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL); + return 0; + } + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { + fd = 0; + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); + return 0; + } + + if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd, + (unsigned char *)a->d, BN_num_bits(a), + (unsigned char *)qinv->d, BN_num_bits(qinv), + (unsigned char *)dp->d, BN_num_bits(dp), + (unsigned char *)p->d, BN_num_bits(p), + (unsigned char *)dq->d, BN_num_bits(dq), + (unsigned char *)q->d, BN_num_bits(q), + (unsigned char *)r->d, &y_len) != 0) { + UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED); + return 0; + } + + p_UBSEC_ubsec_close(fd); + + r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2; + return 1; +} + +#ifndef OPENSSL_NO_DSA +#if NOT_USED +static int ubsec_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) + { + BIGNUM t; + int to_return = 0; + + BN_init(&t); + /* let rr = a1 ^ p1 mod m */ + if (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end; + /* let t = a2 ^ p2 mod m */ + if (!ubsec_mod_exp(&t,a2,p2,m,ctx)) goto end; + /* let rr = rr * t mod m */ + if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; + to_return = 1; +end: + BN_free(&t); + return to_return; + } + +static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + return ubsec_mod_exp(r, a, p, m, ctx); + } +#endif +#endif + +/* + * This function is aliased to mod_exp (with the mont stuff dropped). + */ +static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + int ret = 0; + +#ifndef OPENSSL_NO_RSA + /* Do in software if the key is too large for the hardware. */ + if (BN_num_bits(m) > 1024) + { + const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); + ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx); + } + else +#endif + { + ret = ubsec_mod_exp(r, a, p, m, ctx); + } + + return ret; + } + +#ifndef OPENSSL_NO_DH +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + return ubsec_mod_exp(r, a, p, m, ctx); + } +#endif + +#ifndef OPENSSL_NO_DSA +static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + DSA_SIG *to_return = NULL; + int s_len = 160, r_len = 160, d_len, fd; + BIGNUM m, *r=NULL, *s=NULL; + + BN_init(&m); + + s = BN_new(); + r = BN_new(); + if ((s == NULL) || (r==NULL)) + goto err; + + d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen); + + if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) || + (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) { + UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL); + goto err; + } + + if (BN_bin2bn(dgst,dlen,&m) == NULL) { + UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL); + goto err; + } + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { + fd = 0; + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); + return 0; + } + + if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */ + (unsigned char *)dgst, d_len, + NULL, 0, /* compute random value */ + (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), + (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), + (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), + (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key), + (unsigned char *)r->d, &r_len, + (unsigned char *)s->d, &s_len ) != 0) { + UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_REQUEST_FAILED); + goto err; + } + + p_UBSEC_ubsec_close(fd); + + r->top = (160+BN_BITS2-1)/BN_BITS2; + s->top = (160+BN_BITS2-1)/BN_BITS2; + + to_return = DSA_SIG_new(); + if(to_return == NULL) { + UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL); + goto err; + } + + to_return->r = r; + to_return->s = s; + +err: + if (!to_return) { + if (r) BN_free(r); + if (s) BN_free(s); + } + BN_clear_free(&m); + return to_return; +} + +static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa) + { + int v_len, d_len; + int to_return = 0; + int fd; + BIGNUM v; + + BN_init(&v); + + if(!bn_wexpand(&v, dsa->p->top)) { + UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY ,UBSEC_R_BN_EXPAND_FAIL); + goto err; + } + + v_len = BN_num_bits(dsa->p); + + d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len); + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { + fd = 0; + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); + return 0; + } + + if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */ + (unsigned char *)dgst, d_len, + (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), + (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), + (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), + (unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key), + (unsigned char *)sig->r->d, BN_num_bits(sig->r), + (unsigned char *)sig->s->d, BN_num_bits(sig->s), + (unsigned char *)v.d, &v_len) != 0) { + UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY , UBSEC_R_REQUEST_FAILED); + goto err; + } + + p_UBSEC_ubsec_close(fd); + + to_return = 1; +err: + BN_clear_free(&v); + return to_return; + } +#endif + +#ifndef OPENSSL_NO_DH +static int ubsec_dh_compute_key (unsigned char *key,const BIGNUM *pub_key,DH *dh) + { + return 0; + } + +static int ubsec_dh_generate_key (DH *dh) + { + return 0; + } +#endif + +#ifdef NOT_USED +static int ubsec_rand_bytes(unsigned char *buf, int num) + { + return 0; + } + +static int ubsec_rand_status(void) + { + return 0; + } +#endif + +/* 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_ubsec_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 */ + +#endif /* !OPENSSL_NO_HW_UBSEC */ +#endif /* !OPENSSL_NO_HW */ diff --git a/crypto/engine/vendor_defns/hw_ubsec.h b/crypto/engine/vendor_defns/hw_ubsec.h new file mode 100644 index 000000000..37c830c1e --- /dev/null +++ b/crypto/engine/vendor_defns/hw_ubsec.h @@ -0,0 +1,99 @@ +/****************************************************************************** + * + * Copyright 2000 + * Broadcom Corporation + * 16215 Alton Parkway + * PO Box 57013 + * Irvine CA 92619-7013 + * + *****************************************************************************/ +/* + * Broadcom Corporation uBSec SDK + */ +/* + * Character device header file. + */ +/* + * Revision History: + * + * October 2000 JTT Created. + */ + +#define MAX_PUBLIC_KEY_BITS (1024) +#define MAX_PUBLIC_KEY_BYTES (1024/8) +#define SHA_BIT_SIZE (160) +#define MAX_CRYPTO_KEY_LENGTH 24 +#define MAX_MAC_KEY_LENGTH 64 +#define UBSEC_CRYPTO_DEVICE_NAME ((unsigned char *)"/dev/ubscrypt") +#define UBSEC_KEY_DEVICE_NAME ((unsigned char *)"/dev/ubskey") + +/* Math command types. */ +#define UBSEC_MATH_MODADD 0x0001 +#define UBSEC_MATH_MODSUB 0x0002 +#define UBSEC_MATH_MODMUL 0x0004 +#define UBSEC_MATH_MODEXP 0x0008 +#define UBSEC_MATH_MODREM 0x0010 +#define UBSEC_MATH_MODINV 0x0020 + +typedef long ubsec_MathCommand_t; +typedef long ubsec_RNGCommand_t; + +typedef struct ubsec_crypto_context_s { + unsigned int flags; + unsigned char crypto[MAX_CRYPTO_KEY_LENGTH]; + unsigned char auth[MAX_MAC_KEY_LENGTH]; +} ubsec_crypto_context_t, *ubsec_crypto_context_p; + +/* + * Predeclare the function pointer types that we dynamically load from the DSO. + */ + +typedef int t_UBSEC_ubsec_bytes_to_bits(unsigned char *n, int bytes); + +typedef int t_UBSEC_ubsec_bits_to_bytes(int bits); + +typedef int t_UBSEC_ubsec_open(unsigned char *device); + +typedef int t_UBSEC_ubsec_close(int fd); + +typedef int t_UBSEC_diffie_hellman_generate_ioctl (int fd, + unsigned char *x, int *x_len, unsigned char *y, int *y_len, + unsigned char *g, int g_len, unsigned char *m, int m_len, + unsigned char *userX, int userX_len, int random_bits); + +typedef int t_UBSEC_diffie_hellman_agree_ioctl (int fd, + unsigned char *x, int x_len, unsigned char *y, int y_len, + unsigned char *m, int m_len, unsigned char *k, int *k_len); + +typedef int t_UBSEC_rsa_mod_exp_ioctl (int fd, + unsigned char *x, int x_len, unsigned char *m, int m_len, + unsigned char *e, int e_len, unsigned char *y, int *y_len); + +typedef int t_UBSEC_rsa_mod_exp_crt_ioctl (int fd, + unsigned char *x, int x_len, unsigned char *qinv, int qinv_len, + unsigned char *edq, int edq_len, unsigned char *q, int q_len, + unsigned char *edp, int edp_len, unsigned char *p, int p_len, + unsigned char *y, int *y_len); + +typedef int t_UBSEC_dsa_sign_ioctl (int fd, + int hash, unsigned char *data, int data_len, + unsigned char *rndom, int random_len, + unsigned char *p, int p_len, unsigned char *q, int q_len, + unsigned char *g, int g_len, unsigned char *key, int key_len, + unsigned char *r, int *r_len, unsigned char *s, int *s_len); + +typedef int t_UBSEC_dsa_verify_ioctl (int fd, + int hash, unsigned char *data, int data_len, + unsigned char *p, int p_len, unsigned char *q, int q_len, + unsigned char *g, int g_len, unsigned char *key, int key_len, + unsigned char *r, int r_len, unsigned char *s, int s_len, + unsigned char *v, int *v_len); + +typedef int t_UBSEC_math_accelerate_ioctl(int fd, ubsec_MathCommand_t command, + unsigned char *ModN, int *ModN_len, unsigned char *ExpE, int *ExpE_len, + unsigned char *ParamA, int *ParamA_len, unsigned char *ParamB, int *ParamB_len, + unsigned char *Result, int *Result_len); + +typedef int t_UBSEC_rng_ioctl(int fd, ubsec_RNGCommand_t command, + unsigned char *Result, int *Result_len); + diff --git a/doc/ssl/SSL_COMP_add_compression_method.pod b/doc/ssl/SSL_COMP_add_compression_method.pod new file mode 100644 index 000000000..2a9873911 --- /dev/null +++ b/doc/ssl/SSL_COMP_add_compression_method.pod @@ -0,0 +1,70 @@ +=pod + +=head1 NAME + +SSL_COMP_add_compression_method - handle SSL/TLS integrated compression methods + +=head1 SYNOPSIS + + #include + + int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); + +=head1 DESCRIPTION + +SSL_COMP_add_compression_method() adds the compression method B with +the identifier B to the list of available compression methods. This +list is globally maintained for all SSL operations within this application. +It cannot be set for specific SSL_CTX or SSL objects. + +=head1 NOTES + +The TLS standard (or SSLv3) allows the integration of compression methods +into the communication. The TLS RFC does however not specify compression +methods or their corresponding identifiers, so there is currently no compatible +way to integrate compression with unknown peers. It is therefore currently not +recommended to integrate compression into applications. Applications for +non-public use may agree on certain compression methods. Using different +compression methods with the same identifier will lead to connection failure. + +An OpenSSL client speaking a protocol that allows compression (SSLv3, TLSv1) +will unconditionally send the list of all compression methods enabled with +SSL_COMP_add_compression_method() to the server during the handshake. +Unlike the mechanisms to set a cipher list, there is no method available to +restrict the list of compression method on a per connection basis. + +An OpenSSL server will match the identifiers listed by a client against +its own compression methods and will unconditionally activate compression +when a matching identifier is found. There is no way to restrict the list +of compression methods supported on a per connection basis. + +The OpenSSL library has the compression methods B and (when +especially enabled during compilation) B available. + +=head1 WARNINGS + +Once the identities of the compression methods for the TLS protocol have +been standardized, the compression API will most likely be changed. Using +it in the current state is not recommended. + +=head1 RETURN VALUES + +SSL_COMP_add_compression_method() may return the following values: + +=over 4 + +=item 1 + +The operation succeeded. + +=item 0 + +The operation failed. Check the error queue to find out the reason. + +=back + +=head1 SEE ALSO + +L + +=cut diff --git a/doc/ssl/SSL_CTX_ctrl.pod b/doc/ssl/SSL_CTX_ctrl.pod new file mode 100644 index 000000000..fb6adcf50 --- /dev/null +++ b/doc/ssl/SSL_CTX_ctrl.pod @@ -0,0 +1,34 @@ +=pod + +=head1 NAME + +SSL_CTX_ctrl, SSL_CTX_callback_ctrl, SSL_ctrl, SSL_callback_ctrl - internal handling functions for SSL_CTX and SSL objects + +=head1 SYNOPSIS + + #include + + long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); + long SSL_CTX_callback_ctrl(SSL_CTX *, int cmd, void (*fp)()); + + long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); + long SSL_callback_ctrl(SSL *, int cmd, void (*fp)()); + +=head1 DESCRIPTION + +The SSL_*_ctrl() family of functions is used to manipulate settings of +the SSL_CTX and SSL objects. Depending on the command B the arguments +B, B, or B are evaluated. These functions should never +be called directly. All functionalities needed are made available via +other functions or macros. + +=head1 RETURN VALUES + +The return values of the SSL*_ctrl() functions depend on the command +supplied via the B parameter. + +=head1 SEE ALSO + +L + +=cut diff --git a/doc/ssl/SSL_CTX_set_cert_store.pod b/doc/ssl/SSL_CTX_set_cert_store.pod new file mode 100644 index 000000000..81286ee65 --- /dev/null +++ b/doc/ssl/SSL_CTX_set_cert_store.pod @@ -0,0 +1,57 @@ +=pod + +=head1 NAME + +SSL_CTX_set_cert_store, SSL_CTX_get_cert_store - manipulate X509 certificate verification storage + +=head1 SYNOPSIS + + #include + + void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store); + X509_STORE *SSL_CTX_get_cert_store(SSL_CTX *ctx); + +=head1 DESCRIPTION + +SSL_CTX_set_cert_store() sets/replaces the certificate verification storage +of B to/with B. If another X505_STORE object is currently +set in B, it will be X509_STORE_free()ed. + +SSL_CTX_get_cert_store() returns a pointer to the current certificate +verification storage. + +=head1 NOTES + +In order to verify the certificates presented by the peer, trusted CA +certificates must be accessed. These CA certificates are made available +via lookup methods, handled inside the X509_STORE. From the X509_STORE +the X509_STORE_CTX used when verifying certificates is created. + +Typically the trusted certificate store is handled indirectly via using +L. +Using the SSL_CTX_set_cert_store() and SSL_CTX_get_cert_store() functions +it is possible to manipulate the X509_STORE object beyond the +L +call. + +Currently no detailed documentation on how to use the X509_STORE +object is available. Not all members of the X509_STORE are used when +the verification takes place. So will e.g. the verify_callback() be +overridden with the verify_callback() set via the +L family of functions. +This document must therefore be updated when documentation about the +X509_STORE object and its handling becomes available. + +=head1 RETURN VALUES + +SSL_CTX_set_cert_store() does not return diagnostic output. + +SSL_CTX_get_cert_store() returns the current setting. + +=head1 SEE ALSO + +L, +L, +L + +=cut diff --git a/doc/ssl/SSL_CTX_set_cert_verify_callback.pod b/doc/ssl/SSL_CTX_set_cert_verify_callback.pod new file mode 100644 index 000000000..723fc140d --- /dev/null +++ b/doc/ssl/SSL_CTX_set_cert_verify_callback.pod @@ -0,0 +1,75 @@ +=pod + +=head1 NAME + +SSL_CTX_set_cert_verify_callback - set peer certificate verification procedure + +=head1 SYNOPSIS + + #include + + void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*callback)(), + char *arg); + int (*callback)(); + +=head1 DESCRIPTION + +SSL_CTX_set_cert_verify_callback() sets the verification callback function for +B. SSL objects, that are created from B inherit the setting valid at +the time, L is called. B is currently ignored. + +=head1 NOTES + +Whenever a certificate is verified during a SSL/TLS handshake, a verification +function is called. If the application does not explicitly specify a +verification callback function, the built-in verification function is used. +If a verification callback B is specified via +SSL_CTX_set_cert_verify_callback(), the supplied callback function is called +instead. By setting B to NULL, the default behaviour is restored. + +When the verification must be performed, B will be called with +the argument callback(X509_STORE_CTX *x509_store_ctx). The arguments B +that can be specified when setting B are currently ignored. + +B should return 1 to indicate verification success and 0 to +indicate verification failure. If SSL_VERIFY_PEER is set and B +returns 0, the handshake will fail. As the verification procedure may +allow to continue the connection in case of failure (by always returning 1) +the verification result must be set in any case using the B +member of B, so that the calling application will be informed +about the detailed result of the verification procedure! + +Within B, B has access to the B +function set using L. + +=head1 WARNINGS + +Do not mix the verification callback described in this function with the +B function called during the verification process. The +latter is set using the L +family of functions. + +Providing a complete verification procedure including certificate purpose +settings etc is a complex task. The built-in procedure is quite powerful +and in most cases it should be sufficient to modify its behaviour using +the B function. + +=head1 BUGS + +It is possible to specify arguments to be passed to the verification callback. +Currently they are however not passed but ignored. + +The B function is not specified via a prototype, so that no +type checking takes place. + +=head1 RETURN VALUES + +SSL_CTX_set_cert_verify_callback() does not provide diagnostic information. + +=head1 SEE ALSO + +L, L, +L, +L + +=cut diff --git a/doc/ssl/SSL_CTX_set_info_callback.pod b/doc/ssl/SSL_CTX_set_info_callback.pod new file mode 100644 index 000000000..63d0b8d33 --- /dev/null +++ b/doc/ssl/SSL_CTX_set_info_callback.pod @@ -0,0 +1,153 @@ +=pod + +=head1 NAME + +SSL_CTX_set_info_callback, SSL_CTX_get_info_callback, SSL_set_info_callback, SSL_get_info_callback - handle information callback for SSL connections + +=head1 SYNOPSIS + + #include + + void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*callback)()); + void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(); + + void SSL_set_info_callback(SSL *ssl, void (*callback)()); + void (*SSL_get_info_callback(SSL *ssl))(); + +=head1 DESCRIPTION + +SSL_CTX_set_info_callback() sets the B function, that can be used to +obtain state information for SSL objects created from B during connection +setup and use. The setting for B is overridden from the setting for +a specific SSL object, if specified. +When B is NULL, not callback function is used. + +SSL_set_info_callback() sets the B function, that can be used to +obtain state information for B during connection setup and use. +When B is NULL, the callback setting currently valid for +B is used. + +SSL_CTX_get_info_callback() returns a pointer to the currently set information +callback function for B. + +SSL_get_info_callback() returns a pointer to the currently set information +callback function for B. + +=head1 NOTES + +When setting up a connection and during use, it is possible to obtain state +information from the SSL/TLS engine. When set, an information callback function +is called whenever the state changes, an alert appears, or an error occurs. + +The callback function is called as B. +The B argument specifies information about where (in which context) +the callback function was called. If B is 0, an error condition occurred. +If an alert is handled, SSL_CB_ALERT is set and B specifies the alert +information. + +B is a bitmask made up of the following bits: + +=over 4 + +=item SSL_CB_LOOP + +Callback has been called to indicate state change inside a loop. + +=item SSL_CB_EXIT + +Callback has been called to indicate error exit of a handshake function. +(May be soft error with retry option for non-blocking setups.) + +=item SSL_CB_READ + +Callback has been called during read operation. + +=item SSL_CB_WRITE + +Callback has been called during write operation. + +=item SSL_CB_ALERT + +Callback has been called due to an alert being sent or received. + +=item SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ) + +=item SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE) + +=item SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP) + +=item SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT) + +=item SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP) + +=item SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT) + +=item SSL_CB_HANDSHAKE_START + +Callback has been called because a new handshake is started. + +=item SSL_CB_HANDSHAKE_DONE 0x20 + +Callback has been called because a handshake is finished. + +=back + +The current state information can be obtained using the +L family of functions. + +The B information can be evaluated using the +L family of functions. + +=head1 RETURN VALUES + +SSL_set_info_callback() does not provide diagnostic information. + +SSL_get_info_callback() returns the current setting. + +=head1 EXAMPLES + +The following example callback function prints state strings, information +about alerts being handled and error messages to the B BIO. + + void apps_ssl_info_callback(SSL *s, int where, int ret) + { + const char *str; + int w; + + w=where& ~SSL_ST_MASK; + + if (w & SSL_ST_CONNECT) str="SSL_connect"; + else if (w & SSL_ST_ACCEPT) str="SSL_accept"; + else str="undefined"; + + if (where & SSL_CB_LOOP) + { + BIO_printf(bio_err,"%s:%s\n",str,SSL_state_string_long(s)); + } + else if (where & SSL_CB_ALERT) + { + str=(where & SSL_CB_READ)?"read":"write"; + BIO_printf(bio_err,"SSL3 alert %s:%s:%s\n", + str, + SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } + else if (where & SSL_CB_EXIT) + { + if (ret == 0) + BIO_printf(bio_err,"%s:failed in %s\n", + str,SSL_state_string_long(s)); + else if (ret < 0) + { + BIO_printf(bio_err,"%s:error in %s\n", + str,SSL_state_string_long(s)); + } + } + } + +=head1 SEE ALSO + +L, L, +L + +=cut diff --git a/doc/ssl/SSL_CTX_set_quiet_shutdown.pod b/doc/ssl/SSL_CTX_set_quiet_shutdown.pod new file mode 100644 index 000000000..1d0526d59 --- /dev/null +++ b/doc/ssl/SSL_CTX_set_quiet_shutdown.pod @@ -0,0 +1,63 @@ +=pod + +=head1 NAME + +SSL_CTX_set_quiet_shutdown, SSL_CTX_get_quiet_shutdown, SSL_set_quiet_shutdown, SSL_get_quiet_shutdown - manipulate shutdown behaviour + +=head1 SYNOPSIS + + #include + + void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode); + int SSL_CTX_get_quiet_shutdown(SSL_CTX *ctx); + + void SSL_set_quiet_shutdown(SSL *ssl, int mode); + int SSL_get_quiet_shutdown(SSL *ssl); + +=head1 DESCRIPTION + +SSL_CTX_set_quiet_shutdown() sets the "quiet shutdown" flag for B to be +B. SSL objects created from B inherit the B valid at the time +L is called. B may be 0 or 1. + +SSL_CTX_get_quiet_shutdown() returns the "quiet shutdown" setting of B. + +SSL_set_quiet_shutdown() sets the "quiet shutdown" flag for B to be +B. The setting stays valid until B is removed with +L or SSL_set_quiet_shutdown() is called again. +It is not changed when L is called. +B may be 0 or 1. + +SSL_get_quiet_shutdown() returns the "quiet shutdown" setting of B. + +=head1 NOTES + +Normally when a SSL connection is finished, the parties must send out +"close notify" alert messages using L +for a clean shutdown. + +When setting the "quiet shutdown" flag to 1, L +will set the internal flags to SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN. +(L then behaves like +L called with +SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN.) +The session is thus considered to be shutdown, but no "close notify" alert +is sent to the peer. This behaviour violates the TLS standard. + +The default is normal shutdown behaviour as described by the TLS standard. + +=head1 RETURN VALUES + +SSL_CTX_set_quiet_shutdown() and SSL_set_quiet_shutdown() do not return +diagnostic information. + +SSL_CTX_get_quiet_shutdown() and SSL_get_quiet_shutdown return the current +setting. + +=head1 SEE ALSO + +L, L, +L, L, +L, L + +=cut diff --git a/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod b/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod new file mode 100644 index 000000000..29d1f8a6f --- /dev/null +++ b/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod @@ -0,0 +1,170 @@ +=pod + +=head1 NAME + +SSL_CTX_set_tmp_dh_callback, SSL_CTX_set_tmp_dh, SSL_set_tmp_dh_callback, SSL_set_tmp_dh - handle DH keys for ephemeral key exchange + +=head1 SYNOPSIS + + #include + + void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)); + long SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh); + + void SSL_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)); + long SSL_set_tmp_dh(SSL *ssl, DH *dh) + + DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)); + +=head1 DESCRIPTION + +SSL_CTX_set_tmp_dh_callback() sets the callback function for B to be +used when a DH parameters are required to B. +The callback is inherited by all B objects created from B. + +SSL_CTX_set_tmp_dh() sets DH parameters to be used to be B. +The key is inherited by all B objects created from B. + +SSL_set_tmp_dh_callback() sets the callback only for B. + +SSL_set_tmp_dh() sets the parameters only for B. + +These functions apply to SSL/TLS servers only. + +=head1 NOTES + +When using a cipher with RSA authentication, an ephemeral DH key exchange +can take place. Ciphers with DSA keys always use ephemeral DH keys as well. +In these cases, the session data are negotiated using the +ephemeral/temporary DH key and the key supplied and certified +by the certificate chain is only used for signing. +Anonymous ciphers (without a permanent server key) also use ephemeral DH keys. + +Using ephemeral DH key exchange yields forward secrecy, as the connection +can only be decrypted, when the DH key is known. By generating a temporary +DH key inside the server application that is lost when the application +is left, it becomes impossible for an attacker to decrypt past sessions, +even if he gets hold of the normal (certified) key, as this key was +only used for signing. + +In order to perform a DH key exchange the server must use a DH group +(DH parameters) and generate a DH key. The server will always generate a new +DH key during the negotiation, when the DH parameters are supplied via +callback and/or when the SSL_OP_SINGLE_DH_USE option of +L is set. It will +immediately create a DH key, when DH parameters are supplied via +SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set. In this case, +it may happen that a key is generated on initialization without later +being needed, while on the other hand the computer time during the +negotiation is being saved. + +If "strong" primes were used to generate the DH parameters, it is not strictly +necessary to generate a new key for each handshake but it does improve forward +secrecy. If it is not assured, that "strong" primes were used (see especially +the section about DSA parameters below), SSL_OP_SINGLE_DH_USE must be used +in order to prevent small subgroup attacks. Always using SSL_OP_SINGLE_DH_USE +has an impact on the computer time needed during negotiation, but it is not +very large, so application authors/users should consider to always enable +this option. + +As generating DH parameters is extremely time consuming, an application +should not generate the parameters on the fly but supply the parameters. +DH parameters can be reused, as the actual key is newly generated during +the negotiation. The risk in reusing DH parameters is that an attacker +may specialize on a very often used DH group. Applications should therefore +generate their own DH parameters during the installation process using the +openssl L application. In order to reduce the computer +time needed for this generation, it is possible to use DSA parameters +instead (see L), but in this case SSL_OP_SINGLE_DH_USE +is mandatory. + +Application authors may compile in DH parameters. Files dh512.pem, +dh1024.pem, dh2048.pem, and dh4096 in the 'apps' directory of current +version of the OpenSSL distribution contain the 'SKIP' DH parameters, +which use safe primes and were generated verifiably pseudo-randomly. +These files can be converted into C code using the B<-C> option of the +L application. +Authors may also generate their own set of parameters using +L, but a user may not be sure how the parameters were +generated. The generation of DH parameters during installation is therefore +recommended. + +An application may either directly specify the DH parameters or +can supply the DH parameters via a callback function. The callback approach +has the advantage, that the callback may supply DH parameters for different +key lengths. + +The B is called with the B needed and +the B information. The B flag is set, when the +ephemeral DH key exchange is performed with an export cipher. + +=head1 EXAMPLES + +Handle DH parameters for key lengths of 512 and 1024 bits. (Error handling +partly left out.) + + ... + /* Set up ephemeral DH stuff */ + DH *dh_512 = NULL; + DH *dh_1024 = NULL; + FILE *paramfile; + + ... + /* "openssl dhparam -out dh_param_512.pem -2 512" */ + paramfile = fopen("dh_param_512.pem", "r"); + if (paramfile) { + dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); + fclose(paramfile); + } + /* "openssl dhparam -out dh_param_1024.pem -2 1024" */ + paramfile = fopen("dh_param_1024.pem", "r"); + if (paramfile) { + dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); + fclose(paramfile); + } + ... + + /* "openssl dhparam -C -2 512" etc... */ + DH *get_dh512() { ... } + DH *get_dh1024() { ... } + + DH *tmp_dh_callback(SSL *s, int is_export, int keylength) + { + DH *dh_tmp=NULL; + + switch (keylength) { + case 512: + if (!dh_512) + dh_512 = get_dh512(); + dh_tmp = dh_512; + break; + case 1024: + if (!dh_1024) + dh_1024 = get_dh1024(); + dh_tmp = dh_1024; + break; + default: + /* Generating a key on the fly is very costly, so use what is there */ + setup_dh_parameters_like_above(); + } + return(dh_tmp); + } + +=head1 RETURN VALUES + +SSL_CTX_set_tmp_dh_callback() and SSL_set_tmp_dh_callback() do not return +diagnostic output. + +SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() do return 1 on success and 0 +on failure. Check the error queue to find out the reason of failure. + +=head1 SEE ALSO + +L, L, +L, +L, +L, L + +=cut diff --git a/doc/ssl/SSL_CTX_set_tmp_rsa_callback.pod b/doc/ssl/SSL_CTX_set_tmp_rsa_callback.pod new file mode 100644 index 000000000..f85775927 --- /dev/null +++ b/doc/ssl/SSL_CTX_set_tmp_rsa_callback.pod @@ -0,0 +1,166 @@ +=pod + +=head1 NAME + +SSL_CTX_set_tmp_rsa_callback, SSL_CTX_set_tmp_rsa, SSL_CTX_need_tmp_rsa, SSL_set_tmp_rsa_callback, SSL_set_tmp_rsa, SSL_need_tmp_rsa - handle RSA keys for ephemeral key exchange + +=head1 SYNOPSIS + + #include + + void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*tmp_rsa_callback)(SSL *ssl, int is_export, int keylength)); + long SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, RSA *rsa); + long SSL_CTX_need_tmp_rsa(SSL_CTX *ctx); + + void SSL_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*tmp_rsa_callback)(SSL *ssl, int is_export, int keylength)); + long SSL_set_tmp_rsa(SSL *ssl, RSA *rsa) + long SSL_need_tmp_rsa(SSL *ssl) + + RSA *(*tmp_rsa_callback)(SSL *ssl, int is_export, int keylength)); + +=head1 DESCRIPTION + +SSL_CTX_set_tmp_rsa_callback() sets the callback function for B to be +used when a temporary/ephemeral RSA key is required to B. +The callback is inherited by all SSL objects newly created from B +with . Already created SSL objects are not affected. + +SSL_CTX_set_tmp_rsa() sets the temporary/ephemeral RSA key to be used to be +B. The key is inherited by all SSL objects newly created from B +with . Already created SSL objects are not affected. + +SSL_CTX_need_tmp_rsa() returns 1, if a temporary/ephemeral RSA key is needed +for RSA-based strength-limited 'exportable' ciphersuites because a RSA key +with a keysize larger than 512 bits is installed. + +SSL_set_tmp_rsa_callback() sets the callback only for B. + +SSL_set_tmp_rsa() sets the key only for B. + +SSL_need_tmp_rsa() returns 1, if a temporary/ephemeral RSA key is needed, +for RSA-based strength-limited 'exportable' ciphersuites because a RSA key +with a keysize larger than 512 bits is installed. + +These functions apply to SSL/TLS servers only. + +=head1 NOTES + +When using a cipher with RSA authentication, an ephemeral RSA key exchange +can take place. In this case the session data are negotiated using the +ephemeral/temporary RSA key and the RSA key supplied and certified +by the certificate chain is only used for signing. + +Under previous export restrictions, ciphers with RSA keys shorter (512 bits) +than the usual key length of 1024 bits were created. To use these ciphers +with RSA keys of usual length, an ephemeral key exchange must be performed, +as the normal (certified) key cannot be directly used. + +Using ephemeral RSA key exchange yields forward secrecy, as the connection +can only be decrypted, when the RSA key is known. By generating a temporary +RSA key inside the server application that is lost when the application +is left, it becomes impossible for an attacker to decrypt past sessions, +even if he gets hold of the normal (certified) RSA key, as this key was +used for signing only. The downside is that creating a RSA key is +computationally expensive. + +Additionally, the use of ephemeral RSA key exchange is only allowed in +the TLS standard, when the RSA key can be used for signing only, that is +for export ciphers. Using ephemeral RSA key exchange for other purposes +violates the standard and can break interoperability with clients. +It is therefore strongly recommended to not use ephemeral RSA key +exchange and use EDH (Ephemeral Diffie-Hellman) key exchange instead +in order to achieve forward secrecy (see +L). + +On OpenSSL servers ephemeral RSA key exchange is therefore disabled by default +and must be explicitly enabled using the SSL_OP_EPHEMERAL_RSA option of +L, violating the TLS/SSL +standard. When ephemeral RSA key exchange is required for export ciphers, +it will automatically be used without this option! + +An application may either directly specify the key or can supply the key via +a callback function. The callback approach has the advantage, that the +callback may generate the key only in case it is actually needed. As the +generation of a RSA key is however costly, it will lead to a significant +delay in the handshake procedure. Another advantage of the callback function +is that it can supply keys of different size (e.g. for SSL_OP_EPHEMERAL_RSA +usage) while the explicit setting of the key is only useful for key size of +512 bits to satisfy the export restricted ciphers and does give away key length +if a longer key would be allowed. + +The B is called with the B needed and +the B information. The B flag is set, when the +ephemeral RSA key exchange is performed with an export cipher. + +=head1 EXAMPLES + +Generate temporary RSA keys to prepare ephemeral RSA key exchange. As the +generation of a RSA key costs a lot of computer time, they saved for later +reuse. For demonstration purposes, two keys for 512 bits and 1024 bits +respectively are generated. + + ... + /* Set up ephemeral RSA stuff */ + RSA *rsa_512 = NULL; + RSA *rsa_1024 = NULL; + + rsa_512 = RSA_generate_key(512,RSA_F4,NULL,NULL); + if (rsa_512 == NULL) + evaluate_error_queue(); + + rsa_1024 = RSA_generate_key(1024,RSA_F4,NULL,NULL); + if (rsa_1024 == NULL) + evaluate_error_queue(); + + ... + + RSA *tmp_rsa_callback(SSL *s, int is_export, int keylength) + { + RSA *rsa_tmp=NULL; + + switch (keylength) { + case 512: + if (rsa_512) + rsa_tmp = rsa_512; + else { /* generate on the fly, should not happen in this example */ + rsa_tmp = RSA_generate_key(keylength,RSA_F4,NULL,NULL); + rsa_512 = rsa_tmp; /* Remember for later reuse */ + } + break; + case 1024: + if (rsa_1024) + rsa_tmp=rsa_1024; + else + should_not_happen_in_this_example(); + break; + default: + /* Generating a key on the fly is very costly, so use what is there */ + if (rsa_1024) + rsa_tmp=rsa_1024; + else + rsa_tmp=rsa_512; /* Use at least a shorter key */ + } + return(rsa_tmp); + } + +=head1 RETURN VALUES + +SSL_CTX_set_tmp_rsa_callback() and SSL_set_tmp_rsa_callback() do not return +diagnostic output. + +SSL_CTX_set_tmp_rsa() and SSL_set_tmp_rsa() do return 1 on success and 0 +on failure. Check the error queue to find out the reason of failure. + +SSL_CTX_need_tmp_rsa() and SSL_need_tmp_rsa() return 1 if a temporary +RSA key is needed and 0 otherwise. + +=head1 SEE ALSO + +L, L, +L, +L, +L, L + +=cut diff --git a/doc/ssl/SSL_alert_type_string.pod b/doc/ssl/SSL_alert_type_string.pod new file mode 100644 index 000000000..94e28cc30 --- /dev/null +++ b/doc/ssl/SSL_alert_type_string.pod @@ -0,0 +1,228 @@ +=pod + +=head1 NAME + +SSL_alert_type_string, SSL_alert_type_string_long, SSL_alert_desc_string, SSL_alert_desc_string_long - get textual description of alert information + +=head1 SYNOPSIS + + #include + + const char *SSL_alert_type_string(int value); + const char *SSL_alert_type_string_long(int value); + + const char *SSL_alert_desc_string(int value); + const char *SSL_alert_desc_string_long(int value); + +=head1 DESCRIPTION + +SSL_alert_type_string() returns a one letter string indicating the +type of the alert specified by B. + +SSL_alert_type_string_long() returns a string indicating the type of the alert +specified by B. + +SSL_alert_desc_string() returns a two letter string as a short form +describing the reason of the alert specified by B. + +SSL_alert_desc_string_long() returns a string describing the reason +of the alert specified by B. + +=head1 NOTES + +When one side of an SSL/TLS communication wants to inform the peer about +a special situation, it sends an alert. The alert is sent as a special message +and does not influence the normal data stream (unless its contents results +in the communication being canceled). + +A warning alert is sent, when a non-fatal error condition occurs. The +"close notify" alert is sent as a warning alert. Other examples for +non-fatal errors are certificate errors ("certificate expired", +"unsupported certificate"), for which a warning alert may be sent. +(The sending party may however decide to send a fatal error.) The +receiving side may cancel the connection on reception of a warning +alert on it discretion. + +Several alert messages must be sent as fatal alert messages as specified +by the TLS RFC. A fatal alert always leads to a connection abort. + +=head1 RETURN VALUES + +The following strings can occur for SSL_alert_type_string() or +SSL_alert_type_string_long(): + +=over 4 + +=item "W"/"warning" + +=item "F"/"fatal" + +=item "U"/"unknown" + +This indicates that no support is available for this alert type. +Probably B does not contain a correct alert message. + +=back + +The following strings can occur for SSL_alert_desc_string() or +SSL_alert_desc_string_long(): + +=over 4 + +=item "CN"/"close notify" + +The connection shall be closed. This is a warning alert. + +=item "UM"/"unexpected message" + +An inappropriate message was received. This alert is always fatal +and should never be observed in communication between proper +implementations. + +=item "BM"/"bad record mac" + +This alert is returned if a record is received with an incorrect +MAC. This message is always fatal. + +=item "DF"/"decompression failure" + +The decompression function received improper input (e.g. data +that would expand to excessive length). This message is always +fatal. + +=item "HF"/"handshake failure" + +Reception of a handshake_failure alert message indicates that the +sender was unable to negotiate an acceptable set of security +parameters given the options available. This is a fatal error. + +=item "NC"/"no certificate" + +A client, that was asked to send a certificate, does not send a certificate +(SSLv3 only). + +=item "BC"/"bad certificate" + +A certificate was corrupt, contained signatures that did not +verify correctly, etc + +=item "UC"/"unsupported certificate" + +A certificate was of an unsupported type. + +=item "CR"/"certificate revoked" + +A certificate was revoked by its signer. + +=item "CE"/"certificate expired" + +A certificate has expired or is not currently valid. + +=item "CU"/"certificate unknown" + +Some other (unspecified) issue arose in processing the +certificate, rendering it unacceptable. + +=item "IP"/"illegal parameter" + +A field in the handshake was out of range or inconsistent with +other fields. This is always fatal. + +=item "DC"/"decryption failed" + +A TLSCiphertext decrypted in an invalid way: either it wasn't an +even multiple of the block length or its padding values, when +checked, weren't correct. This message is always fatal. + +=item "RO"/"record overflow" + +A TLSCiphertext record was received which had a length more than +2^14+2048 bytes, or a record decrypted to a TLSCompressed record +with more than 2^14+1024 bytes. This message is always fatal. + +=item "CA"/"unknown CA" + +A valid certificate chain or partial chain was received, but the +certificate was not accepted because the CA certificate could not +be located or couldn't be matched with a known, trusted CA. This +message is always fatal. + +=item "AD"/"access denied" + +A valid certificate was received, but when access control was +applied, the sender decided not to proceed with negotiation. +This message is always fatal. + +=item "DE"/"decode error" + +A message could not be decoded because some field was out of the +specified range or the length of the message was incorrect. This +message is always fatal. + +=item "CY"/"decrypt error" + +A handshake cryptographic operation failed, including being +unable to correctly verify a signature, decrypt a key exchange, +or validate a finished message. + +=item "ER"/"export restriction" + +A negotiation not in compliance with export restrictions was +detected; for example, attempting to transfer a 1024 bit +ephemeral RSA key for the RSA_EXPORT handshake method. This +message is always fatal. + +=item "PV"/"protocol version" + +The protocol version the client has attempted to negotiate is +recognized, but not supported. (For example, old protocol +versions might be avoided for security reasons). This message is +always fatal. + +=item "IS"/"insufficient security" + +Returned instead of handshake_failure when a negotiation has +failed specifically because the server requires ciphers more +secure than those supported by the client. This message is always +fatal. + +=item "IE"/"internal error" + +An internal error unrelated to the peer or the correctness of the +protocol makes it impossible to continue (such as a memory +allocation failure). This message is always fatal. + +=item "US"/"user canceled" + +This handshake is being canceled for some reason unrelated to a +protocol failure. If the user cancels an operation after the +handshake is complete, just closing the connection by sending a +close_notify is more appropriate. This alert should be followed +by a close_notify. This message is generally a warning. + +=item "NR"/"no renegotiation" + +Sent by the client in response to a hello request or by the +server in response to a client hello after initial handshaking. +Either of these would normally lead to renegotiation; when that +is not appropriate, the recipient should respond with this alert; +at that point, the original requester can decide whether to +proceed with the connection. One case where this would be +appropriate would be where a server has spawned a process to +satisfy a request; the process might receive security parameters +(key length, authentication, etc.) at startup and it might be +difficult to communicate changes to these parameters after that +point. This message is always a warning. + +=item "UK"/"unknown" + +This indicates that no description is available for this alert type. +Probably B does not contain a correct alert message. + +=back + +=head1 SEE ALSO + +L, L + +=cut diff --git a/doc/ssl/SSL_get_SSL_CTX.pod b/doc/ssl/SSL_get_SSL_CTX.pod new file mode 100644 index 000000000..52d0227b1 --- /dev/null +++ b/doc/ssl/SSL_get_SSL_CTX.pod @@ -0,0 +1,26 @@ +=pod + +=head1 NAME + +SSL_get_SSL_CTX - get the SSL_CTX from which an SSL is created + +=head1 SYNOPSIS + + #include + + SSL_CTX *SSL_get_SSL_CTX(SSL *ssl); + +=head1 DESCRIPTION + +SSL_get_SSL_CTX() returns a pointer to the SSL_CTX object, from which +B was created with L. + +=head1 RETURN VALUES + +The pointer to the SSL_CTX object is returned. + +=head1 SEE ALSO + +L, L + +=cut diff --git a/doc/ssl/SSL_get_default_timeout.pod b/doc/ssl/SSL_get_default_timeout.pod new file mode 100644 index 000000000..8d43b3134 --- /dev/null +++ b/doc/ssl/SSL_get_default_timeout.pod @@ -0,0 +1,41 @@ +=pod + +=head1 NAME + +SSL_get_default_timeout - get default session timeout value + +=head1 SYNOPSIS + + #include + + long SSL_get_default_timeout(SSL *ssl); + +=head1 DESCRIPTION + +SSL_get_default_timeout() returns the default timeout value assigned to +SSL_SESSION objects negotiated for the protocol valid for B. + +=head1 NOTES + +Whenever a new session is negotiated, it is assigned a timeout value, +after which it will not be accepted for session reuse. If the timeout +value was not explicitly set using +L, the hardcoded default +timeout for the protocol will be used. + +SSL_get_default_timeout() return this hardcoded value, which is 300 seconds +for all currently supported protocols (SSLv2, SSLv3, and TLSv1). + +=head1 RETURN VALUES + +See description. + +=head1 SEE ALSO + +L, +L, +L, +L, +L + +=cut diff --git a/doc/ssl/SSL_rstate_string.pod b/doc/ssl/SSL_rstate_string.pod new file mode 100644 index 000000000..bdb8a1fcd --- /dev/null +++ b/doc/ssl/SSL_rstate_string.pod @@ -0,0 +1,59 @@ +=pod + +=head1 NAME + +SSL_rstate_string, SSL_rstate_string_long - get textual description of state of an SSL object during read operation + +=head1 SYNOPSIS + + #include + + const char *SSL_rstate_string(SSL *ssl); + const char *SSL_rstate_string_long(SSL *ssl); + +=head1 DESCRIPTION + +SSL_rstate_string() returns a 2 letter string indicating the current read state +of the SSL object B. + +SSL_rstate_string_long() returns a string indicating the current read state of +the SSL object B. + +=head1 NOTES + +When performing a read operation, the SSL/TLS engine must parse the record, +consisting of header and body. When working in a blocking environment, +SSL_rstate_string[_long]() should always return "RD"/"read done". + +This function should only seldom be needed in applications. + +=head1 RETURN VALUES + +SSL_rstate_string() and SSL_rstate_string_long() can return the following +values: + +=over 4 + +=item "RH"/"read header" + +The header of the record is being evaluated. + +=item "RB"/"read body" + +The body of the record is being evaluated. + +=item "RD"/"read done" + +The record has been completely processed. + +=item "unknown"/"unknown" + +The read state is unknown. This should never happen. + +=back + +=head1 SEE ALSO + +L + +=cut diff --git a/doc/ssl/SSL_session_reused.pod b/doc/ssl/SSL_session_reused.pod new file mode 100644 index 000000000..da7d06264 --- /dev/null +++ b/doc/ssl/SSL_session_reused.pod @@ -0,0 +1,45 @@ +=pod + +=head1 NAME + +SSL_session_reused - query whether a reused session was negotiated during handshake + +=head1 SYNOPSIS + + #include + + int SSL_session_reused(SSL *ssl); + +=head1 DESCRIPTION + +Query, whether a reused session was negotiated during the handshake. + +=head1 NOTES + +During the negotiation, a client can propose to reuse a session. The server +then looks up the session in its cache. If both client and server agree +on the session, it will be reused and a flag is being set that can be +queried by the application. + +=head1 RETURN VALUES + +The following return values can occur: + +=over 4 + +=item 0 + +A new session was negotiated. + +=item 1 + +A session was reused. + +=back + +=head1 SEE ALSO + +L, L, +L + +=cut diff --git a/doc/ssl/SSL_state_string.pod b/doc/ssl/SSL_state_string.pod new file mode 100644 index 000000000..b4be1aaa4 --- /dev/null +++ b/doc/ssl/SSL_state_string.pod @@ -0,0 +1,45 @@ +=pod + +=head1 NAME + +SSL_state_string, SSL_state_string_long - get textual description of state of an SSL object + +=head1 SYNOPSIS + + #include + + const char *SSL_state_string(SSL *ssl); + const char *SSL_state_string_long(SSL *ssl); + +=head1 DESCRIPTION + +SSL_state_string() returns a 6 letter string indicating the current state +of the SSL object B. + +SSL_state_string_long() returns a string indicating the current state of +the SSL object B. + +=head1 NOTES + +During its use, an SSL objects passes several states. The state is internally +maintained. Querying the state information is not very informative before +or when a connection has been established. It however can be of significant +interest during the handshake. + +When using non-blocking sockets, the function call performing the handshake +may return with SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE condition, +so that SSL_state_string[_long]() may be called. + +For both blocking or non-blocking sockets, the details state information +can be used within the info_callback function set with the +SSL_set_info_callback() call. + +=head1 RETURN VALUES + +Detailed description of possible states to be included later. + +=head1 SEE ALSO + +L, L + +=cut diff --git a/doc/ssl/SSL_want.pod b/doc/ssl/SSL_want.pod new file mode 100644 index 000000000..50cc89db8 --- /dev/null +++ b/doc/ssl/SSL_want.pod @@ -0,0 +1,77 @@ +=pod + +=head1 NAME + +SSL_want, SSL_want_nothing, SSL_want_read, SSL_want_write, SSL_want_x509_lookup - obtain state information TLS/SSL I/O operation + +=head1 SYNOPSIS + + #include + + int SSL_want(SSL *ssl); + int SSL_want_nothing(SSL *ssl); + int SSL_want_read(SSL *ssl); + int SSL_want_write(SSL *ssl); + int SSL_want_x509_lookup(SSL *ssl); + +=head1 DESCRIPTION + +SSL_want() returns state information for the SSL object B. + +The other SSL_want_*() calls are shortcuts for the possible states returned +by SSL_want(). + +=head1 NOTES + +SSL_want() examines the internal state information of the SSL object. Its +return values are similar to that of L. +Unlike L, which also evaluates the +error queue, the results are obtained by examining an internal state flag +only. The information must therefore only be used for normal operation under +non-blocking I/O. Error conditions are not handled and must be treated +using L. + +The result returned by SSL_want() should always be consistent with +the result of L. + +=head1 RETURN VALUES + +The following return values can currently occur for SSL_want(): + +=over 4 + +=item SSL_NOTHING + +There is no data to be written or to be read. + +=item SSL_WRITING + +There are data in the SSL buffer that must be written to the underlying +B layer in order to complete the actual SSL_*() operation. +A call to L should return +SSL_ERROR_WANT_WRITE. + +=item SSL_READING + +More data must be read from the underlying B layer in order to +complete the actual SSL_*() operation. +A call to L should return +SSL_ERROR_WANT_READ. + +=item SSL_X509_LOOKUP + +The operation did not complete because an application callback set by +SSL_CTX_set_client_cert_cb() has asked to be called again. +A call to L should return +SSL_ERROR_WANT_X509_LOOKUP. + +=back + +SSL_want_nothing(), SSL_want_read(), SSL_want_write(), SSL_want_x509_lookup() +return 1, when the corresponding condition is true or 0 otherwise. + +=head1 SEE ALSO + +L, L, L + +=cut diff --git a/shlib/svr5-shared-gcc.sh b/shlib/svr5-shared-gcc.sh new file mode 100755 index 000000000..b36a0375a --- /dev/null +++ b/shlib/svr5-shared-gcc.sh @@ -0,0 +1,48 @@ +#!/usr/bin/sh + +major="0" +minor="9.7" + +slib=libssl +sh_slib=$slib.so.$major.$minor + +clib=libcrypto +sh_clib=$clib.so.$major.$minor + +FLAGS="-O3 -DFILIO_H -fomit-frame-pointer -pthread +SHFLAGS="-DPIC -fPIC" + +touch $sh_clib +touch $sh_slib + +echo collecting all object files for $clib.so +OBJS= +find . -name \*.o -print > allobjs +for obj in `ar t libcrypto.a` +do + OBJS="$OBJS `grep $obj allobjs`" +done + +echo linking $clib.so +gcc -G -o $sh_clib -h $sh_clib $OBJS -lnsl -lsocket + +rm -f $clib.so +ln -s $sh_clib $clib.so + +echo collecting all object files for $slib.so +OBJS= +for obj in `ar t libssl.a` +do + OBJS="$OBJS `grep $obj allobjs`" +done + +echo linking $slib.so +gcc -G -o $sh_slib -h $sh_slib $OBJS -L. -lcrypto + +rm -f $slib.so +ln -s $sh_slib $slib.so + +mv libRSAglue.a libRSAglue.a.orig +mv libcrypto.a libcrypto.a.orig +mv libssl.a libssl.a.orig + diff --git a/shlib/svr5-shared-installed b/shlib/svr5-shared-installed new file mode 100755 index 000000000..544f5a941 --- /dev/null +++ b/shlib/svr5-shared-installed @@ -0,0 +1,28 @@ +#!/usr/bin/sh + +major="0" +minor="9.7" + +slib=libssl +sh_slib=$slib.so.$major.$minor + +clib=libcrypto +sh_clib=$clib.so.$major.$minor + +# If you want them in /usr/local/lib then change INSTALLTOP to point there. +#INSTALLTOP=/usr/local/ssl/lib +INSTALLTOP=/usr/local/lib + +cp -p $sh_clib $INSTALLTOP +cp -p $sh_slib $INSTALLTOP + +PWD=`pwd` +cd $INSTALLTOP +rm -f $INSTALLTOP/$clib.so +ln -s $INSTALLTOP/$sh_clib $clib.so + +rm -f $INSTALLTOP/$slib.so +ln -s $INSTALLTOP/$sh_slib $slib.so + +cd $PWD + diff --git a/shlib/svr5-shared.sh b/shlib/svr5-shared.sh new file mode 100755 index 000000000..a70bb65ba --- /dev/null +++ b/shlib/svr5-shared.sh @@ -0,0 +1,48 @@ +#!/usr/bin/sh + +major="0" +minor="9.7" + +slib=libssl +sh_slib=$slib.so.$major.$minor + +clib=libcrypto +sh_clib=$clib.so.$major.$minor + +FLAGS="-O -DFILIO_H -Kalloca -Kthread" +SHFLAGS="-Kpic -DPIC" + +touch $sh_clib +touch $sh_slib + +echo collecting all object files for $clib.so +OBJS= +find . -name \*.o -print > allobjs +for obj in `ar t libcrypto.a` +do + OBJS="$OBJS `grep $obj allobjs`" +done + +echo linking $clib.so +cc -G -o $sh_clib -h $sh_clib $OBJS -lnsl -lsocket + +rm -f $clib.so +ln -s $sh_clib $clib.so + +echo collecting all object files for $slib.so +OBJS= +for obj in `ar t libssl.a` +do + OBJS="$OBJS `grep $obj allobjs`" +done + +echo linking $slib.so +cc -G -o $sh_slib -h $sh_slib $OBJS -L. -lcrypto + +rm -f $slib.so +ln -s $sh_slib $slib.so + +mv libRSAglue.a libRSAglue.a.orig +mv libcrypto.a libcrypto.a.orig +mv libssl.a libssl.a.orig +