dsa_pub_cmp() doesn't need to check parameters because that is done in
[openssl.git] / crypto / dsa / dsa_ameth.c
index ed0ab2b712c8be5688e27638ea7acc2df1540aa4..a54c4f1938b2a826df5faa7b6471bcbd7136e52b 100644 (file)
@@ -78,19 +78,31 @@ static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
                return 0;
        X509_ALGOR_get0(NULL, &ptype, &pval, palg);
 
-       if (ptype != V_ASN1_SEQUENCE)
+
+       if (ptype == V_ASN1_SEQUENCE)
                {
-               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
-               goto err;
-               }
+               pstr = pval;    
+               pm = pstr->data;
+               pmlen = pstr->length;
 
-       pstr = pval;    
-       pm = pstr->data;
-       pmlen = pstr->length;
+               if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
+                       {
+                       DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
+                       goto err;
+                       }
 
-       if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
+               }
+       else if ((ptype == V_ASN1_NULL) || (ptype == V_ASN1_UNDEF))
                {
-               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
+               if (!(dsa = DSA_new()))
+                       {
+                       DSAerr(DSA_F_DSA_PUB_DECODE, ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               }
+       else
+               {
+               DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
                goto err;
                }
 
@@ -100,7 +112,6 @@ static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
                goto err;
                }
 
-       /* We have parameters now set public key */
        if (!(dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)))
                {
                DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR);
@@ -123,13 +134,13 @@ static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
 static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
        {
        DSA *dsa;
-       void *pval;
+       void *pval = NULL;
        int ptype;
        unsigned char *penc = NULL;
        int penclen;
 
        dsa=pkey->pkey.dsa;
-       if (pkey->save_parameters)
+       if (pkey->save_parameters && dsa->p && dsa->q && dsa->g)
                {
                ASN1_STRING *str;
                str = ASN1_STRING_new();
@@ -143,10 +154,8 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
                ptype = V_ASN1_SEQUENCE;
                }
        else
-               {
                ptype = V_ASN1_UNDEF;
-               pval = NULL;
-               }
+
        dsa->write_params=0;
 
        penclen = i2d_DSAPublicKey(dsa, &penc);
@@ -170,14 +179,6 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
        return 0;
        }
 
-static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
-       {
-       if (BN_cmp(b->pkey.dsa->pub_key,a->pkey.dsa->pub_key) != 0)
-               return 0;
-       else
-               return 1;
-       }
-
 /* In PKCS#8 DSA: you just get a private key integer and parameters in the
  * AlgorithmIdentifier the pubkey must be recalculated.
  */
@@ -282,9 +283,10 @@ static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
        DSAerr(DSA_F_DSA_PRIV_DECODE, EVP_R_DECODE_ERROR);
        dsaerr:
        BN_CTX_free (ctx);
+       if (privkey)
+               ASN1_INTEGER_free(privkey);
        sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
        DSA_free(dsa);
-       EVP_PKEY_free(pkey);
        return 0;
        }
 
@@ -393,6 +395,14 @@ static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
                return 1;
        }
 
+static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+       {
+       if (BN_cmp(b->pkey.dsa->pub_key,a->pkey.dsa->pub_key) != 0)
+               return 0;
+       else
+               return 1;
+       }
+
 static void int_dsa_free(EVP_PKEY *pkey)
        {
        DSA_free(pkey->pkey.dsa);
@@ -400,7 +410,7 @@ static void int_dsa_free(EVP_PKEY *pkey)
 
 static void update_buflen(const BIGNUM *b, size_t *pbuflen)
        {
-       int i;
+       size_t i;
        if (!b)
                return;
        if (*pbuflen < (i = (size_t)BN_num_bytes(b)))
@@ -433,11 +443,13 @@ int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
        else
                ktype = "DSA-Parameters";
 
+#if 0
        if (x->p == NULL)
                {
                DSAerr(DSA_F_DSA_PRINT,DSA_R_MISSING_PARAMETERS);
                goto err;
                }
+#endif
 
        update_buflen(x->p, &buf_len);
        update_buflen(x->q, &buf_len);
@@ -473,6 +485,23 @@ err:
        return(ret);
        }
 
+static int dsa_param_decode(EVP_PKEY *pkey,
+                                       const unsigned char **pder, int derlen)
+       {
+       DSA *dsa;
+       if (!(dsa = d2i_DSAparams(NULL, pder, derlen)))
+               {
+               DSAerr(DSA_F_DSA_PARAM_DECODE, ERR_R_DSA_LIB);
+               return 0;
+               }
+       EVP_PKEY_assign_DSA(pkey, dsa);
+       return 1;
+       }
+
+static int dsa_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
+       {
+       return i2d_DSAparams(pkey->pkey.dsa, pder);
+       }
 
 static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
                                                        ASN1_PCTX *ctx)
@@ -493,6 +522,51 @@ static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
        return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
        }
 
+static int old_dsa_priv_decode(EVP_PKEY *pkey,
+                                       const unsigned char **pder, int derlen)
+       {
+       DSA *dsa;
+       if (!(dsa = d2i_DSAPrivateKey (NULL, pder, derlen)))
+               {
+               DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_DSA_LIB);
+               return 0;
+               }
+       EVP_PKEY_assign_DSA(pkey, dsa);
+       return 1;
+       }
+
+static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+       {
+       return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
+       }
+
+static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+       {
+       switch (op)
+               {
+               case ASN1_PKEY_CTRL_PKCS7_SIGN:
+               if (arg1 == 0)
+                       {
+                       X509_ALGOR *alg1, *alg2;
+                       PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
+                       X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_sha1),
+                                                       V_ASN1_NULL, 0);
+                       X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_dsaWithSHA1),
+                                                       V_ASN1_UNDEF, 0);
+                       }
+               return 1;
+
+               case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+               *(int *)arg2 = NID_sha1;
+               return 2;
+
+               default:
+               return -2;
+
+               }
+
+       }
+
 /* NB these are sorted in pkey_id order, lowest first */
 
 const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = 
@@ -527,7 +601,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
                EVP_PKEY_DSA,
                0,
 
-               "dsa",
+               "DSA",
                "OpenSSL DSA method",
 
                dsa_pub_decode,
@@ -542,14 +616,17 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
                int_dsa_size,
                dsa_bits,
 
-               0,0,
+               dsa_param_decode,
+               dsa_param_encode,
                dsa_missing_parameters,
                dsa_copy_parameters,
                dsa_cmp_parameters,
                dsa_param_print,
 
                int_dsa_free,
-               0
+               dsa_pkey_ctrl,
+               old_dsa_priv_decode,
+               old_dsa_priv_encode
                }
        };