Be tolerant in ECDSA-violating signatures.
[gnutls.git] / lib / gnutls_sig.c
blob5a78e026d480d9b8db5862ccfad6a1a89780912d
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 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <x509_b64.h>
26 #include <auth/cert.h>
27 #include <algorithms.h>
28 #include <gnutls_datum.h>
29 #include <gnutls_mpi.h>
30 #include <gnutls_global.h>
31 #include <gnutls_pk.h>
32 #include <debug.h>
33 #include <gnutls_buffers.h>
34 #include <gnutls_sig.h>
35 #include <gnutls_kx.h>
36 #include <libtasn1.h>
37 #include <ext/signature.h>
38 #include <gnutls_state.h>
39 #include <x509/common.h>
40 #include <abstract_int.h>
42 static int
43 sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
44 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
45 const gnutls_datum_t * hash_concat,
46 gnutls_datum_t * signature);
48 static int
49 encode_ber_digest_info (gnutls_digest_algorithm_t hash,
50 const gnutls_datum_t * digest,
51 gnutls_datum_t * output);
53 /* While this is currently equal to the length of RSA/SHA512
54 * signature, it should also be sufficient for DSS signature and any
55 * other RSA signatures including one with the old MD5/SHA1-combined
56 * format.
58 #define MAX_SIG_SIZE 19 + MAX_HASH_SIZE
60 /* Generates a signature of all the random data and the parameters.
61 * Used in DHE_* ciphersuites.
63 int
64 _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_pcert_st* cert,
65 gnutls_privkey_t pkey, gnutls_datum_t * params,
66 gnutls_datum_t * signature,
67 gnutls_sign_algorithm_t * sign_algo)
69 gnutls_datum_t dconcat;
70 int ret;
71 digest_hd_st td_sha;
72 uint8_t concat[MAX_SIG_SIZE];
73 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
74 gnutls_digest_algorithm_t hash_algo;
76 *sign_algo =
77 _gnutls_session_get_sign_algo (session, cert);
78 if (*sign_algo == GNUTLS_SIGN_UNKNOWN)
80 gnutls_assert ();
81 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
84 hash_algo = _gnutls_sign_get_hash_algorithm (*sign_algo);
86 _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n",
87 session, gnutls_sign_algorithm_get_name (*sign_algo));
89 ret = _gnutls_hash_init (&td_sha, hash_algo);
90 if (ret < 0)
92 gnutls_assert ();
93 return ret;
96 _gnutls_hash (&td_sha, session->security_parameters.client_random,
97 GNUTLS_RANDOM_SIZE);
98 _gnutls_hash (&td_sha, session->security_parameters.server_random,
99 GNUTLS_RANDOM_SIZE);
100 _gnutls_hash (&td_sha, params->data, params->size);
102 switch (gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL))
104 case GNUTLS_PK_RSA:
105 if (!_gnutls_version_has_selectable_sighash (ver))
107 digest_hd_st td_md5;
109 ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
110 if (ret < 0)
112 gnutls_assert ();
113 return ret;
116 _gnutls_hash (&td_md5, session->security_parameters.client_random,
117 GNUTLS_RANDOM_SIZE);
118 _gnutls_hash (&td_md5, session->security_parameters.server_random,
119 GNUTLS_RANDOM_SIZE);
120 _gnutls_hash (&td_md5, params->data, params->size);
122 _gnutls_hash_deinit (&td_md5, concat);
123 _gnutls_hash_deinit (&td_sha, &concat[16]);
125 dconcat.data = concat;
126 dconcat.size = 36;
128 else
129 { /* TLS 1.2 way */
131 _gnutls_hash_deinit (&td_sha, concat);
133 dconcat.data = concat;
134 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
136 break;
137 case GNUTLS_PK_DSA:
138 case GNUTLS_PK_EC:
139 _gnutls_hash_deinit (&td_sha, concat);
141 if (!IS_SHA(hash_algo))
143 gnutls_assert ();
144 return GNUTLS_E_INTERNAL_ERROR;
146 dconcat.data = concat;
147 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
148 break;
150 default:
151 gnutls_assert ();
152 _gnutls_hash_deinit (&td_sha, NULL);
153 return GNUTLS_E_INTERNAL_ERROR;
156 ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
157 if (ret < 0)
159 gnutls_assert ();
162 return ret;
167 /* This will create a PKCS1 or DSA signature, using the given parameters, and the
168 * given data. The output will be allocated and be put in signature.
171 _gnutls_soft_sign (gnutls_pk_algorithm_t algo, gnutls_pk_params_st * params,
172 const gnutls_datum_t * data,
173 gnutls_datum_t * signature)
175 int ret;
177 switch (algo)
179 case GNUTLS_PK_RSA:
180 /* encrypt */
181 if ((ret = _gnutls_pkcs1_rsa_encrypt (signature, data, params, 1)) < 0)
183 gnutls_assert ();
184 return ret;
187 break;
188 default:
189 ret = _gnutls_pk_sign( algo, signature, data, params);
190 if (ret < 0)
192 gnutls_assert ();
193 return ret;
195 break;
198 return 0;
201 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
202 * Cert is the certificate of the corresponding private key. It is only checked if
203 * it supports signing.
205 static int
206 sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
207 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
208 const gnutls_datum_t * hash_concat,
209 gnutls_datum_t * signature)
211 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
212 unsigned int key_usage = 0;
213 /* If our certificate supports signing
216 if (cert != NULL)
218 gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
220 if (key_usage != 0)
221 if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
223 gnutls_assert ();
224 return GNUTLS_E_KEY_USAGE_VIOLATION;
227 /* External signing. Deprecated. To be removed. */
228 if (!pkey)
230 int ret;
232 if (!session->internals.sign_func)
233 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
235 if (!_gnutls_version_has_selectable_sighash (ver))
236 return (*session->internals.sign_func)
237 (session, session->internals.sign_func_userdata,
238 cert->type, &cert->cert, hash_concat, signature);
239 else
241 gnutls_datum_t digest;
243 ret = _gnutls_set_datum(&digest, hash_concat->data, hash_concat->size);
244 if (ret < 0)
245 return gnutls_assert_val(ret);
247 ret = pk_prepare_hash (gnutls_privkey_get_pk_algorithm(pkey, NULL), hash_algo, &digest);
248 if (ret < 0)
250 gnutls_assert ();
251 goto es_cleanup;
254 ret = (*session->internals.sign_func)
255 (session, session->internals.sign_func_userdata,
256 cert->type, &cert->cert, &digest, signature);
257 es_cleanup:
258 gnutls_free(digest.data);
260 return ret;
265 if (!_gnutls_version_has_selectable_sighash (ver))
266 return _gnutls_privkey_sign_hash (pkey, hash_concat, signature);
267 else
268 return gnutls_privkey_sign_hash (pkey, hash_algo, 0, hash_concat, signature);
271 static int
272 verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert,
273 const gnutls_datum_t * hash_concat,
274 gnutls_datum_t * signature, size_t sha1pos,
275 gnutls_sign_algorithm_t sign_algo,
276 gnutls_pk_algorithm_t pk_algo)
278 int ret;
279 gnutls_datum_t vdata;
280 unsigned int key_usage = 0, flags;
282 if (cert == NULL)
284 gnutls_assert ();
285 return GNUTLS_E_CERTIFICATE_ERROR;
288 gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
290 /* If the certificate supports signing continue.
292 if (key_usage != 0)
293 if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
295 gnutls_assert ();
296 return GNUTLS_E_KEY_USAGE_VIOLATION;
299 if (pk_algo == GNUTLS_PK_UNKNOWN)
300 pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
301 switch (pk_algo)
303 case GNUTLS_PK_RSA:
305 vdata.data = hash_concat->data;
306 vdata.size = hash_concat->size;
308 /* verify signature */
309 if (!_gnutls_version_has_selectable_sighash (ver))
310 flags = GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA;
311 else
312 flags = 0;
315 break;
316 case GNUTLS_PK_DSA:
317 case GNUTLS_PK_EC:
319 vdata.data = &hash_concat->data[sha1pos];
320 vdata.size = hash_concat->size - sha1pos;
322 flags = 0;
324 break;
325 default:
326 gnutls_assert ();
327 return GNUTLS_E_INTERNAL_ERROR;
330 ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags,
331 &vdata, signature);
333 if (ret < 0)
334 return gnutls_assert_val(ret);
337 return 0;
341 /* Generates a signature of all the random data and the parameters.
342 * Used in DHE_* ciphersuites.
345 _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert,
346 const gnutls_datum_t * params,
347 gnutls_datum_t * signature,
348 gnutls_sign_algorithm_t sign_algo)
350 gnutls_datum_t dconcat;
351 int ret;
352 digest_hd_st td_md5;
353 digest_hd_st td_sha;
354 uint8_t concat[MAX_SIG_SIZE];
355 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
356 gnutls_digest_algorithm_t hash_algo;
358 if (_gnutls_version_has_selectable_sighash (ver))
360 _gnutls_handshake_log ("HSK[%p]: verify handshake data: using %s\n",
361 session, gnutls_sign_algorithm_get_name (sign_algo));
363 ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, sign_algo);
364 if (ret < 0)
365 return gnutls_assert_val(ret);
367 ret = _gnutls_session_sign_algo_enabled (session, sign_algo);
368 if (ret < 0)
369 return gnutls_assert_val(ret);
371 hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo);
373 else
375 ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
376 if (ret < 0)
378 gnutls_assert ();
379 return ret;
382 _gnutls_hash (&td_md5, session->security_parameters.client_random,
383 GNUTLS_RANDOM_SIZE);
384 _gnutls_hash (&td_md5, session->security_parameters.server_random,
385 GNUTLS_RANDOM_SIZE);
386 _gnutls_hash (&td_md5, params->data, params->size);
388 hash_algo = GNUTLS_DIG_SHA1;
391 ret = _gnutls_hash_init (&td_sha, hash_algo);
392 if (ret < 0)
394 gnutls_assert ();
395 if (!_gnutls_version_has_selectable_sighash (ver))
396 _gnutls_hash_deinit (&td_md5, NULL);
397 return ret;
400 _gnutls_hash (&td_sha, session->security_parameters.client_random,
401 GNUTLS_RANDOM_SIZE);
402 _gnutls_hash (&td_sha, session->security_parameters.server_random,
403 GNUTLS_RANDOM_SIZE);
404 _gnutls_hash (&td_sha, params->data, params->size);
406 if (!_gnutls_version_has_selectable_sighash (ver))
408 _gnutls_hash_deinit (&td_md5, concat);
409 _gnutls_hash_deinit (&td_sha, &concat[16]);
410 dconcat.data = concat;
411 dconcat.size = 36;
413 else
415 _gnutls_hash_deinit (&td_sha, concat);
417 dconcat.data = concat;
418 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
421 ret = verify_tls_hash (ver, cert, &dconcat, signature,
422 dconcat.size -
423 _gnutls_hash_get_algo_len (hash_algo),
424 sign_algo,
425 _gnutls_sign_get_pk_algorithm (sign_algo));
426 if (ret < 0)
428 gnutls_assert ();
429 return ret;
432 return ret;
436 /* Client certificate verify calculations
439 /* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
441 static int
442 _gnutls_handshake_verify_crt_vrfy12 (gnutls_session_t session,
443 gnutls_pcert_st* cert,
444 gnutls_datum_t * signature,
445 gnutls_sign_algorithm_t sign_algo)
447 int ret;
448 uint8_t concat[MAX_HASH_SIZE];
449 gnutls_datum_t dconcat;
450 gnutls_digest_algorithm_t hash_algo;
451 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
452 gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
454 ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
455 if (ret < 0)
456 return gnutls_assert_val(ret);
458 hash_algo = _gnutls_sign_get_hash_algorithm(sign_algo);
460 ret = _gnutls_hash_fast(hash_algo, session->internals.handshake_hash_buffer.data,
461 session->internals.handshake_hash_buffer_prev_len,
462 concat);
463 if (ret < 0)
464 return gnutls_assert_val(ret);
466 dconcat.data = concat;
467 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
469 ret =
470 verify_tls_hash (ver, cert, &dconcat, signature, 0, sign_algo, pk);
471 if (ret < 0)
473 gnutls_assert ();
474 return ret;
477 return ret;
481 /* Verifies a TLS signature (like the one in the client certificate
482 * verify message).
485 _gnutls_handshake_verify_crt_vrfy (gnutls_session_t session,
486 gnutls_pcert_st *cert,
487 gnutls_datum_t * signature,
488 gnutls_sign_algorithm_t sign_algo)
490 int ret;
491 uint8_t concat[MAX_SIG_SIZE];
492 digest_hd_st td_md5;
493 digest_hd_st td_sha;
494 gnutls_datum_t dconcat;
495 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
497 _gnutls_handshake_log ("HSK[%p]: verify cert vrfy: using %s\n",
498 session, gnutls_sign_algorithm_get_name (sign_algo));
501 if (_gnutls_version_has_selectable_sighash(ver))
502 return _gnutls_handshake_verify_crt_vrfy12 (session, cert, signature,
503 sign_algo);
505 ret =
506 _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
507 if (ret < 0)
509 gnutls_assert ();
510 return ret;
513 ret =
514 _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
515 if (ret < 0)
517 gnutls_assert ();
518 _gnutls_hash_deinit (&td_md5, NULL);
519 return GNUTLS_E_HASH_FAILED;
522 _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
523 _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
525 if (ver == GNUTLS_SSL3)
527 ret = _gnutls_generate_master (session, 1);
528 if (ret < 0)
530 _gnutls_hash_deinit (&td_md5, NULL);
531 _gnutls_hash_deinit (&td_sha, NULL);
532 return gnutls_assert_val(ret);
535 ret = _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
536 session->
537 security_parameters.master_secret,
538 GNUTLS_MASTER_SIZE);
539 if (ret < 0)
541 _gnutls_hash_deinit (&td_sha, NULL);
542 return gnutls_assert_val(ret);
545 ret = _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
546 session->
547 security_parameters.master_secret,
548 GNUTLS_MASTER_SIZE);
549 if (ret < 0)
551 return gnutls_assert_val(ret);
554 else
556 _gnutls_hash_deinit (&td_md5, concat);
557 _gnutls_hash_deinit (&td_sha, &concat[16]);
560 dconcat.data = concat;
561 dconcat.size = 20 + 16; /* md5+ sha */
563 ret =
564 verify_tls_hash (ver, cert, &dconcat, signature, 16,
565 GNUTLS_SIGN_UNKNOWN,
566 gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL));
567 if (ret < 0)
569 gnutls_assert ();
570 return ret;
573 return ret;
577 /* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2
579 static int
580 _gnutls_handshake_sign_crt_vrfy12 (gnutls_session_t session,
581 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
582 gnutls_datum_t * signature)
584 gnutls_datum_t dconcat;
585 int ret;
586 uint8_t concat[MAX_SIG_SIZE];
587 gnutls_sign_algorithm_t sign_algo;
588 gnutls_digest_algorithm_t hash_algo;
590 sign_algo =
591 _gnutls_session_get_sign_algo (session, cert);
592 if (sign_algo == GNUTLS_SIGN_UNKNOWN)
594 gnutls_assert ();
595 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
598 hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo);
600 _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n",
601 gnutls_sign_algorithm_get_name (sign_algo),
602 gnutls_mac_get_name ((gnutls_mac_algorithm_t)hash_algo));
604 ret = _gnutls_hash_fast (hash_algo, session->internals.handshake_hash_buffer.data,
605 session->internals.handshake_hash_buffer.length,
606 concat);
607 if (ret < 0)
608 return gnutls_assert_val(ret);
610 dconcat.data = concat;
611 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
613 ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
614 if (ret < 0)
616 gnutls_assert ();
617 return ret;
620 return sign_algo;
624 /* Generates a signature of all the previous sent packets in the
625 * handshake procedure.
626 * 20040227: now it works for SSL 3.0 as well
627 * 20091031: works for TLS 1.2 too!
629 * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
630 * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
633 _gnutls_handshake_sign_crt_vrfy (gnutls_session_t session,
634 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
635 gnutls_datum_t * signature)
637 gnutls_datum_t dconcat;
638 int ret;
639 uint8_t concat[MAX_SIG_SIZE];
640 digest_hd_st td_md5;
641 digest_hd_st td_sha;
642 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
643 gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
645 if (_gnutls_version_has_selectable_sighash(ver))
646 return _gnutls_handshake_sign_crt_vrfy12 (session, cert, pkey,
647 signature);
649 ret =
650 _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
651 if (ret < 0)
653 gnutls_assert ();
654 return ret;
657 _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length);
659 if (ver == GNUTLS_SSL3)
661 ret = _gnutls_generate_master (session, 1);
662 if (ret < 0)
664 gnutls_assert ();
665 _gnutls_hash_deinit (&td_sha, NULL);
666 return ret;
669 ret = _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
670 session->
671 security_parameters.master_secret,
672 GNUTLS_MASTER_SIZE);
673 if (ret < 0)
674 return gnutls_assert_val(ret);
676 else
677 _gnutls_hash_deinit (&td_sha, &concat[16]);
679 /* ensure 1024 bit DSA keys are used */
680 ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN);
681 if (ret < 0)
682 return gnutls_assert_val(ret);
684 switch (pk)
686 case GNUTLS_PK_RSA:
687 ret =
688 _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
689 if (ret < 0)
690 return gnutls_assert_val(ret);
692 _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length);
694 if (ver == GNUTLS_SSL3)
696 ret = _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
697 session->
698 security_parameters.master_secret,
699 GNUTLS_MASTER_SIZE);
700 if (ret < 0)
701 return gnutls_assert_val(ret);
703 else
704 _gnutls_hash_deinit (&td_md5, concat);
706 dconcat.data = concat;
707 dconcat.size = 36;
708 break;
709 case GNUTLS_PK_DSA:
710 case GNUTLS_PK_EC:
712 dconcat.data = &concat[16];
713 dconcat.size = 20;
714 break;
716 default:
717 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
719 ret = sign_tls_hash (session, GNUTLS_DIG_NULL, cert, pkey, &dconcat, signature);
720 if (ret < 0)
722 gnutls_assert ();
725 return ret;
729 pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
730 gnutls_pk_params_st* params,
731 const gnutls_datum_t * data, gnutls_datum_t * digest)
733 int ret;
735 digest->size = _gnutls_hash_get_algo_len (hash);
736 digest->data = gnutls_malloc (digest->size);
737 if (digest->data == NULL)
739 gnutls_assert ();
740 return GNUTLS_E_MEMORY_ERROR;
743 ret = _gnutls_hash_fast (hash, data->data, data->size, digest->data);
744 if (ret < 0)
746 gnutls_assert ();
747 goto cleanup;
750 return 0;
752 cleanup:
753 gnutls_free (digest->data);
754 return ret;
759 * This function will do RSA PKCS #1 1.5 encoding
760 * on the given digest. The given digest must be allocated
761 * and will be freed if replacement is required.
764 pk_prepare_hash (gnutls_pk_algorithm_t pk,
765 gnutls_digest_algorithm_t hash, gnutls_datum_t * digest)
767 int ret;
768 gnutls_datum_t old_digest = { digest->data, digest->size };
770 switch (pk)
772 case GNUTLS_PK_RSA:
773 /* Encode the digest as a DigestInfo
775 if ((ret = encode_ber_digest_info (hash, &old_digest, digest)) != 0)
777 gnutls_assert ();
778 return ret;
781 _gnutls_free_datum (&old_digest);
782 break;
783 case GNUTLS_PK_DSA:
784 case GNUTLS_PK_EC:
785 break;
786 default:
787 gnutls_assert ();
788 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
791 return 0;
794 /* Reads the digest information.
795 * we use DER here, although we should use BER. It works fine
796 * anyway.
799 decode_ber_digest_info (const gnutls_datum_t * info,
800 gnutls_digest_algorithm_t * hash,
801 uint8_t * digest, unsigned int *digest_size)
803 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
804 int result;
805 char str[1024];
806 int len;
808 if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
809 "GNUTLS.DigestInfo",
810 &dinfo)) != ASN1_SUCCESS)
812 gnutls_assert ();
813 return _gnutls_asn2err (result);
816 result = asn1_der_decoding (&dinfo, info->data, info->size, NULL);
817 if (result != ASN1_SUCCESS)
819 gnutls_assert ();
820 asn1_delete_structure (&dinfo);
821 return _gnutls_asn2err (result);
824 len = sizeof (str) - 1;
825 result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len);
826 if (result != ASN1_SUCCESS)
828 gnutls_assert ();
829 asn1_delete_structure (&dinfo);
830 return _gnutls_asn2err (result);
833 *hash = _gnutls_x509_oid_to_digest (str);
835 if (*hash == GNUTLS_DIG_UNKNOWN)
838 _gnutls_debug_log ("verify.c: HASH OID: %s\n", str);
840 gnutls_assert ();
841 asn1_delete_structure (&dinfo);
842 return GNUTLS_E_UNKNOWN_ALGORITHM;
845 len = sizeof (str) - 1;
846 result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len);
847 /* To avoid permitting garbage in the parameters field, either the
848 parameters field is not present, or it contains 0x05 0x00. */
849 if (!(result == ASN1_ELEMENT_NOT_FOUND ||
850 (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
851 memcmp (str, ASN1_NULL, ASN1_NULL_SIZE) == 0)))
853 gnutls_assert ();
854 asn1_delete_structure (&dinfo);
855 return GNUTLS_E_ASN1_GENERIC_ERROR;
858 len = *digest_size;
859 result = asn1_read_value (dinfo, "digest", digest, &len);
861 if (result != ASN1_SUCCESS)
863 gnutls_assert ();
864 *digest_size = len;
865 asn1_delete_structure (&dinfo);
866 return _gnutls_asn2err (result);
869 *digest_size = len;
870 asn1_delete_structure (&dinfo);
872 return 0;
875 /* Writes the digest information and the digest in a DER encoded
876 * structure. The digest info is allocated and stored into the info structure.
878 static int
879 encode_ber_digest_info (gnutls_digest_algorithm_t hash,
880 const gnutls_datum_t * digest,
881 gnutls_datum_t * output)
883 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
884 int result;
885 const char *algo;
886 uint8_t *tmp_output;
887 int tmp_output_size;
889 algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
890 if (algo == NULL)
892 gnutls_assert ();
893 _gnutls_debug_log ("Hash algorithm: %d has no OID\n", hash);
894 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
897 if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
898 "GNUTLS.DigestInfo",
899 &dinfo)) != ASN1_SUCCESS)
901 gnutls_assert ();
902 return _gnutls_asn2err (result);
905 result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
906 if (result != ASN1_SUCCESS)
908 gnutls_assert ();
909 asn1_delete_structure (&dinfo);
910 return _gnutls_asn2err (result);
913 /* Write an ASN.1 NULL in the parameters field. This matches RFC
914 3279 and RFC 4055, although is arguable incorrect from a historic
915 perspective (see those documents for more information).
916 Regardless of what is correct, this appears to be what most
917 implementations do. */
918 result = asn1_write_value (dinfo, "digestAlgorithm.parameters",
919 ASN1_NULL, ASN1_NULL_SIZE);
920 if (result != ASN1_SUCCESS)
922 gnutls_assert ();
923 asn1_delete_structure (&dinfo);
924 return _gnutls_asn2err (result);
927 result = asn1_write_value (dinfo, "digest", digest->data, digest->size);
928 if (result != ASN1_SUCCESS)
930 gnutls_assert ();
931 asn1_delete_structure (&dinfo);
932 return _gnutls_asn2err (result);
935 tmp_output_size = 0;
936 asn1_der_coding (dinfo, "", NULL, &tmp_output_size, NULL);
938 tmp_output = gnutls_malloc (tmp_output_size);
939 if (tmp_output == NULL)
941 gnutls_assert ();
942 asn1_delete_structure (&dinfo);
943 return GNUTLS_E_MEMORY_ERROR;
946 result = asn1_der_coding (dinfo, "", tmp_output, &tmp_output_size, NULL);
947 if (result != ASN1_SUCCESS)
949 gnutls_assert ();
950 asn1_delete_structure (&dinfo);
951 return _gnutls_asn2err (result);
954 asn1_delete_structure (&dinfo);
956 output->size = tmp_output_size;
957 output->data = tmp_output;
959 return 0;