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>
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
)
55 return _gnutls_asn2err (result
);
58 result
= asn1_write_value( sig
, "r", r
->data
, r
->size
);
59 if (result
!= ASN1_SUCCESS
)
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
)
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
);
78 return gnutls_assert_val(result
);
84 _gnutls_encode_ber_rs (gnutls_datum_t
* sig_value
, bigint_t r
, bigint_t s
)
90 asn1_create_element (_gnutls_get_gnutls_asn (),
91 "GNUTLS.DSASignatureValue",
92 &sig
)) != ASN1_SUCCESS
)
95 return _gnutls_asn2err (result
);
98 result
= _gnutls_x509_write_int (sig
, "r", r
, 1);
102 asn1_delete_structure (&sig
);
106 result
= _gnutls_x509_write_int (sig
, "s", s
, 1);
110 asn1_delete_structure (&sig
);
114 result
= _gnutls_x509_der_encode (sig
, "", sig_value
, 0);
115 asn1_delete_structure (&sig
);
118 return gnutls_assert_val(result
);
124 /* decodes the Dss-Sig-Value structure
127 _gnutls_decode_ber_rs (const gnutls_datum_t
* sig_value
, bigint_t
* r
,
134 asn1_create_element (_gnutls_get_gnutls_asn (),
135 "GNUTLS.DSASignatureValue",
136 &sig
)) != ASN1_SUCCESS
)
139 return _gnutls_asn2err (result
);
142 result
= asn1_der_decoding (&sig
, sig_value
->data
, sig_value
->size
, NULL
);
143 if (result
!= ASN1_SUCCESS
)
146 asn1_delete_structure (&sig
);
147 return _gnutls_asn2err (result
);
150 result
= _gnutls_x509_read_int (sig
, "r", r
);
154 asn1_delete_structure (&sig
);
158 result
= _gnutls_x509_read_int (sig
, "s", s
);
162 _gnutls_mpi_release (s
);
163 asn1_delete_structure (&sig
);
167 asn1_delete_structure (&sig
);
172 /* some generic pk functions */
174 int _gnutls_pk_params_copy (gnutls_pk_params_st
* dst
, const gnutls_pk_params_st
* src
)
179 if (src
== NULL
|| src
->params_nr
== 0)
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
;
201 gnutls_pk_params_init (gnutls_pk_params_st
* p
)
203 memset (p
, 0, sizeof (gnutls_pk_params_st
));
207 gnutls_pk_params_release (gnutls_pk_params_st
* p
)
210 for (i
= 0; i
< p
->params_nr
; i
++)
212 _gnutls_mpi_release (&p
->params
[i
]);
218 _gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk
,
219 gnutls_pk_params_st
* params
,
220 gnutls_digest_algorithm_t
* dig
,
225 if (pk
== GNUTLS_PK_DSA
)
231 return _gnutls_x509_verify_algorithm (dig
,
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
;
250 algo
= _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t
) hash
);
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 (),
260 &dinfo
)) != ASN1_SUCCESS
)
263 return _gnutls_asn2err (result
);
266 result
= asn1_write_value (dinfo
, "digestAlgorithm.algorithm", algo
, 1);
267 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
)
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
)
292 asn1_delete_structure (&dinfo
);
293 return _gnutls_asn2err (result
);
297 asn1_der_coding (dinfo
, "", NULL
, &tmp_output_size
, NULL
);
299 tmp_output
= gnutls_malloc (tmp_output_size
);
300 if (tmp_output
== NULL
)
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
)
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
;
323 /* Reads the digest information.
324 * we use DER here, although we should use BER. It works fine
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
;
337 if ((result
= asn1_create_element (_gnutls_get_gnutls_asn (),
339 &dinfo
)) != ASN1_SUCCESS
)
342 return _gnutls_asn2err (result
);
345 result
= asn1_der_decoding (&dinfo
, info
->data
, info
->size
, NULL
);
346 if (result
!= ASN1_SUCCESS
)
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
)
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
);
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)))
383 asn1_delete_structure (&dinfo
);
384 return GNUTLS_E_ASN1_GENERIC_ERROR
;
388 result
= asn1_read_value (dinfo
, "digest", digest
, &len
);
390 if (result
!= ASN1_SUCCESS
)
394 asn1_delete_structure (&dinfo
);
395 return _gnutls_asn2err (result
);
399 asn1_delete_structure (&dinfo
);