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)
50 asn1_create_element(_gnutls_get_gnutls_asn(),
51 "GNUTLS.DSASignatureValue",
52 &sig)) != ASN1_SUCCESS) {
54 return _gnutls_asn2err(result);
57 result = asn1_write_value(sig, "r", r->data, r->size);
58 if (result != ASN1_SUCCESS) {
60 asn1_delete_structure(&sig);
61 return _gnutls_asn2err(result);
64 result = asn1_write_value(sig, "s", s->data, s->size);
65 if (result != ASN1_SUCCESS) {
67 asn1_delete_structure(&sig);
68 return _gnutls_asn2err(result);
71 result = _gnutls_x509_der_encode(sig, "", sig_value, 0);
72 asn1_delete_structure(&sig);
75 return gnutls_assert_val(result);
81 _gnutls_encode_ber_rs(gnutls_datum_t * sig_value, bigint_t r, bigint_t s)
87 asn1_create_element(_gnutls_get_gnutls_asn(),
88 "GNUTLS.DSASignatureValue",
89 &sig)) != ASN1_SUCCESS) {
91 return _gnutls_asn2err(result);
94 result = _gnutls_x509_write_int(sig, "r", r, 1);
97 asn1_delete_structure(&sig);
101 result = _gnutls_x509_write_int(sig, "s", s, 1);
104 asn1_delete_structure(&sig);
108 result = _gnutls_x509_der_encode(sig, "", sig_value, 0);
109 asn1_delete_structure(&sig);
112 return gnutls_assert_val(result);
118 /* decodes the Dss-Sig-Value structure
121 _gnutls_decode_ber_rs(const gnutls_datum_t * sig_value, bigint_t * r,
128 asn1_create_element(_gnutls_get_gnutls_asn(),
129 "GNUTLS.DSASignatureValue",
130 &sig)) != ASN1_SUCCESS) {
132 return _gnutls_asn2err(result);
136 asn1_der_decoding(&sig, sig_value->data, sig_value->size,
138 if (result != ASN1_SUCCESS) {
140 asn1_delete_structure(&sig);
141 return _gnutls_asn2err(result);
144 result = _gnutls_x509_read_int(sig, "r", r);
147 asn1_delete_structure(&sig);
151 result = _gnutls_x509_read_int(sig, "s", s);
154 _gnutls_mpi_release(s);
155 asn1_delete_structure(&sig);
159 asn1_delete_structure(&sig);
164 /* some generic pk functions */
166 int _gnutls_pk_params_copy(gnutls_pk_params_st * dst,
167 const gnutls_pk_params_st * src)
172 if (src == NULL || src->params_nr == 0) {
174 return GNUTLS_E_INVALID_REQUEST;
177 dst->flags = src->flags;
178 dst->algo = src->algo;
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) {
192 for (j = 0; j < i; j++)
193 _gnutls_mpi_release(&dst->params[j]);
194 return GNUTLS_E_MEMORY_ERROR;
197 void gnutls_pk_params_init(gnutls_pk_params_st * p)
199 memset(p, 0, sizeof(gnutls_pk_params_st));
202 void gnutls_pk_params_release(gnutls_pk_params_st * p)
205 for (i = 0; i < p->params_nr; i++) {
206 _gnutls_mpi_release(&p->params[i]);
211 void gnutls_pk_params_clear(gnutls_pk_params_st * p)
214 for (i = 0; i < p->params_nr; i++) {
215 if (p->params[i] != NULL)
216 _gnutls_mpi_clear(p->params[i]);
221 _gnutls_pk_get_hash_algorithm(gnutls_pk_algorithm_t pk,
222 gnutls_pk_params_st * params,
223 gnutls_digest_algorithm_t * dig,
227 if (pk == GNUTLS_PK_DSA)
233 return _gnutls_x509_verify_algorithm(dig, NULL, pk, params);
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.
241 encode_ber_digest_info(const mac_entry_st * e,
242 const gnutls_datum_t * digest,
243 gnutls_datum_t * output)
245 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
251 algo = _gnutls_x509_mac_to_oid(e);
254 _gnutls_debug_log("Hash algorithm: %d has no OID\n",
256 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
259 if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
261 &dinfo)) != ASN1_SUCCESS) {
263 return _gnutls_asn2err(result);
267 asn1_write_value(dinfo, "digestAlgorithm.algorithm", algo, 1);
268 if (result != ASN1_SUCCESS) {
270 asn1_delete_structure(&dinfo);
271 return _gnutls_asn2err(result);
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) {
283 asn1_delete_structure(&dinfo);
284 return _gnutls_asn2err(result);
288 asn1_write_value(dinfo, "digest", digest->data, digest->size);
289 if (result != ASN1_SUCCESS) {
291 asn1_delete_structure(&dinfo);
292 return _gnutls_asn2err(result);
296 result = asn1_der_coding(dinfo, "", NULL, &tmp_output_size, NULL);
297 if (result != ASN1_MEM_ERROR) {
299 asn1_delete_structure(&dinfo);
300 return _gnutls_asn2err(result);
303 tmp_output = gnutls_malloc(tmp_output_size);
304 if (tmp_output == NULL) {
306 asn1_delete_structure(&dinfo);
307 return GNUTLS_E_MEMORY_ERROR;
311 asn1_der_coding(dinfo, "", tmp_output, &tmp_output_size, NULL);
312 if (result != ASN1_SUCCESS) {
314 asn1_delete_structure(&dinfo);
315 return _gnutls_asn2err(result);
318 asn1_delete_structure(&dinfo);
320 output->size = tmp_output_size;
321 output->data = tmp_output;
326 /* Reads the digest information.
327 * we use DER here, although we should use BER. It works fine
331 decode_ber_digest_info(const gnutls_datum_t * info,
332 gnutls_digest_algorithm_t * hash,
333 uint8_t * digest, unsigned int *digest_size)
335 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
337 char str[MAX(MAX_OID_SIZE, MAX_HASH_SIZE)];
340 if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
342 &dinfo)) != ASN1_SUCCESS) {
344 return _gnutls_asn2err(result);
347 result = asn1_der_decoding(&dinfo, info->data, info->size, NULL);
348 if (result != ASN1_SUCCESS) {
350 asn1_delete_structure(&dinfo);
351 return _gnutls_asn2err(result);
354 len = sizeof(str) - 1;
356 asn1_read_value(dinfo, "digestAlgorithm.algorithm", str, &len);
357 if (result != ASN1_SUCCESS) {
359 asn1_delete_structure(&dinfo);
360 return _gnutls_asn2err(result);
363 *hash = _gnutls_x509_oid_to_digest(str);
365 if (*hash == GNUTLS_DIG_UNKNOWN) {
367 _gnutls_debug_log("verify.c: HASH OID: %s\n", str);
370 asn1_delete_structure(&dinfo);
371 return GNUTLS_E_UNKNOWN_ALGORITHM;
374 len = sizeof(str) - 1;
376 asn1_read_value(dinfo, "digestAlgorithm.parameters", str,
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))) {
384 asn1_delete_structure(&dinfo);
385 return GNUTLS_E_ASN1_GENERIC_ERROR;
389 result = asn1_read_value(dinfo, "digest", digest, &len);
391 if (result != ASN1_SUCCESS) {
394 asn1_delete_structure(&dinfo);
395 return _gnutls_asn2err(result);
399 asn1_delete_structure(&dinfo);
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,
414 if (params == NULL) {
416 return GNUTLS_E_INVALID_REQUEST;
419 if (params->algo != GNUTLS_PK_RSA) {
421 return GNUTLS_E_INVALID_REQUEST;
425 ret = _gnutls_mpi_dprint_lz(params->params[0], m);
434 ret = _gnutls_mpi_dprint_lz(params->params[1], e);
443 ret = _gnutls_mpi_dprint_lz(params->params[2], d);
452 ret = _gnutls_mpi_dprint_lz(params->params[3], p);
461 ret = _gnutls_mpi_dprint_lz(params->params[4], q);
470 ret = _gnutls_mpi_dprint_lz(params->params[5], u);
479 ret = _gnutls_mpi_dprint_lz(params->params[6], e1);
488 ret = _gnutls_mpi_dprint_lz(params->params[7], e2);
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);
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,
517 if (params == NULL) {
519 return GNUTLS_E_INVALID_REQUEST;
522 if (params->algo != GNUTLS_PK_DSA) {
524 return GNUTLS_E_INVALID_REQUEST;
529 ret = _gnutls_mpi_dprint_lz(params->params[0], p);
538 ret = _gnutls_mpi_dprint_lz(params->params[1], q);
541 _gnutls_free_datum(p);
549 ret = _gnutls_mpi_dprint_lz(params->params[2], g);
552 _gnutls_free_datum(p);
553 _gnutls_free_datum(q);
561 ret = _gnutls_mpi_dprint_lz(params->params[3], y);
564 _gnutls_free_datum(p);
565 _gnutls_free_datum(g);
566 _gnutls_free_datum(q);
573 ret = _gnutls_mpi_dprint_lz(params->params[4], x);
576 _gnutls_free_datum(y);
577 _gnutls_free_datum(p);
578 _gnutls_free_datum(g);
579 _gnutls_free_datum(q);
587 int _gnutls_params_get_ecc_raw(const gnutls_pk_params_st* params,
588 gnutls_ecc_curve_t * curve,
595 if (params == NULL) {
597 return GNUTLS_E_INVALID_REQUEST;
601 *curve = params->flags;
605 ret = _gnutls_mpi_dprint_lz(params->params[ECC_X], x);
614 ret = _gnutls_mpi_dprint_lz(params->params[ECC_Y], y);
617 _gnutls_free_datum(x);
625 ret = _gnutls_mpi_dprint_lz(params->params[ECC_K], k);
628 _gnutls_free_datum(x);
629 _gnutls_free_datum(y);