From 5a3c0a05c7f2c5d3c584b7c8d6aec836dd724c80 Mon Sep 17 00:00:00 2001 From: djm <> Date: Sat, 6 Sep 2008 12:15:56 +0000 Subject: import of OpenSSL 0.9.8h --- src/lib/libcrypto/engine/eng_all.c | 31 +- src/lib/libcrypto/engine/eng_cnf.c | 7 +- src/lib/libcrypto/engine/eng_ctrl.c | 12 +- src/lib/libcrypto/engine/eng_dyn.c | 108 ++- src/lib/libcrypto/engine/eng_err.c | 16 +- src/lib/libcrypto/engine/eng_fat.c | 26 +- src/lib/libcrypto/engine/eng_init.c | 5 +- src/lib/libcrypto/engine/eng_int.h | 9 + src/lib/libcrypto/engine/eng_lib.c | 18 +- src/lib/libcrypto/engine/eng_list.c | 43 +- src/lib/libcrypto/engine/eng_openssl.c | 25 +- src/lib/libcrypto/engine/eng_padlock.c | 1219 ++++++++++++++++++++++++++++++++ src/lib/libcrypto/engine/eng_pkey.c | 3 - src/lib/libcrypto/engine/eng_table.c | 94 +-- src/lib/libcrypto/engine/engine.h | 158 +++-- src/lib/libcrypto/engine/tb_cipher.c | 2 - src/lib/libcrypto/engine/tb_dh.c | 2 - src/lib/libcrypto/engine/tb_digest.c | 2 - src/lib/libcrypto/engine/tb_dsa.c | 2 - src/lib/libcrypto/engine/tb_ecdh.c | 133 ++++ src/lib/libcrypto/engine/tb_ecdsa.c | 118 ++++ src/lib/libcrypto/engine/tb_rand.c | 2 - src/lib/libcrypto/engine/tb_rsa.c | 2 - src/lib/libcrypto/engine/tb_store.c | 123 ++++ 24 files changed, 1966 insertions(+), 194 deletions(-) create mode 100644 src/lib/libcrypto/engine/eng_padlock.c create mode 100644 src/lib/libcrypto/engine/tb_ecdh.c create mode 100644 src/lib/libcrypto/engine/tb_ecdsa.c create mode 100644 src/lib/libcrypto/engine/tb_store.c (limited to 'src/lib/libcrypto/engine') diff --git a/src/lib/libcrypto/engine/eng_all.c b/src/lib/libcrypto/engine/eng_all.c index 0f6992a40d..8599046717 100644 --- a/src/lib/libcrypto/engine/eng_all.c +++ b/src/lib/libcrypto/engine/eng_all.c @@ -56,8 +56,7 @@ * */ -#include -#include +#include "cryptlib.h" #include "eng_int.h" void ENGINE_load_builtin_engines(void) @@ -68,33 +67,43 @@ void ENGINE_load_builtin_engines(void) * *no* builtin implementations). */ #if 0 ENGINE_load_openssl(); +#endif +#if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) + ENGINE_load_padlock(); #endif ENGINE_load_dynamic(); +#ifndef OPENSSL_NO_STATIC_ENGINE #ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_4758_CCA + ENGINE_load_4758cca(); +#endif +#ifndef OPENSSL_NO_HW_AEP + ENGINE_load_aep(); +#endif +#ifndef OPENSSL_NO_HW_ATALLA + ENGINE_load_atalla(); +#endif #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_SUREWARE + ENGINE_load_sureware(); +#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(); +#if !defined(OPENSSL_NO_GMP) && !defined(OPENSSL_NO_HW_GMP) + ENGINE_load_gmp(); #endif -#ifndef OPENSSL_NO_HW_4758_CCA - ENGINE_load_4758cca(); #endif +#ifndef OPENSSL_NO_HW #if defined(__OpenBSD__) || defined(__FreeBSD__) ENGINE_load_cryptodev(); #endif diff --git a/src/lib/libcrypto/engine/eng_cnf.c b/src/lib/libcrypto/engine/eng_cnf.c index 4225760af1..a97e01e619 100644 --- a/src/lib/libcrypto/engine/eng_cnf.c +++ b/src/lib/libcrypto/engine/eng_cnf.c @@ -56,11 +56,8 @@ * */ -#include -#include -#include "cryptlib.h" +#include "eng_int.h" #include -#include /* #define ENGINE_CONF_DEBUG */ @@ -210,7 +207,7 @@ static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf) if (!elist) { - ENGINEerr(ENGINE_F_ENGINE_MODULE_INIT, ENGINE_R_ENGINES_SECTION_ERROR); + ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT, ENGINE_R_ENGINES_SECTION_ERROR); return 0; } diff --git a/src/lib/libcrypto/engine/eng_ctrl.c b/src/lib/libcrypto/engine/eng_ctrl.c index 412c73fb0f..95b6b455aa 100644 --- a/src/lib/libcrypto/engine/eng_ctrl.c +++ b/src/lib/libcrypto/engine/eng_ctrl.c @@ -53,10 +53,7 @@ * */ -#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. */ @@ -103,7 +100,8 @@ static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num) return -1; } -static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, void (*f)()) +static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, + void (*f)(void)) { int idx; char *s = (char *)p; @@ -181,7 +179,7 @@ static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, void (*f)()) return -1; } -int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) { int ctrl_exists, ref_exists; if(e == NULL) @@ -251,13 +249,13 @@ 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) + long i, void *p, void (*f)(void), int cmd_optional) { int num; if((e == NULL) || (cmd_name == NULL)) { - ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, + ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ERR_R_PASSED_NULL_PARAMETER); return 0; } diff --git a/src/lib/libcrypto/engine/eng_dyn.c b/src/lib/libcrypto/engine/eng_dyn.c index 4139a16e76..acb30c34d8 100644 --- a/src/lib/libcrypto/engine/eng_dyn.c +++ b/src/lib/libcrypto/engine/eng_dyn.c @@ -57,11 +57,7 @@ */ -#include -#include -#include "cryptlib.h" #include "eng_int.h" -#include #include /* Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE loader @@ -70,7 +66,7 @@ /* 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)()); +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); /* Predeclare our context type */ typedef struct st_dynamic_data_ctx dynamic_data_ctx; /* The implementation for the important control command */ @@ -80,7 +76,9 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx); #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) +#define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4) +#define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5) +#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6) /* The constants used when creating the ENGINE */ static const char *engine_dynamic_id = "dynamic"; @@ -102,6 +100,14 @@ static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = { "LIST_ADD", "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_DIR_LOAD, + "DIR_LOAD", + "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_DIR_ADD, + "DIR_ADD", + "Adds a directory from which ENGINEs can be loaded", + ENGINE_CMD_FLAG_STRING}, {DYNAMIC_CMD_LOAD, "LOAD", "Load up the ENGINE specified by other settings", @@ -136,12 +142,18 @@ struct st_dynamic_data_ctx const char *DYNAMIC_F1; /* The symbol name for the "initialise ENGINE structure" function */ const char *DYNAMIC_F2; + /* Whether to never use 'dirs', use 'dirs' as a fallback, or only use + * 'dirs' for loading. Default is to use 'dirs' as a fallback. */ + int dir_load; + /* A stack of directories from which ENGINEs could be loaded */ + STACK *dirs; }; /* This is the "ex_data" index we obtain and reserve for use with our context * structure. */ static int dynamic_ex_data_idx = -1; +static void int_free_str(void *s) { OPENSSL_free(s); } /* 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 @@ -161,6 +173,8 @@ static void dynamic_data_ctx_free_func(void *parent, void *ptr, OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); if(ctx->engine_id) OPENSSL_free((void*)ctx->engine_id); + if(ctx->dirs) + sk_pop_free(ctx->dirs, int_free_str); OPENSSL_free(ctx); } } @@ -175,7 +189,7 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) c = OPENSSL_malloc(sizeof(dynamic_data_ctx)); if(!c) { - ENGINEerr(ENGINE_F_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); + ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); return 0; } memset(c, 0, sizeof(dynamic_data_ctx)); @@ -188,6 +202,14 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) c->list_add_value = 0; c->DYNAMIC_F1 = "v_check"; c->DYNAMIC_F2 = "bind_engine"; + c->dir_load = 1; + c->dirs = sk_new_null(); + if(!c->dirs) + { + ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); + OPENSSL_free(c); + return 0; + } CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); if((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx)) == NULL) @@ -290,7 +312,7 @@ static int dynamic_finish(ENGINE *e) return 0; } -static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) { dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); int initialised; @@ -346,6 +368,34 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) return 1; case DYNAMIC_CMD_LOAD: return dynamic_load(e, ctx); + case DYNAMIC_CMD_DIR_LOAD: + if((i < 0) || (i > 2)) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ENGINE_R_INVALID_ARGUMENT); + return 0; + } + ctx->dir_load = (int)i; + return 1; + case DYNAMIC_CMD_DIR_ADD: + /* a NULL 'p' or a string of zero-length is the same thing */ + if(!p || (strlen((const char *)p) < 1)) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ENGINE_R_INVALID_ARGUMENT); + return 0; + } + { + char *tmp_str = BUF_strdup(p); + if(!tmp_str) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ERR_R_MALLOC_FAILURE); + return 0; + } + sk_insert(ctx->dirs, tmp_str, -1); + } + return 1; default: break; } @@ -353,16 +403,53 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) return 0; } +static int int_load(dynamic_data_ctx *ctx) + { + int num, loop; + /* Unless told not to, try a direct load */ + if((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso, + ctx->DYNAMIC_LIBNAME, NULL, 0)) != NULL) + return 1; + /* If we're not allowed to use 'dirs' or we have none, fail */ + if(!ctx->dir_load || ((num = sk_num(ctx->dirs)) < 1)) + return 0; + for(loop = 0; loop < num; loop++) + { + const char *s = sk_value(ctx->dirs, loop); + char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s); + if(!merge) + return 0; + if(DSO_load(ctx->dynamic_dso, merge, NULL, 0)) + { + /* Found what we're looking for */ + OPENSSL_free(merge); + return 1; + } + OPENSSL_free(merge); + } + 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)) + if(!ctx->dynamic_dso) + ctx->dynamic_dso = DSO_new(); + if(!ctx->DYNAMIC_LIBNAME) + { + if(!ctx->engine_id) + return 0; + ctx->DYNAMIC_LIBNAME = + DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id); + } + if(!int_load(ctx)) { ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND); + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; return 0; } /* We have to find a bind function otherwise it'll always end badly */ @@ -409,6 +496,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) * 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.static_state = ENGINE_get_static_state(); fns.err_fns = ERR_get_implementation(); fns.ex_data_fns = CRYPTO_get_ex_data_implementation(); CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb, diff --git a/src/lib/libcrypto/engine/eng_err.c b/src/lib/libcrypto/engine/eng_err.c index fdc0e7be0f..369f2e22d3 100644 --- a/src/lib/libcrypto/engine/eng_err.c +++ b/src/lib/libcrypto/engine/eng_err.c @@ -73,6 +73,7 @@ static ERR_STRING_DATA ENGINE_str_functs[]= {ERR_FUNC(ENGINE_F_DYNAMIC_CTRL), "DYNAMIC_CTRL"}, {ERR_FUNC(ENGINE_F_DYNAMIC_GET_DATA_CTX), "DYNAMIC_GET_DATA_CTX"}, {ERR_FUNC(ENGINE_F_DYNAMIC_LOAD), "DYNAMIC_LOAD"}, +{ERR_FUNC(ENGINE_F_DYNAMIC_SET_DATA_CTX), "DYNAMIC_SET_DATA_CTX"}, {ERR_FUNC(ENGINE_F_ENGINE_ADD), "ENGINE_add"}, {ERR_FUNC(ENGINE_F_ENGINE_BY_ID), "ENGINE_by_id"}, {ERR_FUNC(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE), "ENGINE_cmd_is_executable"}, @@ -80,7 +81,7 @@ static ERR_STRING_DATA ENGINE_str_functs[]= {ERR_FUNC(ENGINE_F_ENGINE_CTRL_CMD), "ENGINE_ctrl_cmd"}, {ERR_FUNC(ENGINE_F_ENGINE_CTRL_CMD_STRING), "ENGINE_ctrl_cmd_string"}, {ERR_FUNC(ENGINE_F_ENGINE_FINISH), "ENGINE_finish"}, -{ERR_FUNC(ENGINE_F_ENGINE_FREE), "ENGINE_free"}, +{ERR_FUNC(ENGINE_F_ENGINE_FREE_UTIL), "ENGINE_FREE_UTIL"}, {ERR_FUNC(ENGINE_F_ENGINE_GET_CIPHER), "ENGINE_get_cipher"}, {ERR_FUNC(ENGINE_F_ENGINE_GET_DEFAULT_TYPE), "ENGINE_GET_DEFAULT_TYPE"}, {ERR_FUNC(ENGINE_F_ENGINE_GET_DIGEST), "ENGINE_get_digest"}, @@ -91,7 +92,6 @@ static ERR_STRING_DATA ENGINE_str_functs[]= {ERR_FUNC(ENGINE_F_ENGINE_LIST_REMOVE), "ENGINE_LIST_REMOVE"}, {ERR_FUNC(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY), "ENGINE_load_private_key"}, {ERR_FUNC(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY), "ENGINE_load_public_key"}, -{ERR_FUNC(ENGINE_F_ENGINE_MODULE_INIT), "ENGINE_MODULE_INIT"}, {ERR_FUNC(ENGINE_F_ENGINE_NEW), "ENGINE_new"}, {ERR_FUNC(ENGINE_F_ENGINE_REMOVE), "ENGINE_remove"}, {ERR_FUNC(ENGINE_F_ENGINE_SET_DEFAULT_STRING), "ENGINE_set_default_string"}, @@ -100,11 +100,12 @@ static ERR_STRING_DATA ENGINE_str_functs[]= {ERR_FUNC(ENGINE_F_ENGINE_SET_NAME), "ENGINE_set_name"}, {ERR_FUNC(ENGINE_F_ENGINE_TABLE_REGISTER), "ENGINE_TABLE_REGISTER"}, {ERR_FUNC(ENGINE_F_ENGINE_UNLOAD_KEY), "ENGINE_UNLOAD_KEY"}, +{ERR_FUNC(ENGINE_F_ENGINE_UNLOCKED_FINISH), "ENGINE_UNLOCKED_FINISH"}, {ERR_FUNC(ENGINE_F_ENGINE_UP_REF), "ENGINE_up_ref"}, {ERR_FUNC(ENGINE_F_INT_CTRL_HELPER), "INT_CTRL_HELPER"}, {ERR_FUNC(ENGINE_F_INT_ENGINE_CONFIGURE), "INT_ENGINE_CONFIGURE"}, +{ERR_FUNC(ENGINE_F_INT_ENGINE_MODULE_INIT), "INT_ENGINE_MODULE_INIT"}, {ERR_FUNC(ENGINE_F_LOG_MESSAGE), "LOG_MESSAGE"}, -{ERR_FUNC(ENGINE_F_SET_DATA_CTX), "SET_DATA_CTX"}, {0,NULL} }; @@ -156,15 +157,12 @@ static ERR_STRING_DATA ENGINE_str_reasons[]= void ERR_load_ENGINE_strings(void) { - static int init=1; +#ifndef OPENSSL_NO_ERR - if (init) + if (ERR_func_error_string(ENGINE_str_functs[0].error) == NULL) { - init=0; -#ifndef OPENSSL_NO_ERR ERR_load_strings(0,ENGINE_str_functs); ERR_load_strings(0,ENGINE_str_reasons); -#endif - } +#endif } diff --git a/src/lib/libcrypto/engine/eng_fat.c b/src/lib/libcrypto/engine/eng_fat.c index 7ccf7022ee..27c1662f62 100644 --- a/src/lib/libcrypto/engine/eng_fat.c +++ b/src/lib/libcrypto/engine/eng_fat.c @@ -52,11 +52,13 @@ * Hudson (tjh@cryptsoft.com). * */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ -#include -#include "cryptlib.h" #include "eng_int.h" -#include #include int ENGINE_set_default(ENGINE *e, unsigned int flags) @@ -76,6 +78,14 @@ int ENGINE_set_default(ENGINE *e, unsigned int flags) #ifndef OPENSSL_NO_DH if((flags & ENGINE_METHOD_DH) && !ENGINE_set_default_DH(e)) return 0; +#endif +#ifndef OPENSSL_NO_ECDH + if((flags & ENGINE_METHOD_ECDH) && !ENGINE_set_default_ECDH(e)) + return 0; +#endif +#ifndef OPENSSL_NO_ECDSA + if((flags & ENGINE_METHOD_ECDSA) && !ENGINE_set_default_ECDSA(e)) + return 0; #endif if((flags & ENGINE_METHOD_RAND) && !ENGINE_set_default_RAND(e)) return 0; @@ -93,6 +103,10 @@ static int int_def_cb(const char *alg, int len, void *arg) *pflags |= ENGINE_METHOD_RSA; else if (!strncmp(alg, "DSA", len)) *pflags |= ENGINE_METHOD_DSA; + else if (!strncmp(alg, "ECDH", len)) + *pflags |= ENGINE_METHOD_ECDH; + else if (!strncmp(alg, "ECDSA", len)) + *pflags |= ENGINE_METHOD_ECDSA; else if (!strncmp(alg, "DH", len)) *pflags |= ENGINE_METHOD_DH; else if (!strncmp(alg, "RAND", len)) @@ -132,6 +146,12 @@ int ENGINE_register_complete(ENGINE *e) #endif #ifndef OPENSSL_NO_DH ENGINE_register_DH(e); +#endif +#ifndef OPENSSL_NO_ECDH + ENGINE_register_ECDH(e); +#endif +#ifndef OPENSSL_NO_ECDSA + ENGINE_register_ECDSA(e); #endif ENGINE_register_RAND(e); return 1; diff --git a/src/lib/libcrypto/engine/eng_init.c b/src/lib/libcrypto/engine/eng_init.c index 170c1791b3..7633cf5f1d 100644 --- a/src/lib/libcrypto/engine/eng_init.c +++ b/src/lib/libcrypto/engine/eng_init.c @@ -53,10 +53,7 @@ * */ -#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. */ @@ -114,7 +111,7 @@ int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) /* Release the structural reference too */ if(!engine_free_util(e, 0)) { - ENGINEerr(ENGINE_F_ENGINE_FINISH,ENGINE_R_FINISH_FAILED); + ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_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 index 38335f99cd..a5b1edebf4 100644 --- a/src/lib/libcrypto/engine/eng_int.h +++ b/src/lib/libcrypto/engine/eng_int.h @@ -55,10 +55,16 @@ * Hudson (tjh@cryptsoft.com). * */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ #ifndef HEADER_ENGINE_INT_H #define HEADER_ENGINE_INT_H +#include "cryptlib.h" /* Take public definitions from engine.h */ #include @@ -146,7 +152,10 @@ struct engine_st const RSA_METHOD *rsa_meth; const DSA_METHOD *dsa_meth; const DH_METHOD *dh_meth; + const ECDH_METHOD *ecdh_meth; + const ECDSA_METHOD *ecdsa_meth; const RAND_METHOD *rand_meth; + const STORE_METHOD *store_meth; /* Cipher handling is via this callback */ ENGINE_CIPHERS_PTR ciphers; /* Digest handling is via this callback */ diff --git a/src/lib/libcrypto/engine/eng_lib.c b/src/lib/libcrypto/engine/eng_lib.c index a66d0f08af..5815b867f4 100644 --- a/src/lib/libcrypto/engine/eng_lib.c +++ b/src/lib/libcrypto/engine/eng_lib.c @@ -56,11 +56,8 @@ * */ -#include -#include "cryptlib.h" #include "eng_int.h" -#include /* FIXME: This shouldn't be needed */ -#include +#include /* The "new"/"free" stuff first */ @@ -92,6 +89,7 @@ void engine_set_all_null(ENGINE *e) e->dsa_meth = NULL; e->dh_meth = NULL; e->rand_meth = NULL; + e->store_meth = NULL; e->ciphers = NULL; e->digests = NULL; e->destroy = NULL; @@ -110,7 +108,7 @@ int engine_free_util(ENGINE *e, int locked) if(e == NULL) { - ENGINEerr(ENGINE_F_ENGINE_FREE, + ENGINEerr(ENGINE_F_ENGINE_FREE_UTIL, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -319,3 +317,13 @@ const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e) { return e->cmd_defns; } + +/* eng_lib.o is pretty much linked into anything that touches ENGINE already, so + * put the "static_state" hack here. */ + +static int internal_static_hack = 0; + +void *ENGINE_get_static_state(void) + { + return &internal_static_hack; + } diff --git a/src/lib/libcrypto/engine/eng_list.c b/src/lib/libcrypto/engine/eng_list.c index 1cc3217f4c..bd511944ba 100644 --- a/src/lib/libcrypto/engine/eng_list.c +++ b/src/lib/libcrypto/engine/eng_list.c @@ -55,11 +55,13 @@ * Hudson (tjh@cryptsoft.com). * */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ -#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 @@ -323,8 +325,15 @@ static void engine_cpy(ENGINE *dest, const ENGINE *src) #endif #ifndef OPENSSL_NO_DH dest->dh_meth = src->dh_meth; +#endif +#ifndef OPENSSL_NO_ECDH + dest->ecdh_meth = src->ecdh_meth; +#endif +#ifndef OPENSSL_NO_ECDSA + dest->ecdsa_meth = src->ecdsa_meth; #endif dest->rand_meth = src->rand_meth; + dest->store_meth = src->store_meth; dest->ciphers = src->ciphers; dest->digests = src->digests; dest->destroy = src->destroy; @@ -340,6 +349,7 @@ static void engine_cpy(ENGINE *dest, const ENGINE *src) ENGINE *ENGINE_by_id(const char *id) { ENGINE *iterator; + char *load_dir = NULL; if(id == NULL) { ENGINEerr(ENGINE_F_ENGINE_BY_ID, @@ -373,6 +383,7 @@ ENGINE *ENGINE_by_id(const char *id) } } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); +#if 0 if(iterator == NULL) { ENGINEerr(ENGINE_F_ENGINE_BY_ID, @@ -380,6 +391,32 @@ ENGINE *ENGINE_by_id(const char *id) ERR_add_error_data(2, "id=", id); } return iterator; +#else + /* EEK! Experimental code starts */ + if(iterator) return iterator; + /* Prevent infinite recusrion if we're looking for the dynamic engine. */ + if (strcmp(id, "dynamic")) + { +#ifdef OPENSSL_SYS_VMS + if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]"; +#else + if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR; +#endif + iterator = ENGINE_by_id("dynamic"); + if(!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) || + !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) || + !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD", + load_dir, 0) || + !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0)) + goto notfound; + return iterator; + } +notfound: + ENGINEerr(ENGINE_F_ENGINE_BY_ID,ENGINE_R_NO_SUCH_ENGINE); + ERR_add_error_data(2, "id=", id); + return NULL; + /* EEK! Experimental code ends */ +#endif } int ENGINE_up_ref(ENGINE *e) diff --git a/src/lib/libcrypto/engine/eng_openssl.c b/src/lib/libcrypto/engine/eng_openssl.c index 54579eea2e..7c139ae2ef 100644 --- a/src/lib/libcrypto/engine/eng_openssl.c +++ b/src/lib/libcrypto/engine/eng_openssl.c @@ -55,6 +55,11 @@ * Hudson (tjh@cryptsoft.com). * */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ #include @@ -64,6 +69,16 @@ #include #include #include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif /* This testing gunk is implemented (and explained) lower down. It also assumes * the application explicitly calls "ENGINE_load_openssl()" because this is no @@ -125,6 +140,12 @@ static int bind_helper(ENGINE *e) #ifndef OPENSSL_NO_DSA || !ENGINE_set_DSA(e, DSA_get_default_method()) #endif +#ifndef OPENSSL_NO_ECDH + || !ENGINE_set_ECDH(e, ECDH_OpenSSL()) +#endif +#ifndef OPENSSL_NO_ECDSA + || !ENGINE_set_ECDSA(e, ECDSA_OpenSSL()) +#endif #ifndef OPENSSL_NO_DH || !ENGINE_set_DH(e, DH_get_default_method()) #endif @@ -236,6 +257,7 @@ static const EVP_CIPHER test_r4_cipher= sizeof(TEST_RC4_KEY), NULL, NULL, + NULL, NULL }; static const EVP_CIPHER test_r4_40_cipher= @@ -249,6 +271,7 @@ static const EVP_CIPHER test_r4_40_cipher= sizeof(TEST_RC4_KEY), NULL, NULL, + NULL, NULL }; static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, @@ -290,7 +313,7 @@ static int test_sha1_init(EVP_MD_CTX *ctx) #endif return SHA1_Init(ctx->md_data); } -static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,unsigned long count) +static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,size_t count) { #ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n"); diff --git a/src/lib/libcrypto/engine/eng_padlock.c b/src/lib/libcrypto/engine/eng_padlock.c new file mode 100644 index 0000000000..1ba9d85db4 --- /dev/null +++ b/src/lib/libcrypto/engine/eng_padlock.c @@ -0,0 +1,1219 @@ +/* + * Support for VIA PadLock Advanced Cryptography Engine (ACE) + * Written by Michal Ludvig + * http://www.logix.cz/michal + * + * Big thanks to Andy Polyakov for a help with optimization, + * assembler fixes, port to MS Windows and a lot of other + * valuable work on this engine! + */ + +/* ==================================================================== + * 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 +#include +#include +#include +#include +#ifndef OPENSSL_NO_AES +#include +#endif +#include +#include + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PADLOCK + +/* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */ +#if (OPENSSL_VERSION_NUMBER >= 0x00908000L) +# ifndef OPENSSL_NO_DYNAMIC_ENGINE +# define DYNAMIC_ENGINE +# endif +#elif (OPENSSL_VERSION_NUMBER >= 0x00907000L) +# ifdef ENGINE_DYNAMIC_SUPPORT +# define DYNAMIC_ENGINE +# endif +#else +# error "Only OpenSSL >= 0.9.7 is supported" +#endif + +/* VIA PadLock AES is available *ONLY* on some x86 CPUs. + Not only that it doesn't exist elsewhere, but it + even can't be compiled on other platforms! + + In addition, because of the heavy use of inline assembler, + compiler choice is limited to GCC and Microsoft C. */ +#undef COMPILE_HW_PADLOCK +#if !defined(I386_ONLY) && !defined(OPENSSL_NO_INLINE_ASM) +# if (defined(__GNUC__) && (defined(__i386__) || defined(__i386))) || \ + (defined(_MSC_VER) && defined(_M_IX86)) +# define COMPILE_HW_PADLOCK +static ENGINE *ENGINE_padlock (void); +# endif +#endif + +void ENGINE_load_padlock (void) +{ +/* On non-x86 CPUs it just returns. */ +#ifdef COMPILE_HW_PADLOCK + ENGINE *toadd = ENGINE_padlock (); + if (!toadd) return; + ENGINE_add (toadd); + ENGINE_free (toadd); + ERR_clear_error (); +#endif +} + +#ifdef COMPILE_HW_PADLOCK +/* We do these includes here to avoid header problems on platforms that + do not have the VIA padlock anyway... */ +#ifdef _MSC_VER +# include +# define alloca _alloca +#elif defined(NETWARE_CLIB) && defined(__GNUC__) + void *alloca(size_t); +# define alloca(s) __builtin_alloca(s) +#else +# include +#endif + +/* Function for ENGINE detection and control */ +static int padlock_available(void); +static int padlock_init(ENGINE *e); + +/* RNG Stuff */ +static RAND_METHOD padlock_rand; + +/* Cipher Stuff */ +#ifndef OPENSSL_NO_AES +static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); +#endif + +/* Engine names */ +static const char *padlock_id = "padlock"; +static char padlock_name[100]; + +/* Available features */ +static int padlock_use_ace = 0; /* Advanced Cryptography Engine */ +static int padlock_use_rng = 0; /* Random Number Generator */ +#ifndef OPENSSL_NO_AES +static int padlock_aes_align_required = 1; +#endif + +/* ===== Engine "management" functions ===== */ + +/* Prepare the ENGINE structure for registration */ +static int +padlock_bind_helper(ENGINE *e) +{ + /* Check available features */ + padlock_available(); + +#if 1 /* disable RNG for now, see commentary in vicinity of RNG code */ + padlock_use_rng=0; +#endif + + /* Generate a nice engine name with available features */ + BIO_snprintf(padlock_name, sizeof(padlock_name), + "VIA PadLock (%s, %s)", + padlock_use_rng ? "RNG" : "no-RNG", + padlock_use_ace ? "ACE" : "no-ACE"); + + /* Register everything or return with an error */ + if (!ENGINE_set_id(e, padlock_id) || + !ENGINE_set_name(e, padlock_name) || + + !ENGINE_set_init_function(e, padlock_init) || +#ifndef OPENSSL_NO_AES + (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) || +#endif + (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) { + return 0; + } + + /* Everything looks good */ + return 1; +} + +/* Constructor */ +static ENGINE * +ENGINE_padlock(void) +{ + ENGINE *eng = ENGINE_new(); + + if (!eng) { + return NULL; + } + + if (!padlock_bind_helper(eng)) { + ENGINE_free(eng); + return NULL; + } + + return eng; +} + +/* Check availability of the engine */ +static int +padlock_init(ENGINE *e) +{ + return (padlock_use_rng || padlock_use_ace); +} + +/* This stuff is needed if this ENGINE is being compiled into a self-contained + * shared-library. + */ +#ifdef DYNAMIC_ENGINE +static int +padlock_bind_fn(ENGINE *e, const char *id) +{ + if (id && (strcmp(id, padlock_id) != 0)) { + return 0; + } + + if (!padlock_bind_helper(e)) { + return 0; + } + + return 1; +} + +IMPLEMENT_DYNAMIC_CHECK_FN (); +IMPLEMENT_DYNAMIC_BIND_FN (padlock_bind_fn); +#endif /* DYNAMIC_ENGINE */ + +/* ===== Here comes the "real" engine ===== */ + +#ifndef OPENSSL_NO_AES +/* Some AES-related constants */ +#define AES_BLOCK_SIZE 16 +#define AES_KEY_SIZE_128 16 +#define AES_KEY_SIZE_192 24 +#define AES_KEY_SIZE_256 32 + +/* Here we store the status information relevant to the + current context. */ +/* BIG FAT WARNING: + * Inline assembler in PADLOCK_XCRYPT_ASM() + * depends on the order of items in this structure. + * Don't blindly modify, reorder, etc! + */ +struct padlock_cipher_data +{ + unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */ + union { unsigned int pad[4]; + struct { + int rounds:4; + int dgst:1; /* n/a in C3 */ + int align:1; /* n/a in C3 */ + int ciphr:1; /* n/a in C3 */ + unsigned int keygen:1; + int interm:1; + unsigned int encdec:1; + int ksize:2; + } b; + } cword; /* Control word */ + AES_KEY ks; /* Encryption key */ +}; + +/* + * Essentially this variable belongs in thread local storage. + * Having this variable global on the other hand can only cause + * few bogus key reloads [if any at all on single-CPU system], + * so we accept the penatly... + */ +static volatile struct padlock_cipher_data *padlock_saved_context; +#endif + +/* + * ======================================================= + * Inline assembler section(s). + * ======================================================= + * Order of arguments is chosen to facilitate Windows port + * using __fastcall calling convention. If you wish to add + * more routines, keep in mind that first __fastcall + * argument is passed in %ecx and second - in %edx. + * ======================================================= + */ +#if defined(__GNUC__) && __GNUC__>=2 +/* + * As for excessive "push %ebx"/"pop %ebx" found all over. + * When generating position-independent code GCC won't let + * us use "b" in assembler templates nor even respect "ebx" + * in "clobber description." Therefore the trouble... + */ + +/* Helper function - check if a CPUID instruction + is available on this CPU */ +static int +padlock_insn_cpuid_available(void) +{ + int result = -1; + + /* We're checking if the bit #21 of EFLAGS + can be toggled. If yes = CPUID is available. */ + asm volatile ( + "pushf\n" + "popl %%eax\n" + "xorl $0x200000, %%eax\n" + "movl %%eax, %%ecx\n" + "andl $0x200000, %%ecx\n" + "pushl %%eax\n" + "popf\n" + "pushf\n" + "popl %%eax\n" + "andl $0x200000, %%eax\n" + "xorl %%eax, %%ecx\n" + "movl %%ecx, %0\n" + : "=r" (result) : : "eax", "ecx"); + + return (result == 0); +} + +/* Load supported features of the CPU to see if + the PadLock is available. */ +static int +padlock_available(void) +{ + char vendor_string[16]; + unsigned int eax, edx; + + /* First check if the CPUID instruction is available at all... */ + if (! padlock_insn_cpuid_available()) + return 0; + + /* Are we running on the Centaur (VIA) CPU? */ + eax = 0x00000000; + vendor_string[12] = 0; + asm volatile ( + "pushl %%ebx\n" + "cpuid\n" + "movl %%ebx,(%%edi)\n" + "movl %%edx,4(%%edi)\n" + "movl %%ecx,8(%%edi)\n" + "popl %%ebx" + : "+a"(eax) : "D"(vendor_string) : "ecx", "edx"); + if (strcmp(vendor_string, "CentaurHauls") != 0) + return 0; + + /* Check for Centaur Extended Feature Flags presence */ + eax = 0xC0000000; + asm volatile ("pushl %%ebx; cpuid; popl %%ebx" + : "+a"(eax) : : "ecx", "edx"); + if (eax < 0xC0000001) + return 0; + + /* Read the Centaur Extended Feature Flags */ + eax = 0xC0000001; + asm volatile ("pushl %%ebx; cpuid; popl %%ebx" + : "+a"(eax), "=d"(edx) : : "ecx"); + + /* Fill up some flags */ + padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6)); + padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2)); + + return padlock_use_ace + padlock_use_rng; +} + +#ifndef OPENSSL_NO_AES +/* Our own htonl()/ntohl() */ +static inline void +padlock_bswapl(AES_KEY *ks) +{ + size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]); + unsigned int *key = ks->rd_key; + + while (i--) { + asm volatile ("bswapl %0" : "+r"(*key)); + key++; + } +} +#endif + +/* Force key reload from memory to the CPU microcode. + Loading EFLAGS from the stack clears EFLAGS[30] + which does the trick. */ +static inline void +padlock_reload_key(void) +{ + asm volatile ("pushfl; popfl"); +} + +#ifndef OPENSSL_NO_AES +/* + * This is heuristic key context tracing. At first one + * believes that one should use atomic swap instructions, + * but it's not actually necessary. Point is that if + * padlock_saved_context was changed by another thread + * after we've read it and before we compare it with cdata, + * our key *shall* be reloaded upon thread context switch + * and we are therefore set in either case... + */ +static inline void +padlock_verify_context(struct padlock_cipher_data *cdata) +{ + asm volatile ( + "pushfl\n" +" btl $30,(%%esp)\n" +" jnc 1f\n" +" cmpl %2,%1\n" +" je 1f\n" +" popfl\n" +" subl $4,%%esp\n" +"1: addl $4,%%esp\n" +" movl %2,%0" + :"+m"(padlock_saved_context) + : "r"(padlock_saved_context), "r"(cdata) : "cc"); +} + +/* Template for padlock_xcrypt_* modes */ +/* BIG FAT WARNING: + * The offsets used with 'leal' instructions + * describe items of the 'padlock_cipher_data' + * structure. + */ +#define PADLOCK_XCRYPT_ASM(name,rep_xcrypt) \ +static inline void *name(size_t cnt, \ + struct padlock_cipher_data *cdata, \ + void *out, const void *inp) \ +{ void *iv; \ + asm volatile ( "pushl %%ebx\n" \ + " leal 16(%0),%%edx\n" \ + " leal 32(%0),%%ebx\n" \ + rep_xcrypt "\n" \ + " popl %%ebx" \ + : "=a"(iv), "=c"(cnt), "=D"(out), "=S"(inp) \ + : "0"(cdata), "1"(cnt), "2"(out), "3"(inp) \ + : "edx", "cc", "memory"); \ + return iv; \ +} + +/* Generate all functions with appropriate opcodes */ +PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb, ".byte 0xf3,0x0f,0xa7,0xc8") /* rep xcryptecb */ +PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc, ".byte 0xf3,0x0f,0xa7,0xd0") /* rep xcryptcbc */ +PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb, ".byte 0xf3,0x0f,0xa7,0xe0") /* rep xcryptcfb */ +PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb, ".byte 0xf3,0x0f,0xa7,0xe8") /* rep xcryptofb */ +#endif + +/* The RNG call itself */ +static inline unsigned int +padlock_xstore(void *addr, unsigned int edx_in) +{ + unsigned int eax_out; + + asm volatile (".byte 0x0f,0xa7,0xc0" /* xstore */ + : "=a"(eax_out),"=m"(*(unsigned *)addr) + : "D"(addr), "d" (edx_in) + ); + + return eax_out; +} + +/* Why not inline 'rep movsd'? I failed to find information on what + * value in Direction Flag one can expect and consequently have to + * apply "better-safe-than-sorry" approach and assume "undefined." + * I could explicitly clear it and restore the original value upon + * return from padlock_aes_cipher, but it's presumably too much + * trouble for too little gain... + * + * In case you wonder 'rep xcrypt*' instructions above are *not* + * affected by the Direction Flag and pointers advance toward + * larger addresses unconditionally. + */ +static inline unsigned char * +padlock_memcpy(void *dst,const void *src,size_t n) +{ + long *d=dst; + const long *s=src; + + n /= sizeof(*d); + do { *d++ = *s++; } while (--n); + + return dst; +} + +#elif defined(_MSC_VER) +/* + * Unlike GCC these are real functions. In order to minimize impact + * on performance we adhere to __fastcall calling convention in + * order to get two first arguments passed through %ecx and %edx. + * Which kind of suits very well, as instructions in question use + * both %ecx and %edx as input:-) + */ +#define REP_XCRYPT(code) \ + _asm _emit 0xf3 \ + _asm _emit 0x0f _asm _emit 0xa7 \ + _asm _emit code + +/* BIG FAT WARNING: + * The offsets used with 'lea' instructions + * describe items of the 'padlock_cipher_data' + * structure. + */ +#define PADLOCK_XCRYPT_ASM(name,code) \ +static void * __fastcall \ + name (size_t cnt, void *cdata, \ + void *outp, const void *inp) \ +{ _asm mov eax,edx \ + _asm lea edx,[eax+16] \ + _asm lea ebx,[eax+32] \ + _asm mov edi,outp \ + _asm mov esi,inp \ + REP_XCRYPT(code) \ +} + +PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb,0xc8) +PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc,0xd0) +PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb,0xe0) +PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb,0xe8) + +static int __fastcall +padlock_xstore(void *outp,unsigned int code) +{ _asm mov edi,ecx + _asm _emit 0x0f _asm _emit 0xa7 _asm _emit 0xc0 +} + +static void __fastcall +padlock_reload_key(void) +{ _asm pushfd _asm popfd } + +static void __fastcall +padlock_verify_context(void *cdata) +{ _asm { + pushfd + bt DWORD PTR[esp],30 + jnc skip + cmp ecx,padlock_saved_context + je skip + popfd + sub esp,4 + skip: add esp,4 + mov padlock_saved_context,ecx + } +} + +static int +padlock_available(void) +{ _asm { + pushfd + pop eax + mov ecx,eax + xor eax,1<<21 + push eax + popfd + pushfd + pop eax + xor eax,ecx + bt eax,21 + jnc noluck + mov eax,0 + cpuid + xor eax,eax + cmp ebx,'tneC' + jne noluck + cmp edx,'Hrua' + jne noluck + cmp ecx,'slua' + jne noluck + mov eax,0xC0000000 + cpuid + mov edx,eax + xor eax,eax + cmp edx,0xC0000001 + jb noluck + mov eax,0xC0000001 + cpuid + xor eax,eax + bt edx,6 + jnc skip_a + bt edx,7 + jnc skip_a + mov padlock_use_ace,1 + inc eax + skip_a: bt edx,2 + jnc skip_r + bt edx,3 + jnc skip_r + mov padlock_use_rng,1 + inc eax + skip_r: + noluck: + } +} + +static void __fastcall +padlock_bswapl(void *key) +{ _asm { + pushfd + cld + mov esi,ecx + mov edi,ecx + mov ecx,60 + up: lodsd + bswap eax + stosd + loop up + popfd + } +} + +/* MS actually specifies status of Direction Flag and compiler even + * manages to compile following as 'rep movsd' all by itself... + */ +#define padlock_memcpy(o,i,n) ((unsigned char *)memcpy((o),(i),(n)&~3U)) +#endif + +/* ===== AES encryption/decryption ===== */ +#ifndef OPENSSL_NO_AES + +#if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb) +#define NID_aes_128_cfb NID_aes_128_cfb128 +#endif + +#if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb) +#define NID_aes_128_ofb NID_aes_128_ofb128 +#endif + +#if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb) +#define NID_aes_192_cfb NID_aes_192_cfb128 +#endif + +#if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb) +#define NID_aes_192_ofb NID_aes_192_ofb128 +#endif + +#if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb) +#define NID_aes_256_cfb NID_aes_256_cfb128 +#endif + +#if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb) +#define NID_aes_256_ofb NID_aes_256_ofb128 +#endif + +/* List of supported ciphers. */ +static int padlock_cipher_nids[] = { + NID_aes_128_ecb, + NID_aes_128_cbc, + NID_aes_128_cfb, + NID_aes_128_ofb, + + NID_aes_192_ecb, + NID_aes_192_cbc, + NID_aes_192_cfb, + NID_aes_192_ofb, + + NID_aes_256_ecb, + NID_aes_256_cbc, + NID_aes_256_cfb, + NID_aes_256_ofb, +}; +static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids)/ + sizeof(padlock_cipher_nids[0])); + +/* Function prototypes ... */ +static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t nbytes); + +#define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ + ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) +#define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\ + NEAREST_ALIGNED(ctx->cipher_data)) + +#define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE +#define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE +#define EVP_CIPHER_block_size_OFB 1 +#define EVP_CIPHER_block_size_CFB 1 + +/* Declaring so many ciphers by hand would be a pain. + Instead introduce a bit of preprocessor magic :-) */ +#define DECLARE_AES_EVP(ksize,lmode,umode) \ +static const EVP_CIPHER padlock_aes_##ksize##_##lmode = { \ + NID_aes_##ksize##_##lmode, \ + EVP_CIPHER_block_size_##umode, \ + AES_KEY_SIZE_##ksize, \ + AES_BLOCK_SIZE, \ + 0 | EVP_CIPH_##umode##_MODE, \ + padlock_aes_init_key, \ + padlock_aes_cipher, \ + NULL, \ + sizeof(struct padlock_cipher_data) + 16, \ + EVP_CIPHER_set_asn1_iv, \ + EVP_CIPHER_get_asn1_iv, \ + NULL, \ + NULL \ +} + +DECLARE_AES_EVP(128,ecb,ECB); +DECLARE_AES_EVP(128,cbc,CBC); +DECLARE_AES_EVP(128,cfb,CFB); +DECLARE_AES_EVP(128,ofb,OFB); + +DECLARE_AES_EVP(192,ecb,ECB); +DECLARE_AES_EVP(192,cbc,CBC); +DECLARE_AES_EVP(192,cfb,CFB); +DECLARE_AES_EVP(192,ofb,OFB); + +DECLARE_AES_EVP(256,ecb,ECB); +DECLARE_AES_EVP(256,cbc,CBC); +DECLARE_AES_EVP(256,cfb,CFB); +DECLARE_AES_EVP(256,ofb,OFB); + +static int +padlock_ciphers (ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) +{ + /* No specific cipher => return a list of supported nids ... */ + if (!cipher) { + *nids = padlock_cipher_nids; + return padlock_cipher_nids_num; + } + + /* ... or the requested "cipher" otherwise */ + switch (nid) { + case NID_aes_128_ecb: + *cipher = &padlock_aes_128_ecb; + break; + case NID_aes_128_cbc: + *cipher = &padlock_aes_128_cbc; + break; + case NID_aes_128_cfb: + *cipher = &padlock_aes_128_cfb; + break; + case NID_aes_128_ofb: + *cipher = &padlock_aes_128_ofb; + break; + + case NID_aes_192_ecb: + *cipher = &padlock_aes_192_ecb; + break; + case NID_aes_192_cbc: + *cipher = &padlock_aes_192_cbc; + break; + case NID_aes_192_cfb: + *cipher = &padlock_aes_192_cfb; + break; + case NID_aes_192_ofb: + *cipher = &padlock_aes_192_ofb; + break; + + case NID_aes_256_ecb: + *cipher = &padlock_aes_256_ecb; + break; + case NID_aes_256_cbc: + *cipher = &padlock_aes_256_cbc; + break; + case NID_aes_256_cfb: + *cipher = &padlock_aes_256_cfb; + break; + case NID_aes_256_ofb: + *cipher = &padlock_aes_256_ofb; + break; + + default: + /* Sorry, we don't support this NID */ + *cipher = NULL; + return 0; + } + + return 1; +} + +/* Prepare the encryption key for PadLock usage */ +static int +padlock_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + struct padlock_cipher_data *cdata; + int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8; + + if (key==NULL) return 0; /* ERROR */ + + cdata = ALIGNED_CIPHER_DATA(ctx); + memset(cdata, 0, sizeof(struct padlock_cipher_data)); + + /* Prepare Control word. */ + if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) + cdata->cword.b.encdec = 0; + else + cdata->cword.b.encdec = (ctx->encrypt == 0); + cdata->cword.b.rounds = 10 + (key_len - 128) / 32; + cdata->cword.b.ksize = (key_len - 128) / 64; + + switch(key_len) { + case 128: + /* PadLock can generate an extended key for + AES128 in hardware */ + memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128); + cdata->cword.b.keygen = 0; + break; + + case 192: + case 256: + /* Generate an extended AES key in software. + Needed for AES192/AES256 */ + /* Well, the above applies to Stepping 8 CPUs + and is listed as hardware errata. They most + likely will fix it at some point and then + a check for stepping would be due here. */ + if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE || + EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE || + enc) + AES_set_encrypt_key(key, key_len, &cdata->ks); + else + AES_set_decrypt_key(key, key_len, &cdata->ks); +#ifndef AES_ASM + /* OpenSSL C functions use byte-swapped extended key. */ + padlock_bswapl(&cdata->ks); +#endif + cdata->cword.b.keygen = 1; + break; + + default: + /* ERROR */ + return 0; + } + + /* + * This is done to cover for cases when user reuses the + * context for new key. The catch is that if we don't do + * this, padlock_eas_cipher might proceed with old key... + */ + padlock_reload_key (); + + return 1; +} + +/* + * Simplified version of padlock_aes_cipher() used when + * 1) both input and output buffers are at aligned addresses. + * or when + * 2) running on a newer CPU that doesn't require aligned buffers. + */ +static int +padlock_aes_cipher_omnivorous(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata; + void *iv; + + cdata = ALIGNED_CIPHER_DATA(ctx); + padlock_verify_context(cdata); + + switch (EVP_CIPHER_CTX_mode(ctx)) { + case EVP_CIPH_ECB_MODE: + padlock_xcrypt_ecb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg); + break; + + case EVP_CIPH_CBC_MODE: + memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE); + iv = padlock_xcrypt_cbc(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg); + memcpy(ctx->iv, iv, AES_BLOCK_SIZE); + break; + + case EVP_CIPH_CFB_MODE: + memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE); + iv = padlock_xcrypt_cfb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg); + memcpy(ctx->iv, iv, AES_BLOCK_SIZE); + break; + + case EVP_CIPH_OFB_MODE: + memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE); + padlock_xcrypt_ofb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg); + memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE); + break; + + default: + return 0; + } + + memset(cdata->iv, 0, AES_BLOCK_SIZE); + + return 1; +} + +#ifndef PADLOCK_CHUNK +# define PADLOCK_CHUNK 512 /* Must be a power of 2 larger than 16 */ +#endif +#if PADLOCK_CHUNK<16 || PADLOCK_CHUNK&(PADLOCK_CHUNK-1) +# error "insane PADLOCK_CHUNK..." +#endif + +/* Re-align the arguments to 16-Bytes boundaries and run the + encryption function itself. This function is not AES-specific. */ +static int +padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, + const unsigned char *in_arg, size_t nbytes) +{ + struct padlock_cipher_data *cdata; + const void *inp; + unsigned char *out; + void *iv; + int inp_misaligned, out_misaligned, realign_in_loop; + size_t chunk, allocated=0; + + /* ctx->num is maintained in byte-oriented modes, + such as CFB and OFB... */ + if ((chunk = ctx->num)) { /* borrow chunk variable */ + unsigned char *ivp=ctx->iv; + + switch (EVP_CIPHER_CTX_mode(ctx)) { + case EVP_CIPH_CFB_MODE: + if (chunk >= AES_BLOCK_SIZE) + return 0; /* bogus value */ + + if (ctx->encrypt) + while (chunknum = chunk%AES_BLOCK_SIZE; + break; + case EVP_CIPH_OFB_MODE: + if (chunk >= AES_BLOCK_SIZE) + return 0; /* bogus value */ + + while (chunknum = chunk%AES_BLOCK_SIZE; + break; + } + } + + if (nbytes == 0) + return 1; +#if 0 + if (nbytes % AES_BLOCK_SIZE) + return 0; /* are we expected to do tail processing? */ +#else + /* nbytes is always multiple of AES_BLOCK_SIZE in ECB and CBC + modes and arbitrary value in byte-oriented modes, such as + CFB and OFB... */ +#endif + + /* VIA promises CPUs that won't require alignment in the future. + For now padlock_aes_align_required is initialized to 1 and + the condition is never met... */ + /* C7 core is capable to manage unaligned input in non-ECB[!] + mode, but performance penalties appear to be approximately + same as for software alignment below or ~3x. They promise to + improve it in the future, but for now we can just as well + pretend that it can only handle aligned input... */ + if (!padlock_aes_align_required && (nbytes%AES_BLOCK_SIZE)==0) + return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes); + + inp_misaligned = (((size_t)in_arg) & 0x0F); + out_misaligned = (((size_t)out_arg) & 0x0F); + + /* Note that even if output is aligned and input not, + * I still prefer to loop instead of copy the whole + * input and then encrypt in one stroke. This is done + * in order to improve L1 cache utilization... */ + realign_in_loop = out_misaligned|inp_misaligned; + + if (!realign_in_loop && (nbytes%AES_BLOCK_SIZE)==0) + return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes); + + /* this takes one "if" out of the loops */ + chunk = nbytes; + chunk %= PADLOCK_CHUNK; + if (chunk==0) chunk = PADLOCK_CHUNK; + + if (out_misaligned) { + /* optmize for small input */ + allocated = (chunkiv, ctx->iv, AES_BLOCK_SIZE); + goto cbc_shortcut; + do { + if (iv != cdata->iv) + memcpy(cdata->iv, iv, AES_BLOCK_SIZE); + chunk = PADLOCK_CHUNK; + cbc_shortcut: /* optimize for small input */ + if (inp_misaligned) + inp = padlock_memcpy(out, in_arg, chunk); + else + inp = in_arg; + in_arg += chunk; + + iv = padlock_xcrypt_cbc(chunk/AES_BLOCK_SIZE, cdata, out, inp); + + if (out_misaligned) + out_arg = padlock_memcpy(out_arg, out, chunk) + chunk; + else + out = out_arg+=chunk; + + } while (nbytes -= chunk); + memcpy(ctx->iv, iv, AES_BLOCK_SIZE); + break; + + case EVP_CIPH_CFB_MODE: + memcpy (iv = cdata->iv, ctx->iv, AES_BLOCK_SIZE); + chunk &= ~(AES_BLOCK_SIZE-1); + if (chunk) goto cfb_shortcut; + else goto cfb_skiploop; + do { + if (iv != cdata->iv) + memcpy(cdata->iv, iv, AES_BLOCK_SIZE); + chunk = PADLOCK_CHUNK; + cfb_shortcut: /* optimize for small input */ + if (inp_misaligned) + inp = padlock_memcpy(out, in_arg, chunk); + else + inp = in_arg; + in_arg += chunk; + + iv = padlock_xcrypt_cfb(chunk/AES_BLOCK_SIZE, cdata, out, inp); + + if (out_misaligned) + out_arg = padlock_memcpy(out_arg, out, chunk) + chunk; + else + out = out_arg+=chunk; + + nbytes -= chunk; + } while (nbytes >= AES_BLOCK_SIZE); + + cfb_skiploop: + if (nbytes) { + unsigned char *ivp = cdata->iv; + + if (iv != ivp) { + memcpy(ivp, iv, AES_BLOCK_SIZE); + iv = ivp; + } + ctx->num = nbytes; + if (cdata->cword.b.encdec) { + cdata->cword.b.encdec=0; + padlock_reload_key(); + padlock_xcrypt_ecb(1,cdata,ivp,ivp); + cdata->cword.b.encdec=1; + padlock_reload_key(); + while(nbytes) { + unsigned char c = *(in_arg++); + *(out_arg++) = c ^ *ivp; + *(ivp++) = c, nbytes--; + } + } + else { padlock_reload_key(); + padlock_xcrypt_ecb(1,cdata,ivp,ivp); + padlock_reload_key(); + while (nbytes) { + *ivp = *(out_arg++) = *(in_arg++) ^ *ivp; + ivp++, nbytes--; + } + } + } + + memcpy(ctx->iv, iv, AES_BLOCK_SIZE); + break; + + case EVP_CIPH_OFB_MODE: + memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE); + chunk &= ~(AES_BLOCK_SIZE-1); + if (chunk) do { + if (inp_misaligned) + inp = padlock_memcpy(out, in_arg, chunk); + else + inp = in_arg; + in_arg += chunk; + + padlock_xcrypt_ofb(chunk/AES_BLOCK_SIZE, cdata, out, inp); + + if (out_misaligned) + out_arg = padlock_memcpy(out_arg, out, chunk) + chunk; + else + out = out_arg+=chunk; + + nbytes -= chunk; + chunk = PADLOCK_CHUNK; + } while (nbytes >= AES_BLOCK_SIZE); + + if (nbytes) { + unsigned char *ivp = cdata->iv; + + ctx->num = nbytes; + padlock_reload_key(); /* empirically found */ + padlock_xcrypt_ecb(1,cdata,ivp,ivp); + padlock_reload_key(); /* empirically found */ + while (nbytes) { + *(out_arg++) = *(in_arg++) ^ *ivp; + ivp++, nbytes--; + } + } + + memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE); + break; + + default: + return 0; + } + + /* Clean the realign buffer if it was used */ + if (out_misaligned) { + volatile unsigned long *p=(void *)out; + size_t n = allocated/sizeof(*p); + while (n--) *p++=0; + } + + memset(cdata->iv, 0, AES_BLOCK_SIZE); + + return 1; +} + +#endif /* OPENSSL_NO_AES */ + +/* ===== Random Number Generator ===== */ +/* + * This code is not engaged. The reason is that it does not comply + * with recommendations for VIA RNG usage for secure applications + * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it + * provide meaningful error control... + */ +/* Wrapper that provides an interface between the API and + the raw PadLock RNG */ +static int +padlock_rand_bytes(unsigned char *output, int count) +{ + unsigned int eax, buf; + + while (count >= 8) { + eax = padlock_xstore(output, 0); + if (!(eax&(1<<6))) return 0; /* RNG disabled */ + /* this ---vv--- covers DC bias, Raw Bits and String Filter */ + if (eax&(0x1F<<10)) return 0; + if ((eax&0x1F)==0) continue; /* no data, retry... */ + if ((eax&0x1F)!=8) return 0; /* fatal failure... */ + output += 8; + count -= 8; + } + while (count > 0) { + eax = padlock_xstore(&buf, 3); + if (!(eax&(1<<6))) return 0; /* RNG disabled */ + /* this ---vv--- covers DC bias, Raw Bits and String Filter */ + if (eax&(0x1F<<10)) return 0; + if ((eax&0x1F)==0) continue; /* no data, retry... */ + if ((eax&0x1F)!=1) return 0; /* fatal failure... */ + *output++ = (unsigned char)buf; + count--; + } + *(volatile unsigned int *)&buf=0; + + return 1; +} + +/* Dummy but necessary function */ +static int +padlock_rand_status(void) +{ + return 1; +} + +/* Prepare structure for registration */ +static RAND_METHOD padlock_rand = { + NULL, /* seed */ + padlock_rand_bytes, /* bytes */ + NULL, /* cleanup */ + NULL, /* add */ + padlock_rand_bytes, /* pseudorand */ + padlock_rand_status, /* rand status */ +}; + +#endif /* COMPILE_HW_PADLOCK */ + +#endif /* !OPENSSL_NO_HW_PADLOCK */ +#endif /* !OPENSSL_NO_HW */ diff --git a/src/lib/libcrypto/engine/eng_pkey.c b/src/lib/libcrypto/engine/eng_pkey.c index 8c69171511..bc8b21abec 100644 --- a/src/lib/libcrypto/engine/eng_pkey.c +++ b/src/lib/libcrypto/engine/eng_pkey.c @@ -53,10 +53,7 @@ * */ -#include -#include "cryptlib.h" #include "eng_int.h" -#include /* Basic get/set stuff */ diff --git a/src/lib/libcrypto/engine/eng_table.c b/src/lib/libcrypto/engine/eng_table.c index c69a84a8bf..8879a267d1 100644 --- a/src/lib/libcrypto/engine/eng_table.c +++ b/src/lib/libcrypto/engine/eng_table.c @@ -52,49 +52,31 @@ * */ +#include "cryptlib.h" #include -#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 - * */ + /* The 'nid' of this algorithm/mode */ 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. */ + /* ENGINEs that implement this algorithm/mode. */ 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). */ + /* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */ 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. */ +/* The type exposed in eng_int.h */ 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. */ +/* Global flags (ENGINE_TABLE_FLAG_***). */ static unsigned int table_flags = 0; /* API function manipulating 'table_flags' */ @@ -121,10 +103,8 @@ 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(*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; @@ -154,8 +134,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, if(!fnd) { fnd = OPENSSL_malloc(sizeof(ENGINE_PILE)); - if(!fnd) - goto end; + if(!fnd) goto end; fnd->uptodate = 1; fnd->nid = *nids; fnd->sk = sk_ENGINE_new_null(); @@ -164,11 +143,11 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, OPENSSL_free(fnd); goto end; } - fnd->funct= NULL; + fnd->funct = NULL; lh_insert(&(*table)->piles, fnd); } /* A registration shouldn't add duplciate entries */ - sk_ENGINE_delete_ptr(fnd->sk, e); + (void)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; @@ -185,6 +164,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, if(fnd->funct) engine_unlocked_finish(fnd->funct, 0); fnd->funct = e; + fnd->uptodate = 1; } nids++; } @@ -199,8 +179,7 @@ static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e) /* 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 */ + (void)sk_ENGINE_delete(pile->sk, n); pile->uptodate = 0; } if(pile->funct == e) @@ -239,9 +218,7 @@ void engine_table_cleanup(ENGINE_TABLE **table) 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' */ +/* return a functional reference for a given 'nid' */ #ifndef ENGINE_TABLE_DEBUG ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) #else @@ -252,25 +229,21 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, in 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); + fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing " + "registered!\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; + if(!int_table_check(table, 0)) goto end; tmplate.nid = nid; fnd = lh_retrieve(&(*table)->piles, &tmplate); - if(!fnd) - goto end; + if(!fnd) goto end; if(fnd->funct && engine_unlocked_init(fnd->funct)) { #ifdef ENGINE_TABLE_DEBUG @@ -296,34 +269,19 @@ trynext: #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. */ + /* Try to initialise the ENGINE? */ 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'. */ + /* Update '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, " @@ -338,13 +296,9 @@ trynext: } 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; + /* If it failed, it is unlikely to succeed again until some future + * registrations have taken place. In all cases, we cache. */ + if(fnd) fnd->uptodate = 1; #ifdef ENGINE_TABLE_DEBUG if(ret) fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " diff --git a/src/lib/libcrypto/engine/engine.h b/src/lib/libcrypto/engine/engine.h index 900f75ce8d..3ec59338ff 100644 --- a/src/lib/libcrypto/engine/engine.h +++ b/src/lib/libcrypto/engine/engine.h @@ -3,7 +3,7 @@ * project 2000. */ /* ==================================================================== - * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2004 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 @@ -55,6 +55,11 @@ * Hudson (tjh@cryptsoft.com). * */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ #ifndef HEADER_ENGINE_H #define HEADER_ENGINE_H @@ -65,7 +70,7 @@ #error ENGINE is disabled. #endif -#include +#ifndef OPENSSL_NO_DEPRECATED #include #ifndef OPENSSL_NO_RSA #include @@ -76,34 +81,36 @@ #ifndef OPENSSL_NO_DH #include #endif +#ifndef OPENSSL_NO_ECDH +#include +#endif +#ifndef OPENSSL_NO_ECDSA +#include +#endif #include +#include #include -#include #include +#endif + +#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_ECDH (unsigned int)0x0010 +#define ENGINE_METHOD_ECDSA (unsigned int)0x0020 #define ENGINE_METHOD_CIPHERS (unsigned int)0x0040 #define ENGINE_METHOD_DIGESTS (unsigned int)0x0080 +#define ENGINE_METHOD_STORE (unsigned int)0x0100 /* Obvious all-or-nothing cases. */ #define ENGINE_METHOD_ALL (unsigned int)0xFFFF #define ENGINE_METHOD_NONE (unsigned int)0x0000 @@ -173,9 +180,15 @@ typedef void DH_METHOD; 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 */ + when calling the password + callback and the user + interface */ +#define ENGINE_CTRL_LOAD_CONFIGURATION 6 /* Load a configuration, given + a string that represents a + file name or so */ +#define ENGINE_CTRL_LOAD_SECTION 7 /* Load data from a given + section in the already loaded + configuration */ /* These control commands allow an application to deal with an arbitrary engine * in a dynamic way. Warn: Negative return values indicate errors FOR THESE @@ -222,7 +235,7 @@ typedef void DH_METHOD; /* 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 +#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 @@ -257,11 +270,11 @@ typedef struct ENGINE_CMD_DEFN_st } ENGINE_CMD_DEFN; /* Generic function pointer */ -typedef int (*ENGINE_GEN_FUNC_PTR)(); +typedef int (*ENGINE_GEN_FUNC_PTR)(void); /* Generic function pointer taking no arguments */ typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *); /* Specific control function pointer */ -typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)()); +typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)(void)); /* Generic load_key function pointer */ typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, UI_METHOD *ui_method, void *callback_data); @@ -305,15 +318,21 @@ 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); +#ifndef OPENSSL_NO_STATIC_ENGINE +void ENGINE_load_4758cca(void); +void ENGINE_load_aep(void); void ENGINE_load_atalla(void); +void ENGINE_load_chil(void); +void ENGINE_load_cswift(void); +#ifndef OPENSSL_NO_GMP +void ENGINE_load_gmp(void); +#endif 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_ubsec(void); +#endif void ENGINE_load_cryptodev(void); +void ENGINE_load_padlock(void); void ENGINE_load_builtin_engines(void); /* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation @@ -337,6 +356,14 @@ int ENGINE_register_DSA(ENGINE *e); void ENGINE_unregister_DSA(ENGINE *e); void ENGINE_register_all_DSA(void); +int ENGINE_register_ECDH(ENGINE *e); +void ENGINE_unregister_ECDH(ENGINE *e); +void ENGINE_register_all_ECDH(void); + +int ENGINE_register_ECDSA(ENGINE *e); +void ENGINE_unregister_ECDSA(ENGINE *e); +void ENGINE_register_all_ECDSA(void); + int ENGINE_register_DH(ENGINE *e); void ENGINE_unregister_DH(ENGINE *e); void ENGINE_register_all_DH(void); @@ -345,6 +372,10 @@ int ENGINE_register_RAND(ENGINE *e); void ENGINE_unregister_RAND(ENGINE *e); void ENGINE_register_all_RAND(void); +int ENGINE_register_STORE(ENGINE *e); +void ENGINE_unregister_STORE(ENGINE *e); +void ENGINE_register_all_STORE(void); + int ENGINE_register_ciphers(ENGINE *e); void ENGINE_unregister_ciphers(ENGINE *e); void ENGINE_register_all_ciphers(void); @@ -367,7 +398,7 @@ int ENGINE_register_all_complete(void); * 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)()); +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); /* This function tests if an ENGINE-specific command is usable as a "setting". * Eg. in an application's config file that gets processed through @@ -380,7 +411,7 @@ int ENGINE_cmd_is_executable(ENGINE *e, int cmd); * 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); + long i, void *p, void (*f)(void), 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 @@ -417,8 +448,11 @@ 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_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth); +int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_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_STORE(ENGINE *e, const STORE_METHOD *store_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); @@ -429,11 +463,11 @@ 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. */ +/* These functions 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); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); /* This function cleans up anything that needs it. Eg. the ENGINE_add() function * automatically ensures the list cleanup function is registered to be called @@ -449,8 +483,11 @@ 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 ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e); +const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e); const DH_METHOD *ENGINE_get_DH(const ENGINE *e); const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); +const STORE_METHOD *ENGINE_get_STORE(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); @@ -463,7 +500,6 @@ 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 @@ -501,6 +537,8 @@ EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, ENGINE *ENGINE_get_default_RSA(void); /* Same for the other "methods" */ ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_ECDH(void); +ENGINE *ENGINE_get_default_ECDSA(void); ENGINE *ENGINE_get_default_DH(void); ENGINE *ENGINE_get_default_RAND(void); /* These functions can be used to get a functional reference to perform @@ -516,6 +554,8 @@ int ENGINE_set_default_RSA(ENGINE *e); int ENGINE_set_default_string(ENGINE *e, const char *def_list); /* Same for the other "methods" */ int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_ECDH(ENGINE *e); +int ENGINE_set_default_ECDSA(ENGINE *e); int ENGINE_set_default_DH(ENGINE *e); int ENGINE_set_default_RAND(ENGINE *e); int ENGINE_set_default_ciphers(ENGINE *e); @@ -538,17 +578,20 @@ void ENGINE_add_conf_module(void); /**************************/ /* Binary/behaviour compatibility levels */ -#define OSSL_DYNAMIC_VERSION (unsigned long)0x00010200 +#define OSSL_DYNAMIC_VERSION (unsigned long)0x00020000 /* Binary versions older than this are too old for us (whether we're a loader or * a loadee) */ -#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00010200 +#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00020000 /* 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. */ + * 'state' will be used/changed in all operations. The 'static_state' pointer + * allows the loaded library to know if it shares the same static data as the + * calling application (or library), and thus whether these callbacks need to be + * set or not. */ typedef void *(*dyn_MEM_malloc_cb)(size_t); typedef void *(*dyn_MEM_realloc_cb)(void *, size_t); typedef void (*dyn_MEM_free_cb)(void *); @@ -576,6 +619,7 @@ typedef struct st_dynamic_LOCK_fns { } dynamic_LOCK_fns; /* The top-level structure */ typedef struct st_dynamic_fns { + void *static_state; const ERR_FNS *err_fns; const CRYPTO_EX_DATA_IMPL *ex_data_fns; dynamic_MEM_fns mem_fns; @@ -593,7 +637,7 @@ typedef struct st_dynamic_fns { * 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) { \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \ if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \ return 0; } @@ -615,24 +659,35 @@ typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version); typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id, const dynamic_fns *fns); #define IMPLEMENT_DYNAMIC_BIND_FN(fn) \ + OPENSSL_EXPORT \ int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \ - if (ERR_get_implementation() != fns->err_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(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \ + 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; \ + skip_cbs: \ if(!fn(e,id)) return 0; \ return 1; } +/* If the loading application (or library) and the loaded ENGINE library share + * the same static data (eg. they're both dynamically linked to the same + * libcrypto.so) we need a way to avoid trying to set system callbacks - this + * would fail, and for the same reason that it's unnecessary to try. If the + * loaded ENGINE has (or gets from through the loader) its own copy of the + * libcrypto static data, we will need to set the callbacks. The easiest way to + * detect this is to have a function that returns a pointer to some static data + * and let the loading application and loaded ENGINE compare their respective + * values. */ +void *ENGINE_get_static_state(void); + #if defined(__OpenBSD__) || defined(__FreeBSD__) void ENGINE_setup_bsd_cryptodev(void); #endif @@ -649,6 +704,7 @@ void ERR_load_ENGINE_strings(void); #define ENGINE_F_DYNAMIC_CTRL 180 #define ENGINE_F_DYNAMIC_GET_DATA_CTX 181 #define ENGINE_F_DYNAMIC_LOAD 182 +#define ENGINE_F_DYNAMIC_SET_DATA_CTX 183 #define ENGINE_F_ENGINE_ADD 105 #define ENGINE_F_ENGINE_BY_ID 106 #define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170 @@ -656,7 +712,7 @@ void ERR_load_ENGINE_strings(void); #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_FREE_UTIL 108 #define ENGINE_F_ENGINE_GET_CIPHER 185 #define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177 #define ENGINE_F_ENGINE_GET_DIGEST 186 @@ -667,7 +723,6 @@ void ERR_load_ENGINE_strings(void); #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_DEFAULT_STRING 189 @@ -676,11 +731,12 @@ void ERR_load_ENGINE_strings(void); #define ENGINE_F_ENGINE_SET_NAME 130 #define ENGINE_F_ENGINE_TABLE_REGISTER 184 #define ENGINE_F_ENGINE_UNLOAD_KEY 152 +#define ENGINE_F_ENGINE_UNLOCKED_FINISH 191 #define ENGINE_F_ENGINE_UP_REF 190 #define ENGINE_F_INT_CTRL_HELPER 172 #define ENGINE_F_INT_ENGINE_CONFIGURE 188 +#define ENGINE_F_INT_ENGINE_MODULE_INIT 187 #define ENGINE_F_LOG_MESSAGE 141 -#define ENGINE_F_SET_DATA_CTX 183 /* Reason codes. */ #define ENGINE_R_ALREADY_LOADED 100 diff --git a/src/lib/libcrypto/engine/tb_cipher.c b/src/lib/libcrypto/engine/tb_cipher.c index 50b3cec1fa..177fc1fb73 100644 --- a/src/lib/libcrypto/engine/tb_cipher.c +++ b/src/lib/libcrypto/engine/tb_cipher.c @@ -52,8 +52,6 @@ * */ -#include -#include #include "eng_int.h" /* If this symbol is defined then ENGINE_get_cipher_engine(), the function that diff --git a/src/lib/libcrypto/engine/tb_dh.c b/src/lib/libcrypto/engine/tb_dh.c index e290e1702b..6e9d428761 100644 --- a/src/lib/libcrypto/engine/tb_dh.c +++ b/src/lib/libcrypto/engine/tb_dh.c @@ -52,8 +52,6 @@ * */ -#include -#include #include "eng_int.h" /* If this symbol is defined then ENGINE_get_default_DH(), the function that is diff --git a/src/lib/libcrypto/engine/tb_digest.c b/src/lib/libcrypto/engine/tb_digest.c index e82d2a17c9..d3f4bb2747 100644 --- a/src/lib/libcrypto/engine/tb_digest.c +++ b/src/lib/libcrypto/engine/tb_digest.c @@ -52,8 +52,6 @@ * */ -#include -#include #include "eng_int.h" /* If this symbol is defined then ENGINE_get_digest_engine(), the function that diff --git a/src/lib/libcrypto/engine/tb_dsa.c b/src/lib/libcrypto/engine/tb_dsa.c index 7efe181927..e4674f5f07 100644 --- a/src/lib/libcrypto/engine/tb_dsa.c +++ b/src/lib/libcrypto/engine/tb_dsa.c @@ -52,8 +52,6 @@ * */ -#include -#include #include "eng_int.h" /* If this symbol is defined then ENGINE_get_default_DSA(), the function that is diff --git a/src/lib/libcrypto/engine/tb_ecdh.c b/src/lib/libcrypto/engine/tb_ecdh.c new file mode 100644 index 0000000000..c8ec7812c5 --- /dev/null +++ b/src/lib/libcrypto/engine/tb_ecdh.c @@ -0,0 +1,133 @@ +/* crypto/engine/tb_ecdh.c */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * The Elliptic Curve Public-Key Crypto Library (ECC Code) included + * herein is developed by SUN MICROSYSTEMS, INC., and is contributed + * to the OpenSSL project. + * + * The ECC Code is licensed pursuant to the OpenSSL open source + * license provided below. + * + * The ECDH engine software is originally written by Nils Gura and + * Douglas Stebila of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright (c) 2000-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 + * 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 "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_ECDH(), the function that is + * used by ECDH to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_ECDH_DEBUG */ + +static ENGINE_TABLE *ecdh_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_ECDH(ENGINE *e) + { + engine_table_unregister(&ecdh_table, e); + } + +static void engine_unregister_all_ECDH(void) + { + engine_table_cleanup(&ecdh_table); + } + +int ENGINE_register_ECDH(ENGINE *e) + { + if(e->ecdh_meth) + return engine_table_register(&ecdh_table, + engine_unregister_all_ECDH, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_ECDH() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_ECDH(e); + } + +int ENGINE_set_default_ECDH(ENGINE *e) + { + if(e->ecdh_meth) + return engine_table_register(&ecdh_table, + engine_unregister_all_ECDH, 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_ECDH(void) + { + return engine_table_select(&ecdh_table, dummy_nid); + } + +/* Obtains an ECDH implementation from an ENGINE functional reference */ +const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e) + { + return e->ecdh_meth; + } + +/* Sets an ECDH implementation in an ENGINE structure */ +int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth) + { + e->ecdh_meth = ecdh_meth; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_ecdsa.c b/src/lib/libcrypto/engine/tb_ecdsa.c new file mode 100644 index 0000000000..005ecb622c --- /dev/null +++ b/src/lib/libcrypto/engine/tb_ecdsa.c @@ -0,0 +1,118 @@ +/* ==================================================================== + * Copyright (c) 2000-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 + * 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 "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_ECDSA(), the function that is + * used by ECDSA to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_ECDSA_DEBUG */ + +static ENGINE_TABLE *ecdsa_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_ECDSA(ENGINE *e) + { + engine_table_unregister(&ecdsa_table, e); + } + +static void engine_unregister_all_ECDSA(void) + { + engine_table_cleanup(&ecdsa_table); + } + +int ENGINE_register_ECDSA(ENGINE *e) + { + if(e->ecdsa_meth) + return engine_table_register(&ecdsa_table, + engine_unregister_all_ECDSA, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_ECDSA() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_ECDSA(e); + } + +int ENGINE_set_default_ECDSA(ENGINE *e) + { + if(e->ecdsa_meth) + return engine_table_register(&ecdsa_table, + engine_unregister_all_ECDSA, 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_ECDSA(void) + { + return engine_table_select(&ecdsa_table, dummy_nid); + } + +/* Obtains an ECDSA implementation from an ENGINE functional reference */ +const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e) + { + return e->ecdsa_meth; + } + +/* Sets an ECDSA implementation in an ENGINE structure */ +int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth) + { + e->ecdsa_meth = ecdsa_meth; + return 1; + } diff --git a/src/lib/libcrypto/engine/tb_rand.c b/src/lib/libcrypto/engine/tb_rand.c index 69b67111bc..f36f67c0f6 100644 --- a/src/lib/libcrypto/engine/tb_rand.c +++ b/src/lib/libcrypto/engine/tb_rand.c @@ -52,8 +52,6 @@ * */ -#include -#include #include "eng_int.h" /* If this symbol is defined then ENGINE_get_default_RAND(), the function that is diff --git a/src/lib/libcrypto/engine/tb_rsa.c b/src/lib/libcrypto/engine/tb_rsa.c index fee4867f52..fbc707fd26 100644 --- a/src/lib/libcrypto/engine/tb_rsa.c +++ b/src/lib/libcrypto/engine/tb_rsa.c @@ -52,8 +52,6 @@ * */ -#include -#include #include "eng_int.h" /* If this symbol is defined then ENGINE_get_default_RSA(), the function that is diff --git a/src/lib/libcrypto/engine/tb_store.c b/src/lib/libcrypto/engine/tb_store.c new file mode 100644 index 0000000000..8cc435c935 --- /dev/null +++ b/src/lib/libcrypto/engine/tb_store.c @@ -0,0 +1,123 @@ +/* ==================================================================== + * Copyright (c) 2003 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 "eng_int.h" + +/* If this symbol is defined then ENGINE_get_default_STORE(), the function that is + * used by STORE to hook in implementation code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_STORE_DEBUG */ + +static ENGINE_TABLE *store_table = NULL; +static const int dummy_nid = 1; + +void ENGINE_unregister_STORE(ENGINE *e) + { + engine_table_unregister(&store_table, e); + } + +static void engine_unregister_all_STORE(void) + { + engine_table_cleanup(&store_table); + } + +int ENGINE_register_STORE(ENGINE *e) + { + if(e->store_meth) + return engine_table_register(&store_table, + engine_unregister_all_STORE, e, &dummy_nid, 1, 0); + return 1; + } + +void ENGINE_register_all_STORE() + { + ENGINE *e; + + for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) + ENGINE_register_STORE(e); + } + +/* The following two functions are removed because they're useless. */ +#if 0 +int ENGINE_set_default_STORE(ENGINE *e) + { + if(e->store_meth) + return engine_table_register(&store_table, + engine_unregister_all_STORE, e, &dummy_nid, 1, 1); + return 1; + } +#endif + +#if 0 +/* 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_STORE(void) + { + return engine_table_select(&store_table, dummy_nid); + } +#endif + +/* Obtains an STORE implementation from an ENGINE functional reference */ +const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e) + { + return e->store_meth; + } + +/* Sets an STORE implementation in an ENGINE structure */ +int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth) + { + e->store_meth = store_meth; + return 1; + } -- cgit v1.2.3-55-g6feb