From: Richard Levitte Date: Wed, 12 Dec 2001 12:53:13 +0000 (+0000) Subject: Implement failover for ubsec. Submitted by Subramanian Ramamoorthy X-Git-Tag: OpenSSL-engine-0_9_6c^2^2~151 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=f11fd3f4e167531c80ca5e89119762e880e7121b;p=oweals%2Fopenssl.git Implement failover for ubsec. Submitted by Subramanian Ramamoorthy with the following comment: [...] We have implemented failover (ie, if for some reason that the hardware fails, the implementation detects this failure and performs this operation as if no hardware is present, ie, in software) for sometime now and have tested it here with our hardware. [...] This change was cc:ed to exports@crypto.com --- diff --git a/crypto/engine/hw_ubsec.c b/crypto/engine/hw_ubsec.c index b2c60bcd50..afdee37f0b 100644 --- a/crypto/engine/hw_ubsec.c +++ b/crypto/engine/hw_ubsec.c @@ -73,6 +73,8 @@ #include "vendor_defns/hw_ubsec.h" #endif +#define FAIL_TO_SOFTWARE -15 + static int ubsec_destroy(ENGINE *e); static int ubsec_init(ENGINE *e); static int ubsec_finish(ENGINE *e); @@ -184,6 +186,7 @@ static DH_METHOD ubsec_dh = #define UBSEC_F_UBSEC_RSA_MOD_EXP_CRT 105 #define UBSEC_F_UBSEC_DSA_SIGN 106 #define UBSEC_F_UBSEC_DSA_VERIFY 107 +#define UBSEC_F_UBSEC_DH_COMPUTE_KEY 117 /* Error reason codes */ #define UBSEC_R_ALREADY_LOADED 108 #define UBSEC_R_DSO_FAILURE 109 @@ -194,6 +197,7 @@ static DH_METHOD ubsec_dh = #define UBSEC_R_BN_EXPAND_FAIL 114 #define UBSEC_R_REQUEST_FAILED 115 #define UBSEC_R_MISSING_KEY_COMPONENTS 116 + static ERR_STRING_DATA ubsec_str_functs[] = { /* This first element is changed to match the dynamic 'lib' number */ @@ -361,6 +365,9 @@ static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL; #endif static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL; static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL; +static t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL; + +static int max_key_len = 1024; /* ??? */ /* * These are the static string constants for the DSO file name and the function @@ -386,6 +393,7 @@ static const char *UBSEC_F10 = "dsa_verify_ioctl"; #endif static const char *UBSEC_F11 = "math_accelerate_ioctl"; static const char *UBSEC_F12 = "rng_ioctl"; +static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl"; /* Destructor (complements the "ENGINE_ubsec()" constructor) */ static int ubsec_destroy(ENGINE *e) @@ -415,6 +423,7 @@ static int ubsec_init(ENGINE *e) #endif t_UBSEC_math_accelerate_ioctl *p11; t_UBSEC_rng_ioctl *p12; + t_UBSEC_max_key_len_ioctl *p13; int fd = 0; if(ubsec_dso != NULL) @@ -453,7 +462,8 @@ static int ubsec_init(ENGINE *e) #endif !(p11 = (t_UBSEC_math_accelerate_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F11)) || - !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12))) + !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)) || + !(p13 = (t_UBSEC_max_key_len_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F13))) { UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); goto err; @@ -478,17 +488,18 @@ static int ubsec_init(ENGINE *e) #endif p_UBSEC_math_accelerate_ioctl = p11; p_UBSEC_rng_ioctl = p12; + p_UBSEC_max_key_len_ioctl = p13; /* Perform an open to see if there's actually any unit running. */ - if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) - { - p_UBSEC_ubsec_close(fd); - return 1; - } + if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0)) + { + p_UBSEC_ubsec_close(fd); + return 1; + } else - { - UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); - } + { + UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); + } err: if(ubsec_dso) @@ -511,6 +522,7 @@ err: #endif p_UBSEC_math_accelerate_ioctl = NULL; p_UBSEC_rng_ioctl = NULL; + p_UBSEC_max_key_len_ioctl = NULL; return 0; } @@ -546,6 +558,7 @@ static int ubsec_finish(ENGINE *e) #endif p_UBSEC_math_accelerate_ioctl = NULL; p_UBSEC_rng_ioctl = NULL; + p_UBSEC_max_key_len_ioctl = NULL; return 1; } @@ -588,9 +601,9 @@ static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, /* Check if hardware can't handle this argument. */ y_len = BN_num_bits(m); - if (y_len > 1024) { + if (y_len > max_key_len) { UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); - return 0; + return BN_mod_exp(r, a, p, m, ctx); } if(!bn_wexpand(r, m->top)) @@ -603,7 +616,7 @@ static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { fd = 0; UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); - return 0; + return BN_mod_exp(r, a, p, m, ctx); } if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a), @@ -611,7 +624,9 @@ static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0) { UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED); - return 0; + p_UBSEC_ubsec_close(fd); + + return BN_mod_exp(r, a, p, m, ctx); } p_UBSEC_ubsec_close(fd); @@ -635,15 +650,15 @@ static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) goto err; } - /* - * Do in software if argument is too large for hardware. - */ - if ((BN_num_bits(rsa->p)+BN_num_bits(rsa->q)) > 1024) { - const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); - to_return = (*meth->rsa_mod_exp)(r0, I, rsa); - } else { - to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, - rsa->dmq1, rsa->iqmp, ctx); + to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, + rsa->dmq1, rsa->iqmp, ctx); + if (to_return == FAIL_TO_SOFTWARE) + { + /* + * Do in software as hardware failed. + */ + const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); + to_return = (*meth->rsa_mod_exp)(r0, I, rsa); } err: if(ctx) @@ -664,9 +679,9 @@ static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, y_len = BN_num_bits(p) + BN_num_bits(q); /* Check if hardware can't handle this argument. */ - if (y_len > 1024) { + if (y_len > max_key_len) { UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); - return 0; + return FAIL_TO_SOFTWARE; } if (!bn_wexpand(r, p->top + q->top + 1)) { @@ -677,7 +692,7 @@ static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { fd = 0; UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); - return 0; + return FAIL_TO_SOFTWARE; } if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd, @@ -689,7 +704,8 @@ static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, (unsigned char *)q->d, BN_num_bits(q), (unsigned char *)r->d, &y_len) != 0) { UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED); - return 0; + p_UBSEC_ubsec_close(fd); + return FAIL_TO_SOFTWARE; } p_UBSEC_ubsec_close(fd); @@ -739,7 +755,7 @@ static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, #ifndef OPENSSL_NO_RSA /* Do in software if the key is too large for the hardware. */ - if (BN_num_bits(m) > 1024) + if (BN_num_bits(m) > max_key_len) { const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx); @@ -791,9 +807,12 @@ static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) } if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { + const DSA_METHOD *meth; fd = 0; UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); - return 0; + meth = DSA_OpenSSL(); + to_return = meth->dsa_do_sign(dgst, dlen, dsa); + goto err; } if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */ @@ -805,7 +824,13 @@ static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key), (unsigned char *)r->d, &r_len, (unsigned char *)s->d, &s_len ) != 0) { + const DSA_METHOD *meth; + UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_REQUEST_FAILED); + p_UBSEC_ubsec_close(fd); + meth = DSA_OpenSSL(); + to_return = meth->dsa_do_sign(dgst, dlen, dsa); + goto err; } @@ -852,9 +877,12 @@ static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len); if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { + const DSA_METHOD *meth; fd = 0; UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); - return 0; + meth = DSA_OpenSSL(); + to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa); + goto err; } if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */ @@ -866,7 +894,13 @@ static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, (unsigned char *)sig->r->d, BN_num_bits(sig->r), (unsigned char *)sig->s->d, BN_num_bits(sig->s), (unsigned char *)v.d, &v_len) != 0) { + const DSA_METHOD *meth; UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY , UBSEC_R_REQUEST_FAILED); + p_UBSEC_ubsec_close(fd); + + meth = DSA_OpenSSL(); + to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa); + goto err; } @@ -881,21 +915,176 @@ err: #ifndef OPENSSL_NO_DH static int ubsec_dh_compute_key (unsigned char *key,const BIGNUM *pub_key,DH *dh) - { - return 0; - } + { + int ret = -1, + k_len, + fd; + + k_len = BN_num_bits(dh->p); + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) + { + const DH_METHOD *meth; + ENGINEerr(UBSEC_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE); + meth = DH_OpenSSL(); + ret = meth->compute_key(key, pub_key, dh); + goto err; + } + + if (p_UBSEC_diffie_hellman_agree_ioctl(fd, + (unsigned char *)dh->priv_key->d, BN_num_bits(dh->priv_key), + (unsigned char *)pub_key->d, BN_num_bits(pub_key), + (unsigned char *)dh->p->d, BN_num_bits(dh->p), + key, &k_len) != 0) + { + /* Hardware's a no go, failover to software */ + const DH_METHOD *meth; + ENGINEerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, ENGINE_R_REQUEST_FAILED); + p_UBSEC_ubsec_close(fd); + + meth = DH_OpenSSL(); + ret = meth->compute_key(key, pub_key, dh); + + goto err; + } + + p_UBSEC_ubsec_close(fd); + + ret = p_UBSEC_ubsec_bits_to_bytes(k_len); +err: + return ret; + } static int ubsec_dh_generate_key (DH *dh) - { - return 0; - } + { + int ret = 0, + random_bits = 0, + pub_key_len = 0, + priv_key_len = 0, + fd; + BIGNUM *pub_key = NULL; + BIGNUM *priv_key = NULL; + + /* + * How many bits should Random x be? dh_key.c + * sets the range from 0 to num_bits(modulus) ??? + */ + + if (dh->priv_key == NULL) + { + priv_key = BN_new(); + if (priv_key == NULL) goto err; + priv_key_len = BN_num_bits(dh->p); + bn_wexpand(priv_key, dh->p->top); + do + if (!BN_rand_range(priv_key, dh->p)) goto err; + while (BN_is_zero(priv_key)); + random_bits = BN_num_bits(priv_key); + } + else + { + priv_key = dh->priv_key; + } + + if (dh->pub_key == NULL) + { + pub_key = BN_new(); + pub_key_len = BN_num_bits(dh->p); + bn_wexpand(pub_key, dh->p->top); + if(pub_key == NULL) goto err; + } + else + { + pub_key = dh->pub_key; + } + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) + { + const DH_METHOD *meth; + ENGINEerr(UBSEC_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE); + meth = DH_OpenSSL(); + ret = meth->generate_key(dh); + goto err; + } + + if (p_UBSEC_diffie_hellman_generate_ioctl(fd, + (unsigned char *)priv_key->d, &priv_key_len, + (unsigned char *)pub_key->d, &pub_key_len, + (unsigned char *)dh->g->d, BN_num_bits(dh->g), + (unsigned char *)dh->p->d, BN_num_bits(dh->p), + 0, 0, random_bits) != 0) + { + /* Hardware's a no go, failover to software */ + const DH_METHOD *meth; + + ENGINEerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, ENGINE_R_REQUEST_FAILED); + p_UBSEC_ubsec_close(fd); + + meth = DH_OpenSSL(); + ret = meth->generate_key(dh); + + goto err; + } + + p_UBSEC_ubsec_close(fd); + + dh->pub_key = pub_key; + dh->pub_key->top = (pub_key_len + BN_BITS2-1) / BN_BITS2; + dh->priv_key = priv_key; + dh->priv_key->top = (priv_key_len + BN_BITS2-1) / BN_BITS2; + + ret = 1; +err: + return ret; + } #endif -#ifdef NOT_USED -static int ubsec_rand_bytes(unsigned char *buf, int num) - { - return 0; - } +#if NOT_USED +static int ubsec_rand_bytes(unsigned char * buf, + int num) + { + int ret = 0, + fd; + + if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) + { + const RAND_METHOD *meth; + ENGINEerr(UBSEC_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE); + num = p_UBSEC_ubsec_bits_to_bytes(num); + meth = RAND_SSLeay(); + meth->seed(buf, num); + ret = meth->bytes(buf, num); + goto err; + } + + num *= 8; /* bytes to bits */ + + if (p_UBSEC_rng_ioctl(fd, + UBSEC_RNG_DIRECT, + buf, + &num) != 0) + { + /* Hardware's a no go, failover to software */ + const RAND_METHOD *meth; + + ENGINEerr(UBSEC_F_UBSEC_RNG_BYTES, ENGINE_R_REQUEST_FAILED); + p_UBSEC_ubsec_close(fd); + + num = p_UBSEC_ubsec_bits_to_bytes(num); + meth = RAND_SSLeay(); + meth->seed(buf, num); + ret = meth->bytes(buf, num); + + goto err; + } + + p_UBSEC_ubsec_close(fd); + + ret = 1; +err: + return(ret); + } + static int ubsec_rand_status(void) { diff --git a/crypto/engine/vendor_defns/hw_ubsec.h b/crypto/engine/vendor_defns/hw_ubsec.h index 37c830c1e8..b6619d40f2 100644 --- a/crypto/engine/vendor_defns/hw_ubsec.h +++ b/crypto/engine/vendor_defns/hw_ubsec.h @@ -97,3 +97,4 @@ typedef int t_UBSEC_math_accelerate_ioctl(int fd, ubsec_MathCommand_t command, typedef int t_UBSEC_rng_ioctl(int fd, ubsec_RNGCommand_t command, unsigned char *Result, int *Result_len); +typedef int t_UBSEC_max_key_len_ioctl(int fd, int *max_key_len);