Implement failover for ubsec. Submitted by Subramanian Ramamoorthy
authorRichard Levitte <levitte@openssl.org>
Wed, 12 Dec 2001 12:53:13 +0000 (12:53 +0000)
committerRichard Levitte <levitte@openssl.org>
Wed, 12 Dec 2001 12:53:13 +0000 (12:53 +0000)
<sram@broadcom.com> 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

crypto/engine/hw_ubsec.c
crypto/engine/vendor_defns/hw_ubsec.h

index b2c60bc..afdee37 100644 (file)
@@ -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)
        {
index 37c830c..b6619d4 100644 (file)
@@ -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);