diff options
author | Richard Levitte <levitte@openssl.org> | 2000-10-26 21:07:28 +0000 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2000-10-26 21:07:28 +0000 |
commit | 5270e7025e11b2fd1a5bdf8d81feded1167b1c87 (patch) | |
tree | 3bb44c37f4bb6469f738a10127050b023e0d7fb5 /crypto | |
parent | 1df586bec20de86c3086181c565aaee7629bb0a2 (diff) | |
download | openssl-new-5270e7025e11b2fd1a5bdf8d81feded1167b1c87.tar.gz |
Merge the engine branch into the main trunk. All conflicts resolved.
At the same time, add VMS support for Rijndael.
Diffstat (limited to 'crypto')
46 files changed, 6700 insertions, 366 deletions
diff --git a/crypto/Makefile.ssl b/crypto/Makefile.ssl index 72e3fe7fde..7bb2a5ca99 100644 --- a/crypto/Makefile.ssl +++ b/crypto/Makefile.ssl @@ -27,7 +27,7 @@ LIBS= SDIRS= md2 md5 sha mdc2 hmac ripemd \ des rc2 rc4 rc5 idea bf cast \ - bn rsa dsa dh dso \ + bn rsa dsa dh dso engine \ buffer bio stack lhash rand err objects \ evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp rijndael diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 8117323766..d2c91628ac 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -113,13 +113,6 @@ #include <stdio.h> #include "cryptlib.h" #include "bn_lcl.h" -#ifdef ATALLA -# include <alloca.h> -# include <atasi.h> -# include <assert.h> -# include <dlfcn.h> -#endif - #define TABLE_SIZE 32 @@ -183,174 +176,6 @@ err: } -#ifdef ATALLA - -/* - * This routine will dynamically check for the existance of an Atalla AXL-200 - * SSL accelerator module. If one is found, the variable - * asi_accelerator_present is set to 1 and the function pointers - * ptr_ASI_xxxxxx above will be initialized to corresponding ASI API calls. - */ -typedef int tfnASI_GetPerformanceStatistics(int reset_flag, - unsigned int *ret_buf); -typedef int tfnASI_GetHardwareConfig(long card_num, unsigned int *ret_buf); -typedef int tfnASI_RSAPrivateKeyOpFn(RSAPrivateKey * rsaKey, - unsigned char *output, - unsigned char *input, - unsigned int modulus_len); - -static tfnASI_GetHardwareConfig *ptr_ASI_GetHardwareConfig; -static tfnASI_RSAPrivateKeyOpFn *ptr_ASI_RSAPrivateKeyOpFn; -static tfnASI_GetPerformanceStatistics *ptr_ASI_GetPerformanceStatistics; -static int asi_accelerator_present; -static int tried_atalla; - -void atalla_initialize_accelerator_handle(void) - { - void *dl_handle; - int status; - unsigned int config_buf[1024]; - static int tested; - - if(tested) - return; - - tested=1; - - bzero((void *)config_buf, 1024); - - /* - * Check to see if the library is present on the system - */ - dl_handle = dlopen("atasi.so", RTLD_NOW); - if (dl_handle == (void *) NULL) - { -/* printf("atasi.so library is not present on the system\n"); - printf("No HW acceleration available\n");*/ - return; - } - - /* - * The library is present. Now we'll check to insure that the - * LDM is up and running. First we'll get the address of the - * function in the atasi library that we need to see if the - * LDM is operating. - */ - - ptr_ASI_GetHardwareConfig = - (tfnASI_GetHardwareConfig *)dlsym(dl_handle,"ASI_GetHardwareConfig"); - - if (ptr_ASI_GetHardwareConfig) - { - /* - * We found the call, now we'll get our config - * status. If we get a non 0 result, the LDM is not - * running and we cannot use the Atalla ASI * - * library. - */ - status = (*ptr_ASI_GetHardwareConfig)(0L, config_buf); - if (status != 0) - { - printf("atasi.so library is present but not initialized\n"); - printf("No HW acceleration available\n"); - return; - } - } - else - { -/* printf("We found the library, but not the function. Very Strange!\n");*/ - return ; - } - - /* - * It looks like we have acceleration capabilities. Load up the - * pointers to our ASI API calls. - */ - ptr_ASI_RSAPrivateKeyOpFn= - (tfnASI_RSAPrivateKeyOpFn *)dlsym(dl_handle, "ASI_RSAPrivateKeyOpFn"); - if (ptr_ASI_RSAPrivateKeyOpFn == NULL) - { -/* printf("We found the library, but no RSA function. Very Strange!\n");*/ - return; - } - - ptr_ASI_GetPerformanceStatistics = - (tfnASI_GetPerformanceStatistics *)dlsym(dl_handle, "ASI_GetPerformanceStatistics"); - if (ptr_ASI_GetPerformanceStatistics == NULL) - { -/* printf("We found the library, but no stat function. Very Strange!\n");*/ - return; - } - - /* - * Indicate that acceleration is available - */ - asi_accelerator_present = 1; - -/* printf("This system has acceleration!\n");*/ - - return; - } - -/* make sure this only gets called once when bn_mod_exp calls bn_mod_exp_mont */ -int BN_mod_exp_atalla(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m) - { - unsigned char *abin; - unsigned char *pbin; - unsigned char *mbin; - unsigned char *rbin; - int an,pn,mn,ret; - RSAPrivateKey keydata; - - atalla_initialize_accelerator_handle(); - if(!asi_accelerator_present) - return 0; - - -/* We should be able to run without size testing */ -# define ASIZE 128 - an=BN_num_bytes(a); - pn=BN_num_bytes(p); - mn=BN_num_bytes(m); - - if(an <= ASIZE && pn <= ASIZE && mn <= ASIZE) - { - int size=mn; - - assert(an <= mn); - abin=alloca(size); - memset(abin,'\0',mn); - BN_bn2bin(a,abin+size-an); - - pbin=alloca(pn); - BN_bn2bin(p,pbin); - - mbin=alloca(size); - memset(mbin,'\0',mn); - BN_bn2bin(m,mbin+size-mn); - - rbin=alloca(size); - - memset(&keydata,'\0',sizeof keydata); - keydata.privateExponent.data=pbin; - keydata.privateExponent.len=pn; - keydata.modulus.data=mbin; - keydata.modulus.len=size; - - ret=(*ptr_ASI_RSAPrivateKeyOpFn)(&keydata,rbin,abin,keydata.modulus.len); -/*fprintf(stderr,"!%s\n",BN_bn2hex(a));*/ - if(!ret) - { - BN_bin2bn(rbin,keydata.modulus.len,r); -/*fprintf(stderr,"?%s\n",BN_bn2hex(r));*/ - return 1; - } - } - return 0; - } -#endif /* def ATALLA */ - - int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) { @@ -360,13 +185,6 @@ int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, bn_check_top(p); bn_check_top(m); -#ifdef ATALLA - if(BN_mod_exp_atalla(r,a,p,m)) - return 1; -/* If it fails, try the other methods (but don't try atalla again) */ - tried_atalla=1; -#endif - #ifdef MONT_MUL_MOD /* I have finally been able to take out this pre-condition of * the top bit being set. It was caused by an error in BN_div @@ -392,10 +210,6 @@ int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, { ret=BN_mod_exp_simple(r,a,p,m,ctx); } #endif -#ifdef ATALLA - tried_atalla=0; -#endif - return(ret); } @@ -525,12 +339,6 @@ int BN_mod_exp_mont(BIGNUM *rr, BIGNUM *a, const BIGNUM *p, bn_check_top(p); bn_check_top(m); -#ifdef ATALLA - if(!tried_atalla && BN_mod_exp_atalla(rr,a,p,m)) - return 1; -/* If it fails, try the other methods */ -#endif - if (!(m->d[0] & 1)) { BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); @@ -693,19 +501,6 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, t = BN_CTX_get(ctx); if (d == NULL || r == NULL || t == NULL) goto err; -#ifdef ATALLA - if (!tried_atalla) - { - BN_set_word(t, a); - if (BN_mod_exp_atalla(rr, t, p, m)) - { - BN_CTX_end(ctx); - return 1; - } - } -/* If it fails, try the other methods */ -#endif - if (in_mont != NULL) mont=in_mont; else diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 070cf59690..9de60fd528 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -100,7 +100,8 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] = "debug_malloc2", "dso", "dynlock", -#if CRYPTO_NUM_LOCKS != 28 + "engine", +#if CRYPTO_NUM_LOCKS != 29 # error "Inconsistency between crypto.h and cryptlib.c" #endif }; diff --git a/crypto/crypto-lib.com b/crypto/crypto-lib.com index edffeffde1..70e3c91b34 100644 --- a/crypto/crypto-lib.com +++ b/crypto/crypto-lib.com @@ -88,7 +88,7 @@ $! Define The Different Encryption Types. $! $ ENCRYPT_TYPES = "Basic,MD2,MD4,MD5,SHA,MDC2,HMAC,RIPEMD,"+ - "DES,RC2,RC4,RC5,IDEA,BF,CAST,"+ - - "BN,RSA,DSA,DH,DSO,"+ - + "BN,RSA,DSA,DH,DSO,ENGINE,RIJNDAEL,"+ - "BUFFER,BIO,STACK,LHASH,RAND,ERR,OBJECTS,"+ - "EVP,EVP_2,ASN1,ASN1_2,PEM,X509,X509V3,"+ - "CONF,TXT_DB,PKCS7,PKCS12,COMP" @@ -206,6 +206,9 @@ $ LIB_DSA = "dsa_gen,dsa_key,dsa_lib,dsa_asn1,dsa_vrf,dsa_sign,dsa_err,dsa_ossl" $ LIB_DH = "dh_gen,dh_key,dh_lib,dh_check,dh_err" $ LIB_DSO = "dso_dl,dso_dlfcn,dso_err,dso_lib,dso_null,"+ - "dso_openssl,dso_win32,dso_vms" +$ LIB_ENGINE = "engine_err,engine_lib,engine_list,engine_openssl,"+ - + "hw_atalla,hw_cswift,hw_ncipher" +$ LIB_RIJNDAEL = "rijndael-alg-fst" $ LIB_BUFFER = "buffer,buf_err" $ LIB_BIO = "bio_lib,bio_cb,bio_err,"+ - "bss_mem,bss_null,bss_fd,"+ - @@ -1194,7 +1197,9 @@ $ CC = "CC" $ IF ARCH.EQS."VAX" .AND. F$TRNLNM("DECC$CC_DEFAULT").NES."/DECC" - THEN CC = "CC/DECC" $ CC = CC + "/''CC_OPTIMIZE'/''DEBUGGER'/STANDARD=ANSI89" + - - "/NOLIST/PREFIX=ALL/INCLUDE=SYS$DISK:[]" + CCEXTRAFLAGS + "/NOLIST/PREFIX=ALL" + - + "/INCLUDE=(SYS$DISK:[],SYS$DISK:[.ENGINE.VENDOR_DEFNS])" + - + CCEXTRAFLAGS $! $! Define The Linker Options File Name. $! @@ -1226,7 +1231,8 @@ $ WRITE SYS$OUTPUT "There is no VAX C on Alpha!" $ EXIT $ ENDIF $ IF F$TRNLNM("DECC$CC_DEFAULT").EQS."/DECC" THEN CC = "CC/VAXC" -$ CC = CC + "/''CC_OPTIMIZE'/''DEBUGGER'/NOLIST/INCLUDE=SYS$DISK:[]" + - +$ CC = CC + "/''CC_OPTIMIZE'/''DEBUGGER'/NOLIST" + - + "/INCLUDE=(SYS$DISK:[],SYS$DISK:[.ENGINE.VENDOR_DEFNS])" + - CCEXTRAFLAGS $ CCDEFS = """VAXC""," + CCDEFS $! @@ -1258,7 +1264,8 @@ $! $! Use GNU C... $! $ CC = "GCC/NOCASE_HACK/''GCC_OPTIMIZE'/''DEBUGGER'/NOLIST" + - - "/INCLUDE=SYS$DISK:[]" + CCEXTRAFLAGS + "/INCLUDE=(SYS$DISK:[],SYS$DISK:[.ENGINE.VENDOR_DEFNS])" + - + CCEXTRAFLAGS $! $! Define The Linker Options File Name. $! diff --git a/crypto/crypto.h b/crypto/crypto.h index df6ccaff6d..52ee97b71a 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -122,7 +122,8 @@ extern "C" { #define CRYPTO_LOCK_MALLOC2 25 #define CRYPTO_LOCK_DSO 26 #define CRYPTO_LOCK_DYNLOCK 27 -#define CRYPTO_NUM_LOCKS 28 +#define CRYPTO_LOCK_ENGINE 28 +#define CRYPTO_NUM_LOCKS 29 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 diff --git a/crypto/dh/Makefile.ssl b/crypto/dh/Makefile.ssl index ccee00eeca..b9fed3a65e 100644 --- a/crypto/dh/Makefile.ssl +++ b/crypto/dh/Makefile.ssl @@ -101,19 +101,41 @@ dh_gen.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h dh_gen.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h dh_gen.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h dh_gen.o: ../cryptlib.h -dh_key.o: ../../include/openssl/bio.h ../../include/openssl/bn.h -dh_key.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -dh_key.o: ../../include/openssl/dh.h ../../include/openssl/e_os.h -dh_key.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -dh_key.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h +dh_key.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +dh_key.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +dh_key.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +dh_key.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +dh_key.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +dh_key.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +dh_key.o: ../../include/openssl/engine.h ../../include/openssl/err.h +dh_key.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +dh_key.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +dh_key.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +dh_key.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +dh_key.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h dh_key.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h -dh_key.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +dh_key.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +dh_key.o: ../../include/openssl/rc5.h ../../include/openssl/rijndael-alg-fst.h +dh_key.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +dh_key.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +dh_key.o: ../../include/openssl/sha.h ../../include/openssl/stack.h dh_key.o: ../../include/openssl/symhacks.h ../cryptlib.h -dh_lib.o: ../../include/openssl/bio.h ../../include/openssl/bn.h -dh_lib.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -dh_lib.o: ../../include/openssl/dh.h ../../include/openssl/e_os.h -dh_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -dh_lib.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h -dh_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h -dh_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -dh_lib.o: ../cryptlib.h +dh_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +dh_lib.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +dh_lib.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +dh_lib.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +dh_lib.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +dh_lib.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +dh_lib.o: ../../include/openssl/engine.h ../../include/openssl/err.h +dh_lib.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +dh_lib.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +dh_lib.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +dh_lib.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +dh_lib.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +dh_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +dh_lib.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +dh_lib.o: ../../include/openssl/rc5.h ../../include/openssl/rijndael-alg-fst.h +dh_lib.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +dh_lib.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +dh_lib.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +dh_lib.o: ../../include/openssl/symhacks.h ../cryptlib.h diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h index a15fc1c65f..7a8d9f88c2 100644 --- a/crypto/dh/dh.h +++ b/crypto/dh/dh.h @@ -115,7 +115,11 @@ struct dh_st int references; CRYPTO_EX_DATA ex_data; +#if 0 DH_METHOD *meth; +#else + struct engine_st *engine; +#endif }; #define DH_GENERATOR_2 2 @@ -150,10 +154,15 @@ struct dh_st DH_METHOD *DH_OpenSSL(void); -void DH_set_default_method(DH_METHOD *meth); -DH_METHOD *DH_get_default_method(void); +void DH_set_default_openssl_method(DH_METHOD *meth); +DH_METHOD *DH_get_default_openssl_method(void); +#if 0 DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth); DH *DH_new_method(DH_METHOD *meth); +#else +int DH_set_method(DH *dh, struct engine_st *engine); +DH *DH_new_method(struct engine_st *engine); +#endif DH * DH_new(void); void DH_free(DH *dh); diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index 6f9426dd6f..6915d79dcc 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -61,6 +61,7 @@ #include <openssl/bn.h> #include <openssl/rand.h> #include <openssl/dh.h> +#include <openssl/engine.h> static int generate_key(DH *dh); static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh); @@ -72,12 +73,12 @@ static int dh_finish(DH *dh); int DH_generate_key(DH *dh) { - return dh->meth->generate_key(dh); + return ENGINE_get_DH(dh->engine)->generate_key(dh); } int DH_compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) { - return dh->meth->compute_key(key, pub_key, dh); + return ENGINE_get_DH(dh->engine)->compute_key(key, pub_key, dh); } static DH_METHOD dh_ossl = { @@ -137,8 +138,9 @@ static int generate_key(DH *dh) } mont=(BN_MONT_CTX *)dh->method_mont_p; - if (!dh->meth->bn_mod_exp(dh, pub_key,dh->g,priv_key,dh->p,&ctx,mont)) - goto err; + if (!ENGINE_get_DH(dh->engine)->bn_mod_exp(dh, pub_key, dh->g, + priv_key,dh->p,&ctx,mont)) + goto err; dh->pub_key=pub_key; dh->priv_key=priv_key; @@ -177,7 +179,8 @@ static int compute_key(unsigned char *key, BIGNUM *pub_key, DH *dh) } mont=(BN_MONT_CTX *)dh->method_mont_p; - if (!dh->meth->bn_mod_exp(dh, tmp,pub_key,dh->priv_key,dh->p,&ctx,mont)) + if (!ENGINE_get_DH(dh->engine)->bn_mod_exp(dh, tmp, pub_key, + dh->priv_key,dh->p,&ctx,mont)) { DHerr(DH_F_DH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index a8d5340bf4..66803b5565 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -60,6 +60,7 @@ #include "cryptlib.h" #include <openssl/bn.h> #include <openssl/dh.h> +#include <openssl/engine.h> const char *DH_version="Diffie-Hellman" OPENSSL_VERSION_PTEXT; @@ -67,17 +68,32 @@ static DH_METHOD *default_DH_method; static int dh_meth_num = 0; static STACK_OF(CRYPTO_EX_DATA_FUNCS) *dh_meth = NULL; -void DH_set_default_method(DH_METHOD *meth) +void DH_set_default_openssl_method(DH_METHOD *meth) { - default_DH_method = meth; + ENGINE *e; + /* We'll need to notify the "openssl" ENGINE of this + * change too. We won't bother locking things down at + * our end as there was never any locking in these + * functions! */ + if(default_DH_method != meth) + { + default_DH_method = meth; + e = ENGINE_by_id("openssl"); + if(e) + { + ENGINE_set_DH(e, meth); + ENGINE_free(e); + } + } } -DH_METHOD *DH_get_default_method(void) +DH_METHOD *DH_get_default_openssl_method(void) { if(!default_DH_method) default_DH_method = DH_OpenSSL(); return default_DH_method; } +#if 0 DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth) { DH_METHOD *mtmp; @@ -87,14 +103,37 @@ DH_METHOD *DH_set_method(DH *dh, DH_METHOD *meth) if (meth->init) meth->init(dh); return mtmp; } +#else +int DH_set_method(DH *dh, ENGINE *engine) +{ + ENGINE *mtmp; + DH_METHOD *meth; + mtmp = dh->engine; + meth = ENGINE_get_DH(mtmp); + if (!ENGINE_init(engine)) + return 0; + if (meth->finish) meth->finish(dh); + dh->engine= engine; + meth = ENGINE_get_DH(engine); + if (meth->init) meth->init(dh); + /* SHOULD ERROR CHECK THIS!!! */ + ENGINE_finish(mtmp); + return 1; +} +#endif DH *DH_new(void) { return DH_new_method(NULL); } +#if 0 DH *DH_new_method(DH_METHOD *meth) +#else +DH *DH_new_method(ENGINE *engine) +#endif { + DH_METHOD *meth; DH *ret; ret=(DH *)OPENSSL_malloc(sizeof(DH)); @@ -103,8 +142,17 @@ DH *DH_new_method(DH_METHOD *meth) DHerr(DH_F_DH_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } - if(meth) ret->meth = meth; - else ret->meth = DH_get_default_method(); + if(engine) + ret->engine = engine; + else + { + if((ret->engine=ENGINE_get_default_DH()) == NULL) + { + OPENSSL_free(ret); + return NULL; + } + } + meth = ENGINE_get_DH(ret->engine); ret->pad=0; ret->version=0; ret->p=NULL; @@ -119,8 +167,8 @@ DH *DH_new_method(DH_METHOD *meth) ret->counter = NULL; ret->method_mont_p=NULL; ret->references = 1; - ret->flags=ret->meth->flags; - if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + ret->flags=meth->flags; + if ((meth->init != NULL) && !meth->init(ret)) { OPENSSL_free(ret); ret=NULL; @@ -132,6 +180,7 @@ DH *DH_new_method(DH_METHOD *meth) void DH_free(DH *r) { + DH_METHOD *meth; int i; if(r == NULL) return; i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH); @@ -149,7 +198,9 @@ void DH_free(DH *r) CRYPTO_free_ex_data(dh_meth, r, &r->ex_data); - if(r->meth->finish) r->meth->finish(r); + meth = ENGINE_get_DH(r->engine); + if(meth->finish) meth->finish(r); + ENGINE_finish(r->engine); if (r->p != NULL) BN_clear_free(r->p); if (r->g != NULL) BN_clear_free(r->g); diff --git a/crypto/dsa/Makefile.ssl b/crypto/dsa/Makefile.ssl index 1dfdb2d769..f9a6dbbd45 100644 --- a/crypto/dsa/Makefile.ssl +++ b/crypto/dsa/Makefile.ssl @@ -116,39 +116,81 @@ dsa_key.o: ../../include/openssl/rand.h ../../include/openssl/safestack.h dsa_key.o: ../../include/openssl/sha.h ../../include/openssl/stack.h dsa_key.o: ../../include/openssl/symhacks.h ../cryptlib.h dsa_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h -dsa_lib.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h -dsa_lib.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h -dsa_lib.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h -dsa_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -dsa_lib.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h -dsa_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h -dsa_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -dsa_lib.o: ../cryptlib.h +dsa_lib.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +dsa_lib.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +dsa_lib.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +dsa_lib.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +dsa_lib.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +dsa_lib.o: ../../include/openssl/engine.h ../../include/openssl/err.h +dsa_lib.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +dsa_lib.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +dsa_lib.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +dsa_lib.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +dsa_lib.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +dsa_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +dsa_lib.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +dsa_lib.o: ../../include/openssl/rc5.h ../../include/openssl/rijndael-alg-fst.h +dsa_lib.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +dsa_lib.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +dsa_lib.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +dsa_lib.o: ../../include/openssl/symhacks.h ../cryptlib.h dsa_ossl.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h -dsa_ossl.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h -dsa_ossl.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h -dsa_ossl.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h -dsa_ossl.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -dsa_ossl.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h +dsa_ossl.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +dsa_ossl.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +dsa_ossl.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +dsa_ossl.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +dsa_ossl.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +dsa_ossl.o: ../../include/openssl/engine.h ../../include/openssl/err.h +dsa_ossl.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +dsa_ossl.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +dsa_ossl.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +dsa_ossl.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +dsa_ossl.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h dsa_ossl.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h -dsa_ossl.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +dsa_ossl.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +dsa_ossl.o: ../../include/openssl/rc5.h +dsa_ossl.o: ../../include/openssl/rijndael-alg-fst.h +dsa_ossl.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +dsa_ossl.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +dsa_ossl.o: ../../include/openssl/sha.h ../../include/openssl/stack.h dsa_ossl.o: ../../include/openssl/symhacks.h ../cryptlib.h dsa_sign.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h -dsa_sign.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h -dsa_sign.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h -dsa_sign.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h -dsa_sign.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -dsa_sign.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h +dsa_sign.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +dsa_sign.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +dsa_sign.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +dsa_sign.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +dsa_sign.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +dsa_sign.o: ../../include/openssl/engine.h ../../include/openssl/err.h +dsa_sign.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +dsa_sign.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +dsa_sign.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +dsa_sign.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +dsa_sign.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h dsa_sign.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h -dsa_sign.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +dsa_sign.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +dsa_sign.o: ../../include/openssl/rc5.h +dsa_sign.o: ../../include/openssl/rijndael-alg-fst.h +dsa_sign.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +dsa_sign.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +dsa_sign.o: ../../include/openssl/sha.h ../../include/openssl/stack.h dsa_sign.o: ../../include/openssl/symhacks.h ../cryptlib.h dsa_vrf.o: ../../include/openssl/asn1.h ../../include/openssl/asn1_mac.h -dsa_vrf.o: ../../include/openssl/bio.h ../../include/openssl/bn.h -dsa_vrf.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -dsa_vrf.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h -dsa_vrf.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -dsa_vrf.o: ../../include/openssl/err.h ../../include/openssl/lhash.h +dsa_vrf.o: ../../include/openssl/bio.h ../../include/openssl/blowfish.h +dsa_vrf.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h +dsa_vrf.o: ../../include/openssl/cast.h ../../include/openssl/crypto.h +dsa_vrf.o: ../../include/openssl/des.h ../../include/openssl/dh.h +dsa_vrf.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h +dsa_vrf.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h +dsa_vrf.o: ../../include/openssl/err.h ../../include/openssl/evp.h +dsa_vrf.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h +dsa_vrf.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +dsa_vrf.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +dsa_vrf.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h dsa_vrf.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -dsa_vrf.o: ../../include/openssl/rand.h ../../include/openssl/safestack.h -dsa_vrf.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -dsa_vrf.o: ../cryptlib.h +dsa_vrf.o: ../../include/openssl/rand.h ../../include/openssl/rc2.h +dsa_vrf.o: ../../include/openssl/rc4.h ../../include/openssl/rc5.h +dsa_vrf.o: ../../include/openssl/rijndael-alg-fst.h +dsa_vrf.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +dsa_vrf.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +dsa_vrf.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +dsa_vrf.o: ../../include/openssl/symhacks.h ../cryptlib.h diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h index 3ebcc4ae0a..65689a3426 100644 --- a/crypto/dsa/dsa.h +++ b/crypto/dsa/dsa.h @@ -133,7 +133,11 @@ struct dsa_st char *method_mont_p; int references; CRYPTO_EX_DATA ex_data; +#if 0 DSA_METHOD *meth; +#else + struct engine_st *engine; +#endif }; #define DSAparams_dup(x) (DSA *)ASN1_dup((int (*)())i2d_DSAparams, \ @@ -159,12 +163,20 @@ int DSA_do_verify(const unsigned char *dgst,int dgst_len, DSA_METHOD *DSA_OpenSSL(void); -void DSA_set_default_method(DSA_METHOD *); -DSA_METHOD *DSA_get_default_method(void); +void DSA_set_default_openssl_method(DSA_METHOD *); +DSA_METHOD *DSA_get_default_openssl_method(void); +#if 0 DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *); +#else +int DSA_set_method(DSA *dsa, struct engine_st *engine); +#endif DSA * DSA_new(void); +#if 0 DSA * DSA_new_method(DSA_METHOD *meth); +#else +DSA * DSA_new_method(struct engine_st *engine); +#endif int DSA_size(DSA *); /* next 4 return -1 on error */ int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp); diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index be30d18b8a..b31b946ad3 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -63,6 +63,7 @@ #include <openssl/bn.h> #include <openssl/dsa.h> #include <openssl/asn1.h> +#include <openssl/engine.h> const char *DSA_version="DSA" OPENSSL_VERSION_PTEXT; @@ -70,12 +71,26 @@ static DSA_METHOD *default_DSA_method; static int dsa_meth_num = 0; static STACK_OF(CRYPTO_EX_DATA_FUNCS) *dsa_meth = NULL; -void DSA_set_default_method(DSA_METHOD *meth) +void DSA_set_default_openssl_method(DSA_METHOD *meth) { - default_DSA_method = meth; + ENGINE *e; + /* We'll need to notify the "openssl" ENGINE of this + * change too. We won't bother locking things down at + * our end as there was never any locking in these + * functions! */ + if(default_DSA_method != meth) + { + default_DSA_method = meth; + e = ENGINE_by_id("openssl"); + if(e) + { + ENGINE_set_DSA(e, meth); + ENGINE_free(e); + } + } } -DSA_METHOD *DSA_get_default_method(void) +DSA_METHOD *DSA_get_default_openssl_method(void) { if(!default_DSA_method) default_DSA_method = DSA_OpenSSL(); return default_DSA_method; @@ -86,6 +101,7 @@ DSA *DSA_new(void) return DSA_new_method(NULL); } +#if 0 DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *meth) { DSA_METHOD *mtmp; @@ -95,10 +111,33 @@ DSA_METHOD *DSA_set_method(DSA *dsa, DSA_METHOD *meth) if (meth->init) meth->init(dsa); return mtmp; } +#else +int DSA_set_method(DSA *dsa, ENGINE *engine) + { + ENGINE *mtmp; + DSA_METHOD *meth; + mtmp = dsa->engine; + meth = ENGINE_get_DSA(mtmp); + if (!ENGINE_init(engine)) + return 0; + if (meth->finish) meth->finish(dsa); + dsa->engine = engine; + meth = ENGINE_get_DSA(engine); + if (meth->init) meth->init(dsa); + /* SHOULD ERROR CHECK THIS!!! */ + ENGINE_finish(mtmp); + return 1; + } +#endif +#if 0 DSA *DSA_new_method(DSA_METHOD *meth) +#else +DSA *DSA_new_method(ENGINE *engine) +#endif { + DSA_METHOD *meth; DSA *ret; ret=(DSA *)OPENSSL_malloc(sizeof(DSA)); @@ -107,8 +146,17 @@ DSA *DSA_new_method(DSA_METHOD *meth) DSAerr(DSA_F_DSA_NEW,ERR_R_MALLOC_FAILURE); return(NULL); } - if(meth) ret->meth = meth; - else ret->meth = DSA_get_default_method(); + if(engine) + ret->engine = engine; + else + { + if((ret->engine=ENGINE_get_default_DSA()) == NULL) + { + OPENSSL_free(ret); + return NULL; + } + } + meth = ENGINE_get_DSA(ret->engine); ret->pad=0; ret->version=0; ret->write_params=1; @@ -124,8 +172,8 @@ DSA *DSA_new_method(DSA_METHOD *meth) ret->method_mont_p=NULL; ret->references=1; - ret->flags=ret->meth->flags; - if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + ret->flags=meth->flags; + if ((meth->init != NULL) && !meth->init(ret)) { OPENSSL_free(ret); ret=NULL; @@ -138,6 +186,7 @@ DSA *DSA_new_method(DSA_METHOD *meth) void DSA_free(DSA *r) { + DSA_METHOD *meth; int i; if (r == NULL) return; @@ -157,7 +206,9 @@ void DSA_free(DSA *r) CRYPTO_free_ex_data(dsa_meth, r, &r->ex_data); - if(r->meth->finish) r->meth->finish(r); + meth = ENGINE_get_DSA(r->engine); + if(meth->finish) meth->finish(r); + ENGINE_finish(r->engine); if (r->p != NULL) BN_clear_free(r->p); if (r->q != NULL) BN_clear_free(r->q); diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 094356518f..96295dc24f 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -64,6 +64,7 @@ #include <openssl/dsa.h> #include <openssl/rand.h> #include <openssl/asn1.h> +#include <openssl/engine.h> static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); @@ -195,7 +196,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) } /* Compute r = (g^k mod p) mod q */ - if (!dsa->meth->bn_mod_exp(dsa, r,dsa->g,&k,dsa->p,ctx, + if (!ENGINE_get_DSA(dsa->engine)->bn_mod_exp(dsa, r,dsa->g,&k,dsa->p,ctx, (BN_MONT_CTX *)dsa->method_mont_p)) goto err; if (!BN_mod(r,r,dsa->q,ctx)) goto err; @@ -273,7 +274,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, if (!BN_mod(&u1,&u1,dsa->q,ctx)) goto err; #else { - if (!dsa->meth->dsa_mod_exp(dsa, &t1,dsa->g,&u1,dsa->pub_key,&u2, + if (!ENGINE_get_DSA(dsa->engine)->dsa_mod_exp(dsa, &t1,dsa->g,&u1,dsa->pub_key,&u2, dsa->p,ctx,mont)) goto err; /* BN_copy(&u1,&t1); */ /* let u1 = u1 mod q */ diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index 89205026f0..dfe27bae47 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -64,10 +64,11 @@ #include <openssl/dsa.h> #include <openssl/rand.h> #include <openssl/asn1.h> +#include <openssl/engine.h> DSA_SIG * DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { - return dsa->meth->dsa_do_sign(dgst, dlen, dsa); + return ENGINE_get_DSA(dsa->engine)->dsa_do_sign(dgst, dlen, dsa); } int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, @@ -87,6 +88,6 @@ int DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { - return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp); + return ENGINE_get_DSA(dsa->engine)->dsa_sign_setup(dsa, ctx_in, kinvp, rp); } diff --git a/crypto/dsa/dsa_vrf.c b/crypto/dsa/dsa_vrf.c index 03277f80fd..2e891ae491 100644 --- a/crypto/dsa/dsa_vrf.c +++ b/crypto/dsa/dsa_vrf.c @@ -65,11 +65,12 @@ #include <openssl/rand.h> #include <openssl/asn1.h> #include <openssl/asn1_mac.h> +#include <openssl/engine.h> int DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) { - return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa); + return ENGINE_get_DSA(dsa->engine)->dsa_do_verify(dgst, dgst_len, sig, dsa); } /* data has already been hashed (probably with SHA or SHA-1). */ diff --git a/crypto/engine/.cvsignore b/crypto/engine/.cvsignore new file mode 100644 index 0000000000..c6d03a9dbc --- /dev/null +++ b/crypto/engine/.cvsignore @@ -0,0 +1,2 @@ +lib +Makefile.save diff --git a/crypto/engine/Makefile.ssl b/crypto/engine/Makefile.ssl new file mode 100644 index 0000000000..8974ecd9c5 --- /dev/null +++ b/crypto/engine/Makefile.ssl @@ -0,0 +1,256 @@ +# +# OpenSSL/crypto/engine/Makefile +# + +DIR= engine +TOP= ../.. +CC= cc +INCLUDES= -I.. -I../../include +CFLAG=-g +INSTALL_PREFIX= +OPENSSLDIR= /usr/local/ssl +INSTALLTOP=/usr/local/ssl +MAKE= make -f Makefile.ssl +MAKEDEPEND= $(TOP)/util/domd $(TOP) +MAKEFILE= Makefile.ssl +AR= ar r + +CFLAGS= $(INCLUDES) $(CFLAG) + +GENERAL=Makefile +TEST= enginetest.c +APPS= + +LIB=$(TOP)/libcrypto.a +LIBSRC= engine_err.c engine_lib.c engine_list.c engine_openssl.c \ + hw_atalla.c hw_cswift.c hw_ncipher.c hw_nuron.c +LIBOBJ= engine_err.o engine_lib.o engine_list.o engine_openssl.o \ + hw_atalla.o hw_cswift.o hw_ncipher.o hw_nuron.o + +SRC= $(LIBSRC) + +EXHEADER= engine.h +HEADER= $(EXHEADER) + +ALL= $(GENERAL) $(SRC) $(HEADER) + +top: + (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all) + +all: lib + +lib: $(LIBOBJ) + $(AR) $(LIB) $(LIBOBJ) + $(RANLIB) $(LIB) + @touch lib + +files: + $(PERL) $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO + +links: + @$(TOP)/util/point.sh Makefile.ssl Makefile + @$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER) + @$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST) + @$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS) + +install: + @for i in $(EXHEADER) ; \ + do \ + (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \ + chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \ + done; + +tags: + ctags $(SRC) + +tests: + +lint: + lint -DLINT $(INCLUDES) $(SRC)>fluff + +depend: + $(MAKEDEPEND) $(INCLUDES) $(DEPFLAG) $(PROGS) $(LIBSRC) + +dclean: + $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new + mv -f Makefile.new $(MAKEFILE) + +clean: + rm -f *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +engine_err.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +engine_err.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +engine_err.o: ../../include/openssl/cast.h ../../include/openssl/crypto.h +engine_err.o: ../../include/openssl/des.h ../../include/openssl/dh.h +engine_err.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h +engine_err.o: ../../include/openssl/engine.h ../../include/openssl/err.h +engine_err.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +engine_err.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +engine_err.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +engine_err.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +engine_err.o: ../../include/openssl/objects.h +engine_err.o: ../../include/openssl/opensslconf.h +engine_err.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +engine_err.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +engine_err.o: ../../include/openssl/rc5.h +engine_err.o: ../../include/openssl/rijndael-alg-fst.h +engine_err.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +engine_err.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +engine_err.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +engine_err.o: ../../include/openssl/symhacks.h +engine_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +engine_lib.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +engine_lib.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +engine_lib.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +engine_lib.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +engine_lib.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +engine_lib.o: ../../include/openssl/engine.h ../../include/openssl/err.h +engine_lib.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +engine_lib.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +engine_lib.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +engine_lib.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +engine_lib.o: ../../include/openssl/objects.h +engine_lib.o: ../../include/openssl/opensslconf.h +engine_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +engine_lib.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +engine_lib.o: ../../include/openssl/rc5.h +engine_lib.o: ../../include/openssl/rijndael-alg-fst.h +engine_lib.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +engine_lib.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +engine_lib.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +engine_lib.o: ../../include/openssl/symhacks.h ../cryptlib.h engine_int.h +engine_list.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +engine_list.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +engine_list.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +engine_list.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +engine_list.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +engine_list.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h +engine_list.o: ../../include/openssl/engine.h ../../include/openssl/err.h +engine_list.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +engine_list.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +engine_list.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +engine_list.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +engine_list.o: ../../include/openssl/objects.h +engine_list.o: ../../include/openssl/opensslconf.h +engine_list.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +engine_list.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +engine_list.o: ../../include/openssl/rc5.h +engine_list.o: ../../include/openssl/rijndael-alg-fst.h +engine_list.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +engine_list.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +engine_list.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +engine_list.o: ../../include/openssl/symhacks.h ../cryptlib.h engine_int.h +engine_openssl.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +engine_openssl.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +engine_openssl.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +engine_openssl.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +engine_openssl.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +engine_openssl.o: ../../include/openssl/dso.h ../../include/openssl/e_os.h +engine_openssl.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h +engine_openssl.o: ../../include/openssl/err.h ../../include/openssl/evp.h +engine_openssl.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h +engine_openssl.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +engine_openssl.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +engine_openssl.o: ../../include/openssl/obj_mac.h +engine_openssl.o: ../../include/openssl/objects.h +engine_openssl.o: ../../include/openssl/opensslconf.h +engine_openssl.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +engine_openssl.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +engine_openssl.o: ../../include/openssl/rc5.h +engine_openssl.o: ../../include/openssl/rijndael-alg-fst.h +engine_openssl.o: ../../include/openssl/rijndael.h +engine_openssl.o: ../../include/openssl/ripemd.h ../../include/openssl/rsa.h +engine_openssl.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +engine_openssl.o: ../../include/openssl/stack.h +engine_openssl.o: ../../include/openssl/symhacks.h ../cryptlib.h engine_int.h +hw_atalla.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_atalla.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +hw_atalla.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +hw_atalla.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +hw_atalla.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_atalla.o: ../../include/openssl/dso.h ../../include/openssl/e_os.h +hw_atalla.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h +hw_atalla.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_atalla.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h +hw_atalla.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_atalla.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +hw_atalla.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_atalla.o: ../../include/openssl/opensslconf.h +hw_atalla.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +hw_atalla.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +hw_atalla.o: ../../include/openssl/rc5.h +hw_atalla.o: ../../include/openssl/rijndael-alg-fst.h +hw_atalla.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +hw_atalla.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_atalla.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_atalla.o: ../../include/openssl/symhacks.h ../cryptlib.h engine_int.h +hw_atalla.o: vendor_defns/atalla.h +hw_cswift.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_cswift.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +hw_cswift.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +hw_cswift.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +hw_cswift.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_cswift.o: ../../include/openssl/dso.h ../../include/openssl/e_os.h +hw_cswift.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h +hw_cswift.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_cswift.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h +hw_cswift.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_cswift.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +hw_cswift.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_cswift.o: ../../include/openssl/opensslconf.h +hw_cswift.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +hw_cswift.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +hw_cswift.o: ../../include/openssl/rc5.h +hw_cswift.o: ../../include/openssl/rijndael-alg-fst.h +hw_cswift.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +hw_cswift.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_cswift.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_cswift.o: ../../include/openssl/symhacks.h ../cryptlib.h engine_int.h +hw_cswift.o: vendor_defns/cswift.h +hw_ncipher.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_ncipher.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +hw_ncipher.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +hw_ncipher.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +hw_ncipher.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_ncipher.o: ../../include/openssl/dso.h ../../include/openssl/e_os.h +hw_ncipher.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h +hw_ncipher.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_ncipher.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h +hw_ncipher.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_ncipher.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +hw_ncipher.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_ncipher.o: ../../include/openssl/opensslconf.h +hw_ncipher.o: ../../include/openssl/opensslv.h ../../include/openssl/pem.h +hw_ncipher.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_ncipher.o: ../../include/openssl/rand.h ../../include/openssl/rc2.h +hw_ncipher.o: ../../include/openssl/rc4.h ../../include/openssl/rc5.h +hw_ncipher.o: ../../include/openssl/rijndael-alg-fst.h +hw_ncipher.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +hw_ncipher.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_ncipher.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_ncipher.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_ncipher.o: ../../include/openssl/x509_vfy.h ../cryptlib.h engine_int.h +hw_ncipher.o: vendor_defns/hwcryptohook.h +hw_nuron.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_nuron.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +hw_nuron.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +hw_nuron.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +hw_nuron.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_nuron.o: ../../include/openssl/dso.h ../../include/openssl/e_os.h +hw_nuron.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h +hw_nuron.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_nuron.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h +hw_nuron.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_nuron.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +hw_nuron.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_nuron.o: ../../include/openssl/opensslconf.h +hw_nuron.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +hw_nuron.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +hw_nuron.o: ../../include/openssl/rc5.h +hw_nuron.o: ../../include/openssl/rijndael-alg-fst.h +hw_nuron.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +hw_nuron.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_nuron.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_nuron.o: ../../include/openssl/symhacks.h ../cryptlib.h engine_int.h diff --git a/crypto/engine/README b/crypto/engine/README new file mode 100644 index 0000000000..96595e6f35 --- /dev/null +++ b/crypto/engine/README @@ -0,0 +1,278 @@ +NOTES, THOUGHTS, and EVERYTHING +------------------------------- + +(1) Concurrency and locking ... I made a change to the ENGINE_free code + because I spotted a potential hold-up in proceedings (doing too + much inside a lock including calling a callback), there may be + other bits like this. What do the speed/optimisation freaks think + of this aspect of the code and design? There's lots of locking for + manipulation functions and I need that to keep things nice and + solid, but this manipulation is mostly (de)initialisation, I would + think that most run-time locking is purely in the ENGINE_init and + ENGINE_finish calls that might be made when getting handles for + RSA (and friends') structures. These would be mostly reference + count operations as the functional references should always be 1 + or greater at run-time to prevent init/deinit thrashing. + +(2) nCipher support, via the HWCryptoHook API, is now in the code. + Apparently this hasn't been tested too much yet, but it looks + good. :-) Atalla support has been added too, but shares a lot in + common with Ben's original hooks in bn_exp.c (although it has been + ENGINE-ified, and error handling wrapped around it) and it's also + had some low-volume testing, so it should be usable. + +(3) Of more concern, we need to work out (a) how to put together usable + RAND_METHODs for units that just have one "get n or less random + bytes" function, (b) we also need to determine how to hook the code + in crypto/rand/ to use the ENGINE defaults in a way similar to what + has been done in crypto/rsa/, crypto/dsa/, etc. + +(4) ENGINE should really grow to encompass more than 3 public key + algorithms and randomness gathering. The structure/data level of + the engine code is hidden from code outside the crypto/engine/ + directory so change shouldn't be too viral. More important though + is how things should evolve ... this needs thought and discussion. + + +-----------------------------------==*==----------------------------------- + +More notes 2000-08-01 +--------------------- + +Geoff Thorpe, who designed the engine part, wrote a pretty good description +of the thoughts he had when he built it, good enough to include verbatim here +(with his permission) -- Richard Levitte + + +Date: Tue, 1 Aug 2000 16:54:08 +0100 (BST) +From: Geoff Thorpe +Subject: Re: The thoughts to merge BRANCH_engine into the main trunk are + emerging + +Hi there, + +I'm going to try and do some justice to this, but I'm a little short on +time and the there is an endless amount that could be discussed on this +subject. sigh ... please bear with me :-) + +> The changes in BRANCH_engine dig deep into the core of OpenSSL, for example +> into the RSA and RAND routines, adding a level of indirection which is needed +> to keep the abstraction, as far as I understand. It would be a good thing if +> those who do play with those things took a look at the changes that have been +> done in the branch and say out loud how much (or hopefully little) we've made +> fools of ourselves. + +The point here is that the code that has emerged in the BRANCH_engine +branch was based on some initial requirements of mine that I went in and +addressed, and Richard has picked up the ball and run with it too. It +would be really useful to get some review of the approach we've taken, but +first I think I need to describe as best I can the reasons behind what has +been done so far, in particular what issues we have tried to address when +doing this, and what issues we have intentionally (or necessarily) tried +to avoid. + +methods, engines, and evps +-------------------------- + +There has been some dicussion, particularly with Steve, about where this +ENGINE stuff might fit into the conceptual picture as/when we start to +abstract algorithms a little bit to make the library more extensible. In +particular, it would desirable to have algorithms (symmetric, hash, pkc, +etc) abstracted in some way that allows them to be just objects sitting in +a list (or database) ... it'll just happen that the "DSA" object doesn't +support encryption whereas the "RSA" object does. This requires a lot of +consideration to begin to know how to tackle it; in particular how +encapsulated should these things be? If the objects also understand their +own ASN1 encodings and what-not, then it would for example be possible to +add support for elliptic-curve DSA in as a new algorithm and automatically +have ECC-DSA certificates supported in SSL applications. Possible, but not +easy. :-) + +Whatever, it seems that the way to go (if I've grok'd Steve's comments on +this in the past) is to amalgamate these things in EVP as is already done +(I think) for ciphers or hashes (Steve, please correct/elaborate). I +certainly think something should be done in this direction because right +now we have different source directories, types, functions, and methods +for each algorithm - even when conceptually they are very much different +feathers of the same bird. (This is certainly all true for the public-key +stuff, and may be partially true for the other parts.) + +ENGINE was *not* conceived as a way of solving this, far from it. Nor was +it conceived as a way of replacing the various "***_METHOD"s. It was +conceived as an abstraction of a sort of "virtual crypto device". If we +lived in a world where "EVP_ALGO"s (or something like them) encapsulated +particular algorithms like RSA,DSA,MD5,RC4,etc, and "***_METHOD"s +encapsulated interfaces to algorithms (eg. some algo's might support a +PKC_METHOD, a HASH_METHOD, or a CIPHER_METHOD, who knows?), then I would +think that ENGINE would encapsulate an implementation of arbitrarily many +of those algorithms - perhaps as alternatives to existing algorithms +and/or perhaps as new previously unimplemented algorithms. An ENGINE could +be used to contain an alternative software implementation, a wrapper for a +hardware acceleration and/or key-management unit, a comms-wrapper for +distributing cryptographic operations to remote machines, or any other +"devices" your imagination can dream up. + +However, what has been done in the ENGINE branch so far is nothing more +than starting to get our toes wet. I had a couple of self-imposed +requirements when putting the initial abstraction together, and I may have +already posed these in one form or another on the list, but briefly; + + (i) only bother with public key algorithms for now, and maybe RAND too + (motivated by the need to get hardware support going and the fact + this was a comparitively easy subset to address to begin with). + + (ii) don't change (if at all possible) the existing crypto code, ie. the + implementations, the way the ***_METHODs work, etc. + + (iii) ensure that if no function from the ENGINE code is ever called then + things work the way they always did, and there is no memory + allocation (otherwise the failure to cleanup would be a problem - + this is part of the reason no STACKs were used, the other part of + the reason being I found them inappropriate). + + (iv) ensure that all the built-in crypto was encapsulated by one of + these "ENGINE"s and that this engine was automatically selected as + the default. + + (v) provide the minimum hooking possible in the existing crypto code + so that global functions (eg. RSA_public_encrypt) do not need any + extra parameter, yet will use whatever the current default ENGINE + for that RSA key is, and that the default can be set "per-key" + and globally (new keys will assume the global default, and keys + without their own default will be operated on using the global + default). NB: Try and make (v) conflict as little as possible with + (ii). :-) + + (vi) wrap the ENGINE code up in duct tape so you can't even see the + corners. Ie. expose no structures at all, just black-box pointers. + + (v) maintain internally a list of ENGINEs on which a calling + application can iterate, interrogate, etc. Allow a calling + application to hook in new ENGINEs, remove ENGINEs from the list, + and enforce uniqueness within the global list of each ENGINE's + "unique id". + + (vi) keep reference counts for everything - eg. this includes storing a + reference inside each RSA structure to the ENGINE that it uses. + This is freed when the RSA structure is destroyed, or has its + ENGINE explicitly changed. The net effect needs to be that at any + time, it is deterministic to know whether an ENGINE is in use or + can be safely removed (or unloaded in the case of the other type + of reference) without invalidating function pointers that may or + may not be used indavertently in the future. This was actually + one of the biggest problems to overcome in the existing OpenSSL + code - implementations had always been assumed to be ever-present, + so there was no trivial way to get round this. + + (vii) distinguish between structural references and functional + references. + +A *little* detail +----------------- + +While my mind is on it; I'll illustrate the bit in item (vii). This idea +turned out to be very handy - the ENGINEs themselves need to be operated +on and manipulated simply as objects without necessarily trying to +"enable" them for use. Eg. most host machines will not have the necessary +hardware or software to support all the engines one might compile into +OpenSSL, yet it needs to be possible to iterate across the ENGINEs, +querying their names, properties, etc - all happening in a thread-safe +manner that uses reference counts (if you imagine two threads iterating +through a list and one thread removing the ENGINE the other is currently +looking at - you can see the gotcha waiting to happen). For all of this, +*structural references* are used and operate much like the other reference +counts in OpenSSL. + +The other kind of reference count is for *functional* references - these +indicate a reference on which the caller can actually assume the +particular ENGINE to be initialised and usable to perform the operations +it implements. Any increment or decrement of the functional reference +count automatically invokes a corresponding change in the structural +reference count, as it is fairly obvious that a functional reference is a +restricted case of a structural reference. So struct_ref >= funct_ref at +all times. NB: functional references are usually obtained by a call to +ENGINE_init(), but can also be created implicitly by calls that require a +new functional reference to be created, eg. ENGINE_set_default(). Either +way the only time the underlying ENGINE's "init" function is really called +is when the (functional) reference count increases to 1, similarly the +underlying "finish" handler is only called as the count goes down to 0. +The effect of this, for example, is that if you set the default ENGINE for +RSA operations to be "cswift", then its functional reference count will +already be at least 1 so the CryptoSwift shared-library and the card will +stay loaded and initialised until such time as all RSA keys using the +cswift ENGINE are changed or destroyed and the default ENGINE for RSA +operations has been changed. This prevents repeated thrashing of init and +finish handling if the count keeps getting down as far as zero. + +Otherwise, the way the ENGINE code has been put together I think pretty +much reflects the above points. The reason for the ENGINE structure having +individual RSA_METHOD, DSA_METHOD, etc pointers is simply that it was the +easiest way to go about things for now, to hook it all into the raw +RSA,DSA,etc code, and I was trying to the keep the structure invisible +anyway so that the way this is internally managed could be easily changed +later on when we start to work out what's to be done about these other +abstractions. + +Down the line, if some EVP-based technique emerges for adequately +encapsulating algorithms and all their various bits and pieces, then I can +imagine that "ENGINE" would turn into a reference-counting database of +these EVP things, of which the default "openssl" ENGINE would be the +library's own object database of pre-built software implemented algorithms +(and such). It would also be cool to see the idea of "METHOD"s detached +from the algorithms themselves ... so RSA, DSA, ElGamal, etc can all +expose essentially the same METHOD (aka interface), which would include +any querying/flagging stuff to identify what the algorithm can/can't do, +its name, and other stuff like max/min block sizes, key sizes, etc. This +would result in ENGINE similarly detaching its internal database of +algorithm implementations from the function definitions that return +interfaces to them. I think ... + +As for DSOs etc. Well the DSO code is pretty handy (but could be made much +more so) for loading vendor's driver-libraries and talking to them in some +generic way, but right now there's still big problems associated with +actually putting OpenSSL code (ie. new ENGINEs, or anything else for that +matter) in dynamically loadable libraries. These problems won't go away in +a hurry so I don't think we should expect to have any kind of +shared-library extensions any time soon - but solving the problems is a +good thing to aim for, and would as a side-effect probably help make +OpenSSL more usable as a shared-library itself (looking at the things +needed to do this will show you why). + +One of the problems is that if you look at any of the ENGINE +implementations, eg. hw_cswift.c or hw_ncipher.c, you'll see how it needs +a variety of functionality and definitions from various areas of OpenSSL, +including crypto/bn/, crypto/err/, crypto/ itself (locking for example), +crypto/dso/, crypto/engine/, crypto/rsa, etc etc etc. So if similar code +were to be suctioned off into shared libraries, the shared libraries would +either have to duplicate all the definitions and code and avoid loader +conflicts, or OpenSSL would have to somehow expose all that functionality +to the shared-library. If this isn't a big enough problem, the issue of +binary compatibility will be - anyone writing Apache modules can tell you +that (Ralf? Ben? :-). However, I don't think OpenSSL would need to be +quite so forgiving as Apache should be, so OpenSSL could simply tell its +version to the DSO and leave the DSO with the problem of deciding whether +to proceed or bail out for fear of binary incompatibilities. + +Certainly one thing that would go a long way to addressing this is to +embark on a bit of an opaqueness mission. I've set the ENGINE code up with +this in mind - it's so draconian that even to declare your own ENGINE, you +have to get the engine code to create the underlying ENGINE structure, and +then feed in the new ENGINE's function/method pointers through various +"set" functions. The more of the code that takes on such a black-box +approach, the more of the code that will be (a) easy to expose to shared +libraries that need it, and (b) easy to expose to applications wanting to +use OpenSSL itself as a shared-library. From my own explorations in +OpenSSL, the biggest leviathan I've seen that is a problem in this respect +is the BIGNUM code. Trying to "expose" the bignum code through any kind of +organised "METHODs", let alone do all the necessary bignum operations +solely through functions rather than direct access to the structures and +macros, will be a massive pain in the "r"s. + +Anyway, I'm done for now - hope it was readable. Thoughts? + +Cheers, +Geoff + + +-----------------------------------==*==----------------------------------- + diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h new file mode 100644 index 0000000000..78cf41c378 --- /dev/null +++ b/crypto/engine/engine.h @@ -0,0 +1,403 @@ +/* openssl/engine.h */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_ENGINE_H +#define HEADER_ENGINE_H + +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/dh.h> +#include <openssl/rand.h> +#include <openssl/evp.h> +#include <openssl/symhacks.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* These flags are used to control combinations of algorithm (methods) + * by bitwise "OR"ing. */ +#define ENGINE_METHOD_RSA (unsigned int)0x0001 +#define ENGINE_METHOD_DSA (unsigned int)0x0002 +#define ENGINE_METHOD_DH (unsigned int)0x0004 +#define ENGINE_METHOD_RAND (unsigned int)0x0008 +#define ENGINE_METHOD_BN_MOD_EXP (unsigned int)0x0010 +#define ENGINE_METHOD_BN_MOD_EXP_CRT (unsigned int)0x0020 +/* Obvious all-or-nothing cases. */ +#define ENGINE_METHOD_ALL (unsigned int)0xFFFF +#define ENGINE_METHOD_NONE (unsigned int)0x0000 + +/* These flags are used to tell the ctrl function what should be done. + * All command numbers are shared between all engines, even if some don't + * make sense to some engines. In such a case, they do nothing but return + * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */ +#define ENGINE_CTRL_SET_LOGSTREAM 1 +#define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +/* Flags specific to the nCipher "chil" engine */ +#define ENGINE_CTRL_CHIL_SET_FORKCHECK 100 + /* Depending on the value of the (long)i argument, this sets or + * unsets the SimpleForkCheck flag in the CHIL API to enable or + * disable checking and workarounds for applications that fork(). + */ +#define ENGINE_CTRL_CHIL_NO_LOCKING 101 + /* This prevents the initialisation function from providing mutex + * callbacks to the nCipher library. */ + +/* As we're missing a BIGNUM_METHOD, we need a couple of locally + * defined function types that engines can implement. */ + +#ifndef HEADER_ENGINE_INT_H +/* mod_exp operation, calculates; r = a ^ p mod m + * NB: ctx can be NULL, but if supplied, the implementation may use + * it if it wishes. */ +typedef int (*BN_MOD_EXP)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +/* private key operation for RSA, provided seperately in case other + * RSA implementations wish to use it. */ +typedef int (*BN_MOD_EXP_CRT)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp, BN_CTX *ctx); + +/* Generic function pointer */ +typedef void (*ENGINE_GEN_FUNC_PTR)(); +/* Generic function pointer taking no arguments */ +typedef void (*ENGINE_GEN_INT_FUNC_PTR)(void); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR)(int cmd, long i, void *p, void (*f)()); + +/* The list of "engine" types is a static array of (const ENGINE*) + * pointers (not dynamic because static is fine for now and we otherwise + * have to hook an appropriate load/unload function in to initialise and + * cleanup). */ +typedef struct engine_st ENGINE; +#endif + +/* STRUCTURE functions ... all of these functions deal with pointers to + * ENGINE structures where the pointers have a "structural reference". + * This means that their reference is to allow access to the structure + * but it does not imply that the structure is functional. To simply + * increment or decrement the structural reference count, use ENGINE_new + * and ENGINE_free. NB: This is not required when iterating using + * ENGINE_get_next as it will automatically decrement the structural + * reference count of the "current" ENGINE and increment the structural + * reference count of the ENGINE it returns (unless it is NULL). */ + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void); +ENGINE *ENGINE_get_last(void); +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e); +ENGINE *ENGINE_get_prev(ENGINE *e); +/* Add another "ENGINE" type into the array. */ +int ENGINE_add(ENGINE *e); +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e); +/* Retrieve an engine from the list by its unique "id" value. */ +ENGINE *ENGINE_by_id(const char *id); + +/* These functions are useful for manufacturing new ENGINE + * structures. They don't address reference counting at all - + * one uses them to populate an ENGINE structure with personalised + * implementations of things prior to using it directly or adding + * it to the builtin ENGINE list in OpenSSL. These are also here + * so that the ENGINE structure doesn't have to be exposed and + * break binary compatibility! + * + * NB: I'm changing ENGINE_new to force the ENGINE structure to + * be allocated from within OpenSSL. See the comment for + * ENGINE_get_struct_size(). + */ +#if 0 +ENGINE *ENGINE_new(ENGINE *e); +#else +ENGINE *ENGINE_new(void); +#endif +int ENGINE_free(ENGINE *e); +int ENGINE_set_id(ENGINE *e, const char *id); +int ENGINE_set_name(ENGINE *e, const char *name); +int ENGINE_set_RSA(ENGINE *e, RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, DSA_METHOD *dsa_meth); +int ENGINE_set_DH(ENGINE *e, DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, RAND_METHOD *rand_meth); +int ENGINE_set_BN_mod_exp(ENGINE *e, BN_MOD_EXP bn_mod_exp); +int ENGINE_set_BN_mod_exp_crt(ENGINE *e, BN_MOD_EXP_CRT bn_mod_exp_crt); +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); + +/* These return values from within the ENGINE structure. These can + * be useful with functional references as well as structural + * references - it depends which you obtained. Using the result + * for functional purposes if you only obtained a structural + * reference may be problematic! */ +const char *ENGINE_get_id(ENGINE *e); +const char *ENGINE_get_name(ENGINE *e); +RSA_METHOD *ENGINE_get_RSA(ENGINE *e); +DSA_METHOD *ENGINE_get_DSA(ENGINE *e); +DH_METHOD *ENGINE_get_DH(ENGINE *e); +RAND_METHOD *ENGINE_get_RAND(ENGINE *e); +BN_MOD_EXP ENGINE_get_BN_mod_exp(ENGINE *e); +BN_MOD_EXP_CRT ENGINE_get_BN_mod_exp_crt(ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(ENGINE *e); + +/* ENGINE_new is normally passed a NULL in the first parameter because + * the calling code doesn't have access to the definition of the ENGINE + * structure (for good reason). However, if the caller wishes to use + * its own memory allocation or use a static array, the following call + * should be used to check the amount of memory the ENGINE structure + * will occupy. This will make the code more future-proof. + * + * NB: I'm "#if 0"-ing this out because it's better to force the use of + * internally allocated memory. See similar change in ENGINE_new(). + */ +#if 0 +int ENGINE_get_struct_size(void); +#endif + +/* FUNCTIONAL functions. These functions deal with ENGINE structures + * that have (or will) be initialised for use. Broadly speaking, the + * structural functions are useful for iterating the list of available + * engine types, creating new engine types, and other "list" operations. + * These functions actually deal with ENGINEs that are to be used. As + * such these functions can fail (if applicable) when particular + * engines are unavailable - eg. if a hardware accelerator is not + * attached or not functioning correctly. Each ENGINE has 2 reference + * counts; structural and functional. Every time a functional reference + * is obtained or released, a corresponding structural reference is + * automatically obtained or released too. */ + +/* Initialise a engine type for use (or up its reference count if it's + * already in use). This will fail if the engine is not currently + * operational and cannot initialise. */ +int ENGINE_init(ENGINE *e); +/* Free a functional reference to a engine type. This does not require + * a corresponding call to ENGINE_free as it also releases a structural + * reference. */ +int ENGINE_finish(ENGINE *e); +/* Send control parametrised commands to the engine. The possibilities + * to send down an integer, a pointer to data or a function pointer are + * provided. Any of the parameters may or may not be NULL, depending + * on the command number */ +/* WARNING: This is currently experimental and may change radically! */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); + +/* The following functions handle keys that are stored in some secondary + * location, handled by the engine. The storage may be on a card or + * whatever. */ +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + const char *passphrase); +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + const char *passphrase); + +/* This returns a pointer for the current ENGINE structure that + * is (by default) performing any RSA operations. The value returned + * is an incremented reference, so it should be free'd (ENGINE_finish) + * before it is discarded. */ +ENGINE *ENGINE_get_default_RSA(void); +/* Same for the other "methods" */ +ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_DH(void); +ENGINE *ENGINE_get_default_RAND(void); +ENGINE *ENGINE_get_default_BN_mod_exp(void); +ENGINE *ENGINE_get_default_BN_mod_exp_crt(void); + +/* This sets a new default ENGINE structure for performing RSA + * operations. If the result is non-zero (success) then the ENGINE + * structure will have had its reference count up'd so the caller + * should still free their own reference 'e'. */ +int ENGINE_set_default_RSA(ENGINE *e); +/* Same for the other "methods" */ +int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_DH(ENGINE *e); +int ENGINE_set_default_RAND(ENGINE *e); +int ENGINE_set_default_BN_mod_exp(ENGINE *e); +int ENGINE_set_default_BN_mod_exp_crt(ENGINE *e); + +/* The combination "set" - the flags are bitwise "OR"d from the + * ENGINE_METHOD_*** defines above. */ +int ENGINE_set_default(ENGINE *e, unsigned int flags); + +/* Obligatory error function. */ +void ERR_load_ENGINE_strings(void); + +/* + * Error codes for all engine functions. NB: We use "generic" + * function names instead of per-implementation ones because this + * levels the playing field for externally implemented bootstrapped + * support code. As the filename and line number is included, it's + * more important to indicate the type of function, so that + * bootstrapped code (that can't easily add its own errors in) can + * use the same error codes too. + */ + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +/* Error codes for the ENGINE functions. */ + +/* Function codes. */ +#define ENGINE_F_ATALLA_FINISH 135 +#define ENGINE_F_ATALLA_INIT 136 +#define ENGINE_F_ATALLA_MOD_EXP 137 +#define ENGINE_F_ATALLA_RSA_MOD_EXP 138 +#define ENGINE_F_CSWIFT_DSA_SIGN 133 +#define ENGINE_F_CSWIFT_DSA_VERIFY 134 +#define ENGINE_F_CSWIFT_FINISH 100 +#define ENGINE_F_CSWIFT_INIT 101 +#define ENGINE_F_CSWIFT_MOD_EXP 102 +#define ENGINE_F_CSWIFT_MOD_EXP_CRT 103 +#define ENGINE_F_CSWIFT_RSA_MOD_EXP 104 +#define ENGINE_F_ENGINE_ADD 105 +#define ENGINE_F_ENGINE_BY_ID 106 +#define ENGINE_F_ENGINE_CTRL 142 +#define ENGINE_F_ENGINE_FINISH 107 +#define ENGINE_F_ENGINE_FREE 108 +#define ENGINE_F_ENGINE_GET_BN_MOD_EXP 109 +#define ENGINE_F_ENGINE_GET_BN_MOD_EXP_CRT 110 +#define ENGINE_F_ENGINE_GET_CTRL_FUNCTION 144 +#define ENGINE_F_ENGINE_GET_DH 111 +#define ENGINE_F_ENGINE_GET_DSA 112 +#define ENGINE_F_ENGINE_GET_FINISH_FUNCTION 145 +#define ENGINE_F_ENGINE_GET_ID 113 +#define ENGINE_F_ENGINE_GET_INIT_FUNCTION 146 +#define ENGINE_F_ENGINE_GET_NAME 114 +#define ENGINE_F_ENGINE_GET_NEXT 115 +#define ENGINE_F_ENGINE_GET_PREV 116 +#define ENGINE_F_ENGINE_GET_RAND 117 +#define ENGINE_F_ENGINE_GET_RSA 118 +#define ENGINE_F_ENGINE_INIT 119 +#define ENGINE_F_ENGINE_LIST_ADD 120 +#define ENGINE_F_ENGINE_LIST_REMOVE 121 +#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 +#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +#define ENGINE_F_ENGINE_NEW 122 +#define ENGINE_F_ENGINE_REMOVE 123 +#define ENGINE_F_ENGINE_SET_BN_MOD_EXP 124 +#define ENGINE_F_ENGINE_SET_BN_MOD_EXP_CRT 125 +#define ENGINE_F_ENGINE_SET_CTRL_FUNCTION 147 +#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126 +#define ENGINE_F_ENGINE_SET_DH 127 +#define ENGINE_F_ENGINE_SET_DSA 128 +#define ENGINE_F_ENGINE_SET_FINISH_FUNCTION 148 +#define ENGINE_F_ENGINE_SET_ID 129 +#define ENGINE_F_ENGINE_SET_INIT_FUNCTION 149 +#define ENGINE_F_ENGINE_SET_NAME 130 +#define ENGINE_F_ENGINE_SET_RAND 131 +#define ENGINE_F_ENGINE_SET_RSA 132 +#define ENGINE_F_ENGINE_UNLOAD_KEY 152 +#define ENGINE_F_HWCRHK_CTRL 143 +#define ENGINE_F_HWCRHK_FINISH 135 +#define ENGINE_F_HWCRHK_GET_PASS 155 +#define ENGINE_F_HWCRHK_INIT 136 +#define ENGINE_F_HWCRHK_LOAD_PRIVKEY 153 +#define ENGINE_F_HWCRHK_LOAD_PUBKEY 154 +#define ENGINE_F_HWCRHK_MOD_EXP 137 +#define ENGINE_F_HWCRHK_MOD_EXP_CRT 138 +#define ENGINE_F_HWCRHK_RAND_BYTES 139 +#define ENGINE_F_HWCRHK_RSA_MOD_EXP 140 +#define ENGINE_F_LOG_MESSAGE 141 +#define ENGINE_F_NURON_FINISH 157 +#define ENGINE_F_NURON_INIT 156 +#define ENGINE_F_NURON_MOD_EXP 158 + +/* Reason codes. */ +#define ENGINE_R_ALREADY_LOADED 100 +#define ENGINE_R_BIO_WAS_FREED 121 +#define ENGINE_R_BN_CTX_FULL 101 +#define ENGINE_R_BN_EXPAND_FAIL 102 +#define ENGINE_R_CHIL_ERROR 123 +#define ENGINE_R_CONFLICTING_ENGINE_ID 103 +#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +#define ENGINE_R_DSO_FAILURE 104 +#define ENGINE_R_DSO_FUNCTION_NOT_FOUND 131 +#define ENGINE_R_DSO_NOT_FOUND 132 +#define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 +#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 +#define ENGINE_R_FINISH_FAILED 106 +#define ENGINE_R_GET_HANDLE_FAILED 107 +#define ENGINE_R_ID_OR_NAME_MISSING 108 +#define ENGINE_R_INIT_FAILED 109 +#define ENGINE_R_INTERNAL_LIST_ERROR 110 +#define ENGINE_R_MISSING_KEY_COMPONENTS 111 +#define ENGINE_R_NOT_INITIALISED 117 +#define ENGINE_R_NOT_LOADED 112 +#define ENGINE_R_NO_CALLBACK 127 +#define ENGINE_R_NO_CONTROL_FUNCTION 120 +#define ENGINE_R_NO_KEY 124 +#define ENGINE_R_NO_LOAD_FUNCTION 125 +#define ENGINE_R_NO_REFERENCE 130 +#define ENGINE_R_NO_SUCH_ENGINE 116 +#define ENGINE_R_NO_UNLOAD_FUNCTION 126 +#define ENGINE_R_PROVIDE_PARAMETERS 113 +#define ENGINE_R_REQUEST_FAILED 114 +#define ENGINE_R_REQUEST_FALLBACK 118 +#define ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL 122 +#define ENGINE_R_UNIT_FAILURE 115 + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/crypto/engine/engine_err.c b/crypto/engine/engine_err.c new file mode 100644 index 0000000000..44c4fb9dde --- /dev/null +++ b/crypto/engine/engine_err.c @@ -0,0 +1,188 @@ +/* crypto/engine/engine_err.c */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include <stdio.h> +#include <openssl/err.h> +#include <openssl/engine.h> + +/* BEGIN ERROR CODES */ +#ifndef NO_ERR +static ERR_STRING_DATA ENGINE_str_functs[]= + { +{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_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"}, +{ERR_PACK(0,ENGINE_F_CSWIFT_INIT,0), "CSWIFT_INIT"}, +{ERR_PACK(0,ENGINE_F_CSWIFT_MOD_EXP,0), "CSWIFT_MOD_EXP"}, +{ERR_PACK(0,ENGINE_F_CSWIFT_MOD_EXP_CRT,0), "CSWIFT_MOD_EXP_CRT"}, +{ERR_PACK(0,ENGINE_F_CSWIFT_RSA_MOD_EXP,0), "CSWIFT_RSA_MOD_EXP"}, +{ERR_PACK(0,ENGINE_F_ENGINE_ADD,0), "ENGINE_add"}, +{ERR_PACK(0,ENGINE_F_ENGINE_BY_ID,0), "ENGINE_by_id"}, +{ERR_PACK(0,ENGINE_F_ENGINE_CTRL,0), "ENGINE_ctrl"}, +{ERR_PACK(0,ENGINE_F_ENGINE_FINISH,0), "ENGINE_finish"}, +{ERR_PACK(0,ENGINE_F_ENGINE_FREE,0), "ENGINE_free"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_BN_MOD_EXP,0), "ENGINE_get_BN_mod_exp"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_BN_MOD_EXP_CRT,0), "ENGINE_get_BN_mod_exp_crt"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_CTRL_FUNCTION,0), "ENGINE_get_ctrl_function"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_DH,0), "ENGINE_get_DH"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_DSA,0), "ENGINE_get_DSA"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_FINISH_FUNCTION,0), "ENGINE_get_finish_function"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_ID,0), "ENGINE_get_id"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_INIT_FUNCTION,0), "ENGINE_get_init_function"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_NAME,0), "ENGINE_get_name"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_NEXT,0), "ENGINE_get_next"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_PREV,0), "ENGINE_get_prev"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_RAND,0), "ENGINE_get_RAND"}, +{ERR_PACK(0,ENGINE_F_ENGINE_GET_RSA,0), "ENGINE_get_RSA"}, +{ERR_PACK(0,ENGINE_F_ENGINE_INIT,0), "ENGINE_init"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LIST_ADD,0), "ENGINE_LIST_ADD"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LIST_REMOVE,0), "ENGINE_LIST_REMOVE"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,0), "ENGINE_load_private_key"}, +{ERR_PACK(0,ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,0), "ENGINE_load_public_key"}, +{ERR_PACK(0,ENGINE_F_ENGINE_NEW,0), "ENGINE_new"}, +{ERR_PACK(0,ENGINE_F_ENGINE_REMOVE,0), "ENGINE_remove"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_BN_MOD_EXP,0), "ENGINE_set_BN_mod_exp"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_BN_MOD_EXP_CRT,0), "ENGINE_set_BN_mod_exp_crt"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_CTRL_FUNCTION,0), "ENGINE_set_ctrl_function"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_DEFAULT_TYPE,0), "ENGINE_SET_DEFAULT_TYPE"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_DH,0), "ENGINE_set_DH"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_DSA,0), "ENGINE_set_DSA"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_FINISH_FUNCTION,0), "ENGINE_set_finish_function"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_ID,0), "ENGINE_set_id"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_INIT_FUNCTION,0), "ENGINE_set_init_function"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_NAME,0), "ENGINE_set_name"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_RAND,0), "ENGINE_set_RAND"}, +{ERR_PACK(0,ENGINE_F_ENGINE_SET_RSA,0), "ENGINE_set_RSA"}, +{ERR_PACK(0,ENGINE_F_ENGINE_UNLOAD_KEY,0), "ENGINE_UNLOAD_KEY"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_CTRL,0), "HWCRHK_CTRL"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_FINISH,0), "HWCRHK_FINISH"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_GET_PASS,0), "HWCRHK_GET_PASS"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_INIT,0), "HWCRHK_INIT"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_LOAD_PRIVKEY,0), "HWCRHK_LOAD_PRIVKEY"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_LOAD_PUBKEY,0), "HWCRHK_LOAD_PUBKEY"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_MOD_EXP,0), "HWCRHK_MOD_EXP"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_MOD_EXP_CRT,0), "HWCRHK_MOD_EXP_CRT"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_RAND_BYTES,0), "HWCRHK_RAND_BYTES"}, +{ERR_PACK(0,ENGINE_F_HWCRHK_RSA_MOD_EXP,0), "HWCRHK_RSA_MOD_EXP"}, +{ERR_PACK(0,ENGINE_F_LOG_MESSAGE,0), "LOG_MESSAGE"}, +{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"}, +{0,NULL} + }; + +static ERR_STRING_DATA ENGINE_str_reasons[]= + { +{ENGINE_R_ALREADY_LOADED ,"already loaded"}, +{ENGINE_R_BIO_WAS_FREED ,"bio was freed"}, +{ENGINE_R_BN_CTX_FULL ,"BN_CTX full"}, +{ENGINE_R_BN_EXPAND_FAIL ,"bn_expand fail"}, +{ENGINE_R_CHIL_ERROR ,"chil error"}, +{ENGINE_R_CONFLICTING_ENGINE_ID ,"conflicting engine id"}, +{ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"}, +{ENGINE_R_DSO_FAILURE ,"DSO failure"}, +{ENGINE_R_DSO_FUNCTION_NOT_FOUND ,"dso function not found"}, +{ENGINE_R_DSO_NOT_FOUND ,"dso not found"}, +{ENGINE_R_ENGINE_IS_NOT_IN_LIST ,"engine is not in the list"}, +{ENGINE_R_FAILED_LOADING_PRIVATE_KEY ,"failed loading private key"}, +{ENGINE_R_FAILED_LOADING_PUBLIC_KEY ,"failed loading public key"}, +{ENGINE_R_FINISH_FAILED ,"finish failed"}, +{ENGINE_R_GET_HANDLE_FAILED ,"could not obtain hardware handle"}, +{ENGINE_R_ID_OR_NAME_MISSING ,"'id' or 'name' missing"}, +{ENGINE_R_INIT_FAILED ,"init failed"}, +{ENGINE_R_INTERNAL_LIST_ERROR ,"internal list error"}, +{ENGINE_R_MISSING_KEY_COMPONENTS ,"missing key components"}, +{ENGINE_R_NOT_INITIALISED ,"not initialised"}, +{ENGINE_R_NOT_LOADED ,"not loaded"}, +{ENGINE_R_NO_CALLBACK ,"no callback"}, +{ENGINE_R_NO_CONTROL_FUNCTION ,"no control function"}, +{ENGINE_R_NO_KEY ,"no key"}, +{ENGINE_R_NO_LOAD_FUNCTION ,"no load function"}, +{ENGINE_R_NO_REFERENCE ,"no reference"}, +{ENGINE_R_NO_SUCH_ENGINE ,"no such engine"}, +{ENGINE_R_NO_UNLOAD_FUNCTION ,"no unload function"}, +{ENGINE_R_PROVIDE_PARAMETERS ,"provide parameters"}, +{ENGINE_R_REQUEST_FAILED ,"request failed"}, +{ENGINE_R_REQUEST_FALLBACK ,"request fallback"}, +{ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL ,"size too large or too small"}, +{ENGINE_R_UNIT_FAILURE ,"unit failure"}, +{0,NULL} + }; + +#endif + +void ERR_load_ENGINE_strings(void) + { + static int init=1; + + if (init) + { + init=0; +#ifndef NO_ERR + ERR_load_strings(ERR_LIB_ENGINE,ENGINE_str_functs); + ERR_load_strings(ERR_LIB_ENGINE,ENGINE_str_reasons); +#endif + + } + } diff --git a/crypto/engine/engine_int.h b/crypto/engine/engine_int.h new file mode 100644 index 0000000000..d4aa8faca2 --- /dev/null +++ b/crypto/engine/engine_int.h @@ -0,0 +1,164 @@ +/* crypto/engine/engine_int.h */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_ENGINE_INT_H +#define HEADER_ENGINE_INT_H + +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/dh.h> +#include <openssl/rand.h> +#include <openssl/bn.h> +#include <openssl/evp.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Bitwise OR-able values for the "flags" variable in ENGINE. */ +#define ENGINE_FLAGS_MALLOCED 0x0001 + +#ifndef HEADER_ENGINE_H +/* Regrettably, we need to reproduce the "BN" function types here + * because there is no such "BIGNUM_METHOD" as there is with RSA, + * DSA, etc. We do this so that we don't have a case where engine.h + * and engine_int.h conflict with each other. */ +typedef int (*BN_MOD_EXP)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +/* private key operation for RSA, provided seperately in case other + * RSA implementations wish to use it. */ +typedef int (*BN_MOD_EXP_CRT)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp, BN_CTX *ctx); + +/* Generic function pointer */ +typedef int (*ENGINE_GEN_FUNC_PTR)(); +/* Generic function pointer taking no arguments */ +typedef int (*ENGINE_GEN_INT_FUNC_PTR)(void); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR)(int cmd, long i, void *p, void (*f)()); + +#endif + +/* This is a structure for storing implementations of various crypto + * algorithms and functions. */ +typedef struct engine_st + { + const char *id; + const char *name; + RSA_METHOD *rsa_meth; + DSA_METHOD *dsa_meth; + DH_METHOD *dh_meth; + RAND_METHOD *rand_meth; + BN_MOD_EXP bn_mod_exp; + BN_MOD_EXP_CRT bn_mod_exp_crt; + int (*init)(void); + int (*finish)(void); + int (*ctrl)(int cmd, long i, void *p, void (*f)()); + EVP_PKEY *(*load_privkey)(const char *key_id, const char *passphrase); + EVP_PKEY *(*load_pubkey)(const char *key_id, const char *passphrase); + int flags; + /* reference count on the structure itself */ + int struct_ref; + /* reference count on usability of the engine type. NB: This + * controls the loading and initialisation of any functionlity + * required by this engine, whereas the previous count is + * simply to cope with (de)allocation of this structure. Hence, + * running_ref <= struct_ref at all times. */ + int funct_ref; + /* Used to maintain the linked-list of engines. */ + struct engine_st *prev; + struct engine_st *next; + } ENGINE; + +/* BUILT-IN ENGINES. (these functions are only ever called once and + * do not return references - they are purely for bootstrapping). */ + +/* Returns a structure of software only methods (the default). */ +ENGINE *ENGINE_openssl(); + +#ifndef NO_HW + +#ifndef NO_HW_CSWIFT +/* Returns a structure of cswift methods ... NB: This can exist and be + * "used" even on non-cswift systems because the "init" will fail if the + * card/library are not found. */ +ENGINE *ENGINE_cswift(); +#endif /* !NO_HW_CSWIFT */ + +#ifndef NO_HW_NCIPHER +ENGINE *ENGINE_ncipher(); +#endif /* !NO_HW_NCIPHER */ + +#ifndef NO_HW_ATALLA +/* Returns a structure of atalla methods. */ +ENGINE *ENGINE_atalla(); +#endif /* !NO_HW_ATALLA */ + +#ifndef NO_HW_NURON +ENGINE *ENGINE_nuron(); +#endif /* !NO_HW_NURON */ + +#endif /* !NO_HW */ + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_ENGINE_INT_H */ diff --git a/crypto/engine/engine_lib.c b/crypto/engine/engine_lib.c new file mode 100644 index 0000000000..1df07af03a --- /dev/null +++ b/crypto/engine/engine_lib.c @@ -0,0 +1,488 @@ +/* crypto/engine/engine_lib.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <openssl/crypto.h> +#include "cryptlib.h" +#include "engine_int.h" +#include <openssl/engine.h> + +/* These pointers each have their own "functional reference" when they + * are non-NULL. Similarly, when they are retrieved by a call to + * ENGINE_get_default_[RSA|DSA|...] the returned pointer is also a + * reference and the caller is responsible for freeing that when they + * are finished with it (with a call to ENGINE_finish() *NOT* just + * ENGINE_free()!!!!!!). */ +static ENGINE *engine_def_rsa = NULL; +static ENGINE *engine_def_dsa = NULL; +static ENGINE *engine_def_dh = NULL; +static ENGINE *engine_def_rand = NULL; +static ENGINE *engine_def_bn_mod_exp = NULL; +static ENGINE *engine_def_bn_mod_exp_crt = NULL; +/* A static "once-only" flag used to control if/when the above were + * initialised to suitable start-up defaults. */ +static int engine_def_flag = 0; + +/* This is used in certain static utility functions to save code + * repetition for per-algorithm functions. */ +typedef enum { + ENGINE_TYPE_RSA, + ENGINE_TYPE_DSA, + ENGINE_TYPE_DH, + ENGINE_TYPE_RAND, + ENGINE_TYPE_BN_MOD_EXP, + ENGINE_TYPE_BN_MOD_EXP_CRT + } ENGINE_TYPE; + +static void engine_def_check_util(ENGINE **def, ENGINE *val) + { + *def = val; + val->struct_ref++; + val->funct_ref++; + } + +/* In a slight break with convention - this static function must be + * called *outside* any locking of CRYPTO_LOCK_ENGINE. */ +static void engine_def_check(void) + { + ENGINE *e; + if(engine_def_flag) + return; + e = ENGINE_get_first(); + if(e == NULL) + /* The list is empty ... not much we can do! */ + return; + /* We have a structural reference, see if getting a functional + * reference is possible. This is done to cope with init errors + * in the engine - the following locked code does a bunch of + * manual "ENGINE_init"s which do *not* allow such an init + * error so this is worth doing. */ + if(ENGINE_init(e)) + { + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + /* Doing another check here prevents an obvious race + * condition because the whole function itself cannot + * be locked. */ + if(engine_def_flag) + goto skip_set_defaults; + /* OK, we got a functional reference, so we get one each + * for the defaults too. */ + engine_def_check_util(&engine_def_rsa, e); + engine_def_check_util(&engine_def_dsa, e); + engine_def_check_util(&engine_def_dh, e); + engine_def_check_util(&engine_def_rand, e); + engine_def_check_util(&engine_def_bn_mod_exp, e); + engine_def_check_util(&engine_def_bn_mod_exp_crt, e); + engine_def_flag = 1; +skip_set_defaults: + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + /* The "if" needs to be balanced out. */ + ENGINE_finish(e); + } + /* We need to balance out the fact we obtained a structural + * reference to begin with from ENGINE_get_first(). */ + ENGINE_free(e); + } + +/* Initialise a engine type for use (or up its functional reference count + * if it's already in use). */ +int ENGINE_init(ENGINE *e) + { + int to_return = 1; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_INIT,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if((e->funct_ref == 0) && e->init) + /* This is the first functional reference and the engine + * requires initialisation so we do it now. */ + to_return = e->init(); + if(to_return) + { + /* OK, we return a functional reference which is also a + * structural reference. */ + e->struct_ref++; + e->funct_ref++; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return to_return; + } + +/* Free a functional reference to a engine type */ +int ENGINE_finish(ENGINE *e) + { + int to_return = 1; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_FINISH,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if((e->funct_ref == 1) && e->finish) +#if 0 + /* This is the last functional reference and the engine + * requires cleanup so we do it now. */ + to_return = e->finish(); + if(to_return) + { + /* Cleanup the functional reference which is also a + * structural reference. */ + e->struct_ref--; + e->funct_ref--; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); +#else + /* I'm going to deliberately do a convoluted version of this + * piece of code because we don't want "finish" functions + * being called inside a locked block of code, if at all + * possible. I'd rather have this call take an extra couple + * of ticks than have throughput serialised on a externally- + * provided callback function that may conceivably never come + * back. :-( */ + { + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + /* CODE ALERT: This *IS* supposed to be "=" and NOT "==" :-) */ + if((to_return = e->finish())) + { + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + /* Cleanup the functional reference which is also a + * structural reference. */ + e->struct_ref--; + e->funct_ref--; + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + } + } + else + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); +#endif + return to_return; + } + +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + const char *passphrase) + { + EVP_PKEY *pkey; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(e->funct_ref == 0) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_NOT_INITIALISED); + return 0; + } + if (!e->load_privkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + pkey = e->load_privkey(key_id, passphrase); + if (!pkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, + ENGINE_R_FAILED_LOADING_PRIVATE_KEY); + return 0; + } + return pkey; + } + +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + const char *passphrase) + { + EVP_PKEY *pkey; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(e->funct_ref == 0) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_NOT_INITIALISED); + return 0; + } + if (!e->load_pubkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_NO_LOAD_FUNCTION); + return 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + pkey = e->load_pubkey(key_id, passphrase); + if (!pkey) + { + ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, + ENGINE_R_FAILED_LOADING_PUBLIC_KEY); + return 0; + } + return pkey; + } + +/* Initialise a engine type for use (or up its functional reference count + * if it's already in use). */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(e->struct_ref == 0) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_REFERENCE); + return 0; + } + if (!e->ctrl) + { + ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION); + return 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return e->ctrl(cmd, i, p, f); + } + +static ENGINE *engine_get_default_type(ENGINE_TYPE t) + { + ENGINE *ret = NULL; + + /* engine_def_check is lean and mean and won't replace any + * prior default engines ... so we must ensure that it is always + * the first function to get to touch the default values. */ + engine_def_check(); + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + switch(t) + { + case ENGINE_TYPE_RSA: + ret = engine_def_rsa; break; + case ENGINE_TYPE_DSA: + ret = engine_def_dsa; break; + case ENGINE_TYPE_DH: + ret = engine_def_dh; break; + case ENGINE_TYPE_RAND: + ret = engine_def_rand; break; + case ENGINE_TYPE_BN_MOD_EXP: + ret = engine_def_bn_mod_exp; break; + case ENGINE_TYPE_BN_MOD_EXP_CRT: + ret = engine_def_bn_mod_exp_crt; break; + } + /* Unforunately we can't do this work outside the lock with a + * call to ENGINE_init() because that would leave a race + * condition open. */ + if(ret) + { + ret->struct_ref++; + ret->funct_ref++; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } + +ENGINE *ENGINE_get_default_RSA(void) + { + return engine_get_default_type(ENGINE_TYPE_RSA); + } + +ENGINE *ENGINE_get_default_DSA(void) + { + return engine_get_default_type(ENGINE_TYPE_DSA); + } + +ENGINE *ENGINE_get_default_DH(void) + { + return engine_get_default_type(ENGINE_TYPE_DH); + } + +ENGINE *ENGINE_get_default_RAND(void) + { + return engine_get_default_type(ENGINE_TYPE_RAND); + } + +ENGINE *ENGINE_get_default_BN_mod_exp(void) + { + return engine_get_default_type(ENGINE_TYPE_BN_MOD_EXP); + } + +ENGINE *ENGINE_get_default_BN_mod_exp_crt(void) + { + return engine_get_default_type(ENGINE_TYPE_BN_MOD_EXP_CRT); + } + +static int engine_set_default_type(ENGINE_TYPE t, ENGINE *e) + { + ENGINE *old = NULL; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_TYPE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + /* engine_def_check is lean and mean and won't replace any + * prior default engines ... so we must ensure that it is always + * the first function to get to touch the default values. */ + engine_def_check(); + /* Attempt to get a functional reference (we need one anyway, but + * also, 'e' may be just a structural reference being passed in so + * this call may actually be the first). */ + if(!ENGINE_init(e)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_TYPE, + ENGINE_R_INIT_FAILED); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + switch(t) + { + case ENGINE_TYPE_RSA: + old = engine_def_rsa; + engine_def_rsa = e; break; + case ENGINE_TYPE_DSA: + old = engine_def_dsa; + engine_def_dsa = e; break; + case ENGINE_TYPE_DH: + old = engine_def_dh; + engine_def_dh = e; break; + case ENGINE_TYPE_RAND: + old = engine_def_rand; + engine_def_rand = e; break; + case ENGINE_TYPE_BN_MOD_EXP: + old = engine_def_bn_mod_exp; + engine_def_bn_mod_exp = e; break; + case ENGINE_TYPE_BN_MOD_EXP_CRT: + old = engine_def_bn_mod_exp_crt; + engine_def_bn_mod_exp_crt = e; break; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + /* If we've replaced a previous value, then we need to remove the + * functional reference we had. */ + if(old && !ENGINE_finish(old)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_TYPE, + ENGINE_R_FINISH_FAILED); + return 0; + } + return 1; + } + +int ENGINE_set_default_RSA(ENGINE *e) + { + return engine_set_default_type(ENGINE_TYPE_RSA, e); + } + +int ENGINE_set_default_DSA(ENGINE *e) + { + return engine_set_default_type(ENGINE_TYPE_DSA, e); + } + +int ENGINE_set_default_DH(ENGINE *e) + { + return engine_set_default_type(ENGINE_TYPE_DH, e); + } + +int ENGINE_set_default_RAND(ENGINE *e) + { + return engine_set_default_type(ENGINE_TYPE_RAND, e); + } + +int ENGINE_set_default_BN_mod_exp(ENGINE *e) + { + return engine_set_default_type(ENGINE_TYPE_BN_MOD_EXP, e); + } + +int ENGINE_set_default_BN_mod_exp_crt(ENGINE *e) + { + return engine_set_default_type(ENGINE_TYPE_BN_MOD_EXP_CRT, e); + } + +int ENGINE_set_default(ENGINE *e, unsigned int flags) + { + if((flags & ENGINE_METHOD_RSA) && e->rsa_meth && + !ENGINE_set_default_RSA(e)) + return 0; + if((flags & ENGINE_METHOD_DSA) && e->dsa_meth && + !ENGINE_set_default_DSA(e)) + return 0; + if((flags & ENGINE_METHOD_DH) && e->dh_meth && + !ENGINE_set_default_DH(e)) + return 0; + if((flags & ENGINE_METHOD_RAND) && e->rand_meth && + !ENGINE_set_default_RAND(e)) + return 0; + if((flags & ENGINE_METHOD_BN_MOD_EXP) && e->bn_mod_exp && + !ENGINE_set_default_BN_mod_exp(e)) + return 0; + if((flags & ENGINE_METHOD_BN_MOD_EXP_CRT) && e->bn_mod_exp_crt && + !ENGINE_set_default_BN_mod_exp_crt(e)) + return 0; + return 1; + } + diff --git a/crypto/engine/engine_list.c b/crypto/engine/engine_list.c new file mode 100644 index 0000000000..8fe4f305b4 --- /dev/null +++ b/crypto/engine/engine_list.c @@ -0,0 +1,679 @@ +/* crypto/engine/engine_list.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <openssl/crypto.h> +#include "cryptlib.h" +#include "engine_int.h" +#include <openssl/engine.h> + +/* The linked-list of pointers to engine types. engine_list_head + * incorporates an implicit structural reference but engine_list_tail + * does not - the latter is a computational niceity and only points + * to something that is already pointed to by its predecessor in the + * list (or engine_list_head itself). In the same way, the use of the + * "prev" pointer in each ENGINE is to save excessive list iteration, + * it doesn't correspond to an extra structural reference. Hence, + * engine_list_head, and each non-null "next" pointer account for + * the list itself assuming exactly 1 structural reference on each + * list member. */ +static ENGINE *engine_list_head = NULL; +static ENGINE *engine_list_tail = NULL; +/* A boolean switch, used to ensure we only initialise once. This + * is needed because the engine list may genuinely become empty during + * use (so we can't use engine_list_head as an indicator for example. */ +static int engine_list_flag = 0; + +/* These static functions starting with a lower case "engine_" always + * take place when CRYPTO_LOCK_ENGINE has been locked up. */ +static int engine_list_add(ENGINE *e) + { + int conflict = 0; + ENGINE *iterator = NULL; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + iterator = engine_list_head; + while(iterator && !conflict) + { + conflict = (strcmp(iterator->id, e->id) == 0); + iterator = iterator->next; + } + if(conflict) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ENGINE_R_CONFLICTING_ENGINE_ID); + return 0; + } + if(engine_list_head == NULL) + { + /* We are adding to an empty list. */ + if(engine_list_tail) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_head = e; + e->prev = NULL; + } + else + { + /* We are adding to the tail of an existing list. */ + if((engine_list_tail == NULL) || + (engine_list_tail->next != NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, + ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_tail->next = e; + e->prev = engine_list_tail; + } + /* Having the engine in the list assumes a structural + * reference. */ + e->struct_ref++; + /* However it came to be, e is the last item in the list. */ + engine_list_tail = e; + e->next = NULL; + return 1; + } + +static int engine_list_remove(ENGINE *e) + { + ENGINE *iterator; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + /* We need to check that e is in our linked list! */ + iterator = engine_list_head; + while(iterator && (iterator != e)) + iterator = iterator->next; + if(iterator == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, + ENGINE_R_ENGINE_IS_NOT_IN_LIST); + return 0; + } + /* un-link e from the chain. */ + if(e->next) + e->next->prev = e->prev; + if(e->prev) + e->prev->next = e->next; + /* Correct our head/tail if necessary. */ + if(engine_list_head == e) + engine_list_head = e->next; + if(engine_list_tail == e) + engine_list_tail = e->prev; + /* remove our structural reference. */ + e->struct_ref--; + return 1; + } + +/* This check always takes place with CRYPTO_LOCK_ENGINE locked up + * so we're synchronised, but we can't call anything that tries to + * lock it again! :-) NB: For convenience (and code-clarity) we + * don't output errors for failures of the engine_list_add function + * as it will generate errors itself. */ +static int engine_internal_check(void) + { + if(engine_list_flag) + return 1; + /* This is our first time up, we need to populate the list + * with our statically compiled-in engines. */ + if(!engine_list_add(ENGINE_openssl())) + return 0; +#ifndef NO_HW +#ifndef NO_HW_CSWIFT + if(!engine_list_add(ENGINE_cswift())) + return 0; +#endif /* !NO_HW_CSWIFT */ +#ifndef NO_HW_NCIPHER + if(!engine_list_add(ENGINE_ncipher())) + return 0; +#endif /* !NO_HW_NCIPHER */ +#ifndef NO_HW_ATALLA + if(!engine_list_add(ENGINE_atalla())) + return 0; +#endif /* !NO_HW_ATALLA */ +#ifndef NO_HW_NURON + if(!engine_list_add(ENGINE_nuron())) + return 0; +#endif /* !NO_HW_NURON */ +#endif /* !NO_HW */ + engine_list_flag = 1; + return 1; + } + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void) + { + ENGINE *ret = NULL; + + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + if(engine_internal_check()) + { + ret = engine_list_head; + if(ret) + ret->struct_ref++; + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } +ENGINE *ENGINE_get_last(void) + { + ENGINE *ret = NULL; + + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + if(engine_internal_check()) + { + ret = engine_list_tail; + if(ret) + ret->struct_ref++; + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } + +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e) + { + ENGINE *ret = NULL; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + ret = e->next; + e->struct_ref--; + if(ret) + ret->struct_ref++; + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } +ENGINE *ENGINE_get_prev(ENGINE *e) + { + ENGINE *ret = NULL; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_PREV, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + ret = e->prev; + e->struct_ref--; + if(ret) + ret->struct_ref++; + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + return ret; + } + +/* Add another "ENGINE" type into the list. */ +int ENGINE_add(ENGINE *e) + { + int to_return = 1; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_ADD, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if((e->id == NULL) || (e->name == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_ADD, + ENGINE_R_ID_OR_NAME_MISSING); + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(!engine_internal_check() || !engine_list_add(e)) + { + ENGINEerr(ENGINE_F_ENGINE_ADD, + ENGINE_R_INTERNAL_LIST_ERROR); + to_return = 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return to_return; + } + +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e) + { + int to_return = 1; + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_REMOVE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(!engine_internal_check() || !engine_list_remove(e)) + { + ENGINEerr(ENGINE_F_ENGINE_REMOVE, + ENGINE_R_INTERNAL_LIST_ERROR); + to_return = 0; + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return to_return; + } + +ENGINE *ENGINE_by_id(const char *id) + { + ENGINE *iterator = NULL; + if(id == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_BY_ID, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + CRYPTO_r_lock(CRYPTO_LOCK_ENGINE); + if(!engine_internal_check()) + ENGINEerr(ENGINE_F_ENGINE_BY_ID, + ENGINE_R_INTERNAL_LIST_ERROR); + else + { + iterator = engine_list_head; + while(iterator && (strcmp(id, iterator->id) != 0)) + iterator = iterator->next; + if(iterator) + /* We need to return a structural reference */ + iterator->struct_ref++; + } + CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE); + if(iterator == NULL) + ENGINEerr(ENGINE_F_ENGINE_BY_ID, + ENGINE_R_NO_SUCH_ENGINE); + return iterator; + } + +/* As per the comments in engine.h, it is generally better all round + * if the ENGINE structure is allocated within this framework. */ +#if 0 +int ENGINE_get_struct_size(void) + { + return sizeof(ENGINE); + } + +ENGINE *ENGINE_new(ENGINE *e) + { + ENGINE *ret; + + if(e == NULL) + { + ret = (ENGINE *)(OPENSSL_malloc(sizeof(ENGINE)); + if(ret == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_NEW, + ERR_R_MALLOC_FAILURE); + return NULL; + } + } + else + ret = e; + memset(ret, 0, sizeof(ENGINE)); + if(e) + ret->flags = ENGINE_FLAGS_MALLOCED; + ret->struct_ref = 1; + return ret; + } +#else +ENGINE *ENGINE_new(void) + { + ENGINE *ret; + + ret = (ENGINE *)OPENSSL_malloc(sizeof(ENGINE)); + if(ret == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(ENGINE)); + ret->flags = ENGINE_FLAGS_MALLOCED; + ret->struct_ref = 1; + return ret; + } +#endif + +int ENGINE_free(ENGINE *e) + { + int i; + + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_FREE, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + i = CRYPTO_add(&e->struct_ref,-1,CRYPTO_LOCK_ENGINE); +#ifdef REF_PRINT + REF_PRINT("ENGINE",e); +#endif + if (i > 0) return 1; +#ifdef REF_CHECK + if (i < 0) + { + fprintf(stderr,"ENGINE_free, bad reference count\n"); + abort(); + } +#endif + if(e->flags & ENGINE_FLAGS_MALLOCED) + OPENSSL_free(e); + return 1; + } + +int ENGINE_set_id(ENGINE *e, const char *id) + { + if((e == NULL) || (id == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_ID, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->id = id; + return 1; + } + +int ENGINE_set_name(ENGINE *e, const char *name) + { + if((e == NULL) || (name == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_NAME, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->name = name; + return 1; + } + +int ENGINE_set_RSA(ENGINE *e, RSA_METHOD *rsa_meth) + { + if((e == NULL) || (rsa_meth == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_RSA, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->rsa_meth = rsa_meth; + return 1; + } + +int ENGINE_set_DSA(ENGINE *e, DSA_METHOD *dsa_meth) + { + if((e == NULL) || (dsa_meth == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_DSA, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->dsa_meth = dsa_meth; + return 1; + } + +int ENGINE_set_DH(ENGINE *e, DH_METHOD *dh_meth) + { + if((e == NULL) || (dh_meth == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_DH, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->dh_meth = dh_meth; + return 1; + } + +int ENGINE_set_RAND(ENGINE *e, RAND_METHOD *rand_meth) + { + if((e == NULL) || (rand_meth == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_RAND, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->rand_meth = rand_meth; + return 1; + } + +int ENGINE_set_BN_mod_exp(ENGINE *e, BN_MOD_EXP bn_mod_exp) + { + if((e == NULL) || (bn_mod_exp == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_BN_MOD_EXP, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->bn_mod_exp = bn_mod_exp; + return 1; + } + +int ENGINE_set_BN_mod_exp_crt(ENGINE *e, BN_MOD_EXP_CRT bn_mod_exp_crt) + { + if((e == NULL) || (bn_mod_exp_crt == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_BN_MOD_EXP_CRT, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->bn_mod_exp_crt = bn_mod_exp_crt; + return 1; + } + +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f) + { + if((e == NULL) || (init_f == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_INIT_FUNCTION, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->init = init_f; + return 1; + } + +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f) + { + if((e == NULL) || (finish_f == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_FINISH_FUNCTION, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->finish = finish_f; + return 1; + } + +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f) + { + if((e == NULL) || (ctrl_f == NULL)) + { + ENGINEerr(ENGINE_F_ENGINE_SET_CTRL_FUNCTION, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + e->ctrl = ctrl_f; + return 1; + } + +const char *ENGINE_get_id(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_ID, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return e->id; + } + +const char *ENGINE_get_name(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_NAME, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return e->name; + } + +RSA_METHOD *ENGINE_get_RSA(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_RSA, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->rsa_meth; + } + +DSA_METHOD *ENGINE_get_DSA(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_DSA, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->dsa_meth; + } + +DH_METHOD *ENGINE_get_DH(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_DH, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->dh_meth; + } + +RAND_METHOD *ENGINE_get_RAND(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_RAND, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->rand_meth; + } + +BN_MOD_EXP ENGINE_get_BN_mod_exp(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_BN_MOD_EXP, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->bn_mod_exp; + } + +BN_MOD_EXP_CRT ENGINE_get_BN_mod_exp_crt(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_BN_MOD_EXP_CRT, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->bn_mod_exp_crt; + } + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_INIT_FUNCTION, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->init; + } + +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_FINISH_FUNCTION, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->finish; + } + +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(ENGINE *e) + { + if(e == NULL) + { + ENGINEerr(ENGINE_F_ENGINE_GET_CTRL_FUNCTION, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + return e->ctrl; + } + diff --git a/crypto/engine/engine_openssl.c b/crypto/engine/engine_openssl.c new file mode 100644 index 0000000000..9636f51168 --- /dev/null +++ b/crypto/engine/engine_openssl.c @@ -0,0 +1,174 @@ +/* crypto/engine/engine_openssl.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + +#include <stdio.h> +#include <openssl/crypto.h> +#include "cryptlib.h" +#include "engine_int.h" +#include <openssl/engine.h> +#include <openssl/dso.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/dh.h> +#include <openssl/rand.h> +#include <openssl/bn.h> + +/* This is the only function we need to implement as OpenSSL + * doesn't have a native CRT mod_exp. Perhaps this should be + * BN_mod_exp_crt and moved into crypto/bn/ ?? ... dunno. */ +static int openssl_mod_exp_crt(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp, BN_CTX *ctx); + +/* The ENGINE structure that can be pointed to. */ +static ENGINE engine_openssl = + { + "openssl", + "Software default engine support", + NULL, + NULL, + NULL, /* these methods are "stolen" in ENGINE_openssl() */ + NULL, + NULL, + openssl_mod_exp_crt, + NULL, /* no init() */ + NULL, /* no finish() */ + NULL, /* no ctrl() */ + NULL, /* no load_privkey() */ + NULL, /* no load_pubkey() */ + 0, /* no flags */ + 0, 0, /* no references. */ + NULL, NULL /* unlinked */ + }; + +/* As this is only ever called once, there's no need for locking + * (indeed - the lock will already be held by our caller!!!) */ +ENGINE *ENGINE_openssl() + { + /* We need to populate our structure with the software pointers + * that we want to steal. */ + engine_openssl.rsa_meth = RSA_get_default_openssl_method(); + engine_openssl.dsa_meth = DSA_get_default_openssl_method(); + engine_openssl.dh_meth = DH_get_default_openssl_method(); + engine_openssl.rand_meth = RAND_SSLeay(); + engine_openssl.bn_mod_exp = BN_mod_exp; + return &engine_openssl; + } + +/* Chinese Remainder Theorem, taken and adapted from rsa_eay.c */ +static int openssl_mod_exp_crt(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, + const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx) + { + BIGNUM r1,m1; + int ret=0; + BN_CTX *bn_ctx; + BIGNUM *temp_bn = NULL; + + if (ctx) + bn_ctx = ctx; + else + if ((bn_ctx=BN_CTX_new()) == NULL) goto err; + BN_init(&m1); + BN_init(&r1); + /* BN_mul() cannot accept const BIGNUMs so I use the BN_CTX + * to duplicate what I need. <sigh> */ + if ((temp_bn = BN_CTX_get(bn_ctx)) == NULL) goto err; + if (!BN_copy(temp_bn, iqmp)) goto err; + + if (!BN_mod(&r1, a, q, bn_ctx)) goto err; + if (!engine_openssl.bn_mod_exp(&m1, &r1, dmq1, q, bn_ctx)) + goto err; + + if (!BN_mod(&r1, a, p, bn_ctx)) goto err; + if (!engine_openssl.bn_mod_exp(r, &r1, dmp1, p, bn_ctx)) + goto err; + + if (!BN_sub(r, r, &m1)) goto err; + /* This will help stop the size of r0 increasing, which does + * affect the multiply if it optimised for a power of 2 size */ + if (r->neg) + if (!BN_add(r, r, p)) goto err; + + if (!BN_mul(&r1, r, temp_bn, bn_ctx)) goto err; + if (!BN_mod(r, &r1, p, bn_ctx)) goto err; + /* If p < q it is occasionally possible for the correction of + * adding 'p' if r is negative above to leave the result still + * negative. This can break the private key operations: the following + * second correction should *always* correct this rare occurrence. + * This will *never* happen with OpenSSL generated keys because + * they ensure p > q [steve] + */ + if (r->neg) + if (!BN_add(r, r, p)) goto err; + /* Again, BN_mul() will need non-const values. */ + if (!BN_copy(temp_bn, q)) goto err; + if (!BN_mul(&r1, r, temp_bn, bn_ctx)) goto err; + if (!BN_add(r, &r1, &m1)) goto err; + + ret=1; +err: + BN_clear_free(&m1); + BN_clear_free(&r1); + if (temp_bn) + bn_ctx->tos--; + if (!ctx) + BN_CTX_free(bn_ctx); + return(ret); + } diff --git a/crypto/engine/enginetest.c b/crypto/engine/enginetest.c new file mode 100644 index 0000000000..a5a3c47fcb --- /dev/null +++ b/crypto/engine/enginetest.c @@ -0,0 +1,251 @@ +/* crypto/engine/enginetest.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <string.h> +#include <openssl/engine.h> +#include <openssl/err.h> + +static void display_engine_list() + { + ENGINE *h; + int loop; + + h = ENGINE_get_first(); + loop = 0; + printf("listing available engine types\n"); + while(h) + { + printf("engine %i, id = \"%s\", name = \"%s\"\n", + loop++, ENGINE_get_id(h), ENGINE_get_name(h)); + h = ENGINE_get_next(h); + } + printf("end of list\n"); + } + +int main(int argc, char *argv[]) + { + ENGINE *block[512]; + char buf[256]; + const char *id, *name; + ENGINE *ptr; + int loop; + int to_return = 1; + ENGINE *new_h1 = NULL; + ENGINE *new_h2 = NULL; + ENGINE *new_h3 = NULL; + ENGINE *new_h4 = NULL; + + ERR_load_crypto_strings(); + + memset(block, 0, 512 * sizeof(ENGINE *)); + if(((new_h1 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h1, "test_id0") || + !ENGINE_set_name(new_h1, "First test item") || + ((new_h2 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h2, "test_id1") || + !ENGINE_set_name(new_h2, "Second test item") || + ((new_h3 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h3, "test_id2") || + !ENGINE_set_name(new_h3, "Third test item") || + ((new_h4 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h4, "test_id3") || + !ENGINE_set_name(new_h4, "Fourth test item")) + { + printf("Couldn't set up test ENGINE structures\n"); + goto end; + } + printf("\nenginetest beginning\n\n"); + display_engine_list(); + if(!ENGINE_add(new_h1)) + { + printf("Add failed!\n"); + goto end; + } + display_engine_list(); + ptr = ENGINE_get_first(); + if(!ENGINE_remove(ptr)) + { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + if(!ENGINE_add(new_h3) || !ENGINE_add(new_h2)) + { + printf("Add failed!\n"); + goto end; + } + display_engine_list(); + if(!ENGINE_remove(new_h2)) + { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + if(!ENGINE_add(new_h4)) + { + printf("Add failed!\n"); + goto end; + } + display_engine_list(); + if(ENGINE_add(new_h3)) + { + printf("Add *should* have failed but didn't!\n"); + goto end; + } + else + printf("Add that should fail did.\n"); + ERR_clear_error(); + if(ENGINE_remove(new_h2)) + { + printf("Remove *should* have failed but didn't!\n"); + goto end; + } + else + printf("Remove that should fail did.\n"); + if(!ENGINE_remove(new_h1)) + { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + if(!ENGINE_remove(new_h3)) + { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + if(!ENGINE_remove(new_h4)) + { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + /* Depending on whether there's any hardware support compiled + * in, this remove may be destined to fail. */ + ptr = ENGINE_get_first(); + if(ptr) + if(!ENGINE_remove(ptr)) + printf("Remove failed!i - probably no hardware " + "support present.\n"); + display_engine_list(); + if(!ENGINE_add(new_h1) || !ENGINE_remove(new_h1)) + { + printf("Couldn't add and remove to an empty list!\n"); + goto end; + } + else + printf("Successfully added and removed to an empty list!\n"); + printf("About to beef up the engine-type list\n"); + for(loop = 0; loop < 512; loop++) + { + sprintf(buf, "id%i", loop); + id = strdup(buf); + sprintf(buf, "Fake engine type %i", loop); + name = strdup(buf); + if(((block[loop] = ENGINE_new()) == NULL) || + !ENGINE_set_id(block[loop], id) || + !ENGINE_set_name(block[loop], name)) + { + printf("Couldn't create block of ENGINE structures.\n" + "I'll probably also core-dump now, damn.\n"); + goto end; + } + } + for(loop = 0; loop < 512; loop++) + { + if(!ENGINE_add(block[loop])) + { + printf("\nAdding stopped at %i, (%s,%s)\n", + loop, ENGINE_get_id(block[loop]), + ENGINE_get_name(block[loop])); + goto cleanup_loop; + } + else + printf("."); fflush(stdout); + } +cleanup_loop: + printf("\nAbout to empty the engine-type list\n"); + while((ptr = ENGINE_get_first()) != NULL) + { + if(!ENGINE_remove(ptr)) + { + printf("\nRemove failed!\n"); + goto end; + } + printf("."); fflush(stdout); + } + for(loop = 0; loop < 512; loop++) + { + free((char *)(ENGINE_get_id(block[loop]))); + free((char *)(ENGINE_get_name(block[loop]))); + } + printf("\nTests completed happily\n"); + to_return = 0; +end: + if(to_return) + ERR_print_errors_fp(stderr); + if(new_h1) ENGINE_free(new_h1); + if(new_h2) ENGINE_free(new_h2); + if(new_h3) ENGINE_free(new_h3); + if(new_h4) ENGINE_free(new_h4); + for(loop = 0; loop < 512; loop++) + if(block[loop]) + ENGINE_free(block[loop]); + return to_return; + } diff --git a/crypto/engine/hw_atalla.c b/crypto/engine/hw_atalla.c new file mode 100644 index 0000000000..e536420480 --- /dev/null +++ b/crypto/engine/hw_atalla.c @@ -0,0 +1,443 @@ +/* crypto/engine/hw_atalla.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <openssl/crypto.h> +#include "cryptlib.h" +#include <openssl/dso.h> +#include "engine_int.h" +#include <openssl/engine.h> + +#ifndef NO_HW +#ifndef NO_HW_ATALLA + +#ifdef FLAT_INC +#include "atalla.h" +#else +#include "vendor_defns/atalla.h" +#endif + +static int atalla_init(void); +static int atalla_finish(void); + +/* BIGNUM stuff */ +static int atalla_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +/* RSA stuff */ +static int atalla_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa); +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int atalla_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + +/* DSA stuff */ +static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, + BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont); +static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + +/* DH stuff */ +/* This function is alised to mod_exp (with the DH and mont dropped). */ +static int atalla_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD atalla_rsa = + { + "Atalla RSA method", + NULL, + NULL, + NULL, + NULL, + atalla_rsa_mod_exp, + atalla_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; + +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD atalla_dsa = + { + "Atalla DSA method", + NULL, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + NULL, /* dsa_do_verify */ + atalla_dsa_mod_exp, /* dsa_mod_exp */ + atalla_mod_exp_dsa, /* bn_mod_exp */ + NULL, /* init */ + NULL, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD atalla_dh = + { + "Atalla DH method", + NULL, + NULL, + atalla_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; + +/* Our ENGINE structure. */ +static ENGINE engine_atalla = + { + "atalla", + "Atalla hardware engine support", + &atalla_rsa, + &atalla_dsa, + &atalla_dh, + NULL, + atalla_mod_exp, + NULL, + atalla_init, + atalla_finish, + NULL, /* no ctrl() */ + NULL, /* no load_privkey() */ + NULL, /* no load_pubkey() */ + 0, /* no flags */ + 0, 0, /* no references */ + NULL, NULL /* unlinked */ + }; + +/* As this is only ever called once, there's no need for locking + * (indeed - the lock will already be held by our caller!!!) */ +ENGINE *ENGINE_atalla() + { + RSA_METHOD *meth1; + DSA_METHOD *meth2; + DH_METHOD *meth3; + + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the atalla-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1 = RSA_PKCS1_SSLeay(); + atalla_rsa.rsa_pub_enc = meth1->rsa_pub_enc; + atalla_rsa.rsa_pub_dec = meth1->rsa_pub_dec; + atalla_rsa.rsa_priv_enc = meth1->rsa_priv_enc; + atalla_rsa.rsa_priv_dec = meth1->rsa_priv_dec; + + /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish + * bits. */ + meth2 = DSA_OpenSSL(); + atalla_dsa.dsa_do_sign = meth2->dsa_do_sign; + atalla_dsa.dsa_sign_setup = meth2->dsa_sign_setup; + atalla_dsa.dsa_do_verify = meth2->dsa_do_verify; + + /* Much the same for Diffie-Hellman */ + meth3 = DH_OpenSSL(); + atalla_dh.generate_key = meth3->generate_key; + atalla_dh.compute_key = meth3->compute_key; + return &engine_atalla; + } + +/* This is a process-global DSO handle used for loading and unloading + * the Atalla library. NB: This is only set (or unset) during an + * init() or finish() call (reference counts permitting) and they're + * operating with global locks, so this should be thread-safe + * implicitly. */ +static DSO *atalla_dso = NULL; + +/* These are the function pointers that are (un)set when the library has + * successfully (un)loaded. */ +static tfnASI_GetHardwareConfig *p_Atalla_GetHardwareConfig = NULL; +static tfnASI_RSAPrivateKeyOpFn *p_Atalla_RSAPrivateKeyOpFn = NULL; +static tfnASI_GetPerformanceStatistics *p_Atalla_GetPerformanceStatistics = NULL; + +/* (de)initialisation functions. */ +static int atalla_init() + { + tfnASI_GetHardwareConfig *p1; + tfnASI_RSAPrivateKeyOpFn *p2; + tfnASI_GetPerformanceStatistics *p3; + /* Not sure of the origin of this magic value, but Ben's code had it + * and it seemed to have been working for a few people. :-) */ + unsigned int config_buf[1024]; + + if(atalla_dso != NULL) + { + ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_ALREADY_LOADED); + goto err; + } + /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be + * changed unfortunately because the Atalla drivers don't have + * standard library names that can be platform-translated well. */ + /* TODO: Work out how to actually map to the names the Atalla + * drivers really use - for now a symbollic link needs to be + * created on the host system from libatasi.so to atasi.so on + * unix variants. */ + atalla_dso = DSO_load(NULL, ATALLA_LIBNAME, NULL, 0); + if(atalla_dso == NULL) + { + ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_DSO_FAILURE); + goto err; + } + if(!(p1 = (tfnASI_GetHardwareConfig *)DSO_bind_func( + atalla_dso, ATALLA_F1)) || + !(p2 = (tfnASI_RSAPrivateKeyOpFn *)DSO_bind_func( + atalla_dso, ATALLA_F2)) || + !(p3 = (tfnASI_GetPerformanceStatistics *)DSO_bind_func( + atalla_dso, ATALLA_F3))) + { + ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_DSO_FAILURE); + goto err; + } + /* Copy the pointers */ + p_Atalla_GetHardwareConfig = p1; + p_Atalla_RSAPrivateKeyOpFn = p2; + p_Atalla_GetPerformanceStatistics = p3; + /* Perform a basic test to see if there's actually any unit + * running. */ + if(p1(0L, config_buf) != 0) + { + ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_UNIT_FAILURE); + goto err; + } + /* Everything's fine. */ + return 1; +err: + if(atalla_dso) + DSO_free(atalla_dso); + p_Atalla_GetHardwareConfig = NULL; + p_Atalla_RSAPrivateKeyOpFn = NULL; + p_Atalla_GetPerformanceStatistics = NULL; + return 0; + } + +static int atalla_finish() + { + if(atalla_dso == NULL) + { + ENGINEerr(ENGINE_F_ATALLA_FINISH,ENGINE_R_NOT_LOADED); + return 0; + } + if(!DSO_free(atalla_dso)) + { + ENGINEerr(ENGINE_F_ATALLA_FINISH,ENGINE_R_DSO_FAILURE); + return 0; + } + atalla_dso = NULL; + p_Atalla_GetHardwareConfig = NULL; + p_Atalla_RSAPrivateKeyOpFn = NULL; + p_Atalla_GetPerformanceStatistics = NULL; + return 1; + } + +static int atalla_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) + { + /* I need somewhere to store temporary serialised values for + * use with the Atalla API calls. A neat cheat - I'll use + * BIGNUMs from the BN_CTX but access their arrays directly as + * byte arrays <grin>. This way I don't have to clean anything + * up. */ + BIGNUM *modulus; + BIGNUM *exponent; + BIGNUM *argument; + BIGNUM *result; + RSAPrivateKey keydata; + int to_return, numbytes; + + modulus = exponent = argument = result = NULL; + to_return = 0; /* expect failure */ + + if(!atalla_dso) + { + ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_NOT_LOADED); + goto err; + } + /* Prepare the params */ + modulus = BN_CTX_get(ctx); + exponent = BN_CTX_get(ctx); + argument = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + if(!modulus || !exponent || !argument || !result) + { + ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_BN_CTX_FULL); + goto err; + } + if(!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, m->top) || + !bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top)) + { + ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_BN_EXPAND_FAIL); + goto err; + } + /* Prepare the key-data */ + memset(&keydata, 0,sizeof keydata); + numbytes = BN_num_bytes(m); + memset(exponent->d, 0, numbytes); + memset(modulus->d, 0, numbytes); + BN_bn2bin(p, (unsigned char *)exponent->d + numbytes - BN_num_bytes(p)); + BN_bn2bin(m, (unsigned char *)modulus->d + numbytes - BN_num_bytes(m)); + keydata.privateExponent.data = (unsigned char *)exponent->d; + keydata.privateExponent.len = numbytes; + keydata.modulus.data = (unsigned char *)modulus->d; + keydata.modulus.len = numbytes; + /* Prepare the argument */ + memset(argument->d, 0, numbytes); + memset(result->d, 0, numbytes); + BN_bn2bin(a, (unsigned char *)argument->d + numbytes - BN_num_bytes(a)); + /* Perform the operation */ + if(p_Atalla_RSAPrivateKeyOpFn(&keydata, (unsigned char *)result->d, + (unsigned char *)argument->d, + keydata.modulus.len) != 0) + { + ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_REQUEST_FAILED); + goto err; + } + /* Convert the response */ + BN_bin2bn((unsigned char *)result->d, numbytes, r); + to_return = 1; +err: + if(modulus) ctx->tos--; + if(exponent) ctx->tos--; + if(argument) ctx->tos--; + if(result) ctx->tos--; + return to_return; + } + +static int atalla_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) + { + BN_CTX *ctx = NULL; + int to_return = 0; + + if(!atalla_dso) + { + ENGINEerr(ENGINE_F_ATALLA_RSA_MOD_EXP,ENGINE_R_NOT_LOADED); + goto err; + } + if((ctx = BN_CTX_new()) == NULL) + goto err; + if(!rsa->d || !rsa->n) + { + ENGINEerr(ENGINE_F_ATALLA_RSA_MOD_EXP,ENGINE_R_MISSING_KEY_COMPONENTS); + goto err; + } + to_return = atalla_mod_exp(r0, I, rsa->d, rsa->n, ctx); +err: + if(ctx) + BN_CTX_free(ctx); + return to_return; + } + +/* This code was liberated and adapted from the commented-out code in + * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration + * (it doesn't have a CRT form for RSA), this function means that an + * Atalla system running with a DSA server certificate can handshake + * around 5 or 6 times faster/more than an equivalent system running with + * RSA. Just check out the "signs" statistics from the RSA and DSA parts + * of "openssl speed -engine atalla dsa1024 rsa1024". */ +static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, + BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont) + { + BIGNUM t; + int to_return = 0; + + BN_init(&t); + /* let rr = a1 ^ p1 mod m */ + if (!atalla_mod_exp(rr,a1,p1,m,ctx)) goto end; + /* let t = a2 ^ p2 mod m */ + if (!atalla_mod_exp(&t,a2,p2,m,ctx)) goto end; + /* let rr = rr * t mod m */ + if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; + to_return = 1; +end: + BN_free(&t); + return to_return; + } + + +static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + return atalla_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int atalla_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return atalla_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int atalla_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return atalla_mod_exp(r, a, p, m, ctx); + } + +#endif /* !NO_HW_ATALLA */ +#endif /* !NO_HW */ diff --git a/crypto/engine/hw_cswift.c b/crypto/engine/hw_cswift.c new file mode 100644 index 0000000000..5747973c74 --- /dev/null +++ b/crypto/engine/hw_cswift.c @@ -0,0 +1,806 @@ +/* crypto/engine/hw_cswift.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <openssl/crypto.h> +#include "cryptlib.h" +#include <openssl/dso.h> +#include "engine_int.h" +#include <openssl/engine.h> + +#ifndef NO_HW +#ifndef NO_HW_CSWIFT + +/* Attribution notice: Rainbow have generously allowed me to reproduce + * the necessary definitions here from their API. This means the support + * can build independently of whether application builders have the + * API or hardware. This will allow developers to easily produce software + * that has latent hardware support for any users that have accelerators + * installed, without the developers themselves needing anything extra. + * + * I have only clipped the parts from the CryptoSwift header files that + * are (or seem) relevant to the CryptoSwift support code. This is + * simply to keep the file sizes reasonable. + * [Geoff] + */ +#ifdef FLAT_INC +#include "cswift.h" +#else +#include "vendor_defns/cswift.h" +#endif + +static int cswift_init(void); +static int cswift_finish(void); + +/* BIGNUM stuff */ +static int cswift_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +static int cswift_mod_exp_crt(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp, BN_CTX *ctx); + +/* RSA stuff */ +static int cswift_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa); +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int cswift_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + +/* DSA stuff */ +static DSA_SIG *cswift_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa); +static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +/* DH stuff */ +/* This function is alised to mod_exp (with the DH and mont dropped). */ +static int cswift_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD cswift_rsa = + { + "CryptoSwift RSA method", + NULL, + NULL, + NULL, + NULL, + cswift_rsa_mod_exp, + cswift_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; + +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD cswift_dsa = + { + "CryptoSwift DSA method", + cswift_dsa_sign, + NULL, /* dsa_sign_setup */ + cswift_dsa_verify, + NULL, /* dsa_mod_exp */ + NULL, /* bn_mod_exp */ + NULL, /* init */ + NULL, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD cswift_dh = + { + "CryptoSwift DH method", + NULL, + NULL, + cswift_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; + +/* Our ENGINE structure. */ +static ENGINE engine_cswift = + { + "cswift", + "CryptoSwift hardware engine support", + &cswift_rsa, + &cswift_dsa, + &cswift_dh, + NULL, + cswift_mod_exp, + cswift_mod_exp_crt, + cswift_init, + cswift_finish, + NULL, /* no ctrl() */ + NULL, /* no load_privkey() */ + NULL, /* no load_pubkey() */ + 0, /* no flags */ + 0, 0, /* no references */ + NULL, NULL /* unlinked */ + }; + +/* As this is only ever called once, there's no need for locking + * (indeed - the lock will already be held by our caller!!!) */ +ENGINE *ENGINE_cswift() + { + RSA_METHOD *meth1; + DH_METHOD *meth2; + + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the cswift-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1 = RSA_PKCS1_SSLeay(); + cswift_rsa.rsa_pub_enc = meth1->rsa_pub_enc; + cswift_rsa.rsa_pub_dec = meth1->rsa_pub_dec; + cswift_rsa.rsa_priv_enc = meth1->rsa_priv_enc; + cswift_rsa.rsa_priv_dec = meth1->rsa_priv_dec; + + /* Much the same for Diffie-Hellman */ + meth2 = DH_OpenSSL(); + cswift_dh.generate_key = meth2->generate_key; + cswift_dh.compute_key = meth2->compute_key; + return &engine_cswift; + } + +/* This is a process-global DSO handle used for loading and unloading + * the CryptoSwift library. NB: This is only set (or unset) during an + * init() or finish() call (reference counts permitting) and they're + * operating with global locks, so this should be thread-safe + * implicitly. */ +static DSO *cswift_dso = NULL; + +/* These are the function pointers that are (un)set when the library has + * successfully (un)loaded. */ +t_swAcquireAccContext *p_CSwift_AcquireAccContext = NULL; +t_swAttachKeyParam *p_CSwift_AttachKeyParam = NULL; +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 *CSWIFT_F1 = "swAcquireAccContext"; +static const char *CSWIFT_F2 = "swAttachKeyParam"; +static const char *CSWIFT_F3 = "swSimpleRequest"; +static const char *CSWIFT_F4 = "swReleaseAccContext"; + + +/* CryptoSwift library functions and mechanics - these are used by the + * higher-level functions further down. NB: As and where there's no + * error checking, take a look lower down where these functions are + * called, the checking and error handling is probably down there. */ + +/* utility function to obtain a context */ +static int get_context(SW_CONTEXT_HANDLE *hac) + { + SW_STATUS status; + + status = p_CSwift_AcquireAccContext(hac); + if(status != SW_OK) + return 0; + return 1; + } + +/* similarly to release one. */ +static void release_context(SW_CONTEXT_HANDLE hac) + { + p_CSwift_ReleaseAccContext(hac); + } + +/* (de)initialisation functions. */ +static int cswift_init() + { + SW_CONTEXT_HANDLE hac; + t_swAcquireAccContext *p1; + t_swAttachKeyParam *p2; + t_swSimpleRequest *p3; + t_swReleaseAccContext *p4; + + if(cswift_dso != NULL) + { + ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_ALREADY_LOADED); + goto err; + } + /* Attempt to load libswift.so/swift.dll/whatever. */ + cswift_dso = DSO_load(NULL, CSWIFT_LIBNAME, NULL, 0); + if(cswift_dso == NULL) + { + ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_DSO_FAILURE); + goto err; + } + if(!(p1 = (t_swAcquireAccContext *) + DSO_bind_func(cswift_dso, CSWIFT_F1)) || + !(p2 = (t_swAttachKeyParam *) + DSO_bind_func(cswift_dso, CSWIFT_F2)) || + !(p3 = (t_swSimpleRequest *) + DSO_bind_func(cswift_dso, CSWIFT_F3)) || + !(p4 = (t_swReleaseAccContext *) + DSO_bind_func(cswift_dso, CSWIFT_F4))) + { + ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_DSO_FAILURE); + goto err; + } + /* Copy the pointers */ + p_CSwift_AcquireAccContext = p1; + p_CSwift_AttachKeyParam = p2; + p_CSwift_SimpleRequest = p3; + p_CSwift_ReleaseAccContext = p4; + /* Try and get a context - if not, we may have a DSO but no + * accelerator! */ + if(!get_context(&hac)) + { + ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_UNIT_FAILURE); + goto err; + } + release_context(hac); + /* Everything's fine. */ + return 1; +err: + if(cswift_dso) + DSO_free(cswift_dso); + p_CSwift_AcquireAccContext = NULL; + p_CSwift_AttachKeyParam = NULL; + p_CSwift_SimpleRequest = NULL; + p_CSwift_ReleaseAccContext = NULL; + return 0; + } + +static int cswift_finish() + { + if(cswift_dso == NULL) + { + ENGINEerr(ENGINE_F_CSWIFT_FINISH,ENGINE_R_NOT_LOADED); + return 0; + } + if(!DSO_free(cswift_dso)) + { + ENGINEerr(ENGINE_F_CSWIFT_FINISH,ENGINE_R_DSO_FAILURE); + return 0; + } + cswift_dso = NULL; + p_CSwift_AcquireAccContext = NULL; + p_CSwift_AttachKeyParam = NULL; + p_CSwift_SimpleRequest = NULL; + p_CSwift_ReleaseAccContext = NULL; + return 1; + } + +/* Un petit mod_exp */ +static int cswift_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) + { + /* I need somewhere to store temporary serialised values for + * use with the CryptoSwift API calls. A neat cheat - I'll use + * BIGNUMs from the BN_CTX but access their arrays directly as + * byte arrays <grin>. This way I don't have to clean anything + * up. */ + BIGNUM *modulus; + BIGNUM *exponent; + BIGNUM *argument; + BIGNUM *result; + SW_STATUS sw_status; + SW_LARGENUMBER arg, res; + SW_PARAM sw_param; + SW_CONTEXT_HANDLE hac; + int to_return, acquired; + + modulus = exponent = argument = result = NULL; + to_return = 0; /* expect failure */ + acquired = 0; + + if(!get_context(&hac)) + { + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_GET_HANDLE_FAILED); + goto err; + } + acquired = 1; + /* Prepare the params */ + modulus = BN_CTX_get(ctx); + exponent = BN_CTX_get(ctx); + argument = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + if(!modulus || !exponent || !argument || !result) + { + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_BN_CTX_FULL); + goto err; + } + if(!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, p->top) || + !bn_wexpand(argument, a->top) || !bn_wexpand(result, m->top)) + { + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_BN_EXPAND_FAIL); + goto err; + } + sw_param.type = SW_ALG_EXP; + sw_param.up.exp.modulus.nbytes = BN_bn2bin(m, + (unsigned char *)modulus->d); + sw_param.up.exp.modulus.value = (unsigned char *)modulus->d; + sw_param.up.exp.exponent.nbytes = BN_bn2bin(p, + (unsigned char *)exponent->d); + sw_param.up.exp.exponent.value = (unsigned char *)exponent->d; + /* Attach the key params */ + sw_status = p_CSwift_AttachKeyParam(hac, &sw_param); + switch(sw_status) + { + case SW_OK: + break; + case SW_ERR_INPUT_SIZE: + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP, + ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL); + goto err; + default: + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + } + goto err; + } + /* Prepare the argument and response */ + arg.nbytes = BN_bn2bin(a, (unsigned char *)argument->d); + arg.value = (unsigned char *)argument->d; + res.nbytes = BN_num_bytes(m); + memset(result->d, 0, res.nbytes); + res.value = (unsigned char *)result->d; + /* Perform the operation */ + if((sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_MODEXP, &arg, 1, + &res, 1)) != SW_OK) + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + goto err; + } + /* Convert the response */ + BN_bin2bn((unsigned char *)result->d, res.nbytes, r); + to_return = 1; +err: + if(acquired) + release_context(hac); + if(modulus) ctx->tos--; + if(exponent) ctx->tos--; + if(argument) ctx->tos--; + if(result) ctx->tos--; + return to_return; + } + +/* Un petit mod_exp chinois */ +static int cswift_mod_exp_crt(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, + const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx) + { + SW_STATUS sw_status; + SW_LARGENUMBER arg, res; + SW_PARAM sw_param; + SW_CONTEXT_HANDLE hac; + BIGNUM *rsa_p = NULL; + BIGNUM *rsa_q = NULL; + BIGNUM *rsa_dmp1 = NULL; + BIGNUM *rsa_dmq1 = NULL; + BIGNUM *rsa_iqmp = NULL; + BIGNUM *argument = NULL; + BIGNUM *result = NULL; + int to_return = 0; /* expect failure */ + int acquired = 0; + + if(!get_context(&hac)) + { + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_GET_HANDLE_FAILED); + goto err; + } + acquired = 1; + /* Prepare the params */ + rsa_p = BN_CTX_get(ctx); + rsa_q = BN_CTX_get(ctx); + rsa_dmp1 = BN_CTX_get(ctx); + rsa_dmq1 = BN_CTX_get(ctx); + rsa_iqmp = BN_CTX_get(ctx); + argument = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + if(!rsa_p || !rsa_q || !rsa_dmp1 || !rsa_dmq1 || !rsa_iqmp || + !argument || !result) + { + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_BN_CTX_FULL); + goto err; + } + if(!bn_wexpand(rsa_p, p->top) || !bn_wexpand(rsa_q, q->top) || + !bn_wexpand(rsa_dmp1, dmp1->top) || + !bn_wexpand(rsa_dmq1, dmq1->top) || + !bn_wexpand(rsa_iqmp, iqmp->top) || + !bn_wexpand(argument, a->top) || + !bn_wexpand(result, p->top + q->top)) + { + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_BN_EXPAND_FAIL); + goto err; + } + sw_param.type = SW_ALG_CRT; + sw_param.up.crt.p.nbytes = BN_bn2bin(p, (unsigned char *)rsa_p->d); + sw_param.up.crt.p.value = (unsigned char *)rsa_p->d; + sw_param.up.crt.q.nbytes = BN_bn2bin(q, (unsigned char *)rsa_q->d); + sw_param.up.crt.q.value = (unsigned char *)rsa_q->d; + sw_param.up.crt.dmp1.nbytes = BN_bn2bin(dmp1, + (unsigned char *)rsa_dmp1->d); + sw_param.up.crt.dmp1.value = (unsigned char *)rsa_dmp1->d; + sw_param.up.crt.dmq1.nbytes = BN_bn2bin(dmq1, + (unsigned char *)rsa_dmq1->d); + sw_param.up.crt.dmq1.value = (unsigned char *)rsa_dmq1->d; + sw_param.up.crt.iqmp.nbytes = BN_bn2bin(iqmp, + (unsigned char *)rsa_iqmp->d); + sw_param.up.crt.iqmp.value = (unsigned char *)rsa_iqmp->d; + /* Attach the key params */ + sw_status = p_CSwift_AttachKeyParam(hac, &sw_param); + switch(sw_status) + { + case SW_OK: + break; + case SW_ERR_INPUT_SIZE: + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT, + ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL); + goto err; + default: + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + } + goto err; + } + /* Prepare the argument and response */ + arg.nbytes = BN_bn2bin(a, (unsigned char *)argument->d); + arg.value = (unsigned char *)argument->d; + res.nbytes = 2 * BN_num_bytes(p); + memset(result->d, 0, res.nbytes); + res.value = (unsigned char *)result->d; + /* Perform the operation */ + if((sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_MODEXP_CRT, &arg, 1, + &res, 1)) != SW_OK) + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + goto err; + } + /* Convert the response */ + BN_bin2bn((unsigned char *)result->d, res.nbytes, r); + to_return = 1; +err: + if(acquired) + release_context(hac); + if(rsa_p) ctx->tos--; + if(rsa_q) ctx->tos--; + if(rsa_dmp1) ctx->tos--; + if(rsa_dmq1) ctx->tos--; + if(rsa_iqmp) ctx->tos--; + if(argument) ctx->tos--; + if(result) ctx->tos--; + return to_return; + } + +static int cswift_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) + { + BN_CTX *ctx; + int to_return = 0; + + if((ctx = BN_CTX_new()) == NULL) + goto err; + if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) + { + ENGINEerr(ENGINE_F_CSWIFT_RSA_MOD_EXP,ENGINE_R_MISSING_KEY_COMPONENTS); + goto err; + } + to_return = cswift_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, + rsa->dmq1, rsa->iqmp, ctx); +err: + if(ctx) + BN_CTX_free(ctx); + return to_return; + } + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int cswift_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return cswift_mod_exp(r, a, p, m, ctx); + } + +static DSA_SIG *cswift_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + SW_CONTEXT_HANDLE hac; + SW_PARAM sw_param; + SW_STATUS sw_status; + SW_LARGENUMBER arg, res; + unsigned char *ptr; + BN_CTX *ctx; + BIGNUM *dsa_p = NULL; + BIGNUM *dsa_q = NULL; + BIGNUM *dsa_g = NULL; + BIGNUM *dsa_key = NULL; + BIGNUM *result = NULL; + DSA_SIG *to_return = NULL; + int acquired = 0; + + if((ctx = BN_CTX_new()) == NULL) + goto err; + if(!get_context(&hac)) + { + ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_GET_HANDLE_FAILED); + goto err; + } + acquired = 1; + /* Prepare the params */ + dsa_p = BN_CTX_get(ctx); + dsa_q = BN_CTX_get(ctx); + dsa_g = BN_CTX_get(ctx); + dsa_key = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + if(!dsa_p || !dsa_q || !dsa_g || !dsa_key || !result) + { + ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_BN_CTX_FULL); + goto err; + } + if(!bn_wexpand(dsa_p, dsa->p->top) || + !bn_wexpand(dsa_q, dsa->q->top) || + !bn_wexpand(dsa_g, dsa->g->top) || + !bn_wexpand(dsa_key, dsa->priv_key->top) || + !bn_wexpand(result, dsa->p->top)) + { + ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_BN_EXPAND_FAIL); + goto err; + } + sw_param.type = SW_ALG_DSA; + sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p, + (unsigned char *)dsa_p->d); + sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d; + sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q, + (unsigned char *)dsa_q->d); + sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d; + sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g, + (unsigned char *)dsa_g->d); + sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d; + sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->priv_key, + (unsigned char *)dsa_key->d); + sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d; + /* Attach the key params */ + sw_status = p_CSwift_AttachKeyParam(hac, &sw_param); + switch(sw_status) + { + case SW_OK: + break; + case SW_ERR_INPUT_SIZE: + ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN, + ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL); + goto err; + default: + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + } + goto err; + } + /* Prepare the argument and response */ + arg.nbytes = dlen; + arg.value = (unsigned char *)dgst; + res.nbytes = BN_num_bytes(dsa->p); + memset(result->d, 0, res.nbytes); + res.value = (unsigned char *)result->d; + /* Perform the operation */ + sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_SIGN, &arg, 1, + &res, 1); + if(sw_status != SW_OK) + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + goto err; + } + /* Convert the response */ + ptr = (unsigned char *)result->d; + if((to_return = DSA_SIG_new()) == NULL) + goto err; + to_return->r = BN_bin2bn((unsigned char *)result->d, 20, NULL); + to_return->s = BN_bin2bn((unsigned char *)result->d + 20, 20, NULL); + +err: + if(acquired) + release_context(hac); + if(dsa_p) ctx->tos--; + if(dsa_q) ctx->tos--; + if(dsa_g) ctx->tos--; + if(dsa_key) ctx->tos--; + if(result) ctx->tos--; + if(ctx) + BN_CTX_free(ctx); + return to_return; + } + +static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa) + { + SW_CONTEXT_HANDLE hac; + SW_PARAM sw_param; + SW_STATUS sw_status; + SW_LARGENUMBER arg[2], res; + unsigned long sig_result; + BN_CTX *ctx; + BIGNUM *dsa_p = NULL; + BIGNUM *dsa_q = NULL; + BIGNUM *dsa_g = NULL; + BIGNUM *dsa_key = NULL; + BIGNUM *argument = NULL; + int to_return = -1; + int acquired = 0; + + if((ctx = BN_CTX_new()) == NULL) + goto err; + if(!get_context(&hac)) + { + ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_GET_HANDLE_FAILED); + goto err; + } + acquired = 1; + /* Prepare the params */ + dsa_p = BN_CTX_get(ctx); + dsa_q = BN_CTX_get(ctx); + dsa_g = BN_CTX_get(ctx); + dsa_key = BN_CTX_get(ctx); + argument = BN_CTX_get(ctx); + if(!dsa_p || !dsa_q || !dsa_g || !dsa_key || !argument) + { + ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_BN_CTX_FULL); + goto err; + } + if(!bn_wexpand(dsa_p, dsa->p->top) || + !bn_wexpand(dsa_q, dsa->q->top) || + !bn_wexpand(dsa_g, dsa->g->top) || + !bn_wexpand(dsa_key, dsa->pub_key->top) || + !bn_wexpand(argument, 40)) + { + ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_BN_EXPAND_FAIL); + goto err; + } + sw_param.type = SW_ALG_DSA; + sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p, + (unsigned char *)dsa_p->d); + sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d; + sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q, + (unsigned char *)dsa_q->d); + sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d; + sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g, + (unsigned char *)dsa_g->d); + sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d; + sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->pub_key, + (unsigned char *)dsa_key->d); + sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d; + /* Attach the key params */ + sw_status = p_CSwift_AttachKeyParam(hac, &sw_param); + switch(sw_status) + { + case SW_OK: + break; + case SW_ERR_INPUT_SIZE: + ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY, + ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL); + goto err; + default: + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + } + goto err; + } + /* Prepare the argument and response */ + arg[0].nbytes = dgst_len; + arg[0].value = (unsigned char *)dgst; + arg[1].nbytes = 40; + arg[1].value = (unsigned char *)argument->d; + memset(arg[1].value, 0, 40); + BN_bn2bin(sig->r, arg[1].value + 20 - BN_num_bytes(sig->r)); + BN_bn2bin(sig->s, arg[1].value + 40 - BN_num_bytes(sig->s)); + res.nbytes = 4; /* unsigned long */ + res.value = (unsigned char *)(&sig_result); + /* Perform the operation */ + sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_VERIFY, arg, 2, + &res, 1); + if(sw_status != SW_OK) + { + char tmpbuf[20]; + ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_REQUEST_FAILED); + sprintf(tmpbuf, "%ld", sw_status); + ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf); + goto err; + } + /* Convert the response */ + to_return = ((sig_result == 0) ? 0 : 1); + +err: + if(acquired) + release_context(hac); + if(dsa_p) ctx->tos--; + if(dsa_q) ctx->tos--; + if(dsa_g) ctx->tos--; + if(dsa_key) ctx->tos--; + if(argument) ctx->tos--; + if(ctx) + BN_CTX_free(ctx); + return to_return; + } + +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int cswift_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return cswift_mod_exp(r, a, p, m, ctx); + } + +#endif /* !NO_HW_CSWIFT */ +#endif /* !NO_HW */ diff --git a/crypto/engine/hw_ncipher.c b/crypto/engine/hw_ncipher.c new file mode 100644 index 0000000000..f6b06e468f --- /dev/null +++ b/crypto/engine/hw_ncipher.c @@ -0,0 +1,1018 @@ +/* crypto/engine/hw_ncipher.c -*- mode: C; c-file-style: "eay" -*- */ +/* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe + * (geoff@geoffthorpe.net) and Dr Stephen N Henson (shenson@bigfoot.com) + * for the OpenSSL project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <openssl/crypto.h> +#include <openssl/pem.h> +#include "cryptlib.h" +#include <openssl/dso.h> +#include "engine_int.h" +#include <openssl/engine.h> + +#ifndef NO_HW +#ifndef NO_HW_NCIPHER + +/* Attribution notice: nCipher have said several times that it's OK for + * us to implement a general interface to their boxes, and recently declared + * their HWCryptoHook to be public, and therefore available for us to use. + * Thanks, nCipher. + * + * The hwcryptohook.h included here is from May 2000. + * [Richard Levitte] + */ +#ifdef FLAT_INC +#include "hwcryptohook.h" +#else +#include "vendor_defns/hwcryptohook.h" +#endif + +static int hwcrhk_init(void); +static int hwcrhk_finish(void); +static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)()); + +/* Functions to handle mutexes */ +static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*); +static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*); +static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*); +static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*); + +/* BIGNUM stuff */ +static int hwcrhk_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +/* RSA stuff */ +static int hwcrhk_rsa_mod_exp(BIGNUM *r, BIGNUM *I, RSA *rsa); +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int hwcrhk_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + +/* DH stuff */ +/* This function is alised to mod_exp (with the DH and mont dropped). */ +static int hwcrhk_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + +/* RAND stuff */ +static int hwcrhk_rand_bytes(unsigned char *buf, int num); +static int hwcrhk_rand_status(void); + +/* KM stuff */ +static EVP_PKEY *hwcrhk_load_privkey(const char *key_id, + const char *passphrase); +static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id, + const char *passphrase); +static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, + int ind,long argl, void *argp); + +/* Interaction stuff */ +static int hwcrhk_get_pass(const char *prompt_info, + int *len_io, char *buf, + HWCryptoHook_PassphraseContext *ppctx, + HWCryptoHook_CallerContext *cactx); +static void hwcrhk_log_message(void *logstr, const char *message); + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD hwcrhk_rsa = + { + "nCipher RSA method", + NULL, + NULL, + NULL, + NULL, + hwcrhk_rsa_mod_exp, + hwcrhk_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD hwcrhk_dh = + { + "nCipher DH method", + NULL, + NULL, + hwcrhk_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; + +static RAND_METHOD hwcrhk_rand = + { + /* "nCipher RAND method", */ + NULL, + hwcrhk_rand_bytes, + NULL, + NULL, + hwcrhk_rand_bytes, + hwcrhk_rand_status, + }; + +/* Our ENGINE structure. */ +static ENGINE engine_hwcrhk = + { + "chil", + "nCipher hardware engine support", + &hwcrhk_rsa, + NULL, + &hwcrhk_dh, + &hwcrhk_rand, + hwcrhk_mod_exp, + NULL, + hwcrhk_init, + hwcrhk_finish, + hwcrhk_ctrl, + hwcrhk_load_privkey, + hwcrhk_load_pubkey, + 0, /* no flags */ + 0, 0, /* no references */ + NULL, NULL /* unlinked */ + }; + +/* Internal stuff for HWCryptoHook */ + +/* Some structures needed for proper use of thread locks */ +/* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue + into HWCryptoHook_Mutex */ +struct HWCryptoHook_MutexValue + { + int lockid; + }; + +/* hwcryptohook.h has some typedefs that turn + struct HWCryptoHook_PassphraseContextValue + into HWCryptoHook_PassphraseContext */ +struct HWCryptoHook_PassphraseContextValue + { + void *any; + }; + +/* hwcryptohook.h has some typedefs that turn + struct HWCryptoHook_CallerContextValue + into HWCryptoHook_CallerContext */ +struct HWCryptoHook_CallerContextValue + { + void *any; + }; + +/* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL + BIGNUM's, so lets define a couple of conversion macros */ +#define BN2MPI(mp, bn) \ + {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} +#define MPI2BN(bn, mp) \ + {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} + +#if 0 /* Card and password management is not yet supported */ +/* HWCryptoHook callbacks. insert_card() and get_pass() are not yet + defined, because we haven't quite decided on the proper form yet. + log_message() just adds an entry in the error stack. I don't know + if that's good or bad... */ +static int insert_card(const char *prompt_info, + const char *wrong_info, + HWCryptoHook_PassphraseContext *ppctx, + HWCryptoHook_CallerContext *cactx); +static int get_pass(const char *prompt_info, + int *len_io, char *buf, + HWCryptoHook_PassphraseContext *ppctx, + HWCryptoHook_CallerContext *cactx); +#endif + +static BIO *logstream = NULL; +static pem_password_cb *password_callback = NULL; +#if 0 +static void *password_callback_userdata = NULL; +#endif +static int disable_mutex_callbacks = 0; + +/* Stuff to pass to the HWCryptoHook library */ +static HWCryptoHook_InitInfo hwcrhk_globals = { + 0, /* Flags */ + &logstream, /* logstream */ + sizeof(BN_ULONG), /* limbsize */ + 0, /* mslimb first: false for BNs */ + -1, /* msbyte first: use native */ + 0, /* Max mutexes, 0 = no small limit */ + 0, /* Max simultaneous, 0 = default */ + + /* The next few are mutex stuff: we write wrapper functions + around the OS mutex functions. We initialise them to 0 + here, and change that to actual function pointers in hwcrhk_init() + if dynamic locks are supported (that is, if the application + programmer has made sure of setting up callbacks bafore starting + this engine) *and* if disable_mutex_callbacks hasn't been set by + a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */ + sizeof(HWCryptoHook_Mutex), + 0, + 0, + 0, + 0, + + /* The next few are condvar stuff: we write wrapper functions + round the OS functions. Currently not implemented and not + and absolute necessity even in threaded programs, therefore + 0'ed. Will hopefully be implemented some day, since it + enhances the efficiency of HWCryptoHook. */ + 0, /* sizeof(HWCryptoHook_CondVar), */ + 0, /* hwcrhk_cv_init, */ + 0, /* hwcrhk_cv_wait, */ + 0, /* hwcrhk_cv_signal, */ + 0, /* hwcrhk_cv_broadcast, */ + 0, /* hwcrhk_cv_destroy, */ + + hwcrhk_get_pass, /* pass phrase */ + 0, /* insert_card, */ /* insert a card */ + hwcrhk_log_message /* Log message */ +}; + + +/* Now, to our own code */ + +/* As this is only ever called once, there's no need for locking + * (indeed - the lock will already be held by our caller!!!) */ +ENGINE *ENGINE_ncipher() + { + RSA_METHOD *meth1; + DH_METHOD *meth2; + + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the cswift-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1 = RSA_PKCS1_SSLeay(); + hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc; + hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec; + hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc; + hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec; + + /* Much the same for Diffie-Hellman */ + meth2 = DH_OpenSSL(); + hwcrhk_dh.generate_key = meth2->generate_key; + hwcrhk_dh.compute_key = meth2->compute_key; + return &engine_hwcrhk; + } + +/* This is a process-global DSO handle used for loading and unloading + * the HWCryptoHook library. NB: This is only set (or unset) during an + * init() or finish() call (reference counts permitting) and they're + * operating with global locks, so this should be thread-safe + * implicitly. */ +static DSO *hwcrhk_dso = NULL; +static HWCryptoHook_ContextHandle hwcrhk_context = 0; +static int hndidx = -1; /* Index for KM handle. Not really used yet. */ + +/* These are the function pointers that are (un)set when the library has + * successfully (un)loaded. */ +static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL; +static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL; +static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL; +static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL; +static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL; +static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL; +static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL; +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 *n_hwcrhk_Init = "HWCryptoHook_Init"; +static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish"; +static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp"; +static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA"; +static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes"; +static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey"; +static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey"; +static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey"; +static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT"; + +/* HWCryptoHook library functions and mechanics - these are used by the + * higher-level functions further down. NB: As and where there's no + * error checking, take a look lower down where these functions are + * called, the checking and error handling is probably down there. */ + +/* utility function to obtain a context */ +static int get_context(HWCryptoHook_ContextHandle *hac) + { + char tempbuf[1024]; + HWCryptoHook_ErrMsgBuf rmsg; + + rmsg.buf = tempbuf; + rmsg.size = 1024; + + *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, + NULL); + if (!*hac) + return 0; + return 1; + } + +/* similarly to release one. */ +static void release_context(HWCryptoHook_ContextHandle hac) + { + p_hwcrhk_Finish(hac); + } + +/* (de)initialisation functions. */ +static int hwcrhk_init() + { + HWCryptoHook_Init_t *p1; + HWCryptoHook_Finish_t *p2; + HWCryptoHook_ModExp_t *p3; + HWCryptoHook_RSA_t *p4; + HWCryptoHook_RSALoadKey_t *p5; + HWCryptoHook_RSAGetPublicKey_t *p6; + HWCryptoHook_RSAUnloadKey_t *p7; + HWCryptoHook_RandomBytes_t *p8; + HWCryptoHook_ModExpCRT_t *p9; + + if(hwcrhk_dso != NULL) + { + ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED); + goto err; + } + /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */ + hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0); + if(hwcrhk_dso == NULL) + { + ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE); + goto err; + } + if(!(p1 = (HWCryptoHook_Init_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) || + !(p2 = (HWCryptoHook_Finish_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) || + !(p3 = (HWCryptoHook_ModExp_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) || + !(p4 = (HWCryptoHook_RSA_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) || + !(p5 = (HWCryptoHook_RSALoadKey_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) || + !(p6 = (HWCryptoHook_RSAGetPublicKey_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) || + !(p7 = (HWCryptoHook_RSAUnloadKey_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) || + !(p8 = (HWCryptoHook_RandomBytes_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) || + !(p9 = (HWCryptoHook_ModExpCRT_t *) + DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT))) + { + ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE); + goto err; + } + /* Copy the pointers */ + p_hwcrhk_Init = p1; + p_hwcrhk_Finish = p2; + p_hwcrhk_ModExp = p3; + p_hwcrhk_RSA = p4; + p_hwcrhk_RSALoadKey = p5; + p_hwcrhk_RSAGetPublicKey = p6; + p_hwcrhk_RSAUnloadKey = p7; + p_hwcrhk_RandomBytes = p8; + p_hwcrhk_ModExpCRT = p9; + + /* Check if the application decided to support dynamic locks, + and if it does, use them. */ + if (disable_mutex_callbacks == 0 && + CRYPTO_get_dynlock_create_callback() != NULL && + CRYPTO_get_dynlock_lock_callback() != NULL && + CRYPTO_get_dynlock_destroy_callback() != NULL) + { + hwcrhk_globals.mutex_init = hwcrhk_mutex_init; + hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock; + hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock; + hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy; + } + + /* Try and get a context - if not, we may have a DSO but no + * accelerator! */ + if(!get_context(&hwcrhk_context)) + { + ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE); + goto err; + } + /* Everything's fine. */ + if (hndidx == -1) + hndidx = RSA_get_ex_new_index(0, + "nFast HWCryptoHook RSA key handle", + NULL, NULL, hwcrhk_ex_free); + return 1; +err: + if(hwcrhk_dso) + DSO_free(hwcrhk_dso); + hwcrhk_dso = NULL; + p_hwcrhk_Init = NULL; + p_hwcrhk_Finish = NULL; + p_hwcrhk_ModExp = NULL; + p_hwcrhk_RSA = NULL; + p_hwcrhk_RSALoadKey = NULL; + p_hwcrhk_RSAGetPublicKey = NULL; + p_hwcrhk_RSAUnloadKey = NULL; + p_hwcrhk_ModExpCRT = NULL; + p_hwcrhk_RandomBytes = NULL; + return 0; + } + +static int hwcrhk_finish() + { + int to_return = 1; + if(hwcrhk_dso == NULL) + { + ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED); + to_return = 0; + goto err; + } + release_context(hwcrhk_context); + if(!DSO_free(hwcrhk_dso)) + { + ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE); + to_return = 0; + goto err; + } + err: + if (logstream) + BIO_free(logstream); + hwcrhk_dso = NULL; + p_hwcrhk_Init = NULL; + p_hwcrhk_Finish = NULL; + p_hwcrhk_ModExp = NULL; + p_hwcrhk_RSA = NULL; + p_hwcrhk_RSALoadKey = NULL; + p_hwcrhk_RSAGetPublicKey = NULL; + p_hwcrhk_RSAUnloadKey = NULL; + p_hwcrhk_ModExpCRT = NULL; + p_hwcrhk_RandomBytes = NULL; + return to_return; + } + +static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)()) + { + int to_return = 1; + + switch(cmd) + { + case ENGINE_CTRL_SET_LOGSTREAM: + { + BIO *bio = (BIO *)p; + + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if (logstream) + { + BIO_free(logstream); + logstream = NULL; + } + if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1) + logstream = bio; + else + ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED); + } + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + break; + case ENGINE_CTRL_SET_PASSWORD_CALLBACK: + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + password_callback = (pem_password_cb *)f; + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + break; + /* this enables or disables the "SimpleForkCheck" flag used in the + * initialisation structure. */ + case ENGINE_CTRL_CHIL_SET_FORKCHECK: + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + if(i) + hwcrhk_globals.flags |= + HWCryptoHook_InitFlags_SimpleForkCheck; + else + hwcrhk_globals.flags &= + ~HWCryptoHook_InitFlags_SimpleForkCheck; + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + break; + /* This will prevent the initialisation function from "installing" + * the mutex-handling callbacks, even if they are available from + * within the library (or were provided to the library from the + * calling application). This is to remove any baggage for + * applications not using multithreading. */ + case ENGINE_CTRL_CHIL_NO_LOCKING: + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + disable_mutex_callbacks = 1; + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + break; + + /* The command isn't understood by this engine */ + default: + ENGINEerr(ENGINE_F_HWCRHK_CTRL, + ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + to_return = 0; + break; + } + + return to_return; + } + +static EVP_PKEY *hwcrhk_load_privkey(const char *key_id, + const char *passphrase) + { + RSA *rtmp = NULL; + EVP_PKEY *res = NULL; + HWCryptoHook_MPI e, n; + HWCryptoHook_RSAKeyHandle *hptr; + HWCryptoHook_ErrMsgBuf rmsg; + + if(!hwcrhk_context) + { + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY, + ENGINE_R_NOT_INITIALISED); + goto err; + } + hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle)); + if (!hptr) + { + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, + &rmsg, NULL)) + { + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY, + ENGINE_R_CHIL_ERROR); + ERR_add_error_data(1,rmsg.buf); + goto err; + } + if (!*hptr) + { + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY, + ENGINE_R_NO_KEY); + goto err; + } + rtmp = RSA_new_method(&engine_hwcrhk); + RSA_set_ex_data(rtmp, hndidx, (char *)hptr); + rtmp->e = BN_new(); + rtmp->n = BN_new(); + rtmp->flags |= RSA_FLAG_EXT_PKEY; + MPI2BN(rtmp->e, e); + MPI2BN(rtmp->n, n); + if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg) + != HWCRYPTOHOOK_ERROR_MPISIZE) + { + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR); + ERR_add_error_data(1,rmsg.buf); + goto err; + } + + bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG)); + bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG)); + MPI2BN(rtmp->e, e); + MPI2BN(rtmp->n, n); + + if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) + { + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY, + ENGINE_R_CHIL_ERROR); + ERR_add_error_data(1,rmsg.buf); + goto err; + } + rtmp->e->top = e.size / sizeof(BN_ULONG); + bn_fix_top(rtmp->e); + rtmp->n->top = n.size / sizeof(BN_ULONG); + bn_fix_top(rtmp->n); + + res = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(res, rtmp); + + return res; + err: + if (res) + EVP_PKEY_free(res); + if (rtmp) + RSA_free(rtmp); + return NULL; + } + +static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id, const char *passphrase) + { + EVP_PKEY *res = hwcrhk_load_privkey(key_id, passphrase); + + if (res) + switch(res->type) + { + case EVP_PKEY_RSA: + { + RSA *rsa = NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); + rsa = res->pkey.rsa; + res->pkey.rsa = RSA_new(); + res->pkey.rsa->n = rsa->n; + res->pkey.rsa->e = rsa->e; + CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); + RSA_free(rsa); + } + default: + ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY, + ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); + goto err; + } + + return res; + err: + if (res) + EVP_PKEY_free(res); + return NULL; + } + +/* A little mod_exp */ +static int hwcrhk_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) + { + char tempbuf[1024]; + HWCryptoHook_ErrMsgBuf rmsg; + /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, + we use them directly, plus a little macro magic. We only + thing we need to make sure of is that enough space is allocated. */ + HWCryptoHook_MPI m_a, m_p, m_n, m_r; + int to_return, ret; + + to_return = 0; /* expect failure */ + rmsg.buf = tempbuf; + rmsg.size = 1024; + + if(!hwcrhk_context) + { + ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED); + goto err; + } + /* Prepare the params */ + bn_expand2(r, m->top); /* Check for error !! */ + BN2MPI(m_a, a); + BN2MPI(m_p, p); + BN2MPI(m_n, m); + MPI2BN(r, m_r); + + /* Perform the operation */ + ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg); + + /* Convert the response */ + r->top = m_r.size / sizeof(BN_ULONG); + bn_fix_top(r); + + if (ret < 0) + { + /* FIXME: When this error is returned, HWCryptoHook is + telling us that falling back to software computation + might be a good thing. */ + if(ret == HWCRYPTOHOOK_ERROR_FALLBACK) + { + ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK); + } + else + { + ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED); + } + ERR_add_error_data(1,rmsg.buf); + goto err; + } + + to_return = 1; +err: + return to_return; + } + +static int hwcrhk_rsa_mod_exp(BIGNUM *r, BIGNUM *I, RSA *rsa) + { + char tempbuf[1024]; + HWCryptoHook_ErrMsgBuf rmsg; + HWCryptoHook_RSAKeyHandle *hptr; + int to_return = 0, ret; + + if(!hwcrhk_context) + { + ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED); + goto err; + } + + /* This provides support for nForce keys. Since that's opaque data + all we do is provide a handle to the proper key and let HWCryptoHook + take care of the rest. */ + if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx)) + != NULL) + { + HWCryptoHook_MPI m_a, m_r; + + if(!rsa->n) + { + ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP, + ENGINE_R_MISSING_KEY_COMPONENTS); + goto err; + } + + rmsg.buf = tempbuf; + rmsg.size = 1024; + + /* Prepare the params */ + bn_expand2(r, rsa->n->top); /* Check for error !! */ + BN2MPI(m_a, I); + MPI2BN(r, m_r); + + /* Perform the operation */ + ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg); + + /* Convert the response */ + r->top = m_r.size / sizeof(BN_ULONG); + bn_fix_top(r); + + if (ret < 0) + { + /* FIXME: When this error is returned, HWCryptoHook is + telling us that falling back to software computation + might be a good thing. */ + if(ret == HWCRYPTOHOOK_ERROR_FALLBACK) + { + ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK); + } + else + { + ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED); + } + ERR_add_error_data(1,rmsg.buf); + goto err; + } + } + else + { + HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r; + + if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) + { + ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP, + ENGINE_R_MISSING_KEY_COMPONENTS); + goto err; + } + + rmsg.buf = tempbuf; + rmsg.size = 1024; + + /* Prepare the params */ + bn_expand2(r, rsa->n->top); /* Check for error !! */ + BN2MPI(m_a, I); + BN2MPI(m_p, rsa->p); + BN2MPI(m_q, rsa->q); + BN2MPI(m_dmp1, rsa->dmp1); + BN2MPI(m_dmq1, rsa->dmq1); + BN2MPI(m_iqmp, rsa->iqmp); + MPI2BN(r, m_r); + + /* Perform the operation */ + ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q, + m_dmp1, m_dmq1, m_iqmp, &m_r, NULL); + + /* Convert the response */ + r->top = m_r.size / sizeof(BN_ULONG); + bn_fix_top(r); + + if (ret < 0) + { + /* FIXME: When this error is returned, HWCryptoHook is + telling us that falling back to software computation + might be a good thing. */ + if(ret == HWCRYPTOHOOK_ERROR_FALLBACK) + { + ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK); + } + else + { + ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED); + } + ERR_add_error_data(1,rmsg.buf); + goto err; + } + } + /* If we're here, we must be here with some semblance of success :-) */ + to_return = 1; +err: + return to_return; + } + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int hwcrhk_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return hwcrhk_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int hwcrhk_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return hwcrhk_mod_exp(r, a, p, m, ctx); + } + +/* Random bytes are good */ +static int hwcrhk_rand_bytes(unsigned char *buf, int num) + { + char tempbuf[1024]; + HWCryptoHook_ErrMsgBuf rmsg; + int to_return = 0; /* assume failure */ + int ret; + + rmsg.buf = tempbuf; + rmsg.size = 1024; + + if(!hwcrhk_context) + { + ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED); + goto err; + } + + ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg); + if (ret < 0) + { + /* FIXME: When this error is returned, HWCryptoHook is + telling us that falling back to software computation + might be a good thing. */ + if(ret == HWCRYPTOHOOK_ERROR_FALLBACK) + { + ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK); + } + else + { + ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED); + } + ERR_add_error_data(1,rmsg.buf); + goto err; + } + to_return = 1; + err: + return to_return; + } + +static int hwcrhk_rand_status(void) + { + return 1; + } + +/* This cleans up an RSA KM key, called when ex_data is freed */ + +static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, + int ind,long argl, void *argp) +{ + char tempbuf[1024]; + HWCryptoHook_ErrMsgBuf rmsg; + HWCryptoHook_RSAKeyHandle *hptr; + int ret; + + rmsg.buf = tempbuf; + rmsg.size = 1024; + + hptr = (HWCryptoHook_RSAKeyHandle *) item; + if(!hptr) return; + ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL); + OPENSSL_free(hptr); +} + +/* Mutex calls: since the HWCryptoHook model closely follows the POSIX model + * these just wrap the POSIX functions and add some logging. + */ + +static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt, + HWCryptoHook_CallerContext *cactx) + { + mt->lockid = CRYPTO_get_new_dynlockid(); + if (mt->lockid == 0) + return 0; + return 1; + } + +static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt) + { + CRYPTO_w_lock(mt->lockid); + return 1; + } + +void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt) + { + CRYPTO_w_unlock(mt->lockid); + } + +static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt) + { + CRYPTO_destroy_dynlockid(mt->lockid); + } + +static int hwcrhk_get_pass(const char *prompt_info, + int *len_io, char *buf, + HWCryptoHook_PassphraseContext *ppctx, + HWCryptoHook_CallerContext *cactx) + { + int l = 0; + char prompt[1024]; + + if (password_callback == NULL) + { + ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK); + return -1; + } + if (prompt_info) + { + strncpy(prompt, "Card: \"", sizeof(prompt)); + l += 5; + strncpy(prompt + l, prompt_info, sizeof(prompt) - l); + l += strlen(prompt_info); + if (l + 2 < sizeof(prompt)) + { + strncpy(prompt + l, "\"\n", sizeof(prompt) - l); + l += 2; + } + } + if (l < sizeof(prompt) - 1) + { + strncpy(prompt, "Enter Passphrase <enter to cancel>:", + sizeof(prompt) - l); + l += 35; + } + prompt[l] = '\0'; + + /* I know, passing on the prompt instead of the user data *is* + a bad thing. However, that's all we have right now. + -- Richard Levitte */ + *len_io = password_callback(buf, *len_io, 0, prompt); + if(!*len_io) + return -1; + return 0; + } + +static void hwcrhk_log_message(void *logstr, const char *message) + { + BIO *lstream = NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_BIO); + if (logstr) + lstream=*(BIO **)logstr; + if (lstream) + { + BIO_write(lstream, message, strlen(message)); + } + CRYPTO_w_unlock(CRYPTO_LOCK_BIO); + } + +#endif /* !NO_HW_NCIPHER */ +#endif /* !NO_HW */ diff --git a/crypto/engine/hw_nuron.c b/crypto/engine/hw_nuron.c new file mode 100644 index 0000000000..d8a3e3f1fa --- /dev/null +++ b/crypto/engine/hw_nuron.c @@ -0,0 +1,286 @@ +/* crypto/engine/hw_nuron.c */ +/* Written by Ben Laurie for the OpenSSL Project, leaning heavily on Geoff + * Thorpe's Atalla implementation. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <stdio.h> +#include <openssl/crypto.h> +#include "cryptlib.h" +#include <openssl/dso.h> +#include "engine_int.h" +#include <openssl/engine.h> +#include <dlfcn.h> + + +#ifndef NO_HW +#ifndef NO_HW_NURON + +typedef int tfnModExp(BIGNUM *r,BIGNUM *a,const BIGNUM *p,const BIGNUM *m); +static tfnModExp *pfnModExp = NULL; + +static DSO *pvDSOHandle = NULL; + +static int nuron_init() + { + if(pvDSOHandle != NULL) + { + ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_ALREADY_LOADED); + return 0; + } + + pvDSOHandle=DSO_load(NULL,"nuronssl",NULL, + DSO_FLAG_NAME_TRANSLATION_EXT_ONLY); + if(!pvDSOHandle) + { + ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_DSO_NOT_FOUND); + return 0; + } + + pfnModExp=(tfnModExp *)DSO_bind_func(pvDSOHandle,"nuron_mod_exp"); + if(!pfnModExp) + { + ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_DSO_FUNCTION_NOT_FOUND); + return 0; + } + + return 1; + } + +static int nuron_finish() + { + if(pvDSOHandle == NULL) + { + ENGINEerr(ENGINE_F_NURON_FINISH,ENGINE_R_NOT_LOADED); + return 0; + } + if(!DSO_free(pvDSOHandle)) + { + ENGINEerr(ENGINE_F_NURON_FINISH,ENGINE_R_DSO_FAILURE); + return 0; + } + pvDSOHandle=NULL; + pfnModExp=NULL; + return 1; + } + +static int nuron_mod_exp(BIGNUM *r,BIGNUM *a,const BIGNUM *p, + const BIGNUM *m,BN_CTX *ctx) + { + if(!pvDSOHandle) + { + ENGINEerr(ENGINE_F_NURON_MOD_EXP,ENGINE_R_NOT_LOADED); + return 0; + } + return pfnModExp(r,a,p,m); + } + +static int nuron_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) + { + return nuron_mod_exp(r0,I,rsa->d,rsa->n,NULL); + } + +/* This code was liberated and adapted from the commented-out code in + * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration + * (it doesn't have a CRT form for RSA), this function means that an + * Atalla system running with a DSA server certificate can handshake + * around 5 or 6 times faster/more than an equivalent system running with + * RSA. Just check out the "signs" statistics from the RSA and DSA parts + * of "openssl speed -engine atalla dsa1024 rsa1024". */ +static int nuron_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, + BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont) + { + BIGNUM t; + int to_return = 0; + + BN_init(&t); + /* let rr = a1 ^ p1 mod m */ + if (!nuron_mod_exp(rr,a1,p1,m,ctx)) + goto end; + /* let t = a2 ^ p2 mod m */ + if (!nuron_mod_exp(&t,a2,p2,m,ctx)) + goto end; + /* let rr = rr * t mod m */ + if (!BN_mod_mul(rr,rr,&t,m,ctx)) + goto end; + to_return = 1; +end: + BN_free(&t); + return to_return; + } + + +static int nuron_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + return nuron_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int nuron_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return nuron_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int nuron_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return nuron_mod_exp(r, a, p, m, ctx); + } + +static RSA_METHOD nuron_rsa = + { + "Nuron RSA method", + NULL, + NULL, + NULL, + NULL, + nuron_rsa_mod_exp, + nuron_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; + +static DSA_METHOD nuron_dsa = + { + "Nuron DSA method", + NULL, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + NULL, /* dsa_do_verify */ + nuron_dsa_mod_exp, /* dsa_mod_exp */ + nuron_mod_exp_dsa, /* bn_mod_exp */ + NULL, /* init */ + NULL, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +static DH_METHOD nuron_dh = + { + "Nuron DH method", + NULL, + NULL, + nuron_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; + +static ENGINE engine_nuron = + { + "nuron", + "Nuron hardware engine support", + &nuron_rsa, + &nuron_dsa, + &nuron_dh, + NULL, + nuron_mod_exp, + NULL, + nuron_init, + nuron_finish, + NULL, /* no ctrl() */ + NULL, /* no load_privkey() */ + NULL, /* no load_pubkey() */ + 0, /* no flags */ + 0, 0, /* no references */ + NULL, NULL /* unlinked */ + }; + +/* As this is only ever called once, there's no need for locking + * (indeed - the lock will already be held by our caller!!!) */ +ENGINE *ENGINE_nuron() + { + RSA_METHOD *meth1; + DSA_METHOD *meth2; + DH_METHOD *meth3; + + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the nuron-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1=RSA_PKCS1_SSLeay(); + nuron_rsa.rsa_pub_enc=meth1->rsa_pub_enc; + nuron_rsa.rsa_pub_dec=meth1->rsa_pub_dec; + nuron_rsa.rsa_priv_enc=meth1->rsa_priv_enc; + nuron_rsa.rsa_priv_dec=meth1->rsa_priv_dec; + + /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish + * bits. */ + meth2=DSA_OpenSSL(); + nuron_dsa.dsa_do_sign=meth2->dsa_do_sign; + nuron_dsa.dsa_sign_setup=meth2->dsa_sign_setup; + nuron_dsa.dsa_do_verify=meth2->dsa_do_verify; + + /* Much the same for Diffie-Hellman */ + meth3=DH_OpenSSL(); + nuron_dh.generate_key=meth3->generate_key; + nuron_dh.compute_key=meth3->compute_key; + return &engine_nuron; + } + +#endif /* !NO_HW_NURON */ +#endif /* !NO_HW */ diff --git a/crypto/engine/vendor_defns/atalla.h b/crypto/engine/vendor_defns/atalla.h new file mode 100644 index 0000000000..8111649c54 --- /dev/null +++ b/crypto/engine/vendor_defns/atalla.h @@ -0,0 +1,61 @@ +/* This header declares the necessary definitions for using the exponentiation + * acceleration capabilities of Atalla cards. The only cryptographic operation + * is performed by "ASI_RSAPrivateKeyOpFn" and this takes a structure that + * defines an "RSA private key". However, it is really only performing a + * regular mod_exp using the supplied modulus and exponent - no CRT form is + * being used. Hence, it is a generic mod_exp function in disguise, and we use + * it as such. + * + * Thanks to the people at Atalla for letting me know these definitions are + * fine and that they can be reproduced here. + * + * Geoff. + */ + +typedef struct ItemStr + { + unsigned char *data; + int len; + } Item; + +typedef struct RSAPrivateKeyStr + { + void *reserved; + Item version; + Item modulus; + Item publicExponent; + Item privateExponent; + Item prime[2]; + Item exponent[2]; + Item coefficient; + } RSAPrivateKey; + +/* Predeclare the function pointer types that we dynamically load from the DSO. + * These use the same names and form that Ben's original support code had (in + * crypto/bn/bn_exp.c) unless of course I've inadvertently changed the style + * somewhere along the way! + */ + +typedef int tfnASI_GetPerformanceStatistics(int reset_flag, + unsigned int *ret_buf); + +typedef int tfnASI_GetHardwareConfig(long card_num, unsigned int *ret_buf); + +typedef int tfnASI_RSAPrivateKeyOpFn(RSAPrivateKey * rsaKey, + unsigned char *output, + unsigned char *input, + unsigned int modulus_len); + +/* These are the static string constants for the DSO file name and the function + * symbol names to bind to. Regrettably, the DSO name on *nix appears to be + * "atasi.so" rather than something more consistent like "libatasi.so". At the + * time of writing, I'm not sure what the file name on win32 is but clearly + * native name translation is not possible (eg libatasi.so on *nix, and + * 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 *ATALLA_F1 = "ASI_GetHardwareConfig"; +static const char *ATALLA_F2 = "ASI_RSAPrivateKeyOpFn"; +static const char *ATALLA_F3 = "ASI_GetPerformanceStatistics"; + diff --git a/crypto/engine/vendor_defns/cswift.h b/crypto/engine/vendor_defns/cswift.h new file mode 100644 index 0000000000..0af14a1a92 --- /dev/null +++ b/crypto/engine/vendor_defns/cswift.h @@ -0,0 +1,213 @@ +/* Attribution notice: Rainbow have generously allowed me to reproduce + * the necessary definitions here from their API. This means the support + * can build independently of whether application builders have the + * API or hardware. This will allow developers to easily produce software + * that has latent hardware support for any users that have accelertors + * installed, without the developers themselves needing anything extra. + * + * I have only clipped the parts from the CryptoSwift header files that + * are (or seem) relevant to the CryptoSwift support code. This is + * simply to keep the file sizes reasonable. + * [Geoff] + */ + + +/* NB: These type widths do *not* seem right in general, in particular + * they're not terribly friendly to 64-bit architectures (unsigned long) + * will be 64-bit on IA-64 for a start. I'm leaving these alone as they + * agree with Rainbow's API and this will only be called into question + * on platforms with Rainbow support anyway! ;-) */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef long SW_STATUS; /* status */ +typedef unsigned char SW_BYTE; /* 8 bit byte */ +typedef unsigned short SW_U16; /* 16 bit number */ +#if defined(_IRIX) +#include <sgidefs.h> +typedef __uint32_t SW_U32; +#else +typedef unsigned long SW_U32; /* 32 bit integer */ +#endif + +#if defined(WIN32) + typedef struct _SW_U64 { + SW_U32 low32; + SW_U32 high32; + } SW_U64; /* 64 bit integer */ +#elif defined(MAC) + typedef longlong SW_U64 +#else /* Unix variants */ + typedef struct _SW_U64 { + SW_U32 low32; + SW_U32 high32; + } SW_U64; /* 64 bit integer */ +#endif + +/* status codes */ +#define SW_OK (0L) +#define SW_ERR_BASE (-10000L) +#define SW_ERR_NO_CARD (SW_ERR_BASE-1) /* The Card is not present */ +#define SW_ERR_CARD_NOT_READY (SW_ERR_BASE-2) /* The card has not powered */ + /* up yet */ +#define SW_ERR_TIME_OUT (SW_ERR_BASE-3) /* Execution of a command */ + /* time out */ +#define SW_ERR_NO_EXECUTE (SW_ERR_BASE-4) /* The Card failed to */ + /* execute the command */ +#define SW_ERR_INPUT_NULL_PTR (SW_ERR_BASE-5) /* a required pointer is */ + /* NULL */ +#define SW_ERR_INPUT_SIZE (SW_ERR_BASE-6) /* size is invalid, too */ + /* small, too large. */ +#define SW_ERR_INVALID_HANDLE (SW_ERR_BASE-7) /* Invalid SW_ACC_CONTEXT */ + /* handle */ +#define SW_ERR_PENDING (SW_ERR_BASE-8) /* A request is already out- */ + /* standing at this */ + /* context handle */ +#define SW_ERR_AVAILABLE (SW_ERR_BASE-9) /* A result is available. */ +#define SW_ERR_NO_PENDING (SW_ERR_BASE-10)/* No request is pending. */ +#define SW_ERR_NO_MEMORY (SW_ERR_BASE-11)/* Not enough memory */ +#define SW_ERR_BAD_ALGORITHM (SW_ERR_BASE-12)/* Invalid algorithm type */ + /* in SW_PARAM structure */ +#define SW_ERR_MISSING_KEY (SW_ERR_BASE-13)/* No key is associated with */ + /* context. */ + /* swAttachKeyParam() is */ + /* not called. */ +#define SW_ERR_KEY_CMD_MISMATCH \ + (SW_ERR_BASE-14)/* Cannot perform requested */ + /* SW_COMMAND_CODE since */ + /* key attached via */ + /* swAttachKeyParam() */ + /* cannot be used for this*/ + /* SW_COMMAND_CODE. */ +#define SW_ERR_NOT_IMPLEMENTED \ + (SW_ERR_BASE-15)/* Not implemented */ +#define SW_ERR_BAD_COMMAND (SW_ERR_BASE-16)/* Bad command code */ +#define SW_ERR_BAD_ITEM_SIZE (SW_ERR_BASE-17)/* too small or too large in */ + /* the "initems" or */ + /* "outitems". */ +#define SW_ERR_BAD_ACCNUM (SW_ERR_BASE-18)/* Bad accelerator number */ +#define SW_ERR_SELFTEST_FAIL (SW_ERR_BASE-19)/* At least one of the self */ + /* test fail, look at the */ + /* selfTestBitmap in */ + /* SW_ACCELERATOR_INFO for*/ + /* details. */ +#define SW_ERR_MISALIGN (SW_ERR_BASE-20)/* Certain alogrithms require*/ + /* key materials aligned */ + /* in certain order, e.g. */ + /* 128 bit for CRT */ +#define SW_ERR_OUTPUT_NULL_PTR \ + (SW_ERR_BASE-21)/* a required pointer is */ + /* NULL */ +#define SW_ERR_OUTPUT_SIZE \ + (SW_ERR_BASE-22)/* size is invalid, too */ + /* small, too large. */ +#define SW_ERR_FIRMWARE_CHECKSUM \ + (SW_ERR_BASE-23)/* firmware checksum mismatch*/ + /* download failed. */ +#define SW_ERR_UNKNOWN_FIRMWARE \ + (SW_ERR_BASE-24)/* unknown firmware error */ +#define SW_ERR_INTERRUPT (SW_ERR_BASE-25)/* request is abort when */ + /* it's waiting to be */ + /* completed. */ +#define SW_ERR_NVWRITE_FAIL (SW_ERR_BASE-26)/* error in writing to Non- */ + /* volatile memory */ +#define SW_ERR_NVWRITE_RANGE (SW_ERR_BASE-27)/* out of range error in */ + /* writing to NV memory */ +#define SW_ERR_RNG_ERROR (SW_ERR_BASE-28)/* Random Number Generation */ + /* failure */ +#define SW_ERR_DSS_FAILURE (SW_ERR_BASE-29)/* DSS Sign or Verify failure*/ +#define SW_ERR_MODEXP_FAILURE (SW_ERR_BASE-30)/* Failure in various math */ + /* calculations */ +#define SW_ERR_ONBOARD_MEMORY (SW_ERR_BASE-31)/* Error in accessing on - */ + /* board memory */ +#define SW_ERR_FIRMWARE_VERSION \ + (SW_ERR_BASE-32)/* Wrong version in firmware */ + /* update */ +#define SW_ERR_ZERO_WORKING_ACCELERATOR \ + (SW_ERR_BASE-44)/* All accelerators are bad */ + + + /* algorithm type */ +#define SW_ALG_CRT 1 +#define SW_ALG_EXP 2 +#define SW_ALG_DSA 3 +#define SW_ALG_NVDATA 4 + + /* command code */ +#define SW_CMD_MODEXP_CRT 1 /* perform Modular Exponentiation using */ + /* Chinese Remainder Theorem (CRT) */ +#define SW_CMD_MODEXP 2 /* perform Modular Exponentiation */ +#define SW_CMD_DSS_SIGN 3 /* perform DSS sign */ +#define SW_CMD_DSS_VERIFY 4 /* perform DSS verify */ +#define SW_CMD_RAND 5 /* perform random number generation */ +#define SW_CMD_NVREAD 6 /* perform read to nonvolatile RAM */ +#define SW_CMD_NVWRITE 7 /* perform write to nonvolatile RAM */ + +typedef SW_U32 SW_ALGTYPE; /* alogrithm type */ +typedef SW_U32 SW_STATE; /* state */ +typedef SW_U32 SW_COMMAND_CODE; /* command code */ +typedef SW_U32 SW_COMMAND_BITMAP[4]; /* bitmap */ + +typedef struct _SW_LARGENUMBER { + SW_U32 nbytes; /* number of bytes in the buffer "value" */ + SW_BYTE* value; /* the large integer as a string of */ + /* bytes in network (big endian) order */ +} SW_LARGENUMBER; + +typedef struct _SW_CRT { + SW_LARGENUMBER p; /* prime number p */ + SW_LARGENUMBER q; /* prime number q */ + SW_LARGENUMBER dmp1; /* exponent1 */ + SW_LARGENUMBER dmq1; /* exponent2 */ + SW_LARGENUMBER iqmp; /* CRT coefficient */ +} SW_CRT; + +typedef struct _SW_EXP { + SW_LARGENUMBER modulus; /* modulus */ + SW_LARGENUMBER exponent;/* exponent */ +} SW_EXP; + +typedef struct _SW_DSA { + SW_LARGENUMBER p; /* */ + SW_LARGENUMBER q; /* */ + SW_LARGENUMBER g; /* */ + SW_LARGENUMBER key; /* private/public key */ +} SW_DSA; + +typedef struct _SW_NVDATA { + SW_U32 accnum; /* accelerator board number */ + SW_U32 offset; /* offset in byte */ +} SW_NVDATA; + +typedef struct _SW_PARAM { + SW_ALGTYPE type; /* type of the alogrithm */ + union { + SW_CRT crt; + SW_EXP exp; + SW_DSA dsa; + SW_NVDATA nvdata; + } up; +} SW_PARAM; + +typedef SW_U32 SW_CONTEXT_HANDLE; /* opaque context handle */ + + +/* Now the OpenSSL bits, these function types are the for the function + * pointers that will bound into the Rainbow shared libraries. */ +typedef SW_STATUS t_swAcquireAccContext(SW_CONTEXT_HANDLE *hac); +typedef SW_STATUS t_swAttachKeyParam(SW_CONTEXT_HANDLE hac, + SW_PARAM *key_params); +typedef SW_STATUS t_swSimpleRequest(SW_CONTEXT_HANDLE hac, + SW_COMMAND_CODE cmd, + SW_LARGENUMBER pin[], + SW_U32 pin_count, + SW_LARGENUMBER pout[], + SW_U32 pout_count); +typedef SW_STATUS t_swReleaseAccContext(SW_CONTEXT_HANDLE hac); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + diff --git a/crypto/engine/vendor_defns/hwcryptohook.h b/crypto/engine/vendor_defns/hwcryptohook.h new file mode 100644 index 0000000000..ed880515bc --- /dev/null +++ b/crypto/engine/vendor_defns/hwcryptohook.h @@ -0,0 +1,476 @@ +/* + * ModExp / RSA (with/without KM) plugin API + * + * The application will load a dynamic library which + * exports entrypoint(s) defined in this file. + * + * This set of entrypoints provides only a multithreaded, + * synchronous-within-each-thread, facility. + * + * + * This file is Copyright 1998-1999 nCipher Corporation Limited. + * + * This file is provided for your information and assistance. You are + * permitted to copy it verbatim, to use it to create compatible + * software, and for review and comment. However, you may not + * distribute changed versions or other derivative works. All other + * rights are reserved. + * + * IN NO EVENT SHALL NCIPHER CORPORATION LIMITED (`NCIPHER') AND/OR + * ANY OTHER AUTHORS OR DISTRIBUTORS OF THIS FILE BE LIABLE for any + * damages arising directly or indirectly from this file, its use or + * this licence. Without prejudice to the generality of the + * foregoing: all liability shall be excluded for direct, indirect, + * special, incidental, consequential or other damages or any loss of + * profits, business, revenue goodwill or anticipated savings; + * liability shall be excluded even if nCipher or anyone else has been + * advised of the possibility of damage. In any event, if the + * exclusion of liability is not effective, the liability of nCipher + * or any author or distributor shall be limited to the lesser of the + * price paid and 1,000 pounds sterling. This licence only fails to + * exclude or limit liability for death or personal injury arising out + * of negligence, and only to the extent that such an exclusion or + * limitation is not effective. + * + * NCIPHER AND THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ALL + * AND ANY WARRANTIES (WHETHER EXPRESS OR IMPLIED), including, but not + * limited to, any implied warranties of merchantability, fitness for + * a particular purpose, satisfactory quality, and/or non-infringement + * of any third party rights. + * + * US Government use: This software and documentation is Commercial + * Computer Software and Computer Software Documentation, as defined in + * sub-paragraphs (a)(1) and (a)(5) of DFAR 252.227-7014, "Rights in + * Noncommercial Computer Software and Noncommercial Computer Software + * Documentation." Use, duplication or disclosure by the Government is + * subject to the terms and conditions specified here. + * + * By using or distributing this file you will be accepting these + * terms and conditions, including the limitation of liability and + * lack of warranty. If you do not wish to accept these terms and + * conditions, DO NOT USE THE FILE. + * + * + * The actual dynamically loadable plugin, and the library files for + * static linking, which are also provided in this distribution, are + * not covered by the licence described above. You should have + * received a separate licence with terms and conditions for these + * library files; if you received the library files without a licence, + * please contact nCipher. + * + * + * $Id: hwcryptohook.h,v 1.2 2000/10/26 21:06:30 levitte Exp $ + */ + +#ifndef HWCRYPTOHOOK_H +#define HWCRYPTOHOOK_H + +#include <sys/types.h> +#include <stdio.h> + +#ifndef HWCRYPTOHOOK_DECLARE_APPTYPES +#define HWCRYPTOHOOK_DECLARE_APPTYPES 1 +#endif + +#define HWCRYPTOHOOK_ERROR_FAILED -1 +#define HWCRYPTOHOOK_ERROR_FALLBACK -2 +#define HWCRYPTOHOOK_ERROR_MPISIZE -3 + +#if HWCRYPTOHOOK_DECLARE_APPTYPES + +/* These structs are defined by the application and opaque to the + * crypto plugin. The application may define these as it sees fit. + * Default declarations are provided here, but the application may + * #define HWCRYPTOHOOK_DECLARE_APPTYPES 0 + * to prevent these declarations, and instead provide its own + * declarations of these types. (Pointers to them must still be + * ordinary pointers to structs or unions, or the resulting combined + * program will have a type inconsistency.) + */ +typedef struct HWCryptoHook_MutexValue HWCryptoHook_Mutex; +typedef struct HWCryptoHook_CondVarValue HWCryptoHook_CondVar; +typedef struct HWCryptoHook_PassphraseContextValue HWCryptoHook_PassphraseContext; +typedef struct HWCryptoHook_CallerContextValue HWCryptoHook_CallerContext; + +#endif /* HWCRYPTOHOOK_DECLARE_APPTYPES */ + +/* These next two structs are opaque to the application. The crypto + * plugin will return pointers to them; the caller simply manipulates + * the pointers. + */ +typedef struct HWCryptoHook_Context *HWCryptoHook_ContextHandle; +typedef struct HWCryptoHook_RSAKey *HWCryptoHook_RSAKeyHandle; + +typedef struct { + char *buf; + size_t size; +} HWCryptoHook_ErrMsgBuf; +/* Used for error reporting. When a HWCryptoHook function fails it + * will return a sentinel value (0 for pointer-valued functions, or a + * negative number, usually HWCRYPTOHOOK_ERROR_FAILED, for + * integer-valued ones). It will, if an ErrMsgBuf is passed, also put + * an error message there. + * + * size is the size of the buffer. When the buffer is filled, it will + * always be null-terminated. If you pass 0 buf buf you must pass 0 + * for size, and nothing will be recorded (just as if you passed 0 for + * the struct pointer). Size will not be modified when an error is + * recorded. The buffer is always null-terminated even if there is an + * overrun. + * + * The contents of the buffer are not defined if there is no error. + */ + +typedef struct HWCryptoHook_MPIStruct { + unsigned char *buf; + size_t size; +} HWCryptoHook_MPI; +/* When one of these is returned, a pointer is passed to the function. + * At call, size is the space available. Afterwards it is updated. + * buf (the pointer) is not updated. size is in bytes and may be + * zero, but must be a multiple of the limb size. Zero limbs at the + * MS end are not permitted. + */ + +#define HWCryptoHook_InitFlags_FallbackModExp 0x0002UL +#define HWCryptoHook_InitFlags_FallbackRSAImmed 0x0004UL +/* Enable requesting fallback to software in case of problems with the + * hardware support. This indicates to the crypto provider that the + * application is prepared to fall back to software operation if the + * ModExp* or RSAImmed* functions return HWCRYPTOHOOK_ERROR_FALLBACK. + * Without this flag those calls will never return + * HWCRYPTOHOOK_ERROR_FALLBACK. The flag will also cause the crypto + * provider to avoid repeatedly attempting to contact dead hardware + * within a short interval, if appropriate. + */ + +#define HWCryptoHook_InitFlags_SimpleForkCheck 0x0010UL +/* Without _SimpleForkCheck the library is allowed to assume that the + * application will not fork and call the library in the child(ren). + * + * When it is specified, this is allowed. However, after a fork + * neither parent nor child may unload any loaded keys or call + * _Finish. Instead, they should call exit (or die with a signal) + * without calling _Finish. After all the children have died the + * parent may unload keys or call _Finish. + * + * This flag only has any effect on UN*X platforms. + */ + +typedef struct { + unsigned long flags; + void *logstream; /* usually a FILE*. See below. */ + + size_t limbsize; /* bignum format - size of radix type, must be power of 2 */ + int mslimbfirst; /* 0 or 1 */ + int msbytefirst; /* 0 or 1; -1 = native */ + + /* All the callback functions should return 0 on success, or a + * nonzero integer (whose value will be visible in the error message + * put in the buffer passed to the call). + * + * If a callback is not available pass a null function pointer. + * + * The callbacks may not call down again into the crypto plugin. + */ + + /* For thread-safety. Set everything to 0 if you promise only to be + * singlethreaded. maxsimultaneous is the number of calls to + * ModExp[Crt]/RSAImmed{Priv,Pub}/RSA. If you don't know what to + * put there then say 0 and the hook library will use a default. + * + * maxmutexes is a small limit on the number of simultaneous mutexes + * which will be requested by the library. If there is no small + * limit, set it to 0. If the crypto plugin cannot create the + * advertised number of mutexes the calls to its functions may fail. + * If a low number of mutexes is advertised the plugin will try to + * do the best it can. Making larger numbers of mutexes available + * may improve performance and parallelism by reducing contention + * over critical sections. Unavailability of any mutexes, implying + * single-threaded operation, should be indicated by the setting + * mutex_init et al to 0. + */ + int maxmutexes; + int maxsimultaneous; + size_t mutexsize; + int (*mutex_init)(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext *cactx); + int (*mutex_acquire)(HWCryptoHook_Mutex*); + void (*mutex_release)(HWCryptoHook_Mutex*); + void (*mutex_destroy)(HWCryptoHook_Mutex*); + + /* For greater efficiency, can use condition vars internally for + * synchronisation. In this case maxsimultaneous is ignored, but + * the other mutex stuff must be available. In singlethreaded + * programs, set everything to 0. + */ + size_t condvarsize; + int (*condvar_init)(HWCryptoHook_CondVar*, HWCryptoHook_CallerContext *cactx); + int (*condvar_wait)(HWCryptoHook_CondVar*, HWCryptoHook_Mutex*); + void (*condvar_signal)(HWCryptoHook_CondVar*); + void (*condvar_broadcast)(HWCryptoHook_CondVar*); + void (*condvar_destroy)(HWCryptoHook_CondVar*); + + /* The semantics of acquiring and releasing mutexes and broadcasting + * and waiting on condition variables are expected to be those from + * POSIX threads (pthreads). The mutexes may be (in pthread-speak) + * fast mutexes, recursive mutexes, or nonrecursive ones. + * + * The _release/_signal/_broadcast and _destroy functions must + * always succeed when given a valid argument; if they are given an + * invalid argument then the program (crypto plugin + application) + * has an internal error, and they should abort the program. + */ + + int (*getpassphrase)(const char *prompt_info, + int *len_io, char *buf, + HWCryptoHook_PassphraseContext *ppctx, + HWCryptoHook_CallerContext *cactx); + /* Passphrases and the prompt_info, if they contain high-bit-set + * characters, are UTF-8. The prompt_info may be a null pointer if + * no prompt information is available (it should not be an empty + * string). It will not contain text like `enter passphrase'; + * instead it might say something like `Operator Card for John + * Smith' or `SmartCard in nFast Module #1, Slot #1'. + * + * buf points to a buffer in which to return the passphrase; on + * entry *len_io is the length of the buffer. It should be updated + * by the callback. The returned passphrase should not be + * null-terminated by the callback. + */ + + int (*getphystoken)(const char *prompt_info, + const char *wrong_info, + HWCryptoHook_PassphraseContext *ppctx, + HWCryptoHook_CallerContext *cactx); + /* Requests that the human user physically insert a different + * smartcard, DataKey, etc. The plugin should check whether the + * currently inserted token(s) are appropriate, and if they are it + * should not make this call. + * + * prompt_info is as before. wrong_info is a description of the + * currently inserted token(s) so that the user is told what + * something is. wrong_info, like prompt_info, may be null, but + * should not be an empty string. Its contents should be + * syntactically similar to that of prompt_info. + */ + + /* Note that a single LoadKey operation might cause several calls to + * getpassphrase and/or requestphystoken. If requestphystoken is + * not provided (ie, a null pointer is passed) then the plugin may + * not support loading keys for which authorisation by several cards + * is required. If getpassphrase is not provided then cards with + * passphrases may not be supported. + * + * getpassphrase and getphystoken do not need to check that the + * passphrase has been entered correctly or the correct token + * inserted; the crypto plugin will do that. If this is not the + * case then the crypto plugin is responsible for calling these + * routines again as appropriate until the correct token(s) and + * passphrase(s) are supplied as required, or until any retry limits + * implemented by the crypto plugin are reached. + * + * In either case, the application must allow the user to say `no' + * or `cancel' to indicate that they do not know the passphrase or + * have the appropriate token; this should cause the callback to + * return nonzero indicating error. + */ + + void (*logmessage)(void *logstream, const char *message); + /* A log message will be generated at least every time something goes + * wrong and an ErrMsgBuf is filled in (or would be if one was + * provided). Other diagnostic information may be written there too, + * including more detailed reasons for errors which are reported in an + * ErrMsgBuf. + * + * When a log message is generated, this callback is called. It + * should write a message to the relevant logging arrangements. + * + * The message string passed will be null-terminated and may be of arbitrary + * length. It will not be prefixed by the time and date, nor by the + * name of the library that is generating it - if this is required, + * the logmessage callback must do it. The message will not have a + * trailing newline (though it may contain internal newlines). + * + * If a null pointer is passed for logmessage a default function is + * used. The default function treats logstream as a FILE* which has + * been converted to a void*. If logstream is 0 it does nothing. + * Otherwise it prepends the date and time and library name and + * writes the message to logstream. Each line will be prefixed by a + * descriptive string containing the date, time and identity of the + * crypto plugin. Errors on the logstream are not reported + * anywhere, and the default function doesn't flush the stream, so + * the application must set the buffering how it wants it. + * + * The crypto plugin may also provide a facility to have copies of + * log messages sent elsewhere, and or for adjusting the verbosity + * of the log messages; any such facilities will be configured by + * external means. + */ + +} HWCryptoHook_InitInfo; + +typedef +HWCryptoHook_ContextHandle HWCryptoHook_Init_t(const HWCryptoHook_InitInfo *initinfo, + size_t initinfosize, + HWCryptoHook_ErrMsgBuf *errors, + HWCryptoHook_CallerContext *cactx); +extern HWCryptoHook_Init_t HWCryptoHook_Init; + +/* Caller should set initinfosize to the size of the HWCryptoHook struct, + * so it can be extended later. + * + * On success, a message for display or logging by the server, + * including the name and version number of the plugin, will be filled + * in into *errors; on failure *errors is used for error handling, as + * usual. + */ + +/* All these functions return 0 on success, HWCRYPTOHOOK_ERROR_FAILED + * on most failures. HWCRYPTOHOOK_ERROR_MPISIZE means at least one of + * the output MPI buffer(s) was too small; the sizes of all have been + * set to the desired size (and for those where the buffer was large + * enough, the value may have been copied in), and no error message + * has been recorded. + * + * You may pass 0 for the errors struct. In any case, unless you set + * _NoStderr at init time then messages may be reported to stderr. + */ + +/* The RSAImmed* functions (and key managed RSA) only work with + * modules which have an RSA patent licence - currently that means KM + * units; the ModExp* ones work with all modules, so you need a patent + * licence in the software in the US. + */ + +typedef +void HWCryptoHook_Finish_t(HWCryptoHook_ContextHandle hwctx); +extern HWCryptoHook_Finish_t HWCryptoHook_Finish; +/* You must not have any calls going or keys loaded when you call this. */ + +typedef +int HWCryptoHook_RandomBytes_t(HWCryptoHook_ContextHandle hwctx, + unsigned char *buf, size_t len, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_RandomBytes_t HWCryptoHook_RandomBytes; + +typedef +int HWCryptoHook_ModExp_t(HWCryptoHook_ContextHandle hwctx, + HWCryptoHook_MPI a, + HWCryptoHook_MPI p, + HWCryptoHook_MPI n, + HWCryptoHook_MPI *r, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_ModExp_t HWCryptoHook_ModExp; + +typedef +int HWCryptoHook_RSAImmedPub_t(HWCryptoHook_ContextHandle hwctx, + HWCryptoHook_MPI m, + HWCryptoHook_MPI e, + HWCryptoHook_MPI n, + HWCryptoHook_MPI *r, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_RSAImmedPub_t HWCryptoHook_RSAImmedPub; + +typedef +int HWCryptoHook_ModExpCRT_t(HWCryptoHook_ContextHandle hwctx, + HWCryptoHook_MPI a, + HWCryptoHook_MPI p, + HWCryptoHook_MPI q, + HWCryptoHook_MPI dmp1, + HWCryptoHook_MPI dmq1, + HWCryptoHook_MPI iqmp, + HWCryptoHook_MPI *r, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_ModExpCRT_t HWCryptoHook_ModExpCRT; + +typedef +int HWCryptoHook_RSAImmedPriv_t(HWCryptoHook_ContextHandle hwctx, + HWCryptoHook_MPI m, + HWCryptoHook_MPI p, + HWCryptoHook_MPI q, + HWCryptoHook_MPI dmp1, + HWCryptoHook_MPI dmq1, + HWCryptoHook_MPI iqmp, + HWCryptoHook_MPI *r, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_RSAImmedPriv_t HWCryptoHook_RSAImmedPriv; + +/* The RSAImmed* and ModExp* functions may return E_FAILED or + * E_FALLBACK for failure. + * + * E_FAILED means the failure is permanent and definite and there + * should be no attempt to fall back to software. (Eg, for some + * applications, which support only the acceleration-only + * functions, the `key material' may actually be an encoded key + * identifier, and doing the operation in software would give wrong + * answers.) + * + * E_FALLBACK means that doing the computation in software would seem + * reasonable. If an application pays attention to this and is + * able to fall back, it should also set the Fallback init flags. + */ + +typedef +int HWCryptoHook_RSALoadKey_t(HWCryptoHook_ContextHandle hwctx, + const char *key_ident, + HWCryptoHook_RSAKeyHandle *keyhandle_r, + const HWCryptoHook_ErrMsgBuf *errors, + HWCryptoHook_PassphraseContext *ppctx); +extern HWCryptoHook_RSALoadKey_t HWCryptoHook_RSALoadKey; +/* The key_ident is a null-terminated string configured by the + * user via the application's usual configuration mechanisms. + * It is provided to the user by the crypto provider's key management + * system. The user must be able to enter at least any string of between + * 1 and 1023 characters inclusive, consisting of printable 7-bit + * ASCII characters. The provider should avoid using + * any characters except alphanumerics and the punctuation + * characters _ - + . / @ ~ (the user is expected to be able + * to enter these without quoting). The string may be case-sensitive. + * The application may allow the user to enter other NULL-terminated strings, + * and the provider must cope (returning an error if the string is not + * valid). + * + * If the key does not exist, it is _not_ an error - in that case, + * keyhandle_r will be set to 0 instead of to a key handle. + */ + +typedef +int HWCryptoHook_RSAGetPublicKey_t(HWCryptoHook_RSAKeyHandle k, + HWCryptoHook_MPI *n, + HWCryptoHook_MPI *e, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_RSAGetPublicKey_t HWCryptoHook_RSAGetPublicKey; +/* The crypto plugin will not store certificates. + * + * Although this function for acquiring the public key value is + * provided, it is not the purpose of this API to deal fully with the + * handling of the public key. + * + * It is expected that the crypto supplier's key generation program + * will provide general facilities for producing X.509 + * self-certificates and certificate requests in PEM format. These + * will be given to the user so that they can configure them in the + * application, send them to CAs, or whatever. + * + * In case this kind of certificate handling is not appropriate, the + * crypto supplier's key generation program should be able to be + * configured not to generate such a self-certificate or certificate + * request. Then the application will need to do all of this, and + * will need to store and handle the public key and certificates + * itself. + */ + +typedef +int HWCryptoHook_RSAUnloadKey_t(HWCryptoHook_RSAKeyHandle k, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_RSAUnloadKey_t HWCryptoHook_RSAUnloadKey; +/* Might fail due to locking problems, or other serious internal problems. */ + +typedef +int HWCryptoHook_RSA_t(HWCryptoHook_MPI m, + HWCryptoHook_RSAKeyHandle k, + HWCryptoHook_MPI *r, + const HWCryptoHook_ErrMsgBuf *errors); +extern HWCryptoHook_RSA_t HWCryptoHook_RSA; + +#endif /*HWCRYPTOHOOK_H*/ diff --git a/crypto/err/Makefile.ssl b/crypto/err/Makefile.ssl index a31bc78914..00ee86f3c4 100644 --- a/crypto/err/Makefile.ssl +++ b/crypto/err/Makefile.ssl @@ -93,16 +93,17 @@ err_all.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h err_all.o: ../../include/openssl/des.h ../../include/openssl/dh.h err_all.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h err_all.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -err_all.o: ../../include/openssl/err.h ../../include/openssl/evp.h -err_all.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h -err_all.o: ../../include/openssl/md2.h ../../include/openssl/md4.h -err_all.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h -err_all.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -err_all.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -err_all.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs12.h -err_all.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h -err_all.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h -err_all.o: ../../include/openssl/rc5.h ../../include/openssl/rijndael-alg-fst.h +err_all.o: ../../include/openssl/engine.h ../../include/openssl/err.h +err_all.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +err_all.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +err_all.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +err_all.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +err_all.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +err_all.o: ../../include/openssl/opensslv.h ../../include/openssl/pem2.h +err_all.o: ../../include/openssl/pkcs12.h ../../include/openssl/pkcs7.h +err_all.o: ../../include/openssl/rand.h ../../include/openssl/rc2.h +err_all.o: ../../include/openssl/rc4.h ../../include/openssl/rc5.h +err_all.o: ../../include/openssl/rijndael-alg-fst.h err_all.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h err_all.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h err_all.o: ../../include/openssl/sha.h ../../include/openssl/stack.h diff --git a/crypto/err/err.c b/crypto/err/err.c index bfecb86c75..99272e437c 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -157,6 +157,7 @@ static ERR_STRING_DATA ERR_str_libraries[]= {ERR_PACK(ERR_LIB_PKCS12,0,0) ,"PKCS12 routines"}, {ERR_PACK(ERR_LIB_RAND,0,0) ,"random number generator"}, {ERR_PACK(ERR_LIB_DSO,0,0) ,"DSO support routines"}, +{ERR_PACK(ERR_LIB_ENGINE,0,0) ,"engine routines"}, {0,NULL}, }; @@ -208,6 +209,7 @@ static ERR_STRING_DATA ERR_str_reasons[]= {ERR_R_ASN1_LENGTH_MISMATCH ,"asn1 length mismatch"}, {ERR_R_MISSING_ASN1_EOS ,"missing asn1 eos"}, {ERR_R_DSO_LIB ,"DSO lib"}, +{ERR_R_ENGINE_LIB ,"ENGINE lib"}, {0,NULL}, }; diff --git a/crypto/err/err.h b/crypto/err/err.h index 2c3d39c68c..7388a4a937 100644 --- a/crypto/err/err.h +++ b/crypto/err/err.h @@ -132,6 +132,7 @@ typedef struct err_state_st #define ERR_LIB_PKCS12 35 #define ERR_LIB_RAND 36 #define ERR_LIB_DSO 37 +#define ERR_LIB_ENGINE 38 #define ERR_LIB_USER 128 @@ -161,6 +162,7 @@ typedef struct err_state_st #define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),ERR_file_name,__LINE__) #define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),ERR_file_name,__LINE__) #define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),ERR_file_name,__LINE__) +#define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),ERR_file_name,__LINE__) /* Borland C seems too stupid to be able to shift and do longs in * the pre-processor :-( */ @@ -210,6 +212,7 @@ typedef struct err_state_st #define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 #define ERR_R_PKCS12_LIB ERR_LIB_PKCS12 #define ERR_R_DSO_LIB ERR_LIB_DSO +#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE /* fatal error */ #define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index 638ed3fe71..b8315d8272 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -81,8 +81,9 @@ #include <openssl/conf.h> #include <openssl/pkcs12.h> #include <openssl/rand.h> -#include <openssl/err.h> #include <openssl/dso.h> +#include <openssl/engine.h> +#include <openssl/err.h> void ERR_load_crypto_strings(void) { @@ -120,5 +121,6 @@ void ERR_load_crypto_strings(void) ERR_load_PKCS12_strings(); ERR_load_RAND_strings(); ERR_load_DSO_strings(); + ERR_load_ENGINE_strings(); #endif } diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index 02deaa6fc9..861d680e07 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -23,6 +23,7 @@ L RSAREF rsaref/rsaref.h rsaref/rsar_err.c L SSL ssl/ssl.h ssl/ssl_err.c L COMP crypto/comp/comp.h crypto/comp/comp_err.c L RAND crypto/rand/rand.h crypto/rand/rand_err.c +L ENGINE crypto/engine/engine.h crypto/engine/engine_err.c F RSAREF_F_RSA_BN2BIN diff --git a/crypto/install.com b/crypto/install.com index 8c283c4ceb..4780118ab9 100644 --- a/crypto/install.com +++ b/crypto/install.com @@ -34,7 +34,7 @@ $ IF F$PARSE("WRK_SSLINCLUDE:") .EQS. "" THEN - $ $ SDIRS := ,MD2,MD4,MD5,SHA,MDC2,HMAC,RIPEMD,- DES,RC2,RC4,RC5,IDEA,BF,CAST,- - BN,RSA,DSA,DH,DSO,- + BN,RSA,DSA,DH,DSO,ENGINE,RIJNDAEL,- BUFFER,BIO,STACK,LHASH,RAND,ERR,OBJECTS,- EVP,ASN1,PEM,X509,X509V3,CONF,TXT_DB,PKCS7,PKCS12,COMP $ EXHEADER_ := crypto.h,tmdiff.h,opensslv.h,opensslconf.h,ebcdic.h,symhacks.h @@ -57,6 +57,8 @@ $ EXHEADER_RSA := rsa.h $ EXHEADER_DSA := dsa.h $ EXHEADER_DH := dh.h $ EXHEADER_DSO := dso.h +$ EXHEADER_ENGINE := engine.h +$ EXHEADER_RIJNDAEL := rijndael-alg-fst.h,rijndael.h $ EXHEADER_BUFFER := buffer.h $ EXHEADER_BIO := bio.h $ EXHEADER_STACK := stack.h,safestack.h diff --git a/crypto/rand/Makefile.ssl b/crypto/rand/Makefile.ssl index e9a6876b5a..a005df2019 100644 --- a/crypto/rand/Makefile.ssl +++ b/crypto/rand/Makefile.ssl @@ -92,7 +92,24 @@ rand_err.o: ../../include/openssl/err.h ../../include/openssl/lhash.h rand_err.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h rand_err.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h rand_err.o: ../../include/openssl/symhacks.h -rand_lib.o: ../../include/openssl/rand.h +rand_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +rand_lib.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +rand_lib.o: ../../include/openssl/cast.h ../../include/openssl/crypto.h +rand_lib.o: ../../include/openssl/des.h ../../include/openssl/dh.h +rand_lib.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h +rand_lib.o: ../../include/openssl/engine.h ../../include/openssl/evp.h +rand_lib.o: ../../include/openssl/idea.h ../../include/openssl/md2.h +rand_lib.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +rand_lib.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +rand_lib.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +rand_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +rand_lib.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +rand_lib.o: ../../include/openssl/rc5.h +rand_lib.o: ../../include/openssl/rijndael-alg-fst.h +rand_lib.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +rand_lib.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +rand_lib.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +rand_lib.o: ../../include/openssl/symhacks.h rand_win.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h rand_win.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h rand_win.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h diff --git a/crypto/rand/rand.h b/crypto/rand/rand.h index 971880edaa..eb9c8c034d 100644 --- a/crypto/rand/rand.h +++ b/crypto/rand/rand.h @@ -77,7 +77,9 @@ typedef struct rand_meth_st extern int rand_predictable; #endif -void RAND_set_rand_method(RAND_METHOD *meth); +struct engine_st; + +int RAND_set_rand_method(struct engine_st *meth); RAND_METHOD *RAND_get_rand_method(void ); RAND_METHOD *RAND_SSLeay(void); void RAND_cleanup(void ); diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 7da74aab0e..57eff0f132 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -59,59 +59,78 @@ #include <stdio.h> #include <time.h> #include <openssl/rand.h> +#include <openssl/engine.h> -#ifdef NO_RAND -static RAND_METHOD *rand_meth=NULL; -#else -extern RAND_METHOD rand_ssleay_meth; -static RAND_METHOD *rand_meth= &rand_ssleay_meth; -#endif +static ENGINE *rand_engine=NULL; +#if 0 void RAND_set_rand_method(RAND_METHOD *meth) { rand_meth=meth; } +#else +int RAND_set_rand_method(ENGINE *engine) + { + ENGINE *mtmp; + mtmp = rand_engine; + if (!ENGINE_init(engine)) + return 0; + rand_engine = engine; + /* SHOULD ERROR CHECK THIS!!! */ + ENGINE_finish(mtmp); + return 1; + } +#endif RAND_METHOD *RAND_get_rand_method(void) { - return(rand_meth); + if (rand_engine == NULL + && (rand_engine = ENGINE_get_default_RAND()) == NULL) + return NULL; + return ENGINE_get_RAND(rand_engine); } void RAND_cleanup(void) { - if (rand_meth != NULL) - rand_meth->cleanup(); + RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->cleanup) + meth->cleanup(); } void RAND_seed(const void *buf, int num) { - if (rand_meth != NULL) - rand_meth->seed(buf,num); + RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->seed) + meth->seed(buf,num); } void RAND_add(const void *buf, int num, double entropy) { - if (rand_meth != NULL) - rand_meth->add(buf,num,entropy); + RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->add) + meth->add(buf,num,entropy); } int RAND_bytes(unsigned char *buf, int num) { - if (rand_meth != NULL) - return rand_meth->bytes(buf,num); + RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->bytes) + return meth->bytes(buf,num); return(-1); } int RAND_pseudo_bytes(unsigned char *buf, int num) { - if (rand_meth != NULL) - return rand_meth->pseudorand(buf,num); + RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->pseudorand) + return meth->pseudorand(buf,num); return(-1); } int RAND_status(void) { - if (rand_meth != NULL) - return rand_meth->status(); + RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->status) + return meth->status(); return 0; } diff --git a/crypto/rsa/Makefile.ssl b/crypto/rsa/Makefile.ssl index 8fd68a688c..5e01a503cc 100644 --- a/crypto/rsa/Makefile.ssl +++ b/crypto/rsa/Makefile.ssl @@ -87,13 +87,24 @@ rsa_chk.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h rsa_chk.o: ../../include/openssl/opensslv.h ../../include/openssl/rsa.h rsa_chk.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h rsa_chk.o: ../../include/openssl/symhacks.h -rsa_eay.o: ../../include/openssl/bio.h ../../include/openssl/bn.h -rsa_eay.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +rsa_eay.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +rsa_eay.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +rsa_eay.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +rsa_eay.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +rsa_eay.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h rsa_eay.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -rsa_eay.o: ../../include/openssl/err.h ../../include/openssl/lhash.h -rsa_eay.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -rsa_eay.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h -rsa_eay.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h +rsa_eay.o: ../../include/openssl/engine.h ../../include/openssl/err.h +rsa_eay.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +rsa_eay.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +rsa_eay.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +rsa_eay.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +rsa_eay.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +rsa_eay.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +rsa_eay.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +rsa_eay.o: ../../include/openssl/rc5.h ../../include/openssl/rijndael-alg-fst.h +rsa_eay.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h +rsa_eay.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +rsa_eay.o: ../../include/openssl/sha.h ../../include/openssl/stack.h rsa_eay.o: ../../include/openssl/symhacks.h ../cryptlib.h rsa_err.o: ../../include/openssl/bio.h ../../include/openssl/bn.h rsa_err.o: ../../include/openssl/crypto.h ../../include/openssl/err.h @@ -109,14 +120,25 @@ rsa_gen.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h rsa_gen.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h rsa_gen.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h rsa_gen.o: ../cryptlib.h -rsa_lib.o: ../../include/openssl/bio.h ../../include/openssl/bn.h -rsa_lib.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +rsa_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +rsa_lib.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h +rsa_lib.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h +rsa_lib.o: ../../include/openssl/crypto.h ../../include/openssl/des.h +rsa_lib.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h rsa_lib.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -rsa_lib.o: ../../include/openssl/err.h ../../include/openssl/lhash.h -rsa_lib.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +rsa_lib.o: ../../include/openssl/engine.h ../../include/openssl/err.h +rsa_lib.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +rsa_lib.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +rsa_lib.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +rsa_lib.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +rsa_lib.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +rsa_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h +rsa_lib.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h +rsa_lib.o: ../../include/openssl/rc5.h ../../include/openssl/rijndael-alg-fst.h +rsa_lib.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h rsa_lib.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h -rsa_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -rsa_lib.o: ../cryptlib.h +rsa_lib.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +rsa_lib.o: ../../include/openssl/symhacks.h ../cryptlib.h rsa_none.o: ../../include/openssl/bio.h ../../include/openssl/bn.h rsa_none.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h rsa_none.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h @@ -179,15 +201,15 @@ rsa_sign.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h rsa_sign.o: ../../include/openssl/crypto.h ../../include/openssl/des.h rsa_sign.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h rsa_sign.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -rsa_sign.o: ../../include/openssl/err.h ../../include/openssl/evp.h -rsa_sign.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h -rsa_sign.o: ../../include/openssl/md2.h ../../include/openssl/md4.h -rsa_sign.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h -rsa_sign.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -rsa_sign.o: ../../include/openssl/opensslconf.h +rsa_sign.o: ../../include/openssl/engine.h ../../include/openssl/err.h +rsa_sign.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +rsa_sign.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +rsa_sign.o: ../../include/openssl/md4.h ../../include/openssl/md5.h +rsa_sign.o: ../../include/openssl/mdc2.h ../../include/openssl/obj_mac.h +rsa_sign.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h rsa_sign.o: ../../include/openssl/opensslv.h ../../include/openssl/pkcs7.h -rsa_sign.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h -rsa_sign.o: ../../include/openssl/rc5.h +rsa_sign.o: ../../include/openssl/rand.h ../../include/openssl/rc2.h +rsa_sign.o: ../../include/openssl/rc4.h ../../include/openssl/rc5.h rsa_sign.o: ../../include/openssl/rijndael-alg-fst.h rsa_sign.o: ../../include/openssl/rijndael.h ../../include/openssl/ripemd.h rsa_sign.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h index fef4ef5a2d..bda636a365 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -114,7 +114,11 @@ struct rsa_st * this is passed instead of aEVP_PKEY, it is set to 0 */ int pad; int version; +#if 0 RSA_METHOD *meth; +#else + struct engine_st *engine; +#endif BIGNUM *n; BIGNUM *e; BIGNUM *d; @@ -168,7 +172,11 @@ struct rsa_st #define RSA_get_app_data(s) RSA_get_ex_data(s,0) RSA * RSA_new(void); +#if 0 RSA * RSA_new_method(RSA_METHOD *method); +#else +RSA * RSA_new_method(struct engine_st *engine); +#endif int RSA_size(RSA *); RSA * RSA_generate_key(int bits, unsigned long e,void (*callback)(int,int,void *),void *cb_arg); @@ -186,10 +194,14 @@ void RSA_free (RSA *r); int RSA_flags(RSA *r); -void RSA_set_default_method(RSA_METHOD *meth); -RSA_METHOD *RSA_get_default_method(void); +void RSA_set_default_openssl_method(RSA_METHOD *meth); +RSA_METHOD *RSA_get_default_openssl_method(void); RSA_METHOD *RSA_get_method(RSA *rsa); +#if 0 RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth); +#else +int RSA_set_method(RSA *rsa, struct engine_st *engine); +#endif /* This function needs the memory locking malloc callbacks to be installed */ int RSA_memory_lock(RSA *r); diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 618b5bd595..8b8a1e279a 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -61,6 +61,7 @@ #include <openssl/bn.h> #include <openssl/rsa.h> #include <openssl/rand.h> +#include <openssl/engine.h> #ifndef RSA_NULL @@ -97,11 +98,13 @@ RSA_METHOD *RSA_PKCS1_SSLeay(void) static int RSA_eay_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { + const RSA_METHOD *meth; BIGNUM f,ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; + meth = ENGINE_get_RSA(rsa->engine); BN_init(&f); BN_init(&ret); if ((ctx=BN_CTX_new()) == NULL) goto err; @@ -143,7 +146,7 @@ static int RSA_eay_public_encrypt(int flen, unsigned char *from, goto err; } - if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, + if (!meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; /* put in leading 0 bytes if the number is less than the @@ -169,11 +172,13 @@ err: static int RSA_eay_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { + const RSA_METHOD *meth; BIGNUM f,ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; + meth = ENGINE_get_RSA(rsa->engine); BN_init(&f); BN_init(&ret); @@ -213,10 +218,10 @@ static int RSA_eay_private_encrypt(int flen, unsigned char *from, (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) ) - { if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } + { if (!meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } else { - if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err; + if (!meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err; } if (rsa->flags & RSA_FLAG_BLINDING) @@ -245,12 +250,14 @@ err: static int RSA_eay_private_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { + const RSA_METHOD *meth; BIGNUM f,ret; int j,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx=NULL; + meth = ENGINE_get_RSA(rsa->engine); BN_init(&f); BN_init(&ret); ctx=BN_CTX_new(); @@ -287,10 +294,10 @@ static int RSA_eay_private_decrypt(int flen, unsigned char *from, (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) ) - { if (!rsa->meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } + { if (!meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } else { - if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) + if (!meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err; } @@ -338,12 +345,14 @@ err: static int RSA_eay_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { + const RSA_METHOD *meth; BIGNUM f,ret; int i,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx=NULL; + meth = ENGINE_get_RSA(rsa->engine); BN_init(&f); BN_init(&ret); ctx=BN_CTX_new(); @@ -374,7 +383,7 @@ static int RSA_eay_public_decrypt(int flen, unsigned char *from, goto err; } - if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, + if (!meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; p=buf; @@ -409,10 +418,12 @@ err: static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) { + const RSA_METHOD *meth; BIGNUM r1,m1; int ret=0; BN_CTX *ctx; + meth = ENGINE_get_RSA(rsa->engine); if ((ctx=BN_CTX_new()) == NULL) goto err; BN_init(&m1); BN_init(&r1); @@ -436,11 +447,11 @@ static int RSA_eay_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) } if (!BN_mod(&r1,I,rsa->q,ctx)) goto err; - if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx, + if (!meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx, rsa->_method_mod_q)) goto err; if (!BN_mod(&r1,I,rsa->p,ctx)) goto err; - if (!rsa->meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx, + if (!meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx, rsa->_method_mod_p)) goto err; if (!BN_sub(r0,r0,&m1)) goto err; diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index bbddd3f0f0..5e1e8fcdf3 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -62,6 +62,7 @@ #include <openssl/lhash.h> #include <openssl/bn.h> #include <openssl/rsa.h> +#include <openssl/engine.h> const char *RSA_version="RSA" OPENSSL_VERSION_PTEXT; @@ -74,12 +75,26 @@ RSA *RSA_new(void) return(RSA_new_method(NULL)); } -void RSA_set_default_method(RSA_METHOD *meth) +void RSA_set_default_openssl_method(RSA_METHOD *meth) { - default_RSA_meth=meth; + ENGINE *e; + /* We'll need to notify the "openssl" ENGINE of this + * change too. We won't bother locking things down at + * our end as there was never any locking in these + * functions! */ + if(default_RSA_meth != meth) + { + default_RSA_meth = meth; + e = ENGINE_by_id("openssl"); + if(e) + { + ENGINE_set_RSA(e, meth); + ENGINE_free(e); + } + } } -RSA_METHOD *RSA_get_default_method(void) +RSA_METHOD *RSA_get_default_openssl_method(void) { if (default_RSA_meth == NULL) { @@ -99,9 +114,10 @@ RSA_METHOD *RSA_get_default_method(void) RSA_METHOD *RSA_get_method(RSA *rsa) { - return rsa->meth; + return ENGINE_get_RSA(rsa->engine); } +#if 0 RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth) { RSA_METHOD *mtmp; @@ -111,9 +127,32 @@ RSA_METHOD *RSA_set_method(RSA *rsa, RSA_METHOD *meth) if (meth->init) meth->init(rsa); return mtmp; } +#else +int RSA_set_method(RSA *rsa, ENGINE *engine) +{ + ENGINE *mtmp; + RSA_METHOD *meth; + mtmp = rsa->engine; + meth = ENGINE_get_RSA(mtmp); + if (!ENGINE_init(engine)) + return 0; + if (meth->finish) meth->finish(rsa); + rsa->engine = engine; + meth = ENGINE_get_RSA(engine); + if (meth->init) meth->init(rsa); + /* SHOULD ERROR CHECK THIS!!! */ + ENGINE_finish(mtmp); + return 1; +} +#endif +#if 0 RSA *RSA_new_method(RSA_METHOD *meth) +#else +RSA *RSA_new_method(ENGINE *engine) +#endif { + RSA_METHOD *meth; RSA *ret; ret=(RSA *)OPENSSL_malloc(sizeof(RSA)); @@ -123,10 +162,17 @@ RSA *RSA_new_method(RSA_METHOD *meth) return(NULL); } - if (meth == NULL) - ret->meth=RSA_get_default_method(); + if (engine == NULL) + { + if((ret->engine=ENGINE_get_default_RSA()) == NULL) + { + OPENSSL_free(ret); + return NULL; + } + } else - ret->meth=meth; + ret->engine=engine; + meth = ENGINE_get_RSA(ret->engine); ret->pad=0; ret->version=0; @@ -144,8 +190,8 @@ RSA *RSA_new_method(RSA_METHOD *meth) ret->_method_mod_q=NULL; ret->blinding=NULL; ret->bignum_data=NULL; - ret->flags=ret->meth->flags; - if ((ret->meth->init != NULL) && !ret->meth->init(ret)) + ret->flags=meth->flags; + if ((meth->init != NULL) && !meth->init(ret)) { OPENSSL_free(ret); ret=NULL; @@ -157,6 +203,7 @@ RSA *RSA_new_method(RSA_METHOD *meth) void RSA_free(RSA *r) { + RSA_METHOD *meth; int i; if (r == NULL) return; @@ -176,8 +223,10 @@ void RSA_free(RSA *r) CRYPTO_free_ex_data(rsa_meth,r,&r->ex_data); - if (r->meth->finish != NULL) - r->meth->finish(r); + meth = ENGINE_get_RSA(r->engine); + if (meth->finish != NULL) + meth->finish(r); + ENGINE_finish(r->engine); if (r->n != NULL) BN_clear_free(r->n); if (r->e != NULL) BN_clear_free(r->e); @@ -218,30 +267,34 @@ int RSA_size(RSA *r) int RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - return(rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding)); + return(ENGINE_get_RSA(rsa->engine)->rsa_pub_enc(flen, + from, to, rsa, padding)); } int RSA_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - return(rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding)); + return(ENGINE_get_RSA(rsa->engine)->rsa_priv_enc(flen, + from, to, rsa, padding)); } int RSA_private_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - return(rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding)); + return(ENGINE_get_RSA(rsa->engine)->rsa_priv_dec(flen, + from, to, rsa, padding)); } int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - return(rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding)); + return(ENGINE_get_RSA(rsa->engine)->rsa_pub_dec(flen, + from, to, rsa, padding)); } int RSA_flags(RSA *r) { - return((r == NULL)?0:r->meth->flags); + return((r == NULL)?0:ENGINE_get_RSA(r->engine)->flags); } void RSA_blinding_off(RSA *rsa) @@ -275,7 +328,8 @@ int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx) if (!BN_rand(A,BN_num_bits(rsa->n)-1,1,0)) goto err; if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err; - if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) + if (!ENGINE_get_RSA(rsa->engine)->bn_mod_exp(A,A, + rsa->e,rsa->n,ctx,rsa->_method_mod_n)) goto err; rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n); rsa->flags|=RSA_FLAG_BLINDING; diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index 31049b9791..cf00876292 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -62,6 +62,7 @@ #include <openssl/rsa.h> #include <openssl/objects.h> #include <openssl/x509.h> +#include <openssl/engine.h> /* Size of an SSL signature: MD5+SHA1 */ #define SSL_SIG_LENGTH 36 @@ -76,7 +77,8 @@ int RSA_sign(int type, unsigned char *m, unsigned int m_len, X509_ALGOR algor; ASN1_OCTET_STRING digest; if(rsa->flags & RSA_FLAG_SIGN_VER) - return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); + return ENGINE_get_RSA(rsa->engine)->rsa_sign(type, + m, m_len, sigret, siglen, rsa); /* Special case: SSL signature, just check the length */ if(type == NID_md5_sha1) { if(m_len != SSL_SIG_LENGTH) { @@ -151,7 +153,8 @@ int RSA_verify(int dtype, unsigned char *m, unsigned int m_len, } if(rsa->flags & RSA_FLAG_SIGN_VER) - return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa); + return ENGINE_get_RSA(rsa->engine)->rsa_verify(dtype, + m, m_len, sigbuf, siglen, rsa); s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen); if (s == NULL) |