dsa_ameth.c revision 326663
1/*
2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3 * 2006.
4 */
5/* ====================================================================
6 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in
17 *    the documentation and/or other materials provided with the
18 *    distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 *    software must display the following acknowledgment:
22 *    "This product includes software developed by the OpenSSL Project
23 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 *    endorse or promote products derived from this software without
27 *    prior written permission. For written permission, please contact
28 *    licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 *    nor may "OpenSSL" appear in their names without prior written
32 *    permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by the OpenSSL Project
37 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <stdio.h>
60#include "cryptlib.h"
61#include <openssl/x509.h>
62#include <openssl/asn1.h>
63#include <openssl/dsa.h>
64#include <openssl/bn.h>
65#ifndef OPENSSL_NO_CMS
66# include <openssl/cms.h>
67#endif
68#include "asn1_locl.h"
69
70static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
71{
72    const unsigned char *p, *pm;
73    int pklen, pmlen;
74    int ptype;
75    void *pval;
76    ASN1_STRING *pstr;
77    X509_ALGOR *palg;
78    ASN1_INTEGER *public_key = NULL;
79
80    DSA *dsa = NULL;
81
82    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
83        return 0;
84    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
85
86    if (ptype == V_ASN1_SEQUENCE) {
87        pstr = pval;
88        pm = pstr->data;
89        pmlen = pstr->length;
90
91        if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen))) {
92            DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
93            goto err;
94        }
95
96    } else if ((ptype == V_ASN1_NULL) || (ptype == V_ASN1_UNDEF)) {
97        if (!(dsa = DSA_new())) {
98            DSAerr(DSA_F_DSA_PUB_DECODE, ERR_R_MALLOC_FAILURE);
99            goto err;
100        }
101    } else {
102        DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
103        goto err;
104    }
105
106    if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, pklen))) {
107        DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
108        goto err;
109    }
110
111    if (!(dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) {
112        DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR);
113        goto err;
114    }
115
116    ASN1_INTEGER_free(public_key);
117    EVP_PKEY_assign_DSA(pkey, dsa);
118    return 1;
119
120 err:
121    if (public_key)
122        ASN1_INTEGER_free(public_key);
123    if (dsa)
124        DSA_free(dsa);
125    return 0;
126
127}
128
129static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
130{
131    DSA *dsa;
132    int ptype;
133    unsigned char *penc = NULL;
134    int penclen;
135    ASN1_STRING *str = NULL;
136    ASN1_OBJECT *aobj;
137
138    dsa = pkey->pkey.dsa;
139    if (pkey->save_parameters && dsa->p && dsa->q && dsa->g) {
140        str = ASN1_STRING_new();
141        if (!str) {
142            DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
143            goto err;
144        }
145        str->length = i2d_DSAparams(dsa, &str->data);
146        if (str->length <= 0) {
147            DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
148            goto err;
149        }
150        ptype = V_ASN1_SEQUENCE;
151    } else
152        ptype = V_ASN1_UNDEF;
153
154    dsa->write_params = 0;
155
156    penclen = i2d_DSAPublicKey(dsa, &penc);
157
158    if (penclen <= 0) {
159        DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
160        goto err;
161    }
162
163    aobj = OBJ_nid2obj(EVP_PKEY_DSA);
164    if (aobj == NULL)
165        goto err;
166
167    if (X509_PUBKEY_set0_param(pk, aobj, ptype, str, penc, penclen))
168        return 1;
169
170 err:
171    if (penc)
172        OPENSSL_free(penc);
173    if (str)
174        ASN1_STRING_free(str);
175
176    return 0;
177}
178
179/*
180 * In PKCS#8 DSA: you just get a private key integer and parameters in the
181 * AlgorithmIdentifier the pubkey must be recalculated.
182 */
183
184static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
185{
186    const unsigned char *p, *pm;
187    int pklen, pmlen;
188    int ptype;
189    void *pval;
190    ASN1_STRING *pstr;
191    X509_ALGOR *palg;
192    ASN1_INTEGER *privkey = NULL;
193    BN_CTX *ctx = NULL;
194
195    STACK_OF(ASN1_TYPE) *ndsa = NULL;
196    DSA *dsa = NULL;
197
198    int ret = 0;
199
200    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
201        return 0;
202    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
203
204    /* Check for broken DSA PKCS#8, UGH! */
205    if (*p == (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
206        ASN1_TYPE *t1, *t2;
207        if (!(ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen)))
208            goto decerr;
209        if (sk_ASN1_TYPE_num(ndsa) != 2)
210            goto decerr;
211        /*-
212         * Handle Two broken types:
213         * SEQUENCE {parameters, priv_key}
214         * SEQUENCE {pub_key, priv_key}
215         */
216
217        t1 = sk_ASN1_TYPE_value(ndsa, 0);
218        t2 = sk_ASN1_TYPE_value(ndsa, 1);
219        if (t1->type == V_ASN1_SEQUENCE) {
220            p8->broken = PKCS8_EMBEDDED_PARAM;
221            pval = t1->value.ptr;
222        } else if (ptype == V_ASN1_SEQUENCE)
223            p8->broken = PKCS8_NS_DB;
224        else
225            goto decerr;
226
227        if (t2->type != V_ASN1_INTEGER)
228            goto decerr;
229
230        privkey = t2->value.integer;
231    } else {
232        const unsigned char *q = p;
233        if (!(privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)))
234            goto decerr;
235        if (privkey->type == V_ASN1_NEG_INTEGER) {
236            p8->broken = PKCS8_NEG_PRIVKEY;
237            ASN1_STRING_clear_free(privkey);
238            if (!(privkey = d2i_ASN1_UINTEGER(NULL, &q, pklen)))
239                goto decerr;
240        }
241        if (ptype != V_ASN1_SEQUENCE)
242            goto decerr;
243    }
244
245    pstr = pval;
246    pm = pstr->data;
247    pmlen = pstr->length;
248    if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
249        goto decerr;
250    /* We have parameters now set private key */
251    if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
252        DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
253        goto dsaerr;
254    }
255    /* Calculate public key */
256    if (!(dsa->pub_key = BN_new())) {
257        DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
258        goto dsaerr;
259    }
260    if (!(ctx = BN_CTX_new())) {
261        DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
262        goto dsaerr;
263    }
264
265    BN_set_flags(dsa->priv_key, BN_FLG_CONSTTIME);
266    if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
267        DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
268        goto dsaerr;
269    }
270
271    EVP_PKEY_assign_DSA(pkey, dsa);
272
273    ret = 1;
274    goto done;
275
276 decerr:
277    DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_DECODE_ERROR);
278 dsaerr:
279    DSA_free(dsa);
280 done:
281    BN_CTX_free(ctx);
282    if (ndsa)
283        sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
284    else
285        ASN1_STRING_clear_free(privkey);
286    return ret;
287}
288
289static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
290{
291    ASN1_STRING *params = NULL;
292    ASN1_INTEGER *prkey = NULL;
293    unsigned char *dp = NULL;
294    int dplen;
295
296    if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) {
297        DSAerr(DSA_F_DSA_PRIV_ENCODE, DSA_R_MISSING_PARAMETERS);
298        goto err;
299    }
300
301    params = ASN1_STRING_new();
302
303    if (!params) {
304        DSAerr(DSA_F_DSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
305        goto err;
306    }
307
308    params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
309    if (params->length <= 0) {
310        DSAerr(DSA_F_DSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
311        goto err;
312    }
313    params->type = V_ASN1_SEQUENCE;
314
315    /* Get private key into integer */
316    prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
317
318    if (!prkey) {
319        DSAerr(DSA_F_DSA_PRIV_ENCODE, DSA_R_BN_ERROR);
320        goto err;
321    }
322
323    dplen = i2d_ASN1_INTEGER(prkey, &dp);
324
325    ASN1_STRING_clear_free(prkey);
326    prkey = NULL;
327
328    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
329                         V_ASN1_SEQUENCE, params, dp, dplen))
330        goto err;
331
332    return 1;
333
334 err:
335    if (dp != NULL)
336        OPENSSL_free(dp);
337    if (params != NULL)
338        ASN1_STRING_free(params);
339    if (prkey != NULL)
340        ASN1_STRING_clear_free(prkey);
341    return 0;
342}
343
344static int int_dsa_size(const EVP_PKEY *pkey)
345{
346    return (DSA_size(pkey->pkey.dsa));
347}
348
349static int dsa_bits(const EVP_PKEY *pkey)
350{
351    return BN_num_bits(pkey->pkey.dsa->p);
352}
353
354static int dsa_missing_parameters(const EVP_PKEY *pkey)
355{
356    DSA *dsa;
357    dsa = pkey->pkey.dsa;
358    if (dsa == NULL || dsa->p == NULL || dsa->q == NULL || dsa->g == NULL)
359        return 1;
360    return 0;
361}
362
363static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
364{
365    BIGNUM *a;
366
367    if ((a = BN_dup(from->pkey.dsa->p)) == NULL)
368        return 0;
369    if (to->pkey.dsa->p != NULL)
370        BN_free(to->pkey.dsa->p);
371    to->pkey.dsa->p = a;
372
373    if ((a = BN_dup(from->pkey.dsa->q)) == NULL)
374        return 0;
375    if (to->pkey.dsa->q != NULL)
376        BN_free(to->pkey.dsa->q);
377    to->pkey.dsa->q = a;
378
379    if ((a = BN_dup(from->pkey.dsa->g)) == NULL)
380        return 0;
381    if (to->pkey.dsa->g != NULL)
382        BN_free(to->pkey.dsa->g);
383    to->pkey.dsa->g = a;
384    return 1;
385}
386
387static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
388{
389    if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) ||
390        BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) ||
391        BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g))
392        return 0;
393    else
394        return 1;
395}
396
397static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
398{
399    if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0)
400        return 0;
401    else
402        return 1;
403}
404
405static void int_dsa_free(EVP_PKEY *pkey)
406{
407    DSA_free(pkey->pkey.dsa);
408}
409
410static void update_buflen(const BIGNUM *b, size_t *pbuflen)
411{
412    size_t i;
413    if (!b)
414        return;
415    if (*pbuflen < (i = (size_t)BN_num_bytes(b)))
416        *pbuflen = i;
417}
418
419static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
420{
421    unsigned char *m = NULL;
422    int ret = 0;
423    size_t buf_len = 0;
424    const char *ktype = NULL;
425
426    const BIGNUM *priv_key, *pub_key;
427
428    if (ptype == 2)
429        priv_key = x->priv_key;
430    else
431        priv_key = NULL;
432
433    if (ptype > 0)
434        pub_key = x->pub_key;
435    else
436        pub_key = NULL;
437
438    if (ptype == 2)
439        ktype = "Private-Key";
440    else if (ptype == 1)
441        ktype = "Public-Key";
442    else
443        ktype = "DSA-Parameters";
444
445    update_buflen(x->p, &buf_len);
446    update_buflen(x->q, &buf_len);
447    update_buflen(x->g, &buf_len);
448    update_buflen(priv_key, &buf_len);
449    update_buflen(pub_key, &buf_len);
450
451    m = (unsigned char *)OPENSSL_malloc(buf_len + 10);
452    if (m == NULL) {
453        DSAerr(DSA_F_DO_DSA_PRINT, ERR_R_MALLOC_FAILURE);
454        goto err;
455    }
456
457    if (priv_key) {
458        if (!BIO_indent(bp, off, 128))
459            goto err;
460        if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p))
461            <= 0)
462            goto err;
463    }
464
465    if (!ASN1_bn_print(bp, "priv:", priv_key, m, off))
466        goto err;
467    if (!ASN1_bn_print(bp, "pub: ", pub_key, m, off))
468        goto err;
469    if (!ASN1_bn_print(bp, "P:   ", x->p, m, off))
470        goto err;
471    if (!ASN1_bn_print(bp, "Q:   ", x->q, m, off))
472        goto err;
473    if (!ASN1_bn_print(bp, "G:   ", x->g, m, off))
474        goto err;
475    ret = 1;
476 err:
477    if (m != NULL)
478        OPENSSL_free(m);
479    return (ret);
480}
481
482static int dsa_param_decode(EVP_PKEY *pkey,
483                            const unsigned char **pder, int derlen)
484{
485    DSA *dsa;
486    if (!(dsa = d2i_DSAparams(NULL, pder, derlen))) {
487        DSAerr(DSA_F_DSA_PARAM_DECODE, ERR_R_DSA_LIB);
488        return 0;
489    }
490    EVP_PKEY_assign_DSA(pkey, dsa);
491    return 1;
492}
493
494static int dsa_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
495{
496    return i2d_DSAparams(pkey->pkey.dsa, pder);
497}
498
499static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
500                           ASN1_PCTX *ctx)
501{
502    return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
503}
504
505static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
506                         ASN1_PCTX *ctx)
507{
508    return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
509}
510
511static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
512                          ASN1_PCTX *ctx)
513{
514    return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
515}
516
517static int old_dsa_priv_decode(EVP_PKEY *pkey,
518                               const unsigned char **pder, int derlen)
519{
520    DSA *dsa;
521    if (!(dsa = d2i_DSAPrivateKey(NULL, pder, derlen))) {
522        DSAerr(DSA_F_OLD_DSA_PRIV_DECODE, ERR_R_DSA_LIB);
523        return 0;
524    }
525    EVP_PKEY_assign_DSA(pkey, dsa);
526    return 1;
527}
528
529static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
530{
531    return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
532}
533
534static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
535                         const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx)
536{
537    DSA_SIG *dsa_sig;
538    const unsigned char *p;
539    if (!sig) {
540        if (BIO_puts(bp, "\n") <= 0)
541            return 0;
542        else
543            return 1;
544    }
545    p = sig->data;
546    dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
547    if (dsa_sig) {
548        int rv = 0;
549        size_t buf_len = 0;
550        unsigned char *m = NULL;
551        update_buflen(dsa_sig->r, &buf_len);
552        update_buflen(dsa_sig->s, &buf_len);
553        m = OPENSSL_malloc(buf_len + 10);
554        if (m == NULL) {
555            DSAerr(DSA_F_DSA_SIG_PRINT, ERR_R_MALLOC_FAILURE);
556            goto err;
557        }
558
559        if (BIO_write(bp, "\n", 1) != 1)
560            goto err;
561
562        if (!ASN1_bn_print(bp, "r:   ", dsa_sig->r, m, indent))
563            goto err;
564        if (!ASN1_bn_print(bp, "s:   ", dsa_sig->s, m, indent))
565            goto err;
566        rv = 1;
567 err:
568        if (m)
569            OPENSSL_free(m);
570        DSA_SIG_free(dsa_sig);
571        return rv;
572    }
573    return X509_signature_dump(bp, sig, indent);
574}
575
576static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
577{
578    switch (op) {
579    case ASN1_PKEY_CTRL_PKCS7_SIGN:
580        if (arg1 == 0) {
581            int snid, hnid;
582            X509_ALGOR *alg1, *alg2;
583            PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
584            if (alg1 == NULL || alg1->algorithm == NULL)
585                return -1;
586            hnid = OBJ_obj2nid(alg1->algorithm);
587            if (hnid == NID_undef)
588                return -1;
589            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
590                return -1;
591            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
592        }
593        return 1;
594#ifndef OPENSSL_NO_CMS
595    case ASN1_PKEY_CTRL_CMS_SIGN:
596        if (arg1 == 0) {
597            int snid, hnid;
598            X509_ALGOR *alg1, *alg2;
599            CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
600            if (alg1 == NULL || alg1->algorithm == NULL)
601                return -1;
602            hnid = OBJ_obj2nid(alg1->algorithm);
603            if (hnid == NID_undef)
604                return -1;
605            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
606                return -1;
607            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
608        }
609        return 1;
610
611    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
612        *(int *)arg2 = CMS_RECIPINFO_NONE;
613        return 1;
614#endif
615
616    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
617        *(int *)arg2 = NID_sha256;
618        return 2;
619
620    default:
621        return -2;
622
623    }
624
625}
626
627/* NB these are sorted in pkey_id order, lowest first */
628
629const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = {
630
631    {
632     EVP_PKEY_DSA2,
633     EVP_PKEY_DSA,
634     ASN1_PKEY_ALIAS},
635
636    {
637     EVP_PKEY_DSA1,
638     EVP_PKEY_DSA,
639     ASN1_PKEY_ALIAS},
640
641    {
642     EVP_PKEY_DSA4,
643     EVP_PKEY_DSA,
644     ASN1_PKEY_ALIAS},
645
646    {
647     EVP_PKEY_DSA3,
648     EVP_PKEY_DSA,
649     ASN1_PKEY_ALIAS},
650
651    {
652     EVP_PKEY_DSA,
653     EVP_PKEY_DSA,
654     0,
655
656     "DSA",
657     "OpenSSL DSA method",
658
659     dsa_pub_decode,
660     dsa_pub_encode,
661     dsa_pub_cmp,
662     dsa_pub_print,
663
664     dsa_priv_decode,
665     dsa_priv_encode,
666     dsa_priv_print,
667
668     int_dsa_size,
669     dsa_bits,
670
671     dsa_param_decode,
672     dsa_param_encode,
673     dsa_missing_parameters,
674     dsa_copy_parameters,
675     dsa_cmp_parameters,
676     dsa_param_print,
677     dsa_sig_print,
678
679     int_dsa_free,
680     dsa_pkey_ctrl,
681     old_dsa_priv_decode,
682     old_dsa_priv_encode}
683};
684