+ {
+ 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, UBSEC_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, UBSEC_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