Imported Upstream version 3.3.5
[platform/upstream/gnutls.git] / lib / gnutls_pk.c
1 /*
2  * Copyright (C) 2001-2014 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 /* This file contains the functions needed for RSA/DSA public key
24  * encryption and signatures. 
25  */
26
27 #include <gnutls_int.h>
28 #include <gnutls_mpi.h>
29 #include <gnutls_pk.h>
30 #include <gnutls_errors.h>
31 #include <gnutls_datum.h>
32 #include <gnutls_global.h>
33 #include <gnutls_num.h>
34 #include "debug.h"
35 #include <x509/x509_int.h>
36 #include <x509/common.h>
37 #include <random.h>
38
39 /* encodes the Dss-Sig-Value structure
40  */
41 int
42 _gnutls_encode_ber_rs_raw(gnutls_datum_t * sig_value,
43                           const gnutls_datum_t * r,
44                           const gnutls_datum_t * s)
45 {
46         ASN1_TYPE sig;
47         int result;
48
49         if ((result =
50              asn1_create_element(_gnutls_get_gnutls_asn(),
51                                  "GNUTLS.DSASignatureValue",
52                                  &sig)) != ASN1_SUCCESS) {
53                 gnutls_assert();
54                 return _gnutls_asn2err(result);
55         }
56
57         result = asn1_write_value(sig, "r", r->data, r->size);
58         if (result != ASN1_SUCCESS) {
59                 gnutls_assert();
60                 asn1_delete_structure(&sig);
61                 return _gnutls_asn2err(result);
62         }
63
64         result = asn1_write_value(sig, "s", s->data, s->size);
65         if (result != ASN1_SUCCESS) {
66                 gnutls_assert();
67                 asn1_delete_structure(&sig);
68                 return _gnutls_asn2err(result);
69         }
70
71         result = _gnutls_x509_der_encode(sig, "", sig_value, 0);
72         asn1_delete_structure(&sig);
73
74         if (result < 0)
75                 return gnutls_assert_val(result);
76
77         return 0;
78 }
79
80 int
81 _gnutls_encode_ber_rs(gnutls_datum_t * sig_value, bigint_t r, bigint_t s)
82 {
83         ASN1_TYPE sig;
84         int result;
85
86         if ((result =
87              asn1_create_element(_gnutls_get_gnutls_asn(),
88                                  "GNUTLS.DSASignatureValue",
89                                  &sig)) != ASN1_SUCCESS) {
90                 gnutls_assert();
91                 return _gnutls_asn2err(result);
92         }
93
94         result = _gnutls_x509_write_int(sig, "r", r, 1);
95         if (result < 0) {
96                 gnutls_assert();
97                 asn1_delete_structure(&sig);
98                 return result;
99         }
100
101         result = _gnutls_x509_write_int(sig, "s", s, 1);
102         if (result < 0) {
103                 gnutls_assert();
104                 asn1_delete_structure(&sig);
105                 return result;
106         }
107
108         result = _gnutls_x509_der_encode(sig, "", sig_value, 0);
109         asn1_delete_structure(&sig);
110
111         if (result < 0)
112                 return gnutls_assert_val(result);
113
114         return 0;
115 }
116
117
118 /* decodes the Dss-Sig-Value structure
119  */
120 int
121 _gnutls_decode_ber_rs(const gnutls_datum_t * sig_value, bigint_t * r,
122                       bigint_t * s)
123 {
124         ASN1_TYPE sig;
125         int result;
126
127         if ((result =
128              asn1_create_element(_gnutls_get_gnutls_asn(),
129                                  "GNUTLS.DSASignatureValue",
130                                  &sig)) != ASN1_SUCCESS) {
131                 gnutls_assert();
132                 return _gnutls_asn2err(result);
133         }
134
135         result =
136             asn1_der_decoding(&sig, sig_value->data, sig_value->size,
137                               NULL);
138         if (result != ASN1_SUCCESS) {
139                 gnutls_assert();
140                 asn1_delete_structure(&sig);
141                 return _gnutls_asn2err(result);
142         }
143
144         result = _gnutls_x509_read_int(sig, "r", r);
145         if (result < 0) {
146                 gnutls_assert();
147                 asn1_delete_structure(&sig);
148                 return result;
149         }
150
151         result = _gnutls_x509_read_int(sig, "s", s);
152         if (result < 0) {
153                 gnutls_assert();
154                 _gnutls_mpi_release(s);
155                 asn1_delete_structure(&sig);
156                 return result;
157         }
158
159         asn1_delete_structure(&sig);
160
161         return 0;
162 }
163
164 /* some generic pk functions */
165
166 int _gnutls_pk_params_copy(gnutls_pk_params_st * dst,
167                            const gnutls_pk_params_st * src)
168 {
169         unsigned int i, j;
170         dst->params_nr = 0;
171
172         if (src == NULL || src->params_nr == 0) {
173                 gnutls_assert();
174                 return GNUTLS_E_INVALID_REQUEST;
175         }
176
177         dst->flags = src->flags;
178         dst->algo = src->algo;
179
180         for (i = 0; i < src->params_nr; i++) {
181                 dst->params[i] = _gnutls_mpi_copy(src->params[i]);
182                 if (dst->params[i] == NULL) {
183                         goto fail;
184                 }
185
186                 dst->params_nr++;
187         }
188
189         return 0;
190
191 fail:
192         for (j = 0; j < i; j++)
193                 _gnutls_mpi_release(&dst->params[j]);
194         return GNUTLS_E_MEMORY_ERROR;
195 }
196
197 void gnutls_pk_params_init(gnutls_pk_params_st * p)
198 {
199         memset(p, 0, sizeof(gnutls_pk_params_st));
200 }
201
202 void gnutls_pk_params_release(gnutls_pk_params_st * p)
203 {
204         unsigned int i;
205         for (i = 0; i < p->params_nr; i++) {
206                 _gnutls_mpi_release(&p->params[i]);
207         }
208         p->params_nr = 0;
209 }
210
211 void gnutls_pk_params_clear(gnutls_pk_params_st * p)
212 {
213         unsigned int i;
214         for (i = 0; i < p->params_nr; i++) {
215                 if (p->params[i] != NULL)
216                         _gnutls_mpi_clear(p->params[i]);
217         }
218 }
219
220 int
221 _gnutls_pk_get_hash_algorithm(gnutls_pk_algorithm_t pk,
222                               gnutls_pk_params_st * params,
223                               gnutls_digest_algorithm_t * dig,
224                               unsigned int *mand)
225 {
226         if (mand) {
227                 if (pk == GNUTLS_PK_DSA)
228                         *mand = 1;
229                 else
230                         *mand = 0;
231         }
232
233         return _gnutls_x509_verify_algorithm(dig, NULL, pk, params);
234
235 }
236
237 /* Writes the digest information and the digest in a DER encoded
238  * structure. The digest info is allocated and stored into the info structure.
239  */
240 int
241 encode_ber_digest_info(const mac_entry_st * e,
242                        const gnutls_datum_t * digest,
243                        gnutls_datum_t * output)
244 {
245         ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
246         int result;
247         const char *algo;
248         uint8_t *tmp_output;
249         int tmp_output_size;
250
251         algo = _gnutls_x509_mac_to_oid(e);
252         if (algo == NULL) {
253                 gnutls_assert();
254                 _gnutls_debug_log("Hash algorithm: %d has no OID\n",
255                                   e->id);
256                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
257         }
258
259         if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
260                                           "GNUTLS.DigestInfo",
261                                           &dinfo)) != ASN1_SUCCESS) {
262                 gnutls_assert();
263                 return _gnutls_asn2err(result);
264         }
265
266         result =
267             asn1_write_value(dinfo, "digestAlgorithm.algorithm", algo, 1);
268         if (result != ASN1_SUCCESS) {
269                 gnutls_assert();
270                 asn1_delete_structure(&dinfo);
271                 return _gnutls_asn2err(result);
272         }
273
274         /* Write an ASN.1 NULL in the parameters field.  This matches RFC
275            3279 and RFC 4055, although is arguable incorrect from a historic
276            perspective (see those documents for more information).
277            Regardless of what is correct, this appears to be what most
278            implementations do.  */
279         result = asn1_write_value(dinfo, "digestAlgorithm.parameters",
280                                   ASN1_NULL, ASN1_NULL_SIZE);
281         if (result != ASN1_SUCCESS) {
282                 gnutls_assert();
283                 asn1_delete_structure(&dinfo);
284                 return _gnutls_asn2err(result);
285         }
286
287         result =
288             asn1_write_value(dinfo, "digest", digest->data, digest->size);
289         if (result != ASN1_SUCCESS) {
290                 gnutls_assert();
291                 asn1_delete_structure(&dinfo);
292                 return _gnutls_asn2err(result);
293         }
294
295         tmp_output_size = 0;
296         result = asn1_der_coding(dinfo, "", NULL, &tmp_output_size, NULL);
297         if (result != ASN1_MEM_ERROR) {
298                 gnutls_assert();
299                 asn1_delete_structure(&dinfo);
300                 return _gnutls_asn2err(result);
301         }
302
303         tmp_output = gnutls_malloc(tmp_output_size);
304         if (tmp_output == NULL) {
305                 gnutls_assert();
306                 asn1_delete_structure(&dinfo);
307                 return GNUTLS_E_MEMORY_ERROR;
308         }
309
310         result =
311             asn1_der_coding(dinfo, "", tmp_output, &tmp_output_size, NULL);
312         if (result != ASN1_SUCCESS) {
313                 gnutls_assert();
314                 asn1_delete_structure(&dinfo);
315                 return _gnutls_asn2err(result);
316         }
317
318         asn1_delete_structure(&dinfo);
319
320         output->size = tmp_output_size;
321         output->data = tmp_output;
322
323         return 0;
324 }
325
326 /* Reads the digest information.
327  * we use DER here, although we should use BER. It works fine
328  * anyway.
329  */
330 int
331 decode_ber_digest_info(const gnutls_datum_t * info,
332                        gnutls_digest_algorithm_t * hash,
333                        uint8_t * digest, unsigned int *digest_size)
334 {
335         ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
336         int result;
337         char str[MAX(MAX_OID_SIZE, MAX_HASH_SIZE)];
338         int len;
339
340         if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
341                                           "GNUTLS.DigestInfo",
342                                           &dinfo)) != ASN1_SUCCESS) {
343                 gnutls_assert();
344                 return _gnutls_asn2err(result);
345         }
346
347         result = asn1_der_decoding(&dinfo, info->data, info->size, NULL);
348         if (result != ASN1_SUCCESS) {
349                 gnutls_assert();
350                 asn1_delete_structure(&dinfo);
351                 return _gnutls_asn2err(result);
352         }
353
354         len = sizeof(str) - 1;
355         result =
356             asn1_read_value(dinfo, "digestAlgorithm.algorithm", str, &len);
357         if (result != ASN1_SUCCESS) {
358                 gnutls_assert();
359                 asn1_delete_structure(&dinfo);
360                 return _gnutls_asn2err(result);
361         }
362
363         *hash = _gnutls_x509_oid_to_digest(str);
364
365         if (*hash == GNUTLS_DIG_UNKNOWN) {
366
367                 _gnutls_debug_log("verify.c: HASH OID: %s\n", str);
368
369                 gnutls_assert();
370                 asn1_delete_structure(&dinfo);
371                 return GNUTLS_E_UNKNOWN_ALGORITHM;
372         }
373
374         len = sizeof(str) - 1;
375         result =
376             asn1_read_value(dinfo, "digestAlgorithm.parameters", str,
377                             &len);
378         /* To avoid permitting garbage in the parameters field, either the
379            parameters field is not present, or it contains 0x05 0x00. */
380         if (!(result == ASN1_ELEMENT_NOT_FOUND ||
381               (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
382                memcmp(str, ASN1_NULL, ASN1_NULL_SIZE) == 0))) {
383                 gnutls_assert();
384                 asn1_delete_structure(&dinfo);
385                 return GNUTLS_E_ASN1_GENERIC_ERROR;
386         }
387
388         len = *digest_size;
389         result = asn1_read_value(dinfo, "digest", digest, &len);
390
391         if (result != ASN1_SUCCESS) {
392                 gnutls_assert();
393                 *digest_size = len;
394                 asn1_delete_structure(&dinfo);
395                 return _gnutls_asn2err(result);
396         }
397
398         *digest_size = len;
399         asn1_delete_structure(&dinfo);
400
401         return 0;
402 }
403
404 int
405 _gnutls_params_get_rsa_raw(const gnutls_pk_params_st* params,
406                                     gnutls_datum_t * m, gnutls_datum_t * e,
407                                     gnutls_datum_t * d, gnutls_datum_t * p,
408                                     gnutls_datum_t * q, gnutls_datum_t * u,
409                                     gnutls_datum_t * e1,
410                                     gnutls_datum_t * e2)
411 {
412         int ret;
413
414         if (params == NULL) {
415                 gnutls_assert();
416                 return GNUTLS_E_INVALID_REQUEST;
417         }
418
419         if (params->algo != GNUTLS_PK_RSA) {
420                 gnutls_assert();
421                 return GNUTLS_E_INVALID_REQUEST;
422         }
423
424         if (m) {
425                 ret = _gnutls_mpi_dprint_lz(params->params[0], m);
426                 if (ret < 0) {
427                         gnutls_assert();
428                         goto error;
429                 }
430         }
431
432         /* E */
433         if (e) {
434                 ret = _gnutls_mpi_dprint_lz(params->params[1], e);
435                 if (ret < 0) {
436                         gnutls_assert();
437                         goto error;
438                 }
439         }
440
441         /* D */
442         if (d) {
443                 ret = _gnutls_mpi_dprint_lz(params->params[2], d);
444                 if (ret < 0) {
445                         gnutls_assert();
446                         goto error;
447                 }
448         }
449
450         /* P */
451         if (p) {
452                 ret = _gnutls_mpi_dprint_lz(params->params[3], p);
453                 if (ret < 0) {
454                         gnutls_assert();
455                         goto error;
456                 }
457         }
458
459         /* Q */
460         if (q) {
461                 ret = _gnutls_mpi_dprint_lz(params->params[4], q);
462                 if (ret < 0) {
463                         gnutls_assert();
464                         goto error;
465                 }
466         }
467
468         /* U */
469         if (u) {
470                 ret = _gnutls_mpi_dprint_lz(params->params[5], u);
471                 if (ret < 0) {
472                         gnutls_assert();
473                         goto error;
474                 }
475         }
476
477         /* E1 */
478         if (e1) {
479                 ret = _gnutls_mpi_dprint_lz(params->params[6], e1);
480                 if (ret < 0) {
481                         gnutls_assert();
482                         goto error;
483                 }
484         }
485
486         /* E2 */
487         if (e2) {
488                 ret = _gnutls_mpi_dprint_lz(params->params[7], e2);
489                 if (ret < 0) {
490                         gnutls_assert();
491                         goto error;
492                 }
493         }
494
495         return 0;
496
497       error:
498         _gnutls_free_datum(m);
499         _gnutls_free_datum(d);
500         _gnutls_free_datum(e);
501         _gnutls_free_datum(e1);
502         _gnutls_free_datum(e2);
503         _gnutls_free_datum(p);
504         _gnutls_free_datum(q);
505
506         return ret;
507 }
508
509 int
510 _gnutls_params_get_dsa_raw(const gnutls_pk_params_st* params,
511                              gnutls_datum_t * p, gnutls_datum_t * q,
512                              gnutls_datum_t * g, gnutls_datum_t * y,
513                              gnutls_datum_t * x)
514 {
515         int ret;
516
517         if (params == NULL) {
518                 gnutls_assert();
519                 return GNUTLS_E_INVALID_REQUEST;
520         }
521
522         if (params->algo != GNUTLS_PK_DSA) {
523                 gnutls_assert();
524                 return GNUTLS_E_INVALID_REQUEST;
525         }
526
527         /* P */
528         if (p) {
529                 ret = _gnutls_mpi_dprint_lz(params->params[0], p);
530                 if (ret < 0) {
531                         gnutls_assert();
532                         return ret;
533                 }
534         }
535
536         /* Q */
537         if (q) {
538                 ret = _gnutls_mpi_dprint_lz(params->params[1], q);
539                 if (ret < 0) {
540                         gnutls_assert();
541                         _gnutls_free_datum(p);
542                         return ret;
543                 }
544         }
545
546
547         /* G */
548         if (g) {
549                 ret = _gnutls_mpi_dprint_lz(params->params[2], g);
550                 if (ret < 0) {
551                         gnutls_assert();
552                         _gnutls_free_datum(p);
553                         _gnutls_free_datum(q);
554                         return ret;
555                 }
556         }
557
558
559         /* Y */
560         if (y) {
561                 ret = _gnutls_mpi_dprint_lz(params->params[3], y);
562                 if (ret < 0) {
563                         gnutls_assert();
564                         _gnutls_free_datum(p);
565                         _gnutls_free_datum(g);
566                         _gnutls_free_datum(q);
567                         return ret;
568                 }
569         }
570
571         /* X */
572         if (x) {
573                 ret = _gnutls_mpi_dprint_lz(params->params[4], x);
574                 if (ret < 0) {
575                         gnutls_assert();
576                         _gnutls_free_datum(y);
577                         _gnutls_free_datum(p);
578                         _gnutls_free_datum(g);
579                         _gnutls_free_datum(q);
580                         return ret;
581                 }
582         }
583
584         return 0;
585 }
586
587 int _gnutls_params_get_ecc_raw(const gnutls_pk_params_st* params,
588                                        gnutls_ecc_curve_t * curve,
589                                        gnutls_datum_t * x,
590                                        gnutls_datum_t * y,
591                                        gnutls_datum_t * k)
592 {
593         int ret;
594
595         if (params == NULL) {
596                 gnutls_assert();
597                 return GNUTLS_E_INVALID_REQUEST;
598         }
599
600         if (curve)
601                 *curve = params->flags;
602
603         /* X */
604         if (x) {
605                 ret = _gnutls_mpi_dprint_lz(params->params[ECC_X], x);
606                 if (ret < 0) {
607                         gnutls_assert();
608                         return ret;
609                 }
610         }
611
612         /* Y */
613         if (y) {
614                 ret = _gnutls_mpi_dprint_lz(params->params[ECC_Y], y);
615                 if (ret < 0) {
616                         gnutls_assert();
617                         _gnutls_free_datum(x);
618                         return ret;
619                 }
620         }
621
622
623         /* K */
624         if (k) {
625                 ret = _gnutls_mpi_dprint_lz(params->params[ECC_K], k);
626                 if (ret < 0) {
627                         gnutls_assert();
628                         _gnutls_free_datum(x);
629                         _gnutls_free_datum(y);
630                         return ret;
631                 }
632         }
633
634         return 0;
635
636 }