1*d5a216b5Stb /* $OpenBSD: dsa_ameth.c,v 1.59 2024/04/13 14:02:51 tb Exp $ */
2f1535dc8Sdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3f1535dc8Sdjm * project 2006.
4f1535dc8Sdjm */
5f1535dc8Sdjm /* ====================================================================
6f1535dc8Sdjm * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7f1535dc8Sdjm *
8f1535dc8Sdjm * Redistribution and use in source and binary forms, with or without
9f1535dc8Sdjm * modification, are permitted provided that the following conditions
10f1535dc8Sdjm * are met:
11f1535dc8Sdjm *
12f1535dc8Sdjm * 1. Redistributions of source code must retain the above copyright
13f1535dc8Sdjm * notice, this list of conditions and the following disclaimer.
14f1535dc8Sdjm *
15f1535dc8Sdjm * 2. Redistributions in binary form must reproduce the above copyright
16f1535dc8Sdjm * notice, this list of conditions and the following disclaimer in
17f1535dc8Sdjm * the documentation and/or other materials provided with the
18f1535dc8Sdjm * distribution.
19f1535dc8Sdjm *
20f1535dc8Sdjm * 3. All advertising materials mentioning features or use of this
21f1535dc8Sdjm * software must display the following acknowledgment:
22f1535dc8Sdjm * "This product includes software developed by the OpenSSL Project
23f1535dc8Sdjm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24f1535dc8Sdjm *
25f1535dc8Sdjm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f1535dc8Sdjm * endorse or promote products derived from this software without
27f1535dc8Sdjm * prior written permission. For written permission, please contact
28f1535dc8Sdjm * licensing@OpenSSL.org.
29f1535dc8Sdjm *
30f1535dc8Sdjm * 5. Products derived from this software may not be called "OpenSSL"
31f1535dc8Sdjm * nor may "OpenSSL" appear in their names without prior written
32f1535dc8Sdjm * permission of the OpenSSL Project.
33f1535dc8Sdjm *
34f1535dc8Sdjm * 6. Redistributions of any form whatsoever must retain the following
35f1535dc8Sdjm * acknowledgment:
36f1535dc8Sdjm * "This product includes software developed by the OpenSSL Project
37f1535dc8Sdjm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38f1535dc8Sdjm *
39f1535dc8Sdjm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f1535dc8Sdjm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f1535dc8Sdjm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f1535dc8Sdjm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f1535dc8Sdjm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f1535dc8Sdjm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f1535dc8Sdjm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f1535dc8Sdjm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f1535dc8Sdjm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f1535dc8Sdjm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f1535dc8Sdjm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f1535dc8Sdjm * OF THE POSSIBILITY OF SUCH DAMAGE.
51f1535dc8Sdjm * ====================================================================
52f1535dc8Sdjm *
53f1535dc8Sdjm * This product includes cryptographic software written by Eric Young
54f1535dc8Sdjm * (eay@cryptsoft.com). This product includes software written by Tim
55f1535dc8Sdjm * Hudson (tjh@cryptsoft.com).
56f1535dc8Sdjm *
57f1535dc8Sdjm */
58f1535dc8Sdjm
59f1535dc8Sdjm #include <stdio.h>
608cf4d6a6Sjsing
618cf4d6a6Sjsing #include <openssl/opensslconf.h>
628cf4d6a6Sjsing
63f1535dc8Sdjm #include <openssl/asn1.h>
64f1535dc8Sdjm #include <openssl/bn.h>
650214b3aaSjsing #include <openssl/cms.h>
66b6ab114eSjsing #include <openssl/dsa.h>
67b6ab114eSjsing #include <openssl/err.h>
68b6ab114eSjsing #include <openssl/x509.h>
69b6ab114eSjsing
70c9675a23Stb #include "asn1_local.h"
71c9675a23Stb #include "bn_local.h"
72c9675a23Stb #include "dsa_local.h"
73c9675a23Stb #include "evp_local.h"
74*d5a216b5Stb #include "x509_local.h"
75f1535dc8Sdjm
76e85b1b81Smiod static int
dsa_pub_decode(EVP_PKEY * pkey,X509_PUBKEY * pubkey)77e85b1b81Smiod dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
78f1535dc8Sdjm {
79b42bcaecStb X509_ALGOR *algor;
80f1535dc8Sdjm int ptype;
810267c206Stb const void *pval;
825c3bbfbbStb const ASN1_STRING *astr;
835c3bbfbbStb const unsigned char *key, *params, *p;
84b42bcaecStb int key_len, params_len;
855c3bbfbbStb ASN1_INTEGER *aint = NULL;
86f1535dc8Sdjm DSA *dsa = NULL;
87b42bcaecStb int ret = 0;
88f1535dc8Sdjm
895c3bbfbbStb if (!X509_PUBKEY_get0_param(NULL, &key, &key_len, &algor, pubkey))
90b42bcaecStb goto err;
91b42bcaecStb X509_ALGOR_get0(NULL, &ptype, &pval, algor);
92f1535dc8Sdjm
93e85b1b81Smiod if (ptype == V_ASN1_SEQUENCE) {
945c3bbfbbStb astr = pval;
955c3bbfbbStb params = astr->data;
965c3bbfbbStb params_len = astr->length;
97f1535dc8Sdjm
985c3bbfbbStb p = params;
99b42bcaecStb if ((dsa = d2i_DSAparams(NULL, &p, params_len)) == NULL) {
1005067ae9fSbeck DSAerror(DSA_R_DECODE_ERROR);
101f1535dc8Sdjm goto err;
102f1535dc8Sdjm }
103e85b1b81Smiod } else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) {
104b42bcaecStb if ((dsa = DSA_new()) == NULL) {
1055067ae9fSbeck DSAerror(ERR_R_MALLOC_FAILURE);
106f1535dc8Sdjm goto err;
107f1535dc8Sdjm }
108e85b1b81Smiod } else {
1095067ae9fSbeck DSAerror(DSA_R_PARAMETER_ENCODING_ERROR);
110f1535dc8Sdjm goto err;
111f1535dc8Sdjm }
112f1535dc8Sdjm
1135c3bbfbbStb p = key;
1145c3bbfbbStb if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
1155067ae9fSbeck DSAerror(DSA_R_DECODE_ERROR);
116f1535dc8Sdjm goto err;
117f1535dc8Sdjm }
11852d22fd7Stb BN_free(dsa->pub_key);
1195c3bbfbbStb if ((dsa->pub_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
1205067ae9fSbeck DSAerror(DSA_R_BN_DECODE_ERROR);
121f1535dc8Sdjm goto err;
122f1535dc8Sdjm }
12329b50e09Stb
124f1d158b4Stb /* We can only check for key consistency if we have parameters. */
125f1d158b4Stb if (ptype == V_ASN1_SEQUENCE) {
126f1d158b4Stb if (!dsa_check_key(dsa))
127f1d158b4Stb goto err;
128f1d158b4Stb }
129f1d158b4Stb
130b42bcaecStb if (!EVP_PKEY_assign_DSA(pkey, dsa))
131b42bcaecStb goto err;
132b42bcaecStb dsa = NULL;
133b42bcaecStb
134b42bcaecStb ret = 1;
135f1535dc8Sdjm
136f1535dc8Sdjm err:
1375c3bbfbbStb ASN1_INTEGER_free(aint);
138f1535dc8Sdjm DSA_free(dsa);
139b42bcaecStb
140b42bcaecStb return ret;
141f1535dc8Sdjm }
142f1535dc8Sdjm
143e85b1b81Smiod static int
dsa_pub_encode(X509_PUBKEY * pk,const EVP_PKEY * pkey)144e85b1b81Smiod dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
145f1535dc8Sdjm {
1460e358455Stb const DSA *dsa = pkey->pkey.dsa;
1475c3bbfbbStb ASN1_STRING *astr = NULL;
148c3954054Stb int ptype = V_ASN1_UNDEF;
1495c3bbfbbStb ASN1_INTEGER *aint = NULL;
1500e358455Stb ASN1_OBJECT *aobj;
1515c3bbfbbStb unsigned char *params = NULL, *key = NULL;
152fed21370Stb int params_len = 0, key_len = 0;
153fed21370Stb int ret = 0;
154f1535dc8Sdjm
155741c2858Stb if (pkey->save_parameters > 0 && !EVP_PKEY_missing_parameters(pkey)) {
1565c3bbfbbStb if ((params_len = i2d_DSAparams(dsa, ¶ms)) <= 0) {
1570e358455Stb DSAerror(ERR_R_MALLOC_FAILURE);
158fed21370Stb params_len = 0;
1590e358455Stb goto err;
1600e358455Stb }
1615c3bbfbbStb if ((astr = ASN1_STRING_new()) == NULL) {
1625067ae9fSbeck DSAerror(ERR_R_MALLOC_FAILURE);
1633fca064fSmiod goto err;
1643fca064fSmiod }
1655c3bbfbbStb ASN1_STRING_set0(astr, params, params_len);
1665c3bbfbbStb params = NULL;
167fed21370Stb params_len = 0;
168f1535dc8Sdjm ptype = V_ASN1_SEQUENCE;
169c3954054Stb }
170f1535dc8Sdjm
1715c3bbfbbStb if ((aint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL)) == NULL) {
172354ae18bStb DSAerror(ERR_R_MALLOC_FAILURE);
173354ae18bStb goto err;
174354ae18bStb }
1755c3bbfbbStb if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
1765067ae9fSbeck DSAerror(ERR_R_MALLOC_FAILURE);
177fed21370Stb key_len = 0;
178f1535dc8Sdjm goto err;
179f1535dc8Sdjm }
180f1535dc8Sdjm
1810e358455Stb if ((aobj = OBJ_nid2obj(EVP_PKEY_DSA)) == NULL)
1820e358455Stb goto err;
1835c3bbfbbStb if (!X509_PUBKEY_set0_param(pk, aobj, ptype, astr, key, key_len))
1840e358455Stb goto err;
1855c3bbfbbStb astr = NULL;
1865c3bbfbbStb key = NULL;
187fed21370Stb key_len = 0;
1880e358455Stb
189fed21370Stb ret = 1;
190f1535dc8Sdjm
191f1535dc8Sdjm err:
1925c3bbfbbStb ASN1_STRING_free(astr);
1935c3bbfbbStb ASN1_INTEGER_free(aint);
1945c3bbfbbStb freezero(params, params_len);
1955c3bbfbbStb freezero(key, key_len);
196f1535dc8Sdjm
197fed21370Stb return ret;
198f1535dc8Sdjm }
199f1535dc8Sdjm
200b42bcaecStb /*
201b42bcaecStb * In PKCS#8 DSA: you just get a private key integer and parameters in the
202f1535dc8Sdjm * AlgorithmIdentifier the pubkey must be recalculated.
203f1535dc8Sdjm */
204e85b1b81Smiod static int
dsa_priv_decode(EVP_PKEY * pkey,const PKCS8_PRIV_KEY_INFO * p8)2058d6bc8b3Stb dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
206f1535dc8Sdjm {
207b42bcaecStb const X509_ALGOR *algor;
208f1535dc8Sdjm int ptype;
2090267c206Stb const void *pval;
2105c3bbfbbStb const ASN1_STRING *astr;
2115c3bbfbbStb const unsigned char *key, *params, *p;
212b42bcaecStb int key_len, params_len;
2135c3bbfbbStb ASN1_INTEGER *aint = NULL;
214f1535dc8Sdjm BN_CTX *ctx = NULL;
215f1535dc8Sdjm DSA *dsa = NULL;
216ebef6bdeSdoug int ret = 0;
217ebef6bdeSdoug
2185c3bbfbbStb if (!PKCS8_pkey_get0(NULL, &key, &key_len, &algor, p8))
219b42bcaecStb goto err;
220b42bcaecStb X509_ALGOR_get0(NULL, &ptype, &pval, algor);
221ebef6bdeSdoug
222b42bcaecStb if (ptype != V_ASN1_SEQUENCE) {
223b42bcaecStb DSAerror(DSA_R_PARAMETER_ENCODING_ERROR);
224b42bcaecStb goto err;
225b42bcaecStb }
226f1535dc8Sdjm
2275c3bbfbbStb astr = pval;
2285c3bbfbbStb params = astr->data;
2295c3bbfbbStb params_len = astr->length;
230b42bcaecStb
2315c3bbfbbStb p = params;
232b42bcaecStb if ((dsa = d2i_DSAparams(NULL, &p, params_len)) == NULL) {
233b42bcaecStb DSAerror(DSA_R_DECODE_ERROR);
234b42bcaecStb goto err;
235b42bcaecStb }
2365c3bbfbbStb p = key;
2375c3bbfbbStb if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
238b42bcaecStb DSAerror(DSA_R_DECODE_ERROR);
239b42bcaecStb goto err;
240b42bcaecStb }
24152d22fd7Stb BN_free(dsa->priv_key);
2425c3bbfbbStb if ((dsa->priv_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
243b42bcaecStb DSAerror(DSA_R_BN_DECODE_ERROR);
244b42bcaecStb goto err;
245f1535dc8Sdjm }
246f1d158b4Stb
247f1d158b4Stb /* Check the key for basic consistency before doing expensive things. */
248f1d158b4Stb if (!dsa_check_key(dsa))
249b42bcaecStb goto err;
250f1d158b4Stb
251f1535dc8Sdjm /* Calculate public key */
25252d22fd7Stb BN_free(dsa->pub_key);
253b42bcaecStb if ((dsa->pub_key = BN_new()) == NULL) {
2545067ae9fSbeck DSAerror(ERR_R_MALLOC_FAILURE);
255b42bcaecStb goto err;
256f1535dc8Sdjm }
25770901374Sjsing
25870901374Sjsing if ((ctx = BN_CTX_new()) == NULL) {
2595067ae9fSbeck DSAerror(ERR_R_MALLOC_FAILURE);
260b42bcaecStb goto err;
261f1535dc8Sdjm }
262f1535dc8Sdjm
26370901374Sjsing BN_CTX_start(ctx);
26470901374Sjsing
2653a88f7afSbeck if (!BN_mod_exp_ct(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
2665067ae9fSbeck DSAerror(DSA_R_BN_ERROR);
267b42bcaecStb goto err;
268f1535dc8Sdjm }
269f1535dc8Sdjm
270ebef6bdeSdoug if (!EVP_PKEY_assign_DSA(pkey, dsa))
271b42bcaecStb goto err;
272b42bcaecStb dsa = NULL;
273f1535dc8Sdjm
274ebef6bdeSdoug ret = 1;
275f1535dc8Sdjm
276b42bcaecStb err:
277f1535dc8Sdjm DSA_free(dsa);
27870901374Sjsing BN_CTX_end(ctx);
279ebef6bdeSdoug BN_CTX_free(ctx);
2805c3bbfbbStb ASN1_INTEGER_free(aint);
28170901374Sjsing
282ebef6bdeSdoug return ret;
283f1535dc8Sdjm }
284f1535dc8Sdjm
285e85b1b81Smiod static int
dsa_priv_encode(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pkey)286e85b1b81Smiod dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
287f1535dc8Sdjm {
288d4662417Stb const DSA *dsa = pkey->pkey.dsa;
2895c3bbfbbStb ASN1_STRING *astr = NULL;
290fed21370Stb int ptype = V_ASN1_SEQUENCE;
2915c3bbfbbStb ASN1_INTEGER *aint = NULL;
292d4662417Stb ASN1_OBJECT *aobj;
2935c3bbfbbStb unsigned char *params = NULL, *key = NULL;
294fed21370Stb int params_len = 0, key_len = 0;
295fed21370Stb int ret = 0;
296f1535dc8Sdjm
2975c3bbfbbStb if ((params_len = i2d_DSAparams(dsa, ¶ms)) <= 0) {
298d4662417Stb DSAerror(ERR_R_MALLOC_FAILURE);
299fed21370Stb params_len = 0;
300d4662417Stb goto err;
301d4662417Stb }
3025c3bbfbbStb if ((astr = ASN1_STRING_type_new(V_ASN1_SEQUENCE)) == NULL) {
3035067ae9fSbeck DSAerror(ERR_R_MALLOC_FAILURE);
304f1535dc8Sdjm goto err;
305f1535dc8Sdjm }
3065c3bbfbbStb ASN1_STRING_set0(astr, params, params_len);
3075c3bbfbbStb params = NULL;
308fed21370Stb params_len = 0;
309f1535dc8Sdjm
3105c3bbfbbStb if ((aint = BN_to_ASN1_INTEGER(dsa->priv_key, NULL)) == NULL) {
3115067ae9fSbeck DSAerror(DSA_R_BN_ERROR);
312f1535dc8Sdjm goto err;
313f1535dc8Sdjm }
3145c3bbfbbStb if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
315d4662417Stb DSAerror(ERR_R_MALLOC_FAILURE);
316fed21370Stb key_len = 0;
317d4662417Stb goto err;
318d4662417Stb }
319f1535dc8Sdjm
320d4662417Stb if ((aobj = OBJ_nid2obj(NID_dsa)) == NULL)
321d4662417Stb goto err;
3225c3bbfbbStb if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, astr, key, key_len))
323f1535dc8Sdjm goto err;
3245c3bbfbbStb astr = NULL;
3255c3bbfbbStb key = NULL;
326fed21370Stb key_len = 0;
327f1535dc8Sdjm
328fed21370Stb ret = 1;
329f1535dc8Sdjm
330f1535dc8Sdjm err:
3315c3bbfbbStb ASN1_STRING_free(astr);
3325c3bbfbbStb ASN1_INTEGER_free(aint);
3335c3bbfbbStb freezero(params, params_len);
3345c3bbfbbStb freezero(key, key_len);
335d4662417Stb
336fed21370Stb return ret;
337f1535dc8Sdjm }
338f1535dc8Sdjm
339e85b1b81Smiod static int
dsa_size(const EVP_PKEY * pkey)3407244e844Stb dsa_size(const EVP_PKEY *pkey)
341f1535dc8Sdjm {
342e85b1b81Smiod return DSA_size(pkey->pkey.dsa);
343f1535dc8Sdjm }
344f1535dc8Sdjm
345e85b1b81Smiod static int
dsa_bits(const EVP_PKEY * pkey)346e85b1b81Smiod dsa_bits(const EVP_PKEY *pkey)
347f1535dc8Sdjm {
348f1535dc8Sdjm return BN_num_bits(pkey->pkey.dsa->p);
349f1535dc8Sdjm }
350f1535dc8Sdjm
351e85b1b81Smiod static int
dsa_security_bits(const EVP_PKEY * pkey)3525cdf0398Stb dsa_security_bits(const EVP_PKEY *pkey)
3535cdf0398Stb {
3545cdf0398Stb return DSA_security_bits(pkey->pkey.dsa);
3555cdf0398Stb }
3565cdf0398Stb
3575cdf0398Stb static int
dsa_missing_parameters(const EVP_PKEY * pkey)358e85b1b81Smiod dsa_missing_parameters(const EVP_PKEY *pkey)
359f1535dc8Sdjm {
360a13d6b7aStb const DSA *dsa = pkey->pkey.dsa;
361e85b1b81Smiod
362a13d6b7aStb return dsa->p == NULL || dsa->q == NULL || dsa->g == NULL;
363f1535dc8Sdjm }
364f1535dc8Sdjm
365e85b1b81Smiod static int
dsa_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)366e85b1b81Smiod dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
367f1535dc8Sdjm {
368f1535dc8Sdjm BIGNUM *a;
369f1535dc8Sdjm
370f1535dc8Sdjm if ((a = BN_dup(from->pkey.dsa->p)) == NULL)
371f1535dc8Sdjm return 0;
372f1535dc8Sdjm BN_free(to->pkey.dsa->p);
373f1535dc8Sdjm to->pkey.dsa->p = a;
374f1535dc8Sdjm
375f1535dc8Sdjm if ((a = BN_dup(from->pkey.dsa->q)) == NULL)
376f1535dc8Sdjm return 0;
377f1535dc8Sdjm BN_free(to->pkey.dsa->q);
378f1535dc8Sdjm to->pkey.dsa->q = a;
379f1535dc8Sdjm
380f1535dc8Sdjm if ((a = BN_dup(from->pkey.dsa->g)) == NULL)
381f1535dc8Sdjm return 0;
382f1535dc8Sdjm BN_free(to->pkey.dsa->g);
383f1535dc8Sdjm to->pkey.dsa->g = a;
384f1535dc8Sdjm return 1;
385f1535dc8Sdjm }
386f1535dc8Sdjm
387e85b1b81Smiod static int
dsa_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)388e85b1b81Smiod dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
389f1535dc8Sdjm {
390f1535dc8Sdjm if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) ||
391f1535dc8Sdjm BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) ||
392f1535dc8Sdjm BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g))
393f1535dc8Sdjm return 0;
394f1535dc8Sdjm else
395f1535dc8Sdjm return 1;
396f1535dc8Sdjm }
397f1535dc8Sdjm
398e85b1b81Smiod static int
dsa_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)399e85b1b81Smiod dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
400f1535dc8Sdjm {
401f1535dc8Sdjm if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0)
402f1535dc8Sdjm return 0;
403f1535dc8Sdjm else
404f1535dc8Sdjm return 1;
405f1535dc8Sdjm }
406f1535dc8Sdjm
407e85b1b81Smiod static void
dsa_free(EVP_PKEY * pkey)4087244e844Stb dsa_free(EVP_PKEY *pkey)
409f1535dc8Sdjm {
410f1535dc8Sdjm DSA_free(pkey->pkey.dsa);
411f1535dc8Sdjm }
412f1535dc8Sdjm
413e85b1b81Smiod static int
do_dsa_print(BIO * bp,const DSA * x,int off,int ptype)414e85b1b81Smiod do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
415f1535dc8Sdjm {
416f1535dc8Sdjm const char *ktype = NULL;
417f1535dc8Sdjm const BIGNUM *priv_key, *pub_key;
418549c133bStb int ret = 0;
419f1535dc8Sdjm
420f1535dc8Sdjm if (ptype == 2)
421f1535dc8Sdjm priv_key = x->priv_key;
422f1535dc8Sdjm else
423f1535dc8Sdjm priv_key = NULL;
424f1535dc8Sdjm
425f1535dc8Sdjm if (ptype > 0)
426f1535dc8Sdjm pub_key = x->pub_key;
427f1535dc8Sdjm else
428f1535dc8Sdjm pub_key = NULL;
429f1535dc8Sdjm
430f1535dc8Sdjm if (ptype == 2)
431f1535dc8Sdjm ktype = "Private-Key";
432f1535dc8Sdjm else if (ptype == 1)
433f1535dc8Sdjm ktype = "Public-Key";
434f1535dc8Sdjm else
435f1535dc8Sdjm ktype = "DSA-Parameters";
436f1535dc8Sdjm
437e85b1b81Smiod if (priv_key) {
438f1535dc8Sdjm if (!BIO_indent(bp, off, 128))
439f1535dc8Sdjm goto err;
440e85b1b81Smiod if (BIO_printf(bp, "%s: (%d bit)\n", ktype,
441e85b1b81Smiod BN_num_bits(x->p)) <= 0)
442e85b1b81Smiod goto err;
443f1535dc8Sdjm }
444f1535dc8Sdjm
445549c133bStb if (!bn_printf(bp, priv_key, off, "priv:"))
446f1535dc8Sdjm goto err;
447549c133bStb if (!bn_printf(bp, pub_key, off, "pub: "))
448f1535dc8Sdjm goto err;
449549c133bStb if (!bn_printf(bp, x->p, off, "P: "))
450e85b1b81Smiod goto err;
451549c133bStb if (!bn_printf(bp, x->q, off, "Q: "))
452e85b1b81Smiod goto err;
453549c133bStb if (!bn_printf(bp, x->g, off, "G: "))
454e85b1b81Smiod goto err;
455549c133bStb
456f1535dc8Sdjm ret = 1;
457549c133bStb
458f1535dc8Sdjm err:
459d21f5001Stb return ret;
460f1535dc8Sdjm }
461f1535dc8Sdjm
462e85b1b81Smiod static int
dsa_param_decode(EVP_PKEY * pkey,const unsigned char ** params,int params_len)463e6a172b0Stb dsa_param_decode(EVP_PKEY *pkey, const unsigned char **params, int params_len)
464f1535dc8Sdjm {
465b42bcaecStb DSA *dsa = NULL;
466b42bcaecStb int ret = 0;
467e85b1b81Smiod
468e6a172b0Stb if ((dsa = d2i_DSAparams(NULL, params, params_len)) == NULL) {
4695067ae9fSbeck DSAerror(ERR_R_DSA_LIB);
470b42bcaecStb goto err;
471f1535dc8Sdjm }
472b42bcaecStb if (!dsa_check_key(dsa))
473b42bcaecStb goto err;
474b42bcaecStb if (!EVP_PKEY_assign_DSA(pkey, dsa))
475b42bcaecStb goto err;
476b42bcaecStb dsa = NULL;
477b42bcaecStb
478b42bcaecStb ret = 1;
479b42bcaecStb
480b42bcaecStb err:
481f1d158b4Stb DSA_free(dsa);
482b42bcaecStb
483b42bcaecStb return ret;
484f1535dc8Sdjm }
485f1535dc8Sdjm
486e85b1b81Smiod static int
dsa_param_encode(const EVP_PKEY * pkey,unsigned char ** params)487e6a172b0Stb dsa_param_encode(const EVP_PKEY *pkey, unsigned char **params)
488f1535dc8Sdjm {
489e6a172b0Stb return i2d_DSAparams(pkey->pkey.dsa, params);
490f1535dc8Sdjm }
491f1535dc8Sdjm
492e85b1b81Smiod static int
dsa_param_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)493e85b1b81Smiod dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
494f1535dc8Sdjm {
495f1535dc8Sdjm return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
496f1535dc8Sdjm }
497f1535dc8Sdjm
498e85b1b81Smiod static int
dsa_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)499e85b1b81Smiod dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
500f1535dc8Sdjm {
501f1535dc8Sdjm return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
502f1535dc8Sdjm }
503f1535dc8Sdjm
504e85b1b81Smiod static int
dsa_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)505e85b1b81Smiod dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
506f1535dc8Sdjm {
507f1535dc8Sdjm return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
508f1535dc8Sdjm }
509f1535dc8Sdjm
510e85b1b81Smiod static int
old_dsa_priv_decode(EVP_PKEY * pkey,const unsigned char ** key,int key_len)51176239e4fStb old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **key, int key_len)
512f1535dc8Sdjm {
513b42bcaecStb DSA *dsa = NULL;
51490bc814bSmiod BN_CTX *ctx = NULL;
51594bb0884Stb BIGNUM *result;
516b42bcaecStb int ret = 0;
517e85b1b81Smiod
51876239e4fStb if ((dsa = d2i_DSAPrivateKey(NULL, key, key_len)) == NULL) {
5195067ae9fSbeck DSAerror(ERR_R_DSA_LIB);
520ad41f5e1Stb goto err;
521f1535dc8Sdjm }
52290bc814bSmiod
523f1d158b4Stb if (!dsa_check_key(dsa))
52483bd653dStb goto err;
5255c3491c8Stb
52670901374Sjsing if ((ctx = BN_CTX_new()) == NULL)
52790bc814bSmiod goto err;
52890bc814bSmiod
52970901374Sjsing BN_CTX_start(ctx);
53070901374Sjsing
53194bb0884Stb if ((result = BN_CTX_get(ctx)) == NULL)
53294bb0884Stb goto err;
53394bb0884Stb
53490bc814bSmiod /*
53594bb0884Stb * Check that p and q are consistent with each other. dsa_check_key()
53694bb0884Stb * ensures that 1 < q < p. Now check that q divides p - 1.
53790bc814bSmiod */
53870901374Sjsing
53994bb0884Stb if (!BN_sub(result, dsa->p, BN_value_one()))
54090bc814bSmiod goto err;
54194bb0884Stb if (!BN_mod_ct(result, result, dsa->q, ctx))
54290bc814bSmiod goto err;
54394bb0884Stb if (!BN_is_zero(result)) {
5445067ae9fSbeck DSAerror(DSA_R_BAD_Q_VALUE);
54590bc814bSmiod goto err;
54690bc814bSmiod }
54790bc814bSmiod
54890bc814bSmiod /*
5495c3491c8Stb * Check that g generates a multiplicative subgroup of order q.
5505c3491c8Stb * We only check that g^q == 1, so the order is a divisor of q.
5515c3491c8Stb * Once we know that q is prime, this is enough.
5525c3491c8Stb */
5535c3491c8Stb
55494bb0884Stb if (!BN_mod_exp_ct(result, dsa->g, dsa->q, dsa->p, ctx))
5555c3491c8Stb goto err;
55694bb0884Stb if (BN_cmp(result, BN_value_one()) != 0) {
55794bb0884Stb DSAerror(DSA_R_INVALID_PARAMETERS);
5585c3491c8Stb goto err;
5595c3491c8Stb }
5605c3491c8Stb
5615c3491c8Stb /*
56290bc814bSmiod * Check that q is not a composite number.
56390bc814bSmiod */
56490bc814bSmiod
5659af159c9Stb if (BN_is_prime_ex(dsa->q, BN_prime_checks, ctx, NULL) <= 0) {
5665067ae9fSbeck DSAerror(DSA_R_BAD_Q_VALUE);
56790bc814bSmiod goto err;
56890bc814bSmiod }
56990bc814bSmiod
570b42bcaecStb if (!EVP_PKEY_assign_DSA(pkey, dsa))
571b42bcaecStb goto err;
572b42bcaecStb dsa = NULL;
57390bc814bSmiod
574b42bcaecStb ret = 1;
57590bc814bSmiod
57690bc814bSmiod err:
57770901374Sjsing BN_CTX_end(ctx);
57890bc814bSmiod BN_CTX_free(ctx);
57990bc814bSmiod DSA_free(dsa);
580b42bcaecStb
581b42bcaecStb return ret;
582f1535dc8Sdjm }
583f1535dc8Sdjm
584e85b1b81Smiod static int
old_dsa_priv_encode(const EVP_PKEY * pkey,unsigned char ** key)58576239e4fStb old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **key)
586f1535dc8Sdjm {
58776239e4fStb return i2d_DSAPrivateKey(pkey->pkey.dsa, key);
588f1535dc8Sdjm }
589f1535dc8Sdjm
590e85b1b81Smiod static int
dsa_sig_print(BIO * bp,const X509_ALGOR * sigalg,const ASN1_STRING * sig,int indent,ASN1_PCTX * pctx)591e85b1b81Smiod dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig,
592ec07fdf1Sdjm int indent, ASN1_PCTX *pctx)
593ec07fdf1Sdjm {
594ec07fdf1Sdjm DSA_SIG *dsa_sig;
595ec07fdf1Sdjm const unsigned char *p;
596e85b1b81Smiod
597e85b1b81Smiod if (!sig) {
598ec07fdf1Sdjm if (BIO_puts(bp, "\n") <= 0)
599ec07fdf1Sdjm return 0;
600ec07fdf1Sdjm else
601ec07fdf1Sdjm return 1;
602ec07fdf1Sdjm }
603ec07fdf1Sdjm p = sig->data;
604ec07fdf1Sdjm dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
605e85b1b81Smiod if (dsa_sig) {
606ec07fdf1Sdjm int rv = 0;
607ec07fdf1Sdjm
608ec07fdf1Sdjm if (BIO_write(bp, "\n", 1) != 1)
609ec07fdf1Sdjm goto err;
610ec07fdf1Sdjm
611549c133bStb if (!bn_printf(bp, dsa_sig->r, indent, "r: "))
612ec07fdf1Sdjm goto err;
613549c133bStb if (!bn_printf(bp, dsa_sig->s, indent, "s: "))
614ec07fdf1Sdjm goto err;
615ec07fdf1Sdjm rv = 1;
616ec07fdf1Sdjm err:
617ec07fdf1Sdjm DSA_SIG_free(dsa_sig);
618ec07fdf1Sdjm return rv;
619ec07fdf1Sdjm }
620ec07fdf1Sdjm return X509_signature_dump(bp, sig, indent);
621ec07fdf1Sdjm }
622ec07fdf1Sdjm
623e85b1b81Smiod static int
dsa_pkey_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)624e85b1b81Smiod dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
625f1535dc8Sdjm {
626e85b1b81Smiod switch (op) {
627f1535dc8Sdjm case ASN1_PKEY_CTRL_PKCS7_SIGN:
628e85b1b81Smiod if (arg1 == 0) {
629f1535dc8Sdjm int snid, hnid;
630f1535dc8Sdjm X509_ALGOR *alg1, *alg2;
631e85b1b81Smiod
632f1535dc8Sdjm PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
633f1535dc8Sdjm if (alg1 == NULL || alg1->algorithm == NULL)
634f1535dc8Sdjm return -1;
635f1535dc8Sdjm hnid = OBJ_obj2nid(alg1->algorithm);
636f1535dc8Sdjm if (hnid == NID_undef)
637f1535dc8Sdjm return -1;
63823b107b8Stb if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
639f1535dc8Sdjm return -1;
640*d5a216b5Stb if (!X509_ALGOR_set0_by_nid(alg2, snid, V_ASN1_UNDEF,
641*d5a216b5Stb NULL))
642*d5a216b5Stb return -1;
643f1535dc8Sdjm }
644f1535dc8Sdjm return 1;
645f1535dc8Sdjm
6460214b3aaSjsing #ifndef OPENSSL_NO_CMS
6470214b3aaSjsing case ASN1_PKEY_CTRL_CMS_SIGN:
6480214b3aaSjsing if (arg1 == 0) {
6490214b3aaSjsing int snid, hnid;
6500214b3aaSjsing X509_ALGOR *alg1, *alg2;
6510214b3aaSjsing
6520214b3aaSjsing CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
6530214b3aaSjsing if (alg1 == NULL || alg1->algorithm == NULL)
6540214b3aaSjsing return -1;
6550214b3aaSjsing hnid = OBJ_obj2nid(alg1->algorithm);
6560214b3aaSjsing if (hnid == NID_undef)
6570214b3aaSjsing return -1;
6580214b3aaSjsing if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
6590214b3aaSjsing return -1;
660*d5a216b5Stb if (!X509_ALGOR_set0_by_nid(alg2, snid, V_ASN1_UNDEF,
661*d5a216b5Stb NULL))
662*d5a216b5Stb return -1;
6630214b3aaSjsing }
6640214b3aaSjsing return 1;
6650214b3aaSjsing
6660214b3aaSjsing case ASN1_PKEY_CTRL_CMS_RI_TYPE:
6670214b3aaSjsing *(int *)arg2 = CMS_RECIPINFO_NONE;
6680214b3aaSjsing return 1;
6690214b3aaSjsing #endif
6700214b3aaSjsing
671f1535dc8Sdjm case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
672f1535dc8Sdjm *(int *)arg2 = NID_sha1;
673f1535dc8Sdjm return 2;
674f1535dc8Sdjm
675f1535dc8Sdjm default:
676f1535dc8Sdjm return -2;
677f1535dc8Sdjm }
678f1535dc8Sdjm }
679f1535dc8Sdjm
680fa20815cStb const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
6819ed721ecStb .base_method = &dsa_asn1_meth,
682e402ce74Smiod .pkey_id = EVP_PKEY_DSA,
683f1535dc8Sdjm
684e402ce74Smiod .pem_str = "DSA",
685e402ce74Smiod .info = "OpenSSL DSA method",
686f1535dc8Sdjm
687e402ce74Smiod .pub_decode = dsa_pub_decode,
688e402ce74Smiod .pub_encode = dsa_pub_encode,
689e402ce74Smiod .pub_cmp = dsa_pub_cmp,
690e402ce74Smiod .pub_print = dsa_pub_print,
691f1535dc8Sdjm
692e402ce74Smiod .priv_decode = dsa_priv_decode,
693e402ce74Smiod .priv_encode = dsa_priv_encode,
694e402ce74Smiod .priv_print = dsa_priv_print,
695f1535dc8Sdjm
6967244e844Stb .pkey_size = dsa_size,
697e402ce74Smiod .pkey_bits = dsa_bits,
6985cdf0398Stb .pkey_security_bits = dsa_security_bits,
699f1535dc8Sdjm
700e402ce74Smiod .param_decode = dsa_param_decode,
701e402ce74Smiod .param_encode = dsa_param_encode,
702e402ce74Smiod .param_missing = dsa_missing_parameters,
703e402ce74Smiod .param_copy = dsa_copy_parameters,
704e402ce74Smiod .param_cmp = dsa_cmp_parameters,
705e402ce74Smiod .param_print = dsa_param_print,
706e402ce74Smiod .sig_print = dsa_sig_print,
707f1535dc8Sdjm
7087244e844Stb .pkey_free = dsa_free,
709e402ce74Smiod .pkey_ctrl = dsa_pkey_ctrl,
710e402ce74Smiod .old_priv_decode = old_dsa_priv_decode,
711e402ce74Smiod .old_priv_encode = old_dsa_priv_encode
712fa20815cStb };
713fa20815cStb
714fa20815cStb const EVP_PKEY_ASN1_METHOD dsa1_asn1_meth = {
7159ed721ecStb .base_method = &dsa_asn1_meth,
716fa20815cStb .pkey_id = EVP_PKEY_DSA1,
717fa20815cStb .pkey_flags = ASN1_PKEY_ALIAS,
718fa20815cStb };
719fa20815cStb
720fa20815cStb const EVP_PKEY_ASN1_METHOD dsa2_asn1_meth = {
7219ed721ecStb .base_method = &dsa_asn1_meth,
722fa20815cStb .pkey_id = EVP_PKEY_DSA2,
723fa20815cStb .pkey_flags = ASN1_PKEY_ALIAS,
724fa20815cStb };
725fa20815cStb
726fa20815cStb const EVP_PKEY_ASN1_METHOD dsa3_asn1_meth = {
7279ed721ecStb .base_method = &dsa_asn1_meth,
728fa20815cStb .pkey_id = EVP_PKEY_DSA3,
729fa20815cStb .pkey_flags = ASN1_PKEY_ALIAS,
730fa20815cStb };
731fa20815cStb
732fa20815cStb const EVP_PKEY_ASN1_METHOD dsa4_asn1_meth = {
7339ed721ecStb .base_method = &dsa_asn1_meth,
734fa20815cStb .pkey_id = EVP_PKEY_DSA4,
735fa20815cStb .pkey_flags = ASN1_PKEY_ALIAS,
736f1535dc8Sdjm };
737