Merge branch 'upstream' into tizen
[platform/upstream/gnutls.git] / lib / gnutls_sig.c
1 /*
2  * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
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.
12  *
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.
17  *
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/>
20  *
21  */
22
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>
41
42 static int
43 sign_tls_hash(gnutls_session_t session, const mac_entry_st * hash_algo,
44               gnutls_pcert_st * cert, gnutls_privkey_t pkey,
45               const gnutls_datum_t * hash_concat,
46               gnutls_datum_t * signature);
47
48
49 /* While this is currently equal to the length of RSA/SHA512
50  * signature, it should also be sufficient for DSS signature and any
51  * other RSA signatures including one with the old MD5/SHA1-combined
52  * format.
53  */
54 #define MAX_SIG_SIZE 19 + MAX_HASH_SIZE
55
56 /* Generates a signature of all the random data and the parameters.
57  * Used in DHE_* ciphersuites.
58  */
59 int
60 _gnutls_handshake_sign_data(gnutls_session_t session,
61                             gnutls_pcert_st * cert, gnutls_privkey_t pkey,
62                             gnutls_datum_t * params,
63                             gnutls_datum_t * signature,
64                             gnutls_sign_algorithm_t * sign_algo)
65 {
66         gnutls_datum_t dconcat;
67         int ret;
68         digest_hd_st td_sha;
69         uint8_t concat[MAX_SIG_SIZE];
70         const version_entry_st *ver = get_version(session);
71         const mac_entry_st *hash_algo;
72
73         *sign_algo = _gnutls_session_get_sign_algo(session, cert);
74         if (*sign_algo == GNUTLS_SIGN_UNKNOWN) {
75                 gnutls_assert();
76                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
77         }
78
79         gnutls_sign_algorithm_set_server(session, *sign_algo);
80
81         hash_algo =
82             hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo));
83         if (hash_algo == NULL)
84                 return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
85
86         _gnutls_handshake_log
87             ("HSK[%p]: signing handshake data: using %s\n", session,
88              gnutls_sign_algorithm_get_name(*sign_algo));
89
90         ret = _gnutls_hash_init(&td_sha, hash_algo);
91         if (ret < 0) {
92                 gnutls_assert();
93                 return ret;
94         }
95
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);
101
102         switch (gnutls_privkey_get_pk_algorithm(pkey, NULL)) {
103         case GNUTLS_PK_RSA:
104                 if (!_gnutls_version_has_selectable_sighash(ver)) {
105                         digest_hd_st td_md5;
106
107                         ret =
108                             _gnutls_hash_init(&td_md5,
109                                               hash_to_entry
110                                               (GNUTLS_DIG_MD5));
111                         if (ret < 0) {
112                                 gnutls_assert();
113                                 return ret;
114                         }
115
116                         _gnutls_hash(&td_md5,
117                                      session->security_parameters.
118                                      client_random, GNUTLS_RANDOM_SIZE);
119                         _gnutls_hash(&td_md5,
120                                      session->security_parameters.
121                                      server_random, GNUTLS_RANDOM_SIZE);
122                         _gnutls_hash(&td_md5, params->data, params->size);
123
124                         _gnutls_hash_deinit(&td_md5, concat);
125                         _gnutls_hash_deinit(&td_sha, &concat[16]);
126
127                         dconcat.data = concat;
128                         dconcat.size = 36;
129                 } else {        /* TLS 1.2 way */
130
131                         _gnutls_hash_deinit(&td_sha, concat);
132
133                         dconcat.data = concat;
134                         dconcat.size =
135                             _gnutls_hash_get_algo_len(hash_algo);
136                 }
137                 break;
138         case GNUTLS_PK_DSA:
139         case GNUTLS_PK_EC:
140                 _gnutls_hash_deinit(&td_sha, concat);
141
142                 if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) {
143                         gnutls_assert();
144                         return GNUTLS_E_INTERNAL_ERROR;
145                 }
146                 dconcat.data = concat;
147                 dconcat.size = _gnutls_hash_get_algo_len(hash_algo);
148                 break;
149
150         default:
151                 gnutls_assert();
152                 _gnutls_hash_deinit(&td_sha, NULL);
153                 return GNUTLS_E_INTERNAL_ERROR;
154         }
155
156         ret =
157             sign_tls_hash(session, hash_algo, cert, pkey, &dconcat,
158                           signature);
159         if (ret < 0) {
160                 gnutls_assert();
161         }
162
163         return ret;
164
165 }
166
167 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
168  * Cert is the certificate of the corresponding private key. It is only checked if
169  * it supports signing.
170  */
171 static int
172 sign_tls_hash(gnutls_session_t session, const mac_entry_st * hash_algo,
173               gnutls_pcert_st * cert, gnutls_privkey_t pkey,
174               const gnutls_datum_t * hash_concat,
175               gnutls_datum_t * signature)
176 {
177         const version_entry_st *ver = get_version(session);
178         unsigned int key_usage = 0;
179
180         /* If our certificate supports signing
181          */
182         if (cert != NULL) {
183                 gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
184
185                 if (key_usage != 0)
186                         if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
187                                 gnutls_assert();
188                                 _gnutls_audit_log(session,
189                                                   "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
190                         }
191
192                 /* External signing. Deprecated. To be removed. */
193                 if (!pkey) {
194                         int ret;
195
196                         if (!session->internals.sign_func)
197                                 return
198                                     gnutls_assert_val
199                                     (GNUTLS_E_INSUFFICIENT_CREDENTIALS);
200
201                         if (!_gnutls_version_has_selectable_sighash(ver))
202                                 return (*session->internals.sign_func)
203                                     (session,
204                                      session->internals.sign_func_userdata,
205                                      cert->type, &cert->cert, hash_concat,
206                                      signature);
207                         else {
208                                 gnutls_datum_t digest;
209
210                                 ret =
211                                     _gnutls_set_datum(&digest,
212                                                       hash_concat->data,
213                                                       hash_concat->size);
214                                 if (ret < 0)
215                                         return gnutls_assert_val(ret);
216
217                                 ret =
218                                     pk_prepare_hash
219                                     (gnutls_pubkey_get_pk_algorithm
220                                      (cert->pubkey, NULL), hash_algo,
221                                      &digest);
222                                 if (ret < 0) {
223                                         gnutls_assert();
224                                         goto es_cleanup;
225                                 }
226
227                                 ret = (*session->internals.sign_func)
228                                     (session,
229                                      session->internals.sign_func_userdata,
230                                      cert->type, &cert->cert, &digest,
231                                      signature);
232                               es_cleanup:
233                                 gnutls_free(digest.data);
234
235                                 return ret;
236                         }
237                 }
238         }
239
240         if (!_gnutls_version_has_selectable_sighash(ver))
241                 return gnutls_privkey_sign_raw_data(pkey, 0, hash_concat,
242                                                     signature);
243         else
244                 return gnutls_privkey_sign_hash(pkey, 
245                                                 (gnutls_digest_algorithm_t)hash_algo->id,
246                                                 0, hash_concat, signature);
247 }
248
249 static int
250 verify_tls_hash(gnutls_session_t session,
251                 const version_entry_st * ver, gnutls_pcert_st * cert,
252                 const gnutls_datum_t * hash_concat,
253                 gnutls_datum_t * signature, size_t sha1pos,
254                 gnutls_sign_algorithm_t sign_algo,
255                 gnutls_pk_algorithm_t pk_algo)
256 {
257         int ret;
258         gnutls_datum_t vdata;
259         unsigned int key_usage = 0, flags;
260
261         if (cert == NULL) {
262                 gnutls_assert();
263                 return GNUTLS_E_CERTIFICATE_ERROR;
264         }
265
266         gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
267
268         /* If the certificate supports signing continue.
269          */
270         if (key_usage != 0)
271                 if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
272                         gnutls_assert();
273                         _gnutls_audit_log(session,
274                                           "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
275                 }
276
277         if (pk_algo == GNUTLS_PK_UNKNOWN)
278                 pk_algo =
279                     gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
280         switch (pk_algo) {
281         case GNUTLS_PK_RSA:
282
283                 vdata.data = hash_concat->data;
284                 vdata.size = hash_concat->size;
285
286                 /* verify signature */
287                 if (!_gnutls_version_has_selectable_sighash(ver))
288                         flags = GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA;
289                 else
290                         flags = 0;
291                 break;
292         case GNUTLS_PK_DSA:
293         case GNUTLS_PK_EC:
294                 vdata.data = &hash_concat->data[sha1pos];
295                 vdata.size = hash_concat->size - sha1pos;
296
297                 flags = 0;
298
299                 break;
300         default:
301                 gnutls_assert();
302                 return GNUTLS_E_INTERNAL_ERROR;
303         }
304
305         if (session->security_parameters.entity == GNUTLS_CLIENT)
306                 gnutls_sign_algorithm_set_server(session, sign_algo);
307
308         ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags,
309                                          &vdata, signature);
310
311         if (ret < 0)
312                 return gnutls_assert_val(ret);
313
314
315         return 0;
316 }
317
318
319 /* Generates a signature of all the random data and the parameters.
320  * Used in DHE_* ciphersuites.
321  */
322 int
323 _gnutls_handshake_verify_data(gnutls_session_t session,
324                               gnutls_pcert_st * cert,
325                               const gnutls_datum_t * params,
326                               gnutls_datum_t * signature,
327                               gnutls_sign_algorithm_t sign_algo)
328 {
329         gnutls_datum_t dconcat;
330         int ret;
331         digest_hd_st td_md5;
332         digest_hd_st td_sha;
333         uint8_t concat[MAX_SIG_SIZE];
334         const version_entry_st *ver = get_version(session);
335         gnutls_digest_algorithm_t hash_algo;
336         const mac_entry_st *me;
337
338         if (_gnutls_version_has_selectable_sighash(ver)) {
339                 _gnutls_handshake_log
340                     ("HSK[%p]: verify handshake data: using %s\n", session,
341                      gnutls_sign_algorithm_get_name(sign_algo));
342
343                 ret =
344                     _gnutls_pubkey_compatible_with_sig(session,
345                                                        cert->pubkey, ver,
346                                                        sign_algo);
347                 if (ret < 0)
348                         return gnutls_assert_val(ret);
349
350                 ret =
351                     _gnutls_session_sign_algo_enabled(session, sign_algo);
352                 if (ret < 0)
353                         return gnutls_assert_val(ret);
354
355                 hash_algo = gnutls_sign_get_hash_algorithm(sign_algo);
356                 me = hash_to_entry(hash_algo);
357         } else {
358                 me = hash_to_entry(GNUTLS_DIG_MD5);
359                 ret = _gnutls_hash_init(&td_md5, me);
360                 if (ret < 0) {
361                         gnutls_assert();
362                         return ret;
363                 }
364
365                 _gnutls_hash(&td_md5,
366                              session->security_parameters.client_random,
367                              GNUTLS_RANDOM_SIZE);
368                 _gnutls_hash(&td_md5,
369                              session->security_parameters.server_random,
370                              GNUTLS_RANDOM_SIZE);
371                 _gnutls_hash(&td_md5, params->data, params->size);
372
373                 me = hash_to_entry(GNUTLS_DIG_SHA1);
374         }
375
376         ret = _gnutls_hash_init(&td_sha, me);
377         if (ret < 0) {
378                 gnutls_assert();
379                 if (!_gnutls_version_has_selectable_sighash(ver))
380                         _gnutls_hash_deinit(&td_md5, NULL);
381                 return ret;
382         }
383
384         _gnutls_hash(&td_sha, session->security_parameters.client_random,
385                      GNUTLS_RANDOM_SIZE);
386         _gnutls_hash(&td_sha, session->security_parameters.server_random,
387                      GNUTLS_RANDOM_SIZE);
388         _gnutls_hash(&td_sha, params->data, params->size);
389
390         if (!_gnutls_version_has_selectable_sighash(ver)) {
391                 _gnutls_hash_deinit(&td_md5, concat);
392                 _gnutls_hash_deinit(&td_sha, &concat[16]);
393                 dconcat.data = concat;
394                 dconcat.size = 36;
395         } else {
396                 _gnutls_hash_deinit(&td_sha, concat);
397
398                 dconcat.data = concat;
399                 dconcat.size = _gnutls_hash_get_algo_len(me);
400         }
401
402         ret = verify_tls_hash(session, ver, cert, &dconcat, signature,
403                               dconcat.size - _gnutls_hash_get_algo_len(me),
404                               sign_algo,
405                               gnutls_sign_get_pk_algorithm(sign_algo));
406         if (ret < 0) {
407                 gnutls_assert();
408                 return ret;
409         }
410
411         return ret;
412
413 }
414
415 /* Client certificate verify calculations
416  */
417
418 /* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
419  */
420 static int
421 _gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
422                                     gnutls_pcert_st * cert,
423                                     gnutls_datum_t * signature,
424                                     gnutls_sign_algorithm_t sign_algo)
425 {
426         int ret;
427         uint8_t concat[MAX_HASH_SIZE];
428         gnutls_datum_t dconcat;
429         const version_entry_st *ver = get_version(session);
430         gnutls_pk_algorithm_t pk =
431             gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
432         const mac_entry_st *me;
433
434         ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
435         if (ret < 0)
436                 return gnutls_assert_val(ret);
437
438         gnutls_sign_algorithm_set_client(session, sign_algo);
439
440         me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));
441
442         ret =
443             _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
444                               session->internals.handshake_hash_buffer.
445                               data,
446                               session->internals.
447                               handshake_hash_buffer_prev_len, concat);
448         if (ret < 0)
449                 return gnutls_assert_val(ret);
450
451         dconcat.data = concat;
452         dconcat.size = _gnutls_hash_get_algo_len(me);
453
454         ret =
455             verify_tls_hash(session, ver, cert, &dconcat, signature, 0,
456                             sign_algo, pk);
457         if (ret < 0) {
458                 gnutls_assert();
459                 return ret;
460         }
461
462         return ret;
463
464 }
465
466 /* Verifies a TLS signature (like the one in the client certificate
467  * verify message). 
468  */
469 int
470 _gnutls_handshake_verify_crt_vrfy(gnutls_session_t session,
471                                   gnutls_pcert_st * cert,
472                                   gnutls_datum_t * signature,
473                                   gnutls_sign_algorithm_t sign_algo)
474 {
475         int ret;
476         uint8_t concat[MAX_SIG_SIZE];
477         digest_hd_st td_md5;
478         digest_hd_st td_sha;
479         gnutls_datum_t dconcat;
480         const version_entry_st *ver = get_version(session);
481
482         _gnutls_handshake_log("HSK[%p]: verify cert vrfy: using %s\n",
483                               session,
484                               gnutls_sign_algorithm_get_name(sign_algo));
485
486         if (unlikely(ver == NULL))
487                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
488
489         if (_gnutls_version_has_selectable_sighash(ver))
490                 return _gnutls_handshake_verify_crt_vrfy12(session, cert,
491                                                            signature,
492                                                            sign_algo);
493
494         ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5));
495         if (ret < 0) {
496                 gnutls_assert();
497                 return ret;
498         }
499
500         ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
501         if (ret < 0) {
502                 gnutls_assert();
503                 _gnutls_hash_deinit(&td_md5, NULL);
504                 return GNUTLS_E_HASH_FAILED;
505         }
506
507         _gnutls_hash(&td_sha,
508                      session->internals.handshake_hash_buffer.data,
509                      session->internals.handshake_hash_buffer_prev_len);
510         _gnutls_hash(&td_md5,
511                      session->internals.handshake_hash_buffer.data,
512                      session->internals.handshake_hash_buffer_prev_len);
513
514         if (ver->id == GNUTLS_SSL3) {
515                 ret = _gnutls_generate_master(session, 1);
516                 if (ret < 0) {
517                         _gnutls_hash_deinit(&td_md5, NULL);
518                         _gnutls_hash_deinit(&td_sha, NULL);
519                         return gnutls_assert_val(ret);
520                 }
521
522                 ret = _gnutls_mac_deinit_ssl3_handshake(&td_md5, concat,
523                                                         session->security_parameters.
524                                                         master_secret,
525                                                         GNUTLS_MASTER_SIZE);
526                 if (ret < 0) {
527                         _gnutls_hash_deinit(&td_sha, NULL);
528                         return gnutls_assert_val(ret);
529                 }
530
531                 ret =
532                     _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
533                                                       session->security_parameters.
534                                                       master_secret,
535                                                       GNUTLS_MASTER_SIZE);
536                 if (ret < 0) {
537                         return gnutls_assert_val(ret);
538                 }
539         } else {
540                 _gnutls_hash_deinit(&td_md5, concat);
541                 _gnutls_hash_deinit(&td_sha, &concat[16]);
542         }
543
544         dconcat.data = concat;
545         dconcat.size = 20 + 16; /* md5+ sha */
546
547         ret =
548             verify_tls_hash(session, ver, cert, &dconcat, signature, 16,
549                             GNUTLS_SIGN_UNKNOWN,
550                             gnutls_pubkey_get_pk_algorithm(cert->pubkey,
551                                                            NULL));
552         if (ret < 0) {
553                 gnutls_assert();
554                 return ret;
555         }
556
557         return ret;
558 }
559
560 /* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2
561  */
562 static int
563 _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
564                                   gnutls_pcert_st * cert,
565                                   gnutls_privkey_t pkey,
566                                   gnutls_datum_t * signature)
567 {
568         gnutls_datum_t dconcat;
569         int ret;
570         uint8_t concat[MAX_SIG_SIZE];
571         gnutls_sign_algorithm_t sign_algo;
572         const mac_entry_st *me;
573
574         sign_algo = _gnutls_session_get_sign_algo(session, cert);
575         if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
576                 gnutls_assert();
577                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
578         }
579
580         gnutls_sign_algorithm_set_client(session, sign_algo);
581
582         me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));
583
584         _gnutls_debug_log("sign handshake cert vrfy: picked %s with %s\n",
585                           gnutls_sign_algorithm_get_name(sign_algo),
586                           _gnutls_mac_get_name(me));
587
588         ret =
589             _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
590                               session->internals.handshake_hash_buffer.
591                               data,
592                               session->internals.handshake_hash_buffer.
593                               length, concat);
594         if (ret < 0)
595                 return gnutls_assert_val(ret);
596
597         dconcat.data = concat;
598         dconcat.size = _gnutls_hash_get_algo_len(me);
599
600         ret = sign_tls_hash(session, me, cert, pkey, &dconcat, signature);
601         if (ret < 0) {
602                 gnutls_assert();
603                 return ret;
604         }
605
606         return sign_algo;
607 }
608
609
610 /* Generates a signature of all the previous sent packets in the 
611  * handshake procedure. 
612  * 20040227: now it works for SSL 3.0 as well
613  * 20091031: works for TLS 1.2 too!
614  *
615  * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
616  * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
617  */
618 int
619 _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
620                                 gnutls_pcert_st * cert,
621                                 gnutls_privkey_t pkey,
622                                 gnutls_datum_t * signature)
623 {
624         gnutls_datum_t dconcat;
625         int ret;
626         uint8_t concat[MAX_SIG_SIZE];
627         digest_hd_st td_md5;
628         digest_hd_st td_sha;
629         const version_entry_st *ver = get_version(session);
630         gnutls_pk_algorithm_t pk =
631             gnutls_privkey_get_pk_algorithm(pkey, NULL);
632
633         if (unlikely(ver == NULL))
634                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
635
636         if (_gnutls_version_has_selectable_sighash(ver))
637                 return _gnutls_handshake_sign_crt_vrfy12(session, cert,
638                                                          pkey, signature);
639
640         ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
641         if (ret < 0) {
642                 gnutls_assert();
643                 return ret;
644         }
645
646         _gnutls_hash(&td_sha,
647                      session->internals.handshake_hash_buffer.data,
648                      session->internals.handshake_hash_buffer.length);
649
650         if (ver->id == GNUTLS_SSL3) {
651                 ret = _gnutls_generate_master(session, 1);
652                 if (ret < 0) {
653                         gnutls_assert();
654                         _gnutls_hash_deinit(&td_sha, NULL);
655                         return ret;
656                 }
657
658                 ret =
659                     _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
660                                                       session->security_parameters.
661                                                       master_secret,
662                                                       GNUTLS_MASTER_SIZE);
663                 if (ret < 0)
664                         return gnutls_assert_val(ret);
665         } else
666                 _gnutls_hash_deinit(&td_sha, &concat[16]);
667
668         /* ensure 1024 bit DSA keys are used */
669         ret =
670             _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
671                                                GNUTLS_SIGN_UNKNOWN);
672         if (ret < 0)
673                 return gnutls_assert_val(ret);
674
675         switch (pk) {
676         case GNUTLS_PK_RSA:
677                 ret =
678                     _gnutls_hash_init(&td_md5,
679                                       hash_to_entry(GNUTLS_DIG_MD5));
680                 if (ret < 0)
681                         return gnutls_assert_val(ret);
682
683                 _gnutls_hash(&td_md5,
684                              session->internals.handshake_hash_buffer.data,
685                              session->internals.handshake_hash_buffer.
686                              length);
687
688                 if (ver->id == GNUTLS_SSL3) {
689                         ret =
690                             _gnutls_mac_deinit_ssl3_handshake(&td_md5,
691                                                               concat,
692                                                               session->security_parameters.
693                                                               master_secret,
694                                                               GNUTLS_MASTER_SIZE);
695                         if (ret < 0)
696                                 return gnutls_assert_val(ret);
697                 } else
698                         _gnutls_hash_deinit(&td_md5, concat);
699
700                 dconcat.data = concat;
701                 dconcat.size = 36;
702                 break;
703         case GNUTLS_PK_DSA:
704         case GNUTLS_PK_EC:
705
706                 dconcat.data = &concat[16];
707                 dconcat.size = 20;
708                 break;
709
710         default:
711                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
712         }
713         ret =
714             sign_tls_hash(session, NULL, cert, pkey, &dconcat, signature);
715         if (ret < 0) {
716                 gnutls_assert();
717         }
718
719         return ret;
720 }
721
722 int
723 pk_hash_data(gnutls_pk_algorithm_t pk, const mac_entry_st * hash,
724              gnutls_pk_params_st * params,
725              const gnutls_datum_t * data, gnutls_datum_t * digest)
726 {
727         int ret;
728
729         digest->size = _gnutls_hash_get_algo_len(hash);
730         digest->data = gnutls_malloc(digest->size);
731         if (digest->data == NULL) {
732                 gnutls_assert();
733                 return GNUTLS_E_MEMORY_ERROR;
734         }
735
736         ret =
737             _gnutls_hash_fast((gnutls_digest_algorithm_t)hash->id, data->data, data->size,
738                               digest->data);
739         if (ret < 0) {
740                 gnutls_assert();
741                 goto cleanup;
742         }
743
744         return 0;
745
746       cleanup:
747         gnutls_free(digest->data);
748         return ret;
749 }
750
751
752 /* 
753  * This function will do RSA PKCS #1 1.5 encoding
754  * on the given digest. The given digest must be allocated
755  * and will be freed if replacement is required.
756  */
757 int
758 pk_prepare_hash(gnutls_pk_algorithm_t pk,
759                 const mac_entry_st * hash, gnutls_datum_t * digest)
760 {
761         int ret;
762         gnutls_datum_t old_digest = { digest->data, digest->size };
763
764         switch (pk) {
765         case GNUTLS_PK_RSA:
766                 if (unlikely(hash == NULL))
767                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
768                 /* Encode the digest as a DigestInfo
769                  */
770                 if ((ret =
771                      encode_ber_digest_info(hash, &old_digest,
772                                             digest)) != 0) {
773                         gnutls_assert();
774                         return ret;
775                 }
776
777                 _gnutls_free_datum(&old_digest);
778                 break;
779         case GNUTLS_PK_DSA:
780         case GNUTLS_PK_EC:
781                 break;
782         default:
783                 gnutls_assert();
784                 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
785         }
786
787         return 0;
788 }