]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/dsa/dsa_ameth.c
Initial support for pluggable public key ASN1 support. Process most public
[thirdparty/openssl.git] / crypto / dsa / dsa_ameth.c
1 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
2 * project 2006.
3 */
4 /* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
58 #include <stdio.h>
59 #include "cryptlib.h"
60 #include <openssl/x509.h>
61 #include <openssl/asn1.h>
62 #include <openssl/dsa.h>
63
64 static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
65 {
66 const unsigned char *p, *pm;
67 int pklen, pmlen;
68 int ptype;
69 void *pval;
70 ASN1_STRING *pstr;
71 X509_ALGOR *palg;
72 ASN1_INTEGER *public_key = NULL;
73
74 DSA *dsa = NULL;
75
76 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
77 return 0;
78 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
79
80 if (ptype != V_ASN1_SEQUENCE)
81 {
82 DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
83 goto err;
84 }
85
86 pstr = pval;
87 pm = pstr->data;
88 pmlen = pstr->length;
89
90 if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
91 {
92 DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
93 goto err;
94 }
95
96 if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, pklen)))
97 {
98 DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
99 goto err;
100 }
101
102 /* We have parameters now set public key */
103 if (!(dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)))
104 {
105 DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR);
106 goto err;
107 }
108
109 ASN1_INTEGER_free(public_key);
110
111 return 1;
112
113 err:
114 if (pubkey)
115 ASN1_INTEGER_free(public_key);
116 if (dsa)
117 DSA_free(dsa);
118 return 0;
119
120 }
121
122 static int dsa_pub_encode(X509_PUBKEY *pk, EVP_PKEY *pkey)
123 {
124 DSA *dsa;
125 void *pval;
126 int ptype;
127 unsigned char *penc = NULL;
128 int penclen;
129
130 dsa=pkey->pkey.dsa;
131 if (pkey->save_parameters)
132 {
133 ASN1_STRING *str;
134 str = ASN1_STRING_new();
135 str->length = i2d_DSAparams(dsa, &str->data);
136 if (str->length <= 0)
137 {
138 DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
139 goto err;
140 }
141 ptype = V_ASN1_SEQUENCE;
142 }
143 else
144 {
145 ptype = V_ASN1_UNDEF;
146 pval = NULL;
147 }
148 dsa->write_params=0;
149
150 penclen = i2d_DSAPublicKey(dsa, &penc);
151
152 if (penclen <= 0)
153 {
154 DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
155 goto err;
156 }
157
158 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA),
159 ptype, pval, penc, penclen))
160 return 1;
161
162 err:
163 if (penc)
164 OPENSSL_free(penc);
165 if (pval)
166 ASN1_STRING_free(pval);
167
168 return 0;
169 }
170
171 /* In PKCS#8 DSA: you just get a private key integer and parameters in the
172 * AlgorithmIdentifier the pubkey must be recalculated.
173 */
174
175 static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
176 {
177 const unsigned char *p, *pm;
178 int pklen, pmlen;
179 int ptype;
180 void *pval;
181 ASN1_STRING *pstr;
182 X509_ALGOR *palg;
183 ASN1_INTEGER *privkey = NULL;
184 BN_CTX *ctx = NULL;
185
186 STACK_OF(ASN1_TYPE) *ndsa = NULL;
187 DSA *dsa = NULL;
188
189 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
190 return 0;
191 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
192
193 /* Check for broken DSA PKCS#8, UGH! */
194 if (*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
195 {
196 ASN1_TYPE *t1, *t2;
197 if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pklen,
198 d2i_ASN1_TYPE,
199 ASN1_TYPE_free)))
200 goto decerr;
201 if (sk_ASN1_TYPE_num(ndsa) != 2)
202 goto decerr;
203 /* Handle Two broken types:
204 * SEQUENCE {parameters, priv_key}
205 * SEQUENCE {pub_key, priv_key}
206 */
207
208 t1 = sk_ASN1_TYPE_value(ndsa, 0);
209 t2 = sk_ASN1_TYPE_value(ndsa, 1);
210 if (t1->type == V_ASN1_SEQUENCE)
211 {
212 p8->broken = PKCS8_EMBEDDED_PARAM;
213 pval = t1->value.ptr;
214 }
215 else if (ptype == V_ASN1_SEQUENCE)
216 p8->broken = PKCS8_NS_DB;
217 else
218 goto decerr;
219
220 if (t2->type != V_ASN1_INTEGER)
221 goto decerr;
222
223 privkey = t2->value.integer;
224 }
225 else
226 {
227 if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen)))
228 goto decerr;
229 if (ptype != V_ASN1_SEQUENCE)
230 goto decerr;
231 }
232
233 pstr = pval;
234 pm = pstr->data;
235 pmlen = pstr->length;
236 if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
237 goto decerr;
238 /* We have parameters now set private key */
239 if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)))
240 {
241 DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
242 goto dsaerr;
243 }
244 /* Calculate public key */
245 if (!(dsa->pub_key = BN_new()))
246 {
247 DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
248 goto dsaerr;
249 }
250 if (!(ctx = BN_CTX_new()))
251 {
252 DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
253 goto dsaerr;
254 }
255
256 if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx))
257 {
258 DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
259 goto dsaerr;
260 }
261
262 EVP_PKEY_assign_DSA(pkey, dsa);
263 BN_CTX_free (ctx);
264 if(ndsa)
265 sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
266 else
267 ASN1_INTEGER_free(privkey);
268
269 return 1;
270
271 decerr:
272 DSAerr(DSA_F_DSA_PRIV_DECODE, EVP_R_DECODE_ERROR);
273 dsaerr:
274 BN_CTX_free (ctx);
275 sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
276 DSA_free(dsa);
277 EVP_PKEY_free(pkey);
278 return 0;
279 }
280
281 static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
282 {
283 ASN1_STRING *params = NULL;
284 ASN1_INTEGER *prkey = NULL;
285 unsigned char *dp = NULL;
286 int dplen;
287
288 params = ASN1_STRING_new();
289
290 if (!params)
291 {
292 DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
295
296 params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
297 if (params->length <= 0)
298 {
299 DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
300 goto err;
301 }
302 params->type = V_ASN1_SEQUENCE;
303
304 /* Get private key into integer */
305 prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
306
307 if (!prkey)
308 {
309 DSAerr(DSA_F_DSA_PRIV_ENCODE,DSA_R_BN_ERROR);
310 goto err;
311 }
312
313 dplen = i2d_ASN1_INTEGER(prkey, &dp);
314
315 ASN1_INTEGER_free(prkey);
316
317 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
318 V_ASN1_SEQUENCE, params, dp, dplen))
319 goto err;
320
321 return 1;
322
323 err:
324 if (dp != NULL)
325 OPENSSL_free(dp);
326 if (params != NULL)
327 ASN1_STRING_free(params);
328 if (prkey != NULL)
329 ASN1_INTEGER_free(prkey);
330 return 0;
331 }
332
333 /* NB these are sorted in pkey_id order, lowest first */
334
335 const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
336 {
337
338 {
339 EVP_PKEY_DSA2,
340 EVP_PKEY_DSA,
341 ASN1_PKEY_ALIAS
342 },
343
344 {
345 EVP_PKEY_DSA1,
346 EVP_PKEY_DSA,
347 ASN1_PKEY_ALIAS
348 },
349
350 {
351 EVP_PKEY_DSA4,
352 EVP_PKEY_DSA,
353 ASN1_PKEY_ALIAS
354 },
355
356 {
357 EVP_PKEY_DSA3,
358 EVP_PKEY_DSA,
359 ASN1_PKEY_ALIAS
360 },
361
362 {
363 EVP_PKEY_DSA,
364 EVP_PKEY_DSA,
365 0,
366 dsa_pub_decode,
367 dsa_pub_encode,
368 0,
369 dsa_priv_decode,
370 dsa_priv_encode,
371 0,
372 0,
373 0
374 }
375 };
376