removed gnutls_pubkey_get_verify_algorithm() and unnecessary internal APIs
[gnutls: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 /* Writes the digest information and the digest in a DER encoded
221  * structure. The digest info is allocated and stored into the info structure.
222  */
223 int
224 encode_ber_digest_info(const mac_entry_st * e,
225                        const gnutls_datum_t * digest,
226                        gnutls_datum_t * output)
227 {
228         ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
229         int result;
230         const char *algo;
231         uint8_t *tmp_output;
232         int tmp_output_size;
233
234         algo = _gnutls_x509_mac_to_oid(e);
235         if (algo == NULL) {
236                 gnutls_assert();
237                 _gnutls_debug_log("Hash algorithm: %d has no OID\n",
238                                   e->id);
239                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
240         }
241
242         if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
243                                           "GNUTLS.DigestInfo",
244                                           &dinfo)) != ASN1_SUCCESS) {
245                 gnutls_assert();
246                 return _gnutls_asn2err(result);
247         }
248
249         result =
250             asn1_write_value(dinfo, "digestAlgorithm.algorithm", algo, 1);
251         if (result != ASN1_SUCCESS) {
252                 gnutls_assert();
253                 asn1_delete_structure(&dinfo);
254                 return _gnutls_asn2err(result);
255         }
256
257         /* Write an ASN.1 NULL in the parameters field.  This matches RFC
258            3279 and RFC 4055, although is arguable incorrect from a historic
259            perspective (see those documents for more information).
260            Regardless of what is correct, this appears to be what most
261            implementations do.  */
262         result = asn1_write_value(dinfo, "digestAlgorithm.parameters",
263                                   ASN1_NULL, ASN1_NULL_SIZE);
264         if (result != ASN1_SUCCESS) {
265                 gnutls_assert();
266                 asn1_delete_structure(&dinfo);
267                 return _gnutls_asn2err(result);
268         }
269
270         result =
271             asn1_write_value(dinfo, "digest", digest->data, digest->size);
272         if (result != ASN1_SUCCESS) {
273                 gnutls_assert();
274                 asn1_delete_structure(&dinfo);
275                 return _gnutls_asn2err(result);
276         }
277
278         tmp_output_size = 0;
279         result = asn1_der_coding(dinfo, "", NULL, &tmp_output_size, NULL);
280         if (result != ASN1_MEM_ERROR) {
281                 gnutls_assert();
282                 asn1_delete_structure(&dinfo);
283                 return _gnutls_asn2err(result);
284         }
285
286         tmp_output = gnutls_malloc(tmp_output_size);
287         if (tmp_output == NULL) {
288                 gnutls_assert();
289                 asn1_delete_structure(&dinfo);
290                 return GNUTLS_E_MEMORY_ERROR;
291         }
292
293         result =
294             asn1_der_coding(dinfo, "", tmp_output, &tmp_output_size, NULL);
295         if (result != ASN1_SUCCESS) {
296                 gnutls_assert();
297                 asn1_delete_structure(&dinfo);
298                 return _gnutls_asn2err(result);
299         }
300
301         asn1_delete_structure(&dinfo);
302
303         output->size = tmp_output_size;
304         output->data = tmp_output;
305
306         return 0;
307 }
308
309 /* Reads the digest information.
310  * we use DER here, although we should use BER. It works fine
311  * anyway.
312  */
313 int
314 decode_ber_digest_info(const gnutls_datum_t * info,
315                        gnutls_digest_algorithm_t * hash,
316                        uint8_t * digest, unsigned int *digest_size)
317 {
318         ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
319         int result;
320         char str[MAX(MAX_OID_SIZE, MAX_HASH_SIZE)];
321         int len;
322
323         if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
324                                           "GNUTLS.DigestInfo",
325                                           &dinfo)) != ASN1_SUCCESS) {
326                 gnutls_assert();
327                 return _gnutls_asn2err(result);
328         }
329
330         result = asn1_der_decoding(&dinfo, info->data, info->size, NULL);
331         if (result != ASN1_SUCCESS) {
332                 gnutls_assert();
333                 asn1_delete_structure(&dinfo);
334                 return _gnutls_asn2err(result);
335         }
336
337         len = sizeof(str) - 1;
338         result =
339             asn1_read_value(dinfo, "digestAlgorithm.algorithm", str, &len);
340         if (result != ASN1_SUCCESS) {
341                 gnutls_assert();
342                 asn1_delete_structure(&dinfo);
343                 return _gnutls_asn2err(result);
344         }
345
346         *hash = _gnutls_x509_oid_to_digest(str);
347
348         if (*hash == GNUTLS_DIG_UNKNOWN) {
349
350                 _gnutls_debug_log("verify.c: HASH OID: %s\n", str);
351
352                 gnutls_assert();
353                 asn1_delete_structure(&dinfo);
354                 return GNUTLS_E_UNKNOWN_ALGORITHM;
355         }
356
357         len = sizeof(str) - 1;
358         result =
359             asn1_read_value(dinfo, "digestAlgorithm.parameters", str,
360                             &len);
361         /* To avoid permitting garbage in the parameters field, either the
362            parameters field is not present, or it contains 0x05 0x00. */
363         if (!(result == ASN1_ELEMENT_NOT_FOUND ||
364               (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
365                memcmp(str, ASN1_NULL, ASN1_NULL_SIZE) == 0))) {
366                 gnutls_assert();
367                 asn1_delete_structure(&dinfo);
368                 return GNUTLS_E_ASN1_GENERIC_ERROR;
369         }
370
371         len = *digest_size;
372         result = asn1_read_value(dinfo, "digest", digest, &len);
373
374         if (result != ASN1_SUCCESS) {
375                 gnutls_assert();
376                 *digest_size = len;
377                 asn1_delete_structure(&dinfo);
378                 return _gnutls_asn2err(result);
379         }
380
381         *digest_size = len;
382         asn1_delete_structure(&dinfo);
383
384         return 0;
385 }
386
387 int
388 _gnutls_params_get_rsa_raw(const gnutls_pk_params_st* params,
389                                     gnutls_datum_t * m, gnutls_datum_t * e,
390                                     gnutls_datum_t * d, gnutls_datum_t * p,
391                                     gnutls_datum_t * q, gnutls_datum_t * u,
392                                     gnutls_datum_t * e1,
393                                     gnutls_datum_t * e2)
394 {
395         int ret;
396
397         if (params == NULL) {
398                 gnutls_assert();
399                 return GNUTLS_E_INVALID_REQUEST;
400         }
401
402         if (params->algo != GNUTLS_PK_RSA) {
403                 gnutls_assert();
404                 return GNUTLS_E_INVALID_REQUEST;
405         }
406
407         if (m) {
408                 ret = _gnutls_mpi_dprint_lz(params->params[0], m);
409                 if (ret < 0) {
410                         gnutls_assert();
411                         goto error;
412                 }
413         }
414
415         /* E */
416         if (e) {
417                 ret = _gnutls_mpi_dprint_lz(params->params[1], e);
418                 if (ret < 0) {
419                         gnutls_assert();
420                         goto error;
421                 }
422         }
423
424         /* D */
425         if (d && params->params[2]) {
426                 ret = _gnutls_mpi_dprint_lz(params->params[2], d);
427                 if (ret < 0) {
428                         gnutls_assert();
429                         goto error;
430                 }
431         } else if (d) {
432                 d->data = NULL;
433                 d->size = 0;
434         }
435
436         /* P */
437         if (p && params->params[3]) {
438                 ret = _gnutls_mpi_dprint_lz(params->params[3], p);
439                 if (ret < 0) {
440                         gnutls_assert();
441                         goto error;
442                 }
443         } else if (p) {
444                 p->data = NULL;
445                 p->size = 0;
446         }
447
448         /* Q */
449         if (q && params->params[4]) {
450                 ret = _gnutls_mpi_dprint_lz(params->params[4], q);
451                 if (ret < 0) {
452                         gnutls_assert();
453                         goto error;
454                 }
455         } else if (q) {
456                 q->data = NULL;
457                 q->size = 0;
458         }
459
460         /* U */
461         if (u && params->params[5]) {
462                 ret = _gnutls_mpi_dprint_lz(params->params[5], u);
463                 if (ret < 0) {
464                         gnutls_assert();
465                         goto error;
466                 }
467         } else if (u) {
468                 u->data = NULL;
469                 u->size = 0;
470         }
471
472         /* E1 */
473         if (e1 && params->params[6]) {
474                 ret = _gnutls_mpi_dprint_lz(params->params[6], e1);
475                 if (ret < 0) {
476                         gnutls_assert();
477                         goto error;
478                 }
479         } else if (e1) {
480                 e1->data = NULL;
481                 e1->size = 0;
482         }
483
484         /* E2 */
485         if (e2 && params->params[7]) {
486                 ret = _gnutls_mpi_dprint_lz(params->params[7], e2);
487                 if (ret < 0) {
488                         gnutls_assert();
489                         goto error;
490                 }
491         } else if (e2) {
492                 e2->data = NULL;
493                 e2->size = 0;
494         }
495
496         return 0;
497
498       error:
499         _gnutls_free_datum(m);
500         _gnutls_free_datum(d);
501         _gnutls_free_datum(e);
502         _gnutls_free_datum(e1);
503         _gnutls_free_datum(e2);
504         _gnutls_free_datum(p);
505         _gnutls_free_datum(q);
506
507         return ret;
508 }
509
510 int
511 _gnutls_params_get_dsa_raw(const gnutls_pk_params_st* params,
512                              gnutls_datum_t * p, gnutls_datum_t * q,
513                              gnutls_datum_t * g, gnutls_datum_t * y,
514                              gnutls_datum_t * x)
515 {
516         int ret;
517
518         if (params == NULL) {
519                 gnutls_assert();
520                 return GNUTLS_E_INVALID_REQUEST;
521         }
522
523         if (params->algo != GNUTLS_PK_DSA) {
524                 gnutls_assert();
525                 return GNUTLS_E_INVALID_REQUEST;
526         }
527
528         /* P */
529         if (p) {
530                 ret = _gnutls_mpi_dprint_lz(params->params[0], p);
531                 if (ret < 0) {
532                         gnutls_assert();
533                         return ret;
534                 }
535         }
536
537         /* Q */
538         if (q) {
539                 ret = _gnutls_mpi_dprint_lz(params->params[1], q);
540                 if (ret < 0) {
541                         gnutls_assert();
542                         _gnutls_free_datum(p);
543                         return ret;
544                 }
545         }
546
547
548         /* G */
549         if (g) {
550                 ret = _gnutls_mpi_dprint_lz(params->params[2], g);
551                 if (ret < 0) {
552                         gnutls_assert();
553                         _gnutls_free_datum(p);
554                         _gnutls_free_datum(q);
555                         return ret;
556                 }
557         }
558
559
560         /* Y */
561         if (y) {
562                 ret = _gnutls_mpi_dprint_lz(params->params[3], y);
563                 if (ret < 0) {
564                         gnutls_assert();
565                         _gnutls_free_datum(p);
566                         _gnutls_free_datum(g);
567                         _gnutls_free_datum(q);
568                         return ret;
569                 }
570         }
571
572         /* X */
573         if (x) {
574                 ret = _gnutls_mpi_dprint_lz(params->params[4], x);
575                 if (ret < 0) {
576                         gnutls_assert();
577                         _gnutls_free_datum(y);
578                         _gnutls_free_datum(p);
579                         _gnutls_free_datum(g);
580                         _gnutls_free_datum(q);
581                         return ret;
582                 }
583         }
584
585         return 0;
586 }
587
588 int _gnutls_params_get_ecc_raw(const gnutls_pk_params_st* params,
589                                        gnutls_ecc_curve_t * curve,
590                                        gnutls_datum_t * x,
591                                        gnutls_datum_t * y,
592                                        gnutls_datum_t * k)
593 {
594         int ret;
595
596         if (params == NULL) {
597                 gnutls_assert();
598                 return GNUTLS_E_INVALID_REQUEST;
599         }
600
601         if (curve)
602                 *curve = params->flags;
603
604         /* X */
605         if (x) {
606                 ret = _gnutls_mpi_dprint_lz(params->params[ECC_X], x);
607                 if (ret < 0) {
608                         gnutls_assert();
609                         return ret;
610                 }
611         }
612
613         /* Y */
614         if (y) {
615                 ret = _gnutls_mpi_dprint_lz(params->params[ECC_Y], y);
616                 if (ret < 0) {
617                         gnutls_assert();
618                         _gnutls_free_datum(x);
619                         return ret;
620                 }
621         }
622
623
624         /* K */
625         if (k) {
626                 ret = _gnutls_mpi_dprint_lz(params->params[ECC_K], k);
627                 if (ret < 0) {
628                         gnutls_assert();
629                         _gnutls_free_datum(x);
630                         _gnutls_free_datum(y);
631                         return ret;
632                 }
633         }
634
635         return 0;
636
637 }