Transfer parameter handling and key comparison to algorithm methods.
[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, const 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 static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
172         {
173         if (BN_cmp(b->pkey.dsa->pub_key,a->pkey.dsa->pub_key) != 0)
174                 return 0;
175         else
176                 return 1;
177         }
178
179 /* In PKCS#8 DSA: you just get a private key integer and parameters in the
180  * AlgorithmIdentifier the pubkey must be recalculated.
181  */
182         
183 static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
184         {
185         const unsigned char *p, *pm;
186         int pklen, pmlen;
187         int ptype;
188         void *pval;
189         ASN1_STRING *pstr;
190         X509_ALGOR *palg;
191         ASN1_INTEGER *privkey = NULL;
192         BN_CTX *ctx = NULL;
193
194         STACK_OF(ASN1_TYPE) *ndsa = NULL;
195         DSA *dsa = NULL;
196
197         if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
198                 return 0;
199         X509_ALGOR_get0(NULL, &ptype, &pval, palg);
200
201         /* Check for broken DSA PKCS#8, UGH! */
202         if (*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
203                 {
204                 ASN1_TYPE *t1, *t2;
205                 if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pklen, 
206                                                           d2i_ASN1_TYPE,
207                                                           ASN1_TYPE_free)))
208                         goto decerr;
209                 if (sk_ASN1_TYPE_num(ndsa) != 2)
210                         goto decerr;
211                 /* Handle Two broken types:
212                  * SEQUENCE {parameters, priv_key}
213                  * SEQUENCE {pub_key, priv_key}
214                  */
215
216                 t1 = sk_ASN1_TYPE_value(ndsa, 0);
217                 t2 = sk_ASN1_TYPE_value(ndsa, 1);
218                 if (t1->type == V_ASN1_SEQUENCE)
219                         {
220                         p8->broken = PKCS8_EMBEDDED_PARAM;
221                         pval = t1->value.ptr;
222                         }
223                 else if (ptype == V_ASN1_SEQUENCE)
224                         p8->broken = PKCS8_NS_DB;
225                 else
226                         goto decerr;
227
228                 if (t2->type != V_ASN1_INTEGER)
229                         goto decerr;
230
231                 privkey = t2->value.integer;
232                 }
233         else
234                 {
235                 if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen)))
236                         goto decerr;
237                 if (ptype != V_ASN1_SEQUENCE)
238                         goto decerr;
239                 }
240
241         pstr = pval;    
242         pm = pstr->data;
243         pmlen = pstr->length;
244         if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
245                 goto decerr;
246         /* We have parameters now set private key */
247         if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)))
248                 {
249                 DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
250                 goto dsaerr;
251                 }
252         /* Calculate public key */
253         if (!(dsa->pub_key = BN_new()))
254                 {
255                 DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
256                 goto dsaerr;
257                 }
258         if (!(ctx = BN_CTX_new()))
259                 {
260                 DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
261                 goto dsaerr;
262                 }
263                         
264         if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx))
265                 {
266                 DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
267                 goto dsaerr;
268                 }
269
270         EVP_PKEY_assign_DSA(pkey, dsa);
271         BN_CTX_free (ctx);
272         if(ndsa)
273                 sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
274         else
275                 ASN1_INTEGER_free(privkey);
276
277         return 1;
278
279         decerr:
280         DSAerr(DSA_F_DSA_PRIV_DECODE, EVP_R_DECODE_ERROR);
281         dsaerr:
282         BN_CTX_free (ctx);
283         sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
284         DSA_free(dsa);
285         EVP_PKEY_free(pkey);
286         return 0;
287         }
288
289 static 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         params = ASN1_STRING_new();
297
298         if (!params)
299                 {
300                 DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
301                 goto err;
302                 }
303
304         params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
305         if (params->length <= 0)
306                 {
307                 DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
308                 goto err;
309                 }
310         params->type = V_ASN1_SEQUENCE;
311
312         /* Get private key into integer */
313         prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
314
315         if (!prkey)
316                 {
317                 DSAerr(DSA_F_DSA_PRIV_ENCODE,DSA_R_BN_ERROR);
318                 goto err;
319                 }
320
321         dplen = i2d_ASN1_INTEGER(prkey, &dp);
322
323         ASN1_INTEGER_free(prkey);
324
325         if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
326                                 V_ASN1_SEQUENCE, params, dp, dplen))
327                 goto err;
328
329         return 1;
330
331 err:
332         if (dp != NULL)
333                 OPENSSL_free(dp);
334         if (params != NULL)
335                 ASN1_STRING_free(params);
336         if (prkey != NULL)
337                 ASN1_INTEGER_free(prkey);
338         return 0;
339 }
340
341 static int int_dsa_size(const EVP_PKEY *pkey)
342         {
343         return(DSA_size(pkey->pkey.dsa));
344         }
345
346 static int dsa_bits(const EVP_PKEY *pkey)
347         {
348         return BN_num_bits(pkey->pkey.dsa->p);
349         }
350
351 static int dsa_missing_parameters(const EVP_PKEY *pkey)
352         {
353         DSA *dsa;
354         dsa=pkey->pkey.dsa;
355         if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
356                         return 1;
357         return 0;
358         }
359
360 static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
361         {
362         BIGNUM *a;
363
364         if ((a=BN_dup(from->pkey.dsa->p)) == NULL)
365                 return 0;
366         if (to->pkey.dsa->p != NULL)
367                 BN_free(to->pkey.dsa->p);
368         to->pkey.dsa->p=a;
369
370         if ((a=BN_dup(from->pkey.dsa->q)) == NULL)
371                 return 0;
372         if (to->pkey.dsa->q != NULL)
373                 BN_free(to->pkey.dsa->q);
374         to->pkey.dsa->q=a;
375
376         if ((a=BN_dup(from->pkey.dsa->g)) == NULL)
377                 return 0;
378         if (to->pkey.dsa->g != NULL)
379                 BN_free(to->pkey.dsa->g);
380         to->pkey.dsa->g=a;
381         return 1;
382         }
383
384 static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
385         {
386         if (    BN_cmp(a->pkey.dsa->p,b->pkey.dsa->p) ||
387                 BN_cmp(a->pkey.dsa->q,b->pkey.dsa->q) ||
388                 BN_cmp(a->pkey.dsa->g,b->pkey.dsa->g))
389                 return 0;
390         else
391                 return 1;
392         }
393
394 static void int_dsa_free(EVP_PKEY *pkey)
395         {
396         DSA_free(pkey->pkey.dsa);
397         }
398
399 /* NB these are sorted in pkey_id order, lowest first */
400
401 const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = 
402         {
403
404                 {
405                 EVP_PKEY_DSA2,
406                 EVP_PKEY_DSA,
407                 ASN1_PKEY_ALIAS
408                 },
409
410                 {
411                 EVP_PKEY_DSA1,
412                 EVP_PKEY_DSA,
413                 ASN1_PKEY_ALIAS
414                 },
415
416                 {
417                 EVP_PKEY_DSA4,
418                 EVP_PKEY_DSA,
419                 ASN1_PKEY_ALIAS
420                 },
421
422                 {
423                 EVP_PKEY_DSA3,
424                 EVP_PKEY_DSA,
425                 ASN1_PKEY_ALIAS
426                 },
427
428                 {
429                 EVP_PKEY_DSA,
430                 EVP_PKEY_DSA,
431                 0,
432
433                 dsa_pub_decode,
434                 dsa_pub_encode,
435                 dsa_pub_cmp,
436                 0,
437
438                 dsa_priv_decode,
439                 dsa_priv_encode,
440                 0,
441
442                 int_dsa_size,
443                 dsa_bits,
444
445                 0,0,
446                 dsa_missing_parameters,
447                 dsa_copy_parameters,
448                 dsa_cmp_parameters,
449                 0,
450
451                 int_dsa_free,
452                 0
453                 }
454         };
455