Add additional parameter to dsa_builtin_paramgen to output the generated
[openssl.git] / crypto / dsa / dsa_pmeth.c
index 364ba15a12c98915a1c845e637b0d8ec3855d0e3..0ad12e008df7f6802bc262ddcce056b1d2c728d7 100644 (file)
@@ -1,4 +1,4 @@
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2006.
  */
 /* ====================================================================
 #include "cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
-#include <openssl/rsa.h>
 #include <openssl/evp.h>
+#include <openssl/bn.h>
 #include "evp_locl.h"
+#include "dsa_locl.h"
 
 /* DSA pkey context structure */
 
 typedef struct
        {
        /* Parameter gen parameters */
-       int nbits;
+       int nbits;              /* size of p in bits (default: 1024) */
+       int qbits;              /* size of q in bits (default: 160)  */
+       const EVP_MD *pmd;      /* MD for parameter generation */
        /* Keygen callback info */
        int gentmp[2];
        /* message digest */
-       const EVP_MD *md;
+       const EVP_MD *md;       /* MD for the signature */
        } DSA_PKEY_CTX;
 
 static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
@@ -82,6 +85,8 @@ static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
        if (!dctx)
                return 0;
        dctx->nbits = 1024;
+       dctx->qbits = 160;
+       dctx->pmd = NULL;
        dctx->md = NULL;
 
        ctx->data = dctx;
@@ -91,6 +96,20 @@ static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
        return 1;
        }
 
+static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+       {
+       DSA_PKEY_CTX *dctx, *sctx;
+       if (!pkey_dsa_init(dst))
+               return 0;
+               sctx = src->data;
+       dctx = dst->data;
+       dctx->nbits = sctx->nbits;
+       dctx->qbits = sctx->qbits;
+       dctx->pmd = sctx->pmd;
+       dctx->md  = sctx->md;
+       return 1;
+       }
+
 static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
        {
        DSA_PKEY_CTX *dctx = ctx->data;
@@ -98,8 +117,8 @@ static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
                OPENSSL_free(dctx);
        }
 
-static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen,
-                                       const unsigned char *tbs, int tbslen)
+static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+                                       const unsigned char *tbs, size_t tbslen)
        {
        int ret, type;
        unsigned int sltmp;
@@ -113,15 +132,15 @@ static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen,
 
        ret = DSA_sign(type, tbs, tbslen, sig, &sltmp, dsa);
 
-       if (ret < 0)
+       if (ret <= 0)
                return ret;
        *siglen = sltmp;
        return 1;
        }
 
 static int pkey_dsa_verify(EVP_PKEY_CTX *ctx,
-                                       const unsigned char *sig, int siglen,
-                                       const unsigned char *tbs, int tbslen)
+                                       const unsigned char *sig, size_t siglen,
+                                       const unsigned char *tbs, size_t tbslen)
        {
        int ret, type;
        DSA_PKEY_CTX *dctx = ctx->data;
@@ -148,8 +167,28 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                dctx->nbits = p1;
                return 1;
 
+               case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
+               if (p1 != 160 && p1 != 224 && p1 && p1 != 256)
+                       return -2;
+               dctx->qbits = p1;
+               return 1;
+
+               case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
+               if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1   &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha256)
+                       {
+                       DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
+                       return 0;
+                       }
+               dctx->md = p2;
+               return 1;
+
                case EVP_PKEY_CTRL_MD:
-               if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1)
+               if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1   &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_dsa    &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
+                   EVP_MD_type((const EVP_MD *)p2) != NID_sha256)
                        {
                        DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
                        return 0;
@@ -157,6 +196,15 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                dctx->md = p2;
                return 1;
 
+               case EVP_PKEY_CTRL_DIGESTINIT:
+               case EVP_PKEY_CTRL_PKCS7_SIGN:
+               case EVP_PKEY_CTRL_CMS_SIGN:
+               return 1;
+               
+               case EVP_PKEY_CTRL_PEER_KEY:
+                       DSAerr(DSA_F_PKEY_DSA_CTRL,
+                       EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+                       return -2;      
                default:
                return -2;
 
@@ -172,6 +220,18 @@ static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
                nbits = atoi(value);
                return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits);
                }
+       if (!strcmp(type, "dsa_paramgen_q_bits"))
+               {
+               int qbits = atoi(value);
+               return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
+                                        EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, NULL);
+               }
+       if (!strcmp(type, "dsa_paramgen_md"))
+               {
+               return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
+                                        EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, 
+                                        (void *)EVP_get_digestbyname(value));
+               }
        return -2;
        }
 
@@ -191,8 +251,8 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
        dsa = DSA_new();
        if (!dsa)
                return 0;
-       ret = DSA_generate_parameters_ex(dsa, dctx->nbits, NULL, 0, NULL, NULL,
-                                                                       pcb);
+       ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
+                                  NULL, 0, NULL, NULL, NULL, pcb);
        if (ret)
                EVP_PKEY_assign_DSA(pkey, dsa);
        else
@@ -221,8 +281,9 @@ static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 const EVP_PKEY_METHOD dsa_pkey_meth = 
        {
        EVP_PKEY_DSA,
-       0,
+       EVP_PKEY_FLAG_AUTOARGLEN,
        pkey_dsa_init,
+       pkey_dsa_copy,
        pkey_dsa_cleanup,
 
        0,
@@ -245,6 +306,8 @@ const EVP_PKEY_METHOD dsa_pkey_meth =
 
        0,0,
 
+       0,0,
+
        pkey_dsa_ctrl,
        pkey_dsa_ctrl_str