Enhance DH dup functions.
[openssl.git] / crypto / dh / dh_ameth.c
index 2841225f83530181d7e2ea5d85db07319eccdc6b..d19b8e9961b4913e690c550c42ec213caf75ebf8 100644 (file)
@@ -458,34 +458,77 @@ static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
        return 1;
        }
 
-static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src)
        {
        BIGNUM *a;
+       if (src)
+               {
+               a = BN_dup(src);
+               if (!a)
+                       return 0;
+               }
+       else 
+               a = NULL;
+       if (*dst)
+               BN_free(*dst);
+       *dst = a;
+       return 1;
+       }
 
-       if ((a=BN_dup(from->pkey.dh->p)) == NULL)
+static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
+       {
+       if (is_x942 == -1)
+               is_x942 = !!from->q;
+       if (!int_dh_bn_cpy(&to->p, from->p))
                return 0;
-       if (to->pkey.dh->p != NULL)
-               BN_free(to->pkey.dh->p);
-       to->pkey.dh->p=a;
-
-       if ((a=BN_dup(from->pkey.dh->g)) == NULL)
+       if (!int_dh_bn_cpy(&to->g, from->g))
                return 0;
-       if (to->pkey.dh->g != NULL)
-               BN_free(to->pkey.dh->g);
-       to->pkey.dh->g=a;
-       if (from->ameth == &dhx_asn1_meth)
+       if (is_x942)
                {
-               a = BN_dup(from->pkey.dh->q);
-               if (!a)
+               if (!int_dh_bn_cpy(&to->q, from->q))
+                       return 0;
+               if (!int_dh_bn_cpy(&to->j, from->j))
                        return 0;
-               if (to->pkey.dh->q)
-                       BN_free(to->pkey.dh->q);
-               to->pkey.dh->q = a;
+               if(to->seed)
+                       {
+                       OPENSSL_free(to->seed);
+                       to->seed = NULL;
+                       to->seedlen = 0;
+                       }
+               if (from->seed)
+                       {
+                       to->seed = BUF_memdup(from->seed, from->seedlen);
+                       if (!to->seed)
+                               return 0;
+                       to->seedlen = from->seedlen;
+                       }
                }
-
+       else
+               to->length = from->length;
        return 1;
        }
 
+
+DH *DHparams_dup(DH *dh)
+       {
+       DH *ret;
+       ret = DH_new();
+       if (!ret)
+               return NULL;
+       if (!int_dh_param_copy(ret, dh, -1))
+               {
+               DH_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+       {
+       return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
+                                from->ameth == &dhx_asn1_meth);
+       }
+
 static int dh_missing_parameters(const EVP_PKEY *a)
        {
        if (!a->pkey.dh->p || !a->pkey.dh->g)