added new functions
[gnutls.git] / lib / gnutls_pk.c
blobf65b7dad1a99e099cba9212266043f09acb08b78
1 /*
2 * Copyright (C) 2001-2012 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 3 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>
34 #include "debug.h"
35 #include <x509/x509_int.h>
36 #include <x509/common.h>
37 #include <random.h>
39 /* encodes the Dss-Sig-Value structure
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)
46 ASN1_TYPE sig;
47 int result;
49 if ((result =
50 asn1_create_element (_gnutls_get_gnutls_asn (),
51 "GNUTLS.DSASignatureValue",
52 &sig)) != ASN1_SUCCESS)
54 gnutls_assert ();
55 return _gnutls_asn2err (result);
58 result = asn1_write_value( sig, "r", r->data, r->size);
59 if (result != ASN1_SUCCESS)
61 gnutls_assert ();
62 asn1_delete_structure (&sig);
63 return _gnutls_asn2err(result);
66 result = asn1_write_value( sig, "s", s->data, s->size);
67 if (result != ASN1_SUCCESS)
69 gnutls_assert ();
70 asn1_delete_structure (&sig);
71 return _gnutls_asn2err(result);
74 result = _gnutls_x509_der_encode (sig, "", sig_value, 0);
75 asn1_delete_structure (&sig);
77 if (result < 0)
78 return gnutls_assert_val(result);
80 return 0;
83 int
84 _gnutls_encode_ber_rs (gnutls_datum_t * sig_value, bigint_t r, bigint_t s)
86 ASN1_TYPE sig;
87 int result;
89 if ((result =
90 asn1_create_element (_gnutls_get_gnutls_asn (),
91 "GNUTLS.DSASignatureValue",
92 &sig)) != ASN1_SUCCESS)
94 gnutls_assert ();
95 return _gnutls_asn2err (result);
98 result = _gnutls_x509_write_int (sig, "r", r, 1);
99 if (result < 0)
101 gnutls_assert ();
102 asn1_delete_structure (&sig);
103 return result;
106 result = _gnutls_x509_write_int (sig, "s", s, 1);
107 if (result < 0)
109 gnutls_assert ();
110 asn1_delete_structure (&sig);
111 return result;
114 result = _gnutls_x509_der_encode (sig, "", sig_value, 0);
115 asn1_delete_structure (&sig);
117 if (result < 0)
118 return gnutls_assert_val(result);
120 return 0;
124 /* decodes the Dss-Sig-Value structure
127 _gnutls_decode_ber_rs (const gnutls_datum_t * sig_value, bigint_t * r,
128 bigint_t * s)
130 ASN1_TYPE sig;
131 int result;
133 if ((result =
134 asn1_create_element (_gnutls_get_gnutls_asn (),
135 "GNUTLS.DSASignatureValue",
136 &sig)) != ASN1_SUCCESS)
138 gnutls_assert ();
139 return _gnutls_asn2err (result);
142 result = asn1_der_decoding (&sig, sig_value->data, sig_value->size, NULL);
143 if (result != ASN1_SUCCESS)
145 gnutls_assert ();
146 asn1_delete_structure (&sig);
147 return _gnutls_asn2err (result);
150 result = _gnutls_x509_read_int (sig, "r", r);
151 if (result < 0)
153 gnutls_assert ();
154 asn1_delete_structure (&sig);
155 return result;
158 result = _gnutls_x509_read_int (sig, "s", s);
159 if (result < 0)
161 gnutls_assert ();
162 _gnutls_mpi_release (s);
163 asn1_delete_structure (&sig);
164 return result;
167 asn1_delete_structure (&sig);
169 return 0;
172 /* some generic pk functions */
174 int _gnutls_pk_params_copy (gnutls_pk_params_st * dst, const gnutls_pk_params_st * src)
176 unsigned int i, j;
177 dst->params_nr = 0;
179 if (src == NULL || src->params_nr == 0)
181 gnutls_assert ();
182 return GNUTLS_E_INVALID_REQUEST;
185 for (i = 0; i < src->params_nr; i++)
187 dst->params[i] = _gnutls_mpi_set (NULL, src->params[i]);
188 if (dst->params[i] == NULL)
190 for (j = 0; j < i; j++)
191 _gnutls_mpi_release (&dst->params[j]);
192 return GNUTLS_E_MEMORY_ERROR;
194 dst->params_nr++;
197 return 0;
200 void
201 gnutls_pk_params_init (gnutls_pk_params_st * p)
203 memset (p, 0, sizeof (gnutls_pk_params_st));
206 void
207 gnutls_pk_params_release (gnutls_pk_params_st * p)
209 unsigned int i;
210 for (i = 0; i < p->params_nr; i++)
212 _gnutls_mpi_release (&p->params[i]);
214 p->params_nr = 0;
218 _gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk,
219 gnutls_pk_params_st* params,
220 gnutls_digest_algorithm_t * dig,
221 unsigned int *mand)
223 if (mand)
225 if (pk == GNUTLS_PK_DSA)
226 *mand = 1;
227 else
228 *mand = 0;
231 return _gnutls_x509_verify_algorithm (dig,
232 NULL, pk, params);
236 /* Writes the digest information and the digest in a DER encoded
237 * structure. The digest info is allocated and stored into the info structure.
240 encode_ber_digest_info (gnutls_digest_algorithm_t hash,
241 const gnutls_datum_t * digest,
242 gnutls_datum_t * output)
244 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
245 int result;
246 const char *algo;
247 uint8_t *tmp_output;
248 int tmp_output_size;
250 algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
251 if (algo == NULL)
253 gnutls_assert ();
254 _gnutls_debug_log ("Hash algorithm: %d has no OID\n", hash);
255 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
258 if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
259 "GNUTLS.DigestInfo",
260 &dinfo)) != ASN1_SUCCESS)
262 gnutls_assert ();
263 return _gnutls_asn2err (result);
266 result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
267 if (result != ASN1_SUCCESS)
269 gnutls_assert ();
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 gnutls_assert ();
284 asn1_delete_structure (&dinfo);
285 return _gnutls_asn2err (result);
288 result = asn1_write_value (dinfo, "digest", digest->data, digest->size);
289 if (result != ASN1_SUCCESS)
291 gnutls_assert ();
292 asn1_delete_structure (&dinfo);
293 return _gnutls_asn2err (result);
296 tmp_output_size = 0;
297 asn1_der_coding (dinfo, "", NULL, &tmp_output_size, NULL);
299 tmp_output = gnutls_malloc (tmp_output_size);
300 if (tmp_output == NULL)
302 gnutls_assert ();
303 asn1_delete_structure (&dinfo);
304 return GNUTLS_E_MEMORY_ERROR;
307 result = asn1_der_coding (dinfo, "", tmp_output, &tmp_output_size, NULL);
308 if (result != ASN1_SUCCESS)
310 gnutls_assert ();
311 asn1_delete_structure (&dinfo);
312 return _gnutls_asn2err (result);
315 asn1_delete_structure (&dinfo);
317 output->size = tmp_output_size;
318 output->data = tmp_output;
320 return 0;
323 /* Reads the digest information.
324 * we use DER here, although we should use BER. It works fine
325 * anyway.
328 decode_ber_digest_info (const gnutls_datum_t * info,
329 gnutls_digest_algorithm_t * hash,
330 uint8_t * digest, unsigned int *digest_size)
332 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
333 int result;
334 char str[1024];
335 int len;
337 if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
338 "GNUTLS.DigestInfo",
339 &dinfo)) != ASN1_SUCCESS)
341 gnutls_assert ();
342 return _gnutls_asn2err (result);
345 result = asn1_der_decoding (&dinfo, info->data, info->size, NULL);
346 if (result != ASN1_SUCCESS)
348 gnutls_assert ();
349 asn1_delete_structure (&dinfo);
350 return _gnutls_asn2err (result);
353 len = sizeof (str) - 1;
354 result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len);
355 if (result != ASN1_SUCCESS)
357 gnutls_assert ();
358 asn1_delete_structure (&dinfo);
359 return _gnutls_asn2err (result);
362 *hash = _gnutls_x509_oid_to_digest (str);
364 if (*hash == GNUTLS_DIG_UNKNOWN)
367 _gnutls_debug_log ("verify.c: HASH OID: %s\n", str);
369 gnutls_assert ();
370 asn1_delete_structure (&dinfo);
371 return GNUTLS_E_UNKNOWN_ALGORITHM;
374 len = sizeof (str) - 1;
375 result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len);
376 /* To avoid permitting garbage in the parameters field, either the
377 parameters field is not present, or it contains 0x05 0x00. */
378 if (!(result == ASN1_ELEMENT_NOT_FOUND ||
379 (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
380 memcmp (str, ASN1_NULL, ASN1_NULL_SIZE) == 0)))
382 gnutls_assert ();
383 asn1_delete_structure (&dinfo);
384 return GNUTLS_E_ASN1_GENERIC_ERROR;
387 len = *digest_size;
388 result = asn1_read_value (dinfo, "digest", digest, &len);
390 if (result != ASN1_SUCCESS)
392 gnutls_assert ();
393 *digest_size = len;
394 asn1_delete_structure (&dinfo);
395 return _gnutls_asn2err (result);
398 *digest_size = len;
399 asn1_delete_structure (&dinfo);
401 return 0;