2 * Copyright (C) 2001-2014 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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.
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.
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/>
23 /* This file contains the functions needed for RSA/DSA public key
24 * encryption and signatures.
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>
35 #include <x509/x509_int.h>
36 #include <x509/common.h>
39 /* encodes the Dss-Sig-Value structure
42 _gnutls_encode_ber_rs_raw(gnutls_datum_t * sig_value,
43 const gnutls_datum_t * r,
44 const gnutls_datum_t * s)
51 asn1_create_element(_gnutls_get_gnutls_asn(),
52 "GNUTLS.DSASignatureValue",
53 &sig)) != ASN1_SUCCESS) {
55 return _gnutls_asn2err(result);
58 if (r->data[0] >= 0x80) {
59 tmp = gnutls_malloc(r->size+1);
61 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
64 memcpy(&tmp[1], r->data, r->size);
66 result = asn1_write_value(sig, "r", tmp, 1+r->size);
71 result = asn1_write_value(sig, "r", r->data, r->size);
73 if (result != ASN1_SUCCESS) {
75 ret = _gnutls_asn2err(result);
79 if (s->data[0] >= 0x80) {
80 tmp = gnutls_malloc(s->size+1);
82 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
85 memcpy(&tmp[1], s->data, s->size);
87 result = asn1_write_value(sig, "s", tmp, 1+s->size);
92 result = asn1_write_value(sig, "s", s->data, s->size);
95 if (result != ASN1_SUCCESS) {
97 ret = _gnutls_asn2err(result);
101 ret = _gnutls_x509_der_encode(sig, "", sig_value, 0);
109 asn1_delete_structure(&sig);
114 _gnutls_encode_ber_rs(gnutls_datum_t * sig_value, bigint_t r, bigint_t s)
120 asn1_create_element(_gnutls_get_gnutls_asn(),
121 "GNUTLS.DSASignatureValue",
122 &sig)) != ASN1_SUCCESS) {
124 return _gnutls_asn2err(result);
127 result = _gnutls_x509_write_int(sig, "r", r, 1);
130 asn1_delete_structure(&sig);
134 result = _gnutls_x509_write_int(sig, "s", s, 1);
137 asn1_delete_structure(&sig);
141 result = _gnutls_x509_der_encode(sig, "", sig_value, 0);
142 asn1_delete_structure(&sig);
145 return gnutls_assert_val(result);
151 /* decodes the Dss-Sig-Value structure
154 _gnutls_decode_ber_rs(const gnutls_datum_t * sig_value, bigint_t * r,
161 asn1_create_element(_gnutls_get_gnutls_asn(),
162 "GNUTLS.DSASignatureValue",
163 &sig)) != ASN1_SUCCESS) {
165 return _gnutls_asn2err(result);
169 asn1_der_decoding(&sig, sig_value->data, sig_value->size,
171 if (result != ASN1_SUCCESS) {
173 asn1_delete_structure(&sig);
174 return _gnutls_asn2err(result);
177 result = _gnutls_x509_read_int(sig, "r", r);
180 asn1_delete_structure(&sig);
184 result = _gnutls_x509_read_int(sig, "s", s);
187 _gnutls_mpi_release(s);
188 asn1_delete_structure(&sig);
192 asn1_delete_structure(&sig);
197 /* some generic pk functions */
199 int _gnutls_pk_params_copy(gnutls_pk_params_st * dst,
200 const gnutls_pk_params_st * src)
205 if (src == NULL || src->params_nr == 0) {
207 return GNUTLS_E_INVALID_REQUEST;
210 dst->flags = src->flags;
211 dst->algo = src->algo;
213 for (i = 0; i < src->params_nr; i++) {
214 dst->params[i] = _gnutls_mpi_copy(src->params[i]);
215 if (dst->params[i] == NULL) {
225 for (j = 0; j < i; j++)
226 _gnutls_mpi_release(&dst->params[j]);
227 return GNUTLS_E_MEMORY_ERROR;
230 void gnutls_pk_params_init(gnutls_pk_params_st * p)
232 memset(p, 0, sizeof(gnutls_pk_params_st));
235 void gnutls_pk_params_release(gnutls_pk_params_st * p)
238 for (i = 0; i < p->params_nr; i++) {
239 _gnutls_mpi_release(&p->params[i]);
244 void gnutls_pk_params_clear(gnutls_pk_params_st * p)
247 for (i = 0; i < p->params_nr; i++) {
248 if (p->params[i] != NULL)
249 _gnutls_mpi_clear(p->params[i]);
254 _gnutls_pk_get_hash_algorithm(gnutls_pk_algorithm_t pk,
255 gnutls_pk_params_st * params,
256 gnutls_digest_algorithm_t * dig,
260 if (pk == GNUTLS_PK_DSA)
266 return _gnutls_x509_verify_algorithm(dig, NULL, pk, params);
270 /* Writes the digest information and the digest in a DER encoded
271 * structure. The digest info is allocated and stored into the info structure.
274 encode_ber_digest_info(const mac_entry_st * e,
275 const gnutls_datum_t * digest,
276 gnutls_datum_t * output)
278 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
284 algo = _gnutls_x509_mac_to_oid(e);
287 _gnutls_debug_log("Hash algorithm: %d has no OID\n",
289 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
292 if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
294 &dinfo)) != ASN1_SUCCESS) {
296 return _gnutls_asn2err(result);
300 asn1_write_value(dinfo, "digestAlgorithm.algorithm", algo, 1);
301 if (result != ASN1_SUCCESS) {
303 asn1_delete_structure(&dinfo);
304 return _gnutls_asn2err(result);
307 /* Write an ASN.1 NULL in the parameters field. This matches RFC
308 3279 and RFC 4055, although is arguable incorrect from a historic
309 perspective (see those documents for more information).
310 Regardless of what is correct, this appears to be what most
311 implementations do. */
312 result = asn1_write_value(dinfo, "digestAlgorithm.parameters",
313 ASN1_NULL, ASN1_NULL_SIZE);
314 if (result != ASN1_SUCCESS) {
316 asn1_delete_structure(&dinfo);
317 return _gnutls_asn2err(result);
321 asn1_write_value(dinfo, "digest", digest->data, digest->size);
322 if (result != ASN1_SUCCESS) {
324 asn1_delete_structure(&dinfo);
325 return _gnutls_asn2err(result);
329 result = asn1_der_coding(dinfo, "", NULL, &tmp_output_size, NULL);
330 if (result != ASN1_MEM_ERROR) {
332 asn1_delete_structure(&dinfo);
333 return _gnutls_asn2err(result);
336 tmp_output = gnutls_malloc(tmp_output_size);
337 if (tmp_output == NULL) {
339 asn1_delete_structure(&dinfo);
340 return GNUTLS_E_MEMORY_ERROR;
344 asn1_der_coding(dinfo, "", tmp_output, &tmp_output_size, NULL);
345 if (result != ASN1_SUCCESS) {
347 asn1_delete_structure(&dinfo);
348 return _gnutls_asn2err(result);
351 asn1_delete_structure(&dinfo);
353 output->size = tmp_output_size;
354 output->data = tmp_output;
359 /* Reads the digest information.
360 * we use DER here, although we should use BER. It works fine
364 decode_ber_digest_info(const gnutls_datum_t * info,
365 gnutls_digest_algorithm_t * hash,
366 uint8_t * digest, unsigned int *digest_size)
368 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
370 char str[MAX(MAX_OID_SIZE, MAX_HASH_SIZE)];
373 if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
375 &dinfo)) != ASN1_SUCCESS) {
377 return _gnutls_asn2err(result);
380 result = asn1_der_decoding(&dinfo, info->data, info->size, NULL);
381 if (result != ASN1_SUCCESS) {
383 asn1_delete_structure(&dinfo);
384 return _gnutls_asn2err(result);
387 len = sizeof(str) - 1;
389 asn1_read_value(dinfo, "digestAlgorithm.algorithm", str, &len);
390 if (result != ASN1_SUCCESS) {
392 asn1_delete_structure(&dinfo);
393 return _gnutls_asn2err(result);
396 *hash = _gnutls_x509_oid_to_digest(str);
398 if (*hash == GNUTLS_DIG_UNKNOWN) {
400 _gnutls_debug_log("verify.c: HASH OID: %s\n", str);
403 asn1_delete_structure(&dinfo);
404 return GNUTLS_E_UNKNOWN_ALGORITHM;
407 len = sizeof(str) - 1;
409 asn1_read_value(dinfo, "digestAlgorithm.parameters", str,
411 /* To avoid permitting garbage in the parameters field, either the
412 parameters field is not present, or it contains 0x05 0x00. */
413 if (!(result == ASN1_ELEMENT_NOT_FOUND ||
414 (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
415 memcmp(str, ASN1_NULL, ASN1_NULL_SIZE) == 0))) {
417 asn1_delete_structure(&dinfo);
418 return GNUTLS_E_ASN1_GENERIC_ERROR;
422 result = asn1_read_value(dinfo, "digest", digest, &len);
424 if (result != ASN1_SUCCESS) {
427 asn1_delete_structure(&dinfo);
428 return _gnutls_asn2err(result);
432 asn1_delete_structure(&dinfo);
438 _gnutls_params_get_rsa_raw(const gnutls_pk_params_st* params,
439 gnutls_datum_t * m, gnutls_datum_t * e,
440 gnutls_datum_t * d, gnutls_datum_t * p,
441 gnutls_datum_t * q, gnutls_datum_t * u,
447 if (params == NULL) {
449 return GNUTLS_E_INVALID_REQUEST;
452 if (params->algo != GNUTLS_PK_RSA) {
454 return GNUTLS_E_INVALID_REQUEST;
458 ret = _gnutls_mpi_dprint_lz(params->params[0], m);
467 ret = _gnutls_mpi_dprint_lz(params->params[1], e);
475 if (d && params->params[2]) {
476 ret = _gnutls_mpi_dprint_lz(params->params[2], d);
487 if (p && params->params[3]) {
488 ret = _gnutls_mpi_dprint_lz(params->params[3], p);
499 if (q && params->params[4]) {
500 ret = _gnutls_mpi_dprint_lz(params->params[4], q);
511 if (u && params->params[5]) {
512 ret = _gnutls_mpi_dprint_lz(params->params[5], u);
523 if (e1 && params->params[6]) {
524 ret = _gnutls_mpi_dprint_lz(params->params[6], e1);
535 if (e2 && params->params[7]) {
536 ret = _gnutls_mpi_dprint_lz(params->params[7], e2);
549 _gnutls_free_datum(m);
550 _gnutls_free_datum(d);
551 _gnutls_free_datum(e);
552 _gnutls_free_datum(e1);
553 _gnutls_free_datum(e2);
554 _gnutls_free_datum(p);
555 _gnutls_free_datum(q);
561 _gnutls_params_get_dsa_raw(const gnutls_pk_params_st* params,
562 gnutls_datum_t * p, gnutls_datum_t * q,
563 gnutls_datum_t * g, gnutls_datum_t * y,
568 if (params == NULL) {
570 return GNUTLS_E_INVALID_REQUEST;
573 if (params->algo != GNUTLS_PK_DSA) {
575 return GNUTLS_E_INVALID_REQUEST;
580 ret = _gnutls_mpi_dprint_lz(params->params[0], p);
589 ret = _gnutls_mpi_dprint_lz(params->params[1], q);
592 _gnutls_free_datum(p);
600 ret = _gnutls_mpi_dprint_lz(params->params[2], g);
603 _gnutls_free_datum(p);
604 _gnutls_free_datum(q);
612 ret = _gnutls_mpi_dprint_lz(params->params[3], y);
615 _gnutls_free_datum(p);
616 _gnutls_free_datum(g);
617 _gnutls_free_datum(q);
624 ret = _gnutls_mpi_dprint_lz(params->params[4], x);
627 _gnutls_free_datum(y);
628 _gnutls_free_datum(p);
629 _gnutls_free_datum(g);
630 _gnutls_free_datum(q);
638 int _gnutls_params_get_ecc_raw(const gnutls_pk_params_st* params,
639 gnutls_ecc_curve_t * curve,
646 if (params == NULL) {
648 return GNUTLS_E_INVALID_REQUEST;
652 *curve = params->flags;
656 ret = _gnutls_mpi_dprint_lz(params->params[ECC_X], x);
665 ret = _gnutls_mpi_dprint_lz(params->params[ECC_Y], y);
668 _gnutls_free_datum(x);
676 ret = _gnutls_mpi_dprint_lz(params->params[ECC_K], k);
679 _gnutls_free_datum(x);
680 _gnutls_free_datum(y);