1280304Sjkim/*
2280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3280304Sjkim * 2006.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13280304Sjkim *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <stdio.h>
60238384Sjkim#include "cryptlib.h"
61238384Sjkim#include <openssl/asn1t.h>
62238384Sjkim#include <openssl/x509.h>
63238384Sjkim#include <openssl/evp.h>
64238384Sjkim#include <openssl/bn.h>
65238384Sjkim#include "evp_locl.h"
66238384Sjkim#include "dsa_locl.h"
67238384Sjkim
68238384Sjkim/* DSA pkey context structure */
69238384Sjkim
70280304Sjkimtypedef struct {
71280304Sjkim    /* Parameter gen parameters */
72280304Sjkim    int nbits;                  /* size of p in bits (default: 1024) */
73280304Sjkim    int qbits;                  /* size of q in bits (default: 160) */
74280304Sjkim    const EVP_MD *pmd;          /* MD for parameter generation */
75280304Sjkim    /* Keygen callback info */
76280304Sjkim    int gentmp[2];
77280304Sjkim    /* message digest */
78280304Sjkim    const EVP_MD *md;           /* MD for the signature */
79280304Sjkim} DSA_PKEY_CTX;
80238384Sjkim
81238384Sjkimstatic int pkey_dsa_init(EVP_PKEY_CTX *ctx)
82280304Sjkim{
83280304Sjkim    DSA_PKEY_CTX *dctx;
84280304Sjkim    dctx = OPENSSL_malloc(sizeof(DSA_PKEY_CTX));
85280304Sjkim    if (!dctx)
86280304Sjkim        return 0;
87280304Sjkim    dctx->nbits = 1024;
88280304Sjkim    dctx->qbits = 160;
89280304Sjkim    dctx->pmd = NULL;
90280304Sjkim    dctx->md = NULL;
91238384Sjkim
92280304Sjkim    ctx->data = dctx;
93280304Sjkim    ctx->keygen_info = dctx->gentmp;
94280304Sjkim    ctx->keygen_info_count = 2;
95238384Sjkim
96280304Sjkim    return 1;
97280304Sjkim}
98280304Sjkim
99238384Sjkimstatic int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
100280304Sjkim{
101280304Sjkim    DSA_PKEY_CTX *dctx, *sctx;
102280304Sjkim    if (!pkey_dsa_init(dst))
103280304Sjkim        return 0;
104280304Sjkim    sctx = src->data;
105280304Sjkim    dctx = dst->data;
106280304Sjkim    dctx->nbits = sctx->nbits;
107280304Sjkim    dctx->qbits = sctx->qbits;
108280304Sjkim    dctx->pmd = sctx->pmd;
109280304Sjkim    dctx->md = sctx->md;
110280304Sjkim    return 1;
111280304Sjkim}
112238384Sjkim
113238384Sjkimstatic void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
114280304Sjkim{
115280304Sjkim    DSA_PKEY_CTX *dctx = ctx->data;
116280304Sjkim    if (dctx)
117280304Sjkim        OPENSSL_free(dctx);
118280304Sjkim}
119238384Sjkim
120280304Sjkimstatic int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
121280304Sjkim                         size_t *siglen, const unsigned char *tbs,
122280304Sjkim                         size_t tbslen)
123280304Sjkim{
124280304Sjkim    int ret, type;
125280304Sjkim    unsigned int sltmp;
126280304Sjkim    DSA_PKEY_CTX *dctx = ctx->data;
127280304Sjkim    DSA *dsa = ctx->pkey->pkey.dsa;
128238384Sjkim
129280304Sjkim    if (dctx->md)
130280304Sjkim        type = EVP_MD_type(dctx->md);
131280304Sjkim    else
132280304Sjkim        type = NID_sha1;
133238384Sjkim
134280304Sjkim    ret = DSA_sign(type, tbs, tbslen, sig, &sltmp, dsa);
135238384Sjkim
136280304Sjkim    if (ret <= 0)
137280304Sjkim        return ret;
138280304Sjkim    *siglen = sltmp;
139280304Sjkim    return 1;
140280304Sjkim}
141238384Sjkim
142238384Sjkimstatic int pkey_dsa_verify(EVP_PKEY_CTX *ctx,
143280304Sjkim                           const unsigned char *sig, size_t siglen,
144280304Sjkim                           const unsigned char *tbs, size_t tbslen)
145280304Sjkim{
146280304Sjkim    int ret, type;
147280304Sjkim    DSA_PKEY_CTX *dctx = ctx->data;
148280304Sjkim    DSA *dsa = ctx->pkey->pkey.dsa;
149238384Sjkim
150280304Sjkim    if (dctx->md)
151280304Sjkim        type = EVP_MD_type(dctx->md);
152280304Sjkim    else
153280304Sjkim        type = NID_sha1;
154238384Sjkim
155280304Sjkim    ret = DSA_verify(type, tbs, tbslen, sig, siglen, dsa);
156238384Sjkim
157280304Sjkim    return ret;
158280304Sjkim}
159238384Sjkim
160238384Sjkimstatic int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
161280304Sjkim{
162280304Sjkim    DSA_PKEY_CTX *dctx = ctx->data;
163280304Sjkim    switch (type) {
164280304Sjkim    case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS:
165280304Sjkim        if (p1 < 256)
166280304Sjkim            return -2;
167280304Sjkim        dctx->nbits = p1;
168280304Sjkim        return 1;
169238384Sjkim
170280304Sjkim    case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
171280304Sjkim        if (p1 != 160 && p1 != 224 && p1 && p1 != 256)
172280304Sjkim            return -2;
173280304Sjkim        dctx->qbits = p1;
174280304Sjkim        return 1;
175238384Sjkim
176280304Sjkim    case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
177280304Sjkim        if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
178280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
179280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_sha256) {
180280304Sjkim            DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
181280304Sjkim            return 0;
182280304Sjkim        }
183280304Sjkim        dctx->md = p2;
184280304Sjkim        return 1;
185238384Sjkim
186280304Sjkim    case EVP_PKEY_CTRL_MD:
187280304Sjkim        if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
188280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_dsa &&
189280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA &&
190280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
191280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
192280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
193280304Sjkim            EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
194280304Sjkim            DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
195280304Sjkim            return 0;
196280304Sjkim        }
197280304Sjkim        dctx->md = p2;
198280304Sjkim        return 1;
199238384Sjkim
200280304Sjkim    case EVP_PKEY_CTRL_DIGESTINIT:
201280304Sjkim    case EVP_PKEY_CTRL_PKCS7_SIGN:
202280304Sjkim    case EVP_PKEY_CTRL_CMS_SIGN:
203280304Sjkim        return 1;
204238384Sjkim
205280304Sjkim    case EVP_PKEY_CTRL_PEER_KEY:
206280304Sjkim        DSAerr(DSA_F_PKEY_DSA_CTRL,
207280304Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
208280304Sjkim        return -2;
209280304Sjkim    default:
210280304Sjkim        return -2;
211280304Sjkim
212280304Sjkim    }
213280304Sjkim}
214280304Sjkim
215238384Sjkimstatic int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
216280304Sjkim                             const char *type, const char *value)
217280304Sjkim{
218280304Sjkim    if (!strcmp(type, "dsa_paramgen_bits")) {
219280304Sjkim        int nbits;
220280304Sjkim        nbits = atoi(value);
221280304Sjkim        return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits);
222280304Sjkim    }
223280304Sjkim    if (!strcmp(type, "dsa_paramgen_q_bits")) {
224280304Sjkim        int qbits = atoi(value);
225280304Sjkim        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
226280304Sjkim                                 EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits,
227280304Sjkim                                 NULL);
228280304Sjkim    }
229280304Sjkim    if (!strcmp(type, "dsa_paramgen_md")) {
230280304Sjkim        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
231280304Sjkim                                 EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0,
232280304Sjkim                                 (void *)EVP_get_digestbyname(value));
233280304Sjkim    }
234280304Sjkim    return -2;
235280304Sjkim}
236238384Sjkim
237238384Sjkimstatic int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
238280304Sjkim{
239280304Sjkim    DSA *dsa = NULL;
240280304Sjkim    DSA_PKEY_CTX *dctx = ctx->data;
241280304Sjkim    BN_GENCB *pcb, cb;
242280304Sjkim    int ret;
243280304Sjkim    if (ctx->pkey_gencb) {
244280304Sjkim        pcb = &cb;
245280304Sjkim        evp_pkey_set_cb_translate(pcb, ctx);
246280304Sjkim    } else
247280304Sjkim        pcb = NULL;
248280304Sjkim    dsa = DSA_new();
249280304Sjkim    if (!dsa)
250280304Sjkim        return 0;
251280304Sjkim    ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
252280304Sjkim                               NULL, 0, NULL, NULL, NULL, pcb);
253280304Sjkim    if (ret)
254280304Sjkim        EVP_PKEY_assign_DSA(pkey, dsa);
255280304Sjkim    else
256280304Sjkim        DSA_free(dsa);
257280304Sjkim    return ret;
258280304Sjkim}
259238384Sjkim
260238384Sjkimstatic int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
261280304Sjkim{
262280304Sjkim    DSA *dsa = NULL;
263280304Sjkim    if (ctx->pkey == NULL) {
264280304Sjkim        DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET);
265280304Sjkim        return 0;
266280304Sjkim    }
267280304Sjkim    dsa = DSA_new();
268280304Sjkim    if (!dsa)
269280304Sjkim        return 0;
270280304Sjkim    EVP_PKEY_assign_DSA(pkey, dsa);
271280304Sjkim    /* Note: if error return, pkey is freed by parent routine */
272280304Sjkim    if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
273280304Sjkim        return 0;
274280304Sjkim    return DSA_generate_key(pkey->pkey.dsa);
275280304Sjkim}
276238384Sjkim
277280304Sjkimconst EVP_PKEY_METHOD dsa_pkey_meth = {
278280304Sjkim    EVP_PKEY_DSA,
279280304Sjkim    EVP_PKEY_FLAG_AUTOARGLEN,
280280304Sjkim    pkey_dsa_init,
281280304Sjkim    pkey_dsa_copy,
282280304Sjkim    pkey_dsa_cleanup,
283238384Sjkim
284280304Sjkim    0,
285280304Sjkim    pkey_dsa_paramgen,
286238384Sjkim
287280304Sjkim    0,
288280304Sjkim    pkey_dsa_keygen,
289238384Sjkim
290280304Sjkim    0,
291280304Sjkim    pkey_dsa_sign,
292238384Sjkim
293280304Sjkim    0,
294280304Sjkim    pkey_dsa_verify,
295238384Sjkim
296280304Sjkim    0, 0,
297238384Sjkim
298280304Sjkim    0, 0, 0, 0,
299238384Sjkim
300280304Sjkim    0, 0,
301238384Sjkim
302280304Sjkim    0, 0,
303238384Sjkim
304280304Sjkim    0, 0,
305238384Sjkim
306280304Sjkim    pkey_dsa_ctrl,
307280304Sjkim    pkey_dsa_ctrl_str
308280304Sjkim};
309