Tizen 2.0 Release
[external/libgnutls26.git] / lib / gnutls_sig.c
1 /*
2  * Copyright (C) 2001, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
3  * Software Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <x509_b64.h>
29 #include <auth_cert.h>
30 #include <gnutls_algorithms.h>
31 #include <gnutls_cert.h>
32 #include <gnutls_datum.h>
33 #include <gnutls_mpi.h>
34 #include <gnutls_global.h>
35 #include <gnutls_pk.h>
36 #include <debug.h>
37 #include <gnutls_buffers.h>
38 #include <gnutls_sig.h>
39 #include <gnutls_kx.h>
40 #include <libtasn1.h>
41 #include <ext_signature.h>
42 #include <gnutls_state.h>
43 #include <x509/common.h>
44
45 static int
46 sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
47                   gnutls_cert * cert, gnutls_privkey_t pkey,
48                   const gnutls_datum_t * hash_concat,
49                   gnutls_datum_t * signature);
50
51 /* While this is currently equal to the length of RSA/SHA512
52  * signature, it should also be sufficient for DSS signature and any
53  * other RSA signatures including one with the old MD5/SHA1-combined
54  * format.
55  */
56 #define MAX_SIG_SIZE 19 + MAX_HASH_SIZE
57
58 /* Generates a signature of all the random data and the parameters.
59  * Used in DHE_* ciphersuites.
60  */
61 int
62 _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_cert * cert,
63                              gnutls_privkey_t pkey, gnutls_datum_t * params,
64                              gnutls_datum_t * signature,
65                              gnutls_sign_algorithm_t * sign_algo)
66 {
67   gnutls_datum_t dconcat;
68   int ret;
69   digest_hd_st td_sha;
70   opaque concat[MAX_SIG_SIZE];
71   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
72   gnutls_digest_algorithm_t hash_algo;
73
74   *sign_algo =
75     _gnutls_session_get_sign_algo (session, cert);
76   if (*sign_algo == GNUTLS_SIGN_UNKNOWN)
77     {
78       gnutls_assert ();
79       return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
80     }
81
82   hash_algo = _gnutls_sign_get_hash_algorithm (*sign_algo);
83
84   _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n",
85                     session, gnutls_sign_algorithm_get_name (*sign_algo));
86
87   ret = _gnutls_hash_init (&td_sha, hash_algo);
88   if (ret < 0)
89     {
90       gnutls_assert ();
91       return ret;
92     }
93
94   _gnutls_hash (&td_sha, session->security_parameters.client_random,
95                 GNUTLS_RANDOM_SIZE);
96   _gnutls_hash (&td_sha, session->security_parameters.server_random,
97                 GNUTLS_RANDOM_SIZE);
98   _gnutls_hash (&td_sha, params->data, params->size);
99
100   switch (cert->subject_pk_algorithm)
101     {
102     case GNUTLS_PK_RSA:
103       if (!_gnutls_version_has_selectable_sighash (ver))
104         {
105           digest_hd_st td_md5;
106
107           ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
108           if (ret < 0)
109             {
110               gnutls_assert ();
111               return ret;
112             }
113
114           _gnutls_hash (&td_md5, session->security_parameters.client_random,
115                         GNUTLS_RANDOM_SIZE);
116           _gnutls_hash (&td_md5, session->security_parameters.server_random,
117                         GNUTLS_RANDOM_SIZE);
118           _gnutls_hash (&td_md5, params->data, params->size);
119
120           _gnutls_hash_deinit (&td_md5, concat);
121           _gnutls_hash_deinit (&td_sha, &concat[16]);
122
123           dconcat.data = concat;
124           dconcat.size = 36;
125         }
126       else
127         { /* TLS 1.2 way */
128
129           _gnutls_hash_deinit (&td_sha, concat);
130
131           dconcat.data = concat;
132           dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
133         }
134       break;
135     case GNUTLS_PK_DSA:
136       _gnutls_hash_deinit (&td_sha, concat);
137
138       if ((hash_algo != GNUTLS_DIG_SHA1) && (hash_algo != GNUTLS_DIG_SHA224)
139           && (hash_algo != GNUTLS_DIG_SHA256))
140         {
141           gnutls_assert ();
142           return GNUTLS_E_INTERNAL_ERROR;
143         }
144       dconcat.data = concat;
145       dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
146       break;
147
148     default:
149       gnutls_assert ();
150       _gnutls_hash_deinit (&td_sha, NULL);
151       return GNUTLS_E_INTERNAL_ERROR;
152     }
153
154   ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
155   if (ret < 0)
156     {
157       gnutls_assert ();
158     }
159
160   return ret;
161
162 }
163
164
165 /* This will create a PKCS1 or DSA signature, using the given parameters, and the
166  * given data. The output will be allocated and be put in signature.
167  */
168 int
169 _gnutls_soft_sign (gnutls_pk_algorithm_t algo, bigint_t * params,
170                    int params_size, const gnutls_datum_t * data,
171                    gnutls_datum_t * signature)
172 {
173   int ret;
174
175   switch (algo)
176     {
177     case GNUTLS_PK_RSA:
178       /* encrypt */
179       if ((ret = _gnutls_pkcs1_rsa_encrypt (signature, data, params,
180                                             params_size, 1)) < 0)
181         {
182           gnutls_assert ();
183           return ret;
184         }
185
186       break;
187     case GNUTLS_PK_DSA:
188       /* sign */
189       if ((ret = _gnutls_dsa_sign (signature, data, params, params_size)) < 0)
190         {
191           gnutls_assert ();
192           return ret;
193         }
194       break;
195     default:
196       gnutls_assert ();
197       return GNUTLS_E_INTERNAL_ERROR;
198       break;
199     }
200
201   return 0;
202 }
203
204 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
205  * Cert is the certificate of the corresponding private key. It is only checked if
206  * it supports signing.
207  */
208 static int
209 sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
210                   gnutls_cert * cert, gnutls_privkey_t pkey,
211                   const gnutls_datum_t * hash_concat,
212                   gnutls_datum_t * signature)
213 {
214   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
215
216   /* If our certificate supports signing
217    */
218
219   if (cert != NULL)
220     {
221       if (cert->key_usage != 0)
222         if (!(cert->key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
223           {
224             gnutls_assert ();
225             return GNUTLS_E_KEY_USAGE_VIOLATION;
226           }
227
228       /* External signing. */
229       if (!pkey)
230         {
231           int ret;
232
233           if (!session->internals.sign_func)
234             return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
235
236           if (!_gnutls_version_has_selectable_sighash (ver))
237             return (*session->internals.sign_func)
238               (session, session->internals.sign_func_userdata,
239                cert->cert_type, &cert->raw, hash_concat, signature);
240           else
241             {
242               gnutls_datum_t digest;
243
244               ret = _gnutls_set_datum(&digest, hash_concat->data, hash_concat->size);
245               if (ret < 0)
246                 return gnutls_assert_val(ret);
247               
248               ret = pk_prepare_hash (gnutls_privkey_get_pk_algorithm(pkey, NULL), hash_algo, &digest);
249               if (ret < 0)
250                 {
251                   gnutls_assert ();
252                   goto es_cleanup;
253                 }
254
255               ret = (*session->internals.sign_func)
256                 (session, session->internals.sign_func_userdata,
257                  cert->cert_type, &cert->raw, &digest, signature);
258 es_cleanup:
259               gnutls_free(digest.data);
260               
261               return ret;
262             }
263         }
264     }
265
266    if (!_gnutls_version_has_selectable_sighash (ver))
267     return _gnutls_privkey_sign_hash (pkey, hash_concat, signature);
268   else
269     return gnutls_privkey_sign_hash (pkey, hash_algo, 0, hash_concat, signature);
270 }
271
272 static int
273 verify_tls_hash (gnutls_protocol_t ver, gnutls_cert * cert,
274                     const gnutls_datum_t * hash_concat,
275                     gnutls_datum_t * signature, size_t sha1pos,
276                     gnutls_pk_algorithm_t pk_algo)
277 {
278   int ret;
279   gnutls_datum_t vdata;
280
281   if (cert == NULL || cert->version == 0)
282     {                           /* this is the only way to check
283                                  * if it is initialized
284                                  */
285       gnutls_assert ();
286       return GNUTLS_E_CERTIFICATE_ERROR;
287     }
288
289   /* If the certificate supports signing continue.
290    */
291   if (cert->key_usage != 0)
292     if (!(cert->key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
293       {
294         gnutls_assert ();
295         return GNUTLS_E_KEY_USAGE_VIOLATION;
296       }
297
298   if (pk_algo == GNUTLS_PK_UNKNOWN)
299     pk_algo = cert->subject_pk_algorithm;
300   switch (pk_algo)
301     {
302     case GNUTLS_PK_RSA:
303
304       vdata.data = hash_concat->data;
305       vdata.size = hash_concat->size;
306
307       /* verify signature */
308       if (!_gnutls_version_has_selectable_sighash (ver))
309         ret = _gnutls_rsa_verify (&vdata, signature, cert->params,
310                                      cert->params_size, 1);
311       else
312         ret = pubkey_verify_sig( NULL, &vdata, signature, pk_algo, 
313           cert->params, cert->params_size);
314
315       if (ret < 0)
316         {
317           gnutls_assert ();
318           return ret;
319         }
320
321       break;
322     case GNUTLS_PK_DSA:
323
324       vdata.data = &hash_concat->data[sha1pos];
325       vdata.size = hash_concat->size - sha1pos;
326
327       ret = pubkey_verify_sig( NULL, &vdata, signature, pk_algo, 
328         cert->params, cert->params_size);
329       /* verify signature */
330       if (ret < 0)
331         {
332           gnutls_assert ();
333           return ret;
334         }
335
336       break;
337     default:
338       gnutls_assert ();
339       return GNUTLS_E_INTERNAL_ERROR;
340     }
341
342
343
344   return 0;
345 }
346
347
348 /* Generates a signature of all the random data and the parameters.
349  * Used in DHE_* ciphersuites.
350  */
351 int
352 _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_cert * cert,
353                                const gnutls_datum_t * params,
354                                gnutls_datum_t * signature,
355                                gnutls_sign_algorithm_t algo)
356 {
357   gnutls_datum_t dconcat;
358   int ret;
359   digest_hd_st td_md5;
360   digest_hd_st td_sha;
361   opaque concat[MAX_SIG_SIZE];
362   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
363   gnutls_digest_algorithm_t hash_algo;
364
365   if (_gnutls_version_has_selectable_sighash (ver))
366     {
367       _gnutls_handshake_log ("HSK[%p]: verify handshake data: using %s\n",
368                     session, gnutls_sign_algorithm_get_name (algo));
369
370       ret = cert_compatible_with_sig(cert, ver, algo);
371       if (ret < 0)
372         return gnutls_assert_val(ret);
373
374       ret = _gnutls_session_sign_algo_enabled (session, algo);
375       if (ret < 0)
376         return gnutls_assert_val(ret);
377
378       hash_algo = _gnutls_sign_get_hash_algorithm (algo);
379     }
380   else
381     {
382       ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
383       if (ret < 0)
384         {
385           gnutls_assert ();
386           return ret;
387         }
388
389       _gnutls_hash (&td_md5, session->security_parameters.client_random,
390                     GNUTLS_RANDOM_SIZE);
391       _gnutls_hash (&td_md5, session->security_parameters.server_random,
392                     GNUTLS_RANDOM_SIZE);
393       _gnutls_hash (&td_md5, params->data, params->size);
394
395       hash_algo = GNUTLS_DIG_SHA1;
396     }
397
398   ret = _gnutls_hash_init (&td_sha, hash_algo);
399   if (ret < 0)
400     {
401       gnutls_assert ();
402       if (!_gnutls_version_has_selectable_sighash (ver))
403         _gnutls_hash_deinit (&td_md5, NULL);
404       return ret;
405     }
406
407   _gnutls_hash (&td_sha, session->security_parameters.client_random,
408                 GNUTLS_RANDOM_SIZE);
409   _gnutls_hash (&td_sha, session->security_parameters.server_random,
410                 GNUTLS_RANDOM_SIZE);
411   _gnutls_hash (&td_sha, params->data, params->size);
412
413   if (!_gnutls_version_has_selectable_sighash (ver))
414     {
415       _gnutls_hash_deinit (&td_md5, concat);
416       _gnutls_hash_deinit (&td_sha, &concat[16]);
417       dconcat.data = concat;
418       dconcat.size = 36;
419     }
420   else
421     {
422       _gnutls_hash_deinit (&td_sha, concat);
423
424       dconcat.data = concat;
425       dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
426     }
427
428   ret = verify_tls_hash (ver, cert, &dconcat, signature,
429                             dconcat.size -
430                             _gnutls_hash_get_algo_len (hash_algo),
431                             _gnutls_sign_get_pk_algorithm (algo));
432   if (ret < 0)
433     {
434       gnutls_assert ();
435       return ret;
436     }
437
438   return ret;
439
440 }
441
442 /* Client certificate verify calculations
443  */
444
445 /* this is _gnutls_handshake_verify_cert_vrfy for TLS 1.2
446  */
447 static int
448 _gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
449                                       gnutls_cert * cert,
450                                       gnutls_datum_t * signature,
451                                       gnutls_sign_algorithm_t sign_algo)
452 {
453   int ret;
454   opaque concat[MAX_SIG_SIZE];
455   digest_hd_st td;
456   gnutls_datum_t dconcat;
457   gnutls_sign_algorithm_t _sign_algo;
458   gnutls_digest_algorithm_t hash_algo;
459   digest_hd_st *handshake_td;
460   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
461
462   handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
463   hash_algo = handshake_td->algorithm;
464   _sign_algo =
465     _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, hash_algo);
466
467   if (_sign_algo != sign_algo)
468     {
469       handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
470       hash_algo = handshake_td->algorithm;
471       _sign_algo =
472         _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, hash_algo);
473       if (sign_algo != _sign_algo)
474         {
475           gnutls_assert ();
476           return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
477         }
478     }
479
480   ret = _gnutls_hash_copy (&td, handshake_td);
481   if (ret < 0)
482     {
483       gnutls_assert ();
484       return GNUTLS_E_HASH_FAILED;
485     }
486
487   _gnutls_hash_deinit (&td, concat);
488
489   dconcat.data = concat;
490   dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
491
492   ret =
493     verify_tls_hash (ver, cert, &dconcat, signature, 0,
494                         cert->subject_pk_algorithm);
495   if (ret < 0)
496     {
497       gnutls_assert ();
498       return ret;
499     }
500
501   return ret;
502
503 }
504
505 /* Verifies a TLS signature (like the one in the client certificate
506  * verify message). 
507  */
508 int
509 _gnutls_handshake_verify_cert_vrfy (gnutls_session_t session,
510                                     gnutls_cert * cert,
511                                     gnutls_datum_t * signature,
512                                     gnutls_sign_algorithm_t sign_algo)
513 {
514   int ret;
515   opaque concat[MAX_SIG_SIZE];
516   digest_hd_st td_md5;
517   digest_hd_st td_sha;
518   gnutls_datum_t dconcat;
519   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
520
521   _gnutls_handshake_log ("HSK[%p]: verify cert vrfy: using %s\n",
522                     session, gnutls_sign_algorithm_get_name (sign_algo));
523
524   if (session->security_parameters.handshake_mac_handle_type ==
525       HANDSHAKE_MAC_TYPE_12)
526     {
527       return _gnutls_handshake_verify_cert_vrfy12 (session, cert, signature,
528                                                    sign_algo);
529     }
530   else if (session->security_parameters.handshake_mac_handle_type !=
531            HANDSHAKE_MAC_TYPE_10)
532     {
533       gnutls_assert ();
534       return GNUTLS_E_INTERNAL_ERROR;
535     }
536
537   ret =
538     _gnutls_hash_copy (&td_md5,
539                        &session->internals.handshake_mac_handle.tls10.md5);
540   if (ret < 0)
541     {
542       gnutls_assert ();
543       return ret;
544     }
545
546   ret =
547     _gnutls_hash_copy (&td_sha,
548                        &session->internals.handshake_mac_handle.tls10.sha);
549   if (ret < 0)
550     {
551       gnutls_assert ();
552       _gnutls_hash_deinit (&td_md5, NULL);
553       return GNUTLS_E_HASH_FAILED;
554     }
555
556   if (ver == GNUTLS_SSL3)
557     {
558       ret = _gnutls_generate_master (session, 1);
559       if (ret < 0)
560         {
561           gnutls_assert ();
562           return ret;
563         }
564
565       _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
566                                          session->
567                                          security_parameters.master_secret,
568                                          GNUTLS_MASTER_SIZE);
569       _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
570                                          session->
571                                          security_parameters.master_secret,
572                                          GNUTLS_MASTER_SIZE);
573     }
574   else
575     {
576       _gnutls_hash_deinit (&td_md5, concat);
577       _gnutls_hash_deinit (&td_sha, &concat[16]);
578     }
579
580   dconcat.data = concat;
581   dconcat.size = 20 + 16;       /* md5+ sha */
582
583   ret =
584     verify_tls_hash (ver, cert, &dconcat, signature, 16,
585                         cert->subject_pk_algorithm);
586   if (ret < 0)
587     {
588       gnutls_assert ();
589       return ret;
590     }
591
592   return ret;
593
594 }
595
596 /* the same as _gnutls_handshake_sign_cert_vrfy except that it is made for TLS 1.2
597  */
598 static int
599 _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
600                                     gnutls_cert * cert, gnutls_privkey_t pkey,
601                                     gnutls_datum_t * signature)
602 {
603   gnutls_datum_t dconcat;
604   int ret;
605   opaque concat[MAX_SIG_SIZE];
606   digest_hd_st td;
607   gnutls_sign_algorithm_t sign_algo;
608   gnutls_digest_algorithm_t hash_algo;
609   digest_hd_st *handshake_td;
610
611   sign_algo =
612     _gnutls_session_get_sign_algo (session, cert);
613   if (sign_algo == GNUTLS_SIGN_UNKNOWN)
614     {
615       gnutls_assert ();
616       return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
617     }
618
619   hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo);
620
621   _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n",
622                     gnutls_sign_algorithm_get_name (sign_algo),
623                     gnutls_mac_get_name (hash_algo));
624
625   if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha1.algorithm)
626     handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
627   else if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha256.algorithm)
628     handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
629   else
630     return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* too bad we only support SHA1 and SHA256 */
631
632   ret = _gnutls_hash_copy (&td, handshake_td);
633   if (ret < 0)
634     {
635       gnutls_assert ();
636       return ret;
637     }
638
639   _gnutls_hash_deinit (&td, concat);
640
641   dconcat.data = concat;
642   dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
643
644   ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
645   if (ret < 0)
646     {
647       gnutls_assert ();
648       return ret;
649     }
650
651   return sign_algo;
652 }
653
654
655 /* Generates a signature of all the previous sent packets in the 
656  * handshake procedure. 
657  * 20040227: now it works for SSL 3.0 as well
658  * 20091031: works for TLS 1.2 too!
659  *
660  * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
661  * For TLS1.2 returns the signature algorithm used on success, or a negative value;
662  */
663 int
664 _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
665                                   gnutls_cert * cert, gnutls_privkey_t pkey,
666                                   gnutls_datum_t * signature)
667 {
668   gnutls_datum_t dconcat;
669   int ret, hash_algo;
670   opaque concat[MAX_SIG_SIZE];
671   digest_hd_st td_md5;
672   digest_hd_st td_sha;
673   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
674
675   if (session->security_parameters.handshake_mac_handle_type ==
676       HANDSHAKE_MAC_TYPE_12)
677     {
678       return _gnutls_handshake_sign_cert_vrfy12 (session, cert, pkey,
679                                                  signature);
680     }
681   else if (session->security_parameters.handshake_mac_handle_type !=
682            HANDSHAKE_MAC_TYPE_10)
683     {
684       gnutls_assert ();
685       return GNUTLS_E_INTERNAL_ERROR;
686     }
687
688   ret =
689     _gnutls_hash_copy (&td_sha,
690                        &session->internals.handshake_mac_handle.tls10.sha);
691   if (ret < 0)
692     {
693       gnutls_assert ();
694       return ret;
695     }
696
697   if (ver == GNUTLS_SSL3)
698     {
699       ret = _gnutls_generate_master (session, 1);
700       if (ret < 0)
701         {
702           gnutls_assert ();
703           return ret;
704         }
705
706       _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
707                                          session->
708                                          security_parameters.master_secret,
709                                          GNUTLS_MASTER_SIZE);
710     }
711   else
712     _gnutls_hash_deinit (&td_sha, &concat[16]);
713
714   switch (cert->subject_pk_algorithm)
715     {
716     case GNUTLS_PK_RSA:
717       ret =
718         _gnutls_hash_copy (&td_md5,
719                            &session->internals.handshake_mac_handle.tls10.
720                            md5);
721       if (ret < 0)
722         {
723           gnutls_assert ();
724           return ret;
725         }
726
727       if (ver == GNUTLS_SSL3)
728         _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
729                                            session->
730                                            security_parameters.master_secret,
731                                            GNUTLS_MASTER_SIZE);
732       else
733         _gnutls_hash_deinit (&td_md5, concat);
734
735       dconcat.data = concat;
736       dconcat.size = 36;
737       break;
738     case GNUTLS_PK_DSA:
739       /* ensure 1024 bit DSA keys are used */
740       hash_algo = _gnutls_dsa_q_to_hash (cert->params[1], NULL);
741       if (!_gnutls_version_has_selectable_sighash (ver) && hash_algo != GNUTLS_DIG_SHA1)
742         return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
743
744       dconcat.data = &concat[16];
745       dconcat.size = 20;
746       break;
747
748     default:
749       return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
750     }
751   ret = sign_tls_hash (session, GNUTLS_DIG_NULL, cert, pkey, &dconcat, signature);
752   if (ret < 0)
753     {
754       gnutls_assert ();
755     }
756
757   return ret;
758 }
759
760 int
761 pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
762               bigint_t * params,
763               const gnutls_datum_t * data, gnutls_datum_t * digest)
764 {
765   int ret;
766
767   digest->size = _gnutls_hash_get_algo_len (hash);
768   digest->data = gnutls_malloc (digest->size);
769   if (digest->data == NULL)
770     {
771       gnutls_assert ();
772       return GNUTLS_E_MEMORY_ERROR;
773     }
774
775   ret = _gnutls_hash_fast (hash, data->data, data->size, digest->data);
776   if (ret < 0)
777     {
778       gnutls_assert ();
779       goto cleanup;
780     }
781
782   return 0;
783
784 cleanup:
785   gnutls_free (digest->data);
786   return ret;
787 }
788
789 /* Writes the digest information and the digest in a DER encoded
790  * structure. The digest info is allocated and stored into the info structure.
791  */
792 static int
793 encode_ber_digest_info (gnutls_digest_algorithm_t hash,
794                         const gnutls_datum_t * digest,
795                         gnutls_datum_t * output)
796 {
797   ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
798   int result;
799   const char *algo;
800   opaque *tmp_output;
801   int tmp_output_size;
802
803   algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
804   if (algo == NULL)
805     {
806       gnutls_assert ();
807       _gnutls_x509_log ("Hash algorithm: %d\n", hash);
808       return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
809     }
810
811   if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
812                                      "GNUTLS.DigestInfo",
813                                      &dinfo)) != ASN1_SUCCESS)
814     {
815       gnutls_assert ();
816       return _gnutls_asn2err (result);
817     }
818
819   result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
820   if (result != ASN1_SUCCESS)
821     {
822       gnutls_assert ();
823       asn1_delete_structure (&dinfo);
824       return _gnutls_asn2err (result);
825     }
826
827   /* Write an ASN.1 NULL in the parameters field.  This matches RFC
828      3279 and RFC 4055, although is arguable incorrect from a historic
829      perspective (see those documents for more information).
830      Regardless of what is correct, this appears to be what most
831      implementations do.  */
832   result = asn1_write_value (dinfo, "digestAlgorithm.parameters",
833                              ASN1_NULL, ASN1_NULL_SIZE);
834   if (result != ASN1_SUCCESS)
835     {
836       gnutls_assert ();
837       asn1_delete_structure (&dinfo);
838       return _gnutls_asn2err (result);
839     }
840
841   result = asn1_write_value (dinfo, "digest", digest->data, digest->size);
842   if (result != ASN1_SUCCESS)
843     {
844       gnutls_assert ();
845       asn1_delete_structure (&dinfo);
846       return _gnutls_asn2err (result);
847     }
848
849   tmp_output_size = 0;
850   asn1_der_coding (dinfo, "", NULL, &tmp_output_size, NULL);
851
852   tmp_output = gnutls_malloc (tmp_output_size);
853   if (output->data == NULL)
854     {
855       gnutls_assert ();
856       asn1_delete_structure (&dinfo);
857       return GNUTLS_E_MEMORY_ERROR;
858     }
859
860   result = asn1_der_coding (dinfo, "", tmp_output, &tmp_output_size, NULL);
861   if (result != ASN1_SUCCESS)
862     {
863       gnutls_assert ();
864       asn1_delete_structure (&dinfo);
865       return _gnutls_asn2err (result);
866     }
867
868   asn1_delete_structure (&dinfo);
869
870   output->size = tmp_output_size;
871   output->data = tmp_output;
872
873   return 0;
874 }
875
876 /* 
877  * This function will do RSA PKCS #1 1.5 encoding
878  * on the given digest. The given digest must be allocated
879  * and will be freed if replacement is required.
880  */
881 int
882 pk_prepare_hash (gnutls_pk_algorithm_t pk,
883                  gnutls_digest_algorithm_t hash, gnutls_datum_t * digest)
884 {
885   int ret;
886   gnutls_datum old_digest = { digest->data, digest->size };
887
888   switch (pk)
889     {
890     case GNUTLS_PK_RSA:
891       /* Encode the digest as a DigestInfo
892        */
893       if ((ret = encode_ber_digest_info (hash, &old_digest, digest)) != 0)
894         {
895           gnutls_assert ();
896           return ret;
897         }
898
899       _gnutls_free_datum (&old_digest);
900       break;
901     case GNUTLS_PK_DSA:
902       break;
903     default:
904       gnutls_assert ();
905       return GNUTLS_E_UNIMPLEMENTED_FEATURE;
906     }
907
908   return 0;
909 }