From e2f3ae12528589e21b509e870125feab14445770 Mon Sep 17 00:00:00 2001 From: Geoff Thorpe Date: Thu, 19 Apr 2001 01:45:40 +0000 Subject: [PATCH] Some more tweaks to ENGINE code. This change adds some basic control commands to the existing ENGINEs (except the software 'openssl' engine). All these engines currently load shared-libraries for hardware APIs, so they've all been given "SO_PATH" commands that will configure the chosen ENGINE to load its shared library from the given path. Eg. by calling; ENGINE_ctrl_cmd_string(e, "SO_PATH", , 0). The nCipher 'chil' ENGINE has also had "FORK_CHECK" and "THREAD_LOCKING" commands added so these settings could be handled via application-level configuration rather than in application source code. Changes to "openssl engine" to test and examine these control commands will be made shortly. It will also provide the necessary tips to application programs wanting to support these dynamic control commands. --- crypto/engine/engine.h | 4 ++++ crypto/engine/engine_err.c | 4 ++++ crypto/engine/hw_atalla.c | 42 +++++++++++++++++++++++++++++++-- crypto/engine/hw_cswift.c | 48 ++++++++++++++++++++++++++++++++++---- crypto/engine/hw_ncipher.c | 45 +++++++++++++++++++++++++++++++++-- crypto/engine/hw_nuron.c | 46 ++++++++++++++++++++++++++++++++---- crypto/engine/hw_ubsec.c | 41 ++++++++++++++++++++++++++++++-- 7 files changed, 216 insertions(+), 14 deletions(-) diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h index 3e72909804..48300fe769 100644 --- a/crypto/engine/engine.h +++ b/crypto/engine/engine.h @@ -422,10 +422,12 @@ void ERR_load_ENGINE_strings(void); /* Error codes for the ENGINE functions. */ /* Function codes. */ +#define ENGINE_F_ATALLA_CTRL 173 #define ENGINE_F_ATALLA_FINISH 159 #define ENGINE_F_ATALLA_INIT 160 #define ENGINE_F_ATALLA_MOD_EXP 161 #define ENGINE_F_ATALLA_RSA_MOD_EXP 162 +#define ENGINE_F_CSWIFT_CTRL 174 #define ENGINE_F_CSWIFT_DSA_SIGN 133 #define ENGINE_F_CSWIFT_DSA_VERIFY 134 #define ENGINE_F_CSWIFT_FINISH 100 @@ -465,9 +467,11 @@ void ERR_load_ENGINE_strings(void); #define ENGINE_F_HWCRHK_RSA_MOD_EXP 140 #define ENGINE_F_INT_CTRL_HELPER 172 #define ENGINE_F_LOG_MESSAGE 141 +#define ENGINE_F_NURON_CTRL 175 #define ENGINE_F_NURON_FINISH 157 #define ENGINE_F_NURON_INIT 156 #define ENGINE_F_NURON_MOD_EXP 158 +#define ENGINE_F_UBSEC_CTRL 176 #define ENGINE_F_UBSEC_DSA_SIGN 163 #define ENGINE_F_UBSEC_DSA_VERIFY 164 #define ENGINE_F_UBSEC_FINISH 165 diff --git a/crypto/engine/engine_err.c b/crypto/engine/engine_err.c index 11c738ea74..24202a1bee 100644 --- a/crypto/engine/engine_err.c +++ b/crypto/engine/engine_err.c @@ -66,10 +66,12 @@ #ifndef OPENSSL_NO_ERR static ERR_STRING_DATA ENGINE_str_functs[]= { +{ERR_PACK(0,ENGINE_F_ATALLA_CTRL,0), "ATALLA_CTRL"}, {ERR_PACK(0,ENGINE_F_ATALLA_FINISH,0), "ATALLA_FINISH"}, {ERR_PACK(0,ENGINE_F_ATALLA_INIT,0), "ATALLA_INIT"}, {ERR_PACK(0,ENGINE_F_ATALLA_MOD_EXP,0), "ATALLA_MOD_EXP"}, {ERR_PACK(0,ENGINE_F_ATALLA_RSA_MOD_EXP,0), "ATALLA_RSA_MOD_EXP"}, +{ERR_PACK(0,ENGINE_F_CSWIFT_CTRL,0), "CSWIFT_CTRL"}, {ERR_PACK(0,ENGINE_F_CSWIFT_DSA_SIGN,0), "CSWIFT_DSA_SIGN"}, {ERR_PACK(0,ENGINE_F_CSWIFT_DSA_VERIFY,0), "CSWIFT_DSA_VERIFY"}, {ERR_PACK(0,ENGINE_F_CSWIFT_FINISH,0), "CSWIFT_FINISH"}, @@ -109,9 +111,11 @@ static ERR_STRING_DATA ENGINE_str_functs[]= {ERR_PACK(0,ENGINE_F_HWCRHK_RSA_MOD_EXP,0), "HWCRHK_RSA_MOD_EXP"}, {ERR_PACK(0,ENGINE_F_INT_CTRL_HELPER,0), "INT_CTRL_HELPER"}, {ERR_PACK(0,ENGINE_F_LOG_MESSAGE,0), "LOG_MESSAGE"}, +{ERR_PACK(0,ENGINE_F_NURON_CTRL,0), "NURON_CTRL"}, {ERR_PACK(0,ENGINE_F_NURON_FINISH,0), "NURON_FINISH"}, {ERR_PACK(0,ENGINE_F_NURON_INIT,0), "NURON_INIT"}, {ERR_PACK(0,ENGINE_F_NURON_MOD_EXP,0), "NURON_MOD_EXP"}, +{ERR_PACK(0,ENGINE_F_UBSEC_CTRL,0), "UBSEC_CTRL"}, {ERR_PACK(0,ENGINE_F_UBSEC_DSA_SIGN,0), "UBSEC_DSA_SIGN"}, {ERR_PACK(0,ENGINE_F_UBSEC_DSA_VERIFY,0), "UBSEC_DSA_VERIFY"}, {ERR_PACK(0,ENGINE_F_UBSEC_FINISH,0), "UBSEC_FINISH"}, diff --git a/crypto/engine/hw_atalla.c b/crypto/engine/hw_atalla.c index e3407e73c7..8bf702aac0 100644 --- a/crypto/engine/hw_atalla.c +++ b/crypto/engine/hw_atalla.c @@ -73,6 +73,7 @@ static int atalla_init(ENGINE *e); static int atalla_finish(ENGINE *e); +static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); /* BIGNUM stuff */ static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, @@ -98,6 +99,15 @@ static int atalla_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +/* The definitions for control commands specific to this engine */ +#define ATALLA_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN atalla_cmd_defns[] = { + {ATALLA_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'atasi' shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} + }; /* Our internal RSA_METHOD that we provide pointers to */ static RSA_METHOD atalla_rsa = @@ -166,7 +176,9 @@ ENGINE *ENGINE_atalla() !ENGINE_set_DH(ret, &atalla_dh) || !ENGINE_set_BN_mod_exp(ret, atalla_mod_exp) || !ENGINE_set_init_function(ret, atalla_init) || - !ENGINE_set_finish_function(ret, atalla_finish)) + !ENGINE_set_finish_function(ret, atalla_finish) || + !ENGINE_set_ctrl_function(ret, atalla_ctrl) || + !ENGINE_set_cmd_defns(ret, atalla_cmd_defns)) { ENGINE_free(ret); return NULL; @@ -220,7 +232,8 @@ static tfnASI_GetPerformanceStatistics *p_Atalla_GetPerformanceStatistics = NULL * atasi.dll on win32). For the purposes of testing, I have created a symbollic * link called "libatasi.so" so that we can use native name-translation - a * better solution will be needed. */ -static const char *ATALLA_LIBNAME = "atasi"; +static const char def_ATALLA_LIBNAME[] = "atasi"; +static const char *ATALLA_LIBNAME = def_ATALLA_LIBNAME; static const char *ATALLA_F1 = "ASI_GetHardwareConfig"; static const char *ATALLA_F2 = "ASI_RSAPrivateKeyOpFn"; static const char *ATALLA_F3 = "ASI_GetPerformanceStatistics"; @@ -304,6 +317,31 @@ static int atalla_finish(ENGINE *e) return 1; } +static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialised = ((atalla_dso == NULL) ? 0 : 1); + switch(cmd) + { + case ATALLA_CMD_SO_PATH: + if(p == NULL) + { + ENGINEerr(ENGINE_F_ATALLA_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(initialised) + { + ENGINEerr(ENGINE_F_ATALLA_CTRL,ENGINE_R_ALREADY_LOADED); + return 0; + } + ATALLA_LIBNAME = (const char *)p; + return 1; + default: + break; + } + ENGINEerr(ENGINE_F_ATALLA_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; + } + static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) { diff --git a/crypto/engine/hw_cswift.c b/crypto/engine/hw_cswift.c index e9f62f61d3..15983525e1 100644 --- a/crypto/engine/hw_cswift.c +++ b/crypto/engine/hw_cswift.c @@ -83,8 +83,9 @@ #include "vendor_defns/cswift.h" #endif -static int cswift_init(ENGINE *); -static int cswift_finish(ENGINE *); +static int cswift_init(ENGINE *e); +static int cswift_finish(ENGINE *e); +static int cswift_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); /* BIGNUM stuff */ static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, @@ -110,6 +111,15 @@ static int cswift_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +/* The definitions for control commands specific to this engine */ +#define CSWIFT_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN cswift_cmd_defns[] = { + {CSWIFT_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'cswift' shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} + }; /* Our internal RSA_METHOD that we provide pointers to */ static RSA_METHOD cswift_rsa = @@ -178,7 +188,9 @@ ENGINE *ENGINE_cswift() !ENGINE_set_BN_mod_exp(ret, &cswift_mod_exp) || !ENGINE_set_BN_mod_exp_crt(ret, &cswift_mod_exp_crt) || !ENGINE_set_init_function(ret, cswift_init) || - !ENGINE_set_finish_function(ret, cswift_finish)) + !ENGINE_set_finish_function(ret, cswift_finish) || + !ENGINE_set_ctrl_function(ret, cswift_ctrl) || + !ENGINE_set_cmd_defns(ret, cswift_cmd_defns)) { ENGINE_free(ret); return NULL; @@ -219,7 +231,8 @@ t_swSimpleRequest *p_CSwift_SimpleRequest = NULL; t_swReleaseAccContext *p_CSwift_ReleaseAccContext = NULL; /* Used in the DSO operations. */ -static const char *CSWIFT_LIBNAME = "swift"; +static const char def_CSWIFT_LIBNAME[] = "swift"; +static const char *CSWIFT_LIBNAME = def_CSWIFT_LIBNAME; static const char *CSWIFT_F1 = "swAcquireAccContext"; static const char *CSWIFT_F2 = "swAttachKeyParam"; static const char *CSWIFT_F3 = "swSimpleRequest"; @@ -326,6 +339,33 @@ static int cswift_finish(ENGINE *e) return 1; } +static int cswift_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialised = ((cswift_dso == NULL) ? 0 : 1); + switch(cmd) + { + case CSWIFT_CMD_SO_PATH: + if(p == NULL) + { + ENGINEerr(ENGINE_F_CSWIFT_CTRL, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(initialised) + { + ENGINEerr(ENGINE_F_CSWIFT_CTRL, + ENGINE_R_ALREADY_LOADED); + return 0; + } + CSWIFT_LIBNAME = (const char *)p; + return 1; + default: + break; + } + ENGINEerr(ENGINE_F_CSWIFT_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; + } + /* Un petit mod_exp */ static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) diff --git a/crypto/engine/hw_ncipher.c b/crypto/engine/hw_ncipher.c index 792893a2fd..dc645d554b 100644 --- a/crypto/engine/hw_ncipher.c +++ b/crypto/engine/hw_ncipher.c @@ -126,6 +126,26 @@ static int hwcrhk_get_pass(const char *prompt_info, HWCryptoHook_CallerContext *cactx); static void hwcrhk_log_message(void *logstr, const char *message); +/* The definitions for control commands specific to this engine */ +#define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE +#define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1) +#define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2) +static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = { + {HWCRHK_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'hwcrhk' shared library", + ENGINE_CMD_FLAG_STRING}, + {HWCRHK_CMD_FORK_CHECK, + "FORK_CHECK", + "Turns fork() checking on or off (boolean)", + ENGINE_CMD_FLAG_NUMERIC}, + {HWCRHK_CMD_THREAD_LOCKING, + "THREAD_LOCKING", + "Turns thread-safe locking on or off (boolean)", + ENGINE_CMD_FLAG_NUMERIC}, + {0, NULL, NULL, 0} + }; + /* Our internal RSA_METHOD that we provide pointers to */ static RSA_METHOD hwcrhk_rsa = { @@ -289,7 +309,8 @@ ENGINE *ENGINE_ncipher() !ENGINE_set_finish_function(ret, hwcrhk_finish) || !ENGINE_set_ctrl_function(ret, hwcrhk_ctrl) || !ENGINE_set_load_privkey_function(ret, hwcrhk_load_privkey) || - !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey)) + !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey) || + !ENGINE_set_cmd_defns(ret, hwcrhk_cmd_defns)) { ENGINE_free(ret); return NULL; @@ -337,7 +358,8 @@ static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL; static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL; /* Used in the DSO operations. */ -static const char *HWCRHK_LIBNAME = "nfhwcrhk"; +static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk"; +static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME; static const char *n_hwcrhk_Init = "HWCryptoHook_Init"; static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish"; static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp"; @@ -513,6 +535,19 @@ static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) switch(cmd) { + case HWCRHK_CMD_SO_PATH: + if(hwcrhk_dso) + { + ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_ALREADY_LOADED); + return 0; + } + if(p == NULL) + { + ENGINEerr(ENGINE_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + HWCRHK_LIBNAME = (const char *)p; + return 1; case ENGINE_CTRL_SET_LOGSTREAM: { BIO *bio = (BIO *)p; @@ -538,6 +573,7 @@ static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) /* this enables or disables the "SimpleForkCheck" flag used in the * initialisation structure. */ case ENGINE_CTRL_CHIL_SET_FORKCHECK: + case HWCRHK_CMD_FORK_CHECK: CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); if(i) hwcrhk_globals.flags |= @@ -557,6 +593,11 @@ static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) disable_mutex_callbacks = 1; CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); break; + case HWCRHK_CMD_THREAD_LOCKING: + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + disable_mutex_callbacks = ((i == 0) ? 0 : 1); + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + break; /* The command isn't understood by this engine */ default: diff --git a/crypto/engine/hw_nuron.c b/crypto/engine/hw_nuron.c index d85de3f9ac..d5697dade6 100644 --- a/crypto/engine/hw_nuron.c +++ b/crypto/engine/hw_nuron.c @@ -66,9 +66,20 @@ #ifndef OPENSSL_NO_HW #ifndef OPENSSL_NO_HW_NURON -static const char *NURON_LIBNAME = "nuronssl"; +static const char def_NURON_LIBNAME[] = "nuronssl"; +static const char *NURON_LIBNAME = def_NURON_LIBNAME; static const char *NURON_F1 = "nuron_mod_exp"; +/* The definitions for control commands specific to this engine */ +#define NURON_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN nuron_cmd_defns[] = { + {NURON_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'nuronssl' shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} + }; + typedef int tfnModExp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,const BIGNUM *m); static tfnModExp *pfnModExp = NULL; @@ -82,7 +93,7 @@ static int nuron_init(ENGINE *e) return 0; } - pvDSOHandle=DSO_load(NULL, NURON_LIBNAME, NULL, + pvDSOHandle = DSO_load(NULL, NURON_LIBNAME, NULL, DSO_FLAG_NAME_TRANSLATION_EXT_ONLY); if(!pvDSOHandle) { @@ -90,7 +101,7 @@ static int nuron_init(ENGINE *e) return 0; } - pfnModExp=(tfnModExp *)DSO_bind_func(pvDSOHandle, NURON_F1); + pfnModExp = (tfnModExp *)DSO_bind_func(pvDSOHandle, NURON_F1); if(!pfnModExp) { ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_DSO_FUNCTION_NOT_FOUND); @@ -117,6 +128,31 @@ static int nuron_finish(ENGINE *e) return 1; } +static int nuron_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialised = ((pvDSOHandle == NULL) ? 0 : 1); + switch(cmd) + { + case NURON_CMD_SO_PATH: + if(p == NULL) + { + ENGINEerr(ENGINE_F_NURON_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(initialised) + { + ENGINEerr(ENGINE_F_NURON_CTRL,ENGINE_R_ALREADY_LOADED); + return 0; + } + NURON_LIBNAME = (const char *)p; + return 1; + default: + break; + } + ENGINEerr(ENGINE_F_NURON_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; +} + static int nuron_mod_exp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p, const BIGNUM *m,BN_CTX *ctx) { @@ -250,7 +286,9 @@ ENGINE *ENGINE_nuron() !ENGINE_set_DH(ret, &nuron_dh) || !ENGINE_set_BN_mod_exp(ret, nuron_mod_exp) || !ENGINE_set_init_function(ret, nuron_init) || - !ENGINE_set_finish_function(ret, nuron_finish)) + !ENGINE_set_finish_function(ret, nuron_finish) || + !ENGINE_set_ctrl_function(ret, nuron_ctrl) || + !ENGINE_set_cmd_defns(ret, nuron_cmd_defns)) { ENGINE_free(ret); return NULL; diff --git a/crypto/engine/hw_ubsec.c b/crypto/engine/hw_ubsec.c index a05211f27a..d948135568 100644 --- a/crypto/engine/hw_ubsec.c +++ b/crypto/engine/hw_ubsec.c @@ -75,6 +75,7 @@ static int ubsec_init(ENGINE *e); static int ubsec_finish(ENGINE *e); +static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx); static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, @@ -104,7 +105,16 @@ static int ubsec_dh_generate_key(DH *dh); static int ubsec_rand_bytes(unsigned char *buf, int num); static int ubsec_rand_status(void); #endif - + +#define UBSEC_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = { + {UBSEC_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'ubsec' shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} + }; + /* Our internal RSA_METHOD that we provide pointers to */ static RSA_METHOD ubsec_rsa = @@ -175,7 +185,9 @@ ENGINE *ENGINE_ubsec() !ENGINE_set_BN_mod_exp(ret, ubsec_mod_exp) || !ENGINE_set_BN_mod_exp_crt(ret, ubsec_mod_exp_crt) || !ENGINE_set_init_function(ret, ubsec_init) || - !ENGINE_set_finish_function(ret, ubsec_finish)) + !ENGINE_set_finish_function(ret, ubsec_finish) || + !ENGINE_set_ctrl_function(ret, ubsec_ctrl) || + !ENGINE_set_cmd_defns(ret, ubsec_cmd_defns)) { ENGINE_free(ret); return NULL; @@ -373,6 +385,31 @@ static int ubsec_finish(ENGINE *e) return 1; } +static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialised = ((ubsec_dso == NULL) ? 0 : 1); + switch(cmd) + { + case UBSEC_CMD_SO_PATH: + if(p == NULL) + { + ENGINEerr(ENGINE_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(initialised) + { + ENGINEerr(ENGINE_F_UBSEC_CTRL,ENGINE_R_ALREADY_LOADED); + return 0; + } + UBSEC_LIBNAME = (const char *)p; + return 1; + default: + break; + } + ENGINEerr(ENGINE_F_UBSEC_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; + } + static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) { -- 2.25.1