Revert "Imported Upstream version 3.4.11"
[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         gnutls_sign_algorithm_set_server(session, sign_algo);
306
307         ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags,
308                                          &vdata, signature);
309
310         if (ret < 0)
311                 return gnutls_assert_val(ret);
312
313
314         return 0;
315 }
316
317
318 /* Generates a signature of all the random data and the parameters.
319  * Used in DHE_* ciphersuites.
320  */
321 int
322 _gnutls_handshake_verify_data(gnutls_session_t session,
323                               gnutls_pcert_st * cert,
324                               const gnutls_datum_t * params,
325                               gnutls_datum_t * signature,
326                               gnutls_sign_algorithm_t sign_algo)
327 {
328         gnutls_datum_t dconcat;
329         int ret;
330         digest_hd_st td_md5;
331         digest_hd_st td_sha;
332         uint8_t concat[MAX_SIG_SIZE];
333         const version_entry_st *ver = get_version(session);
334         gnutls_digest_algorithm_t hash_algo;
335         const mac_entry_st *me;
336
337         if (_gnutls_version_has_selectable_sighash(ver)) {
338                 _gnutls_handshake_log
339                     ("HSK[%p]: verify handshake data: using %s\n", session,
340                      gnutls_sign_algorithm_get_name(sign_algo));
341
342                 ret =
343                     _gnutls_pubkey_compatible_with_sig(session,
344                                                        cert->pubkey, ver,
345                                                        sign_algo);
346                 if (ret < 0)
347                         return gnutls_assert_val(ret);
348
349                 ret =
350                     _gnutls_session_sign_algo_enabled(session, sign_algo);
351                 if (ret < 0)
352                         return gnutls_assert_val(ret);
353
354                 hash_algo = gnutls_sign_get_hash_algorithm(sign_algo);
355                 me = hash_to_entry(hash_algo);
356         } else {
357                 me = hash_to_entry(GNUTLS_DIG_MD5);
358                 ret = _gnutls_hash_init(&td_md5, me);
359                 if (ret < 0) {
360                         gnutls_assert();
361                         return ret;
362                 }
363
364                 _gnutls_hash(&td_md5,
365                              session->security_parameters.client_random,
366                              GNUTLS_RANDOM_SIZE);
367                 _gnutls_hash(&td_md5,
368                              session->security_parameters.server_random,
369                              GNUTLS_RANDOM_SIZE);
370                 _gnutls_hash(&td_md5, params->data, params->size);
371
372                 me = hash_to_entry(GNUTLS_DIG_SHA1);
373         }
374
375         ret = _gnutls_hash_init(&td_sha, me);
376         if (ret < 0) {
377                 gnutls_assert();
378                 if (!_gnutls_version_has_selectable_sighash(ver))
379                         _gnutls_hash_deinit(&td_md5, NULL);
380                 return ret;
381         }
382
383         _gnutls_hash(&td_sha, session->security_parameters.client_random,
384                      GNUTLS_RANDOM_SIZE);
385         _gnutls_hash(&td_sha, session->security_parameters.server_random,
386                      GNUTLS_RANDOM_SIZE);
387         _gnutls_hash(&td_sha, params->data, params->size);
388
389         if (!_gnutls_version_has_selectable_sighash(ver)) {
390                 _gnutls_hash_deinit(&td_md5, concat);
391                 _gnutls_hash_deinit(&td_sha, &concat[16]);
392                 dconcat.data = concat;
393                 dconcat.size = 36;
394         } else {
395                 _gnutls_hash_deinit(&td_sha, concat);
396
397                 dconcat.data = concat;
398                 dconcat.size = _gnutls_hash_get_algo_len(me);
399         }
400
401         ret = verify_tls_hash(session, ver, cert, &dconcat, signature,
402                               dconcat.size - _gnutls_hash_get_algo_len(me),
403                               sign_algo,
404                               gnutls_sign_get_pk_algorithm(sign_algo));
405         if (ret < 0) {
406                 gnutls_assert();
407                 return ret;
408         }
409
410         return ret;
411
412 }
413
414 /* Client certificate verify calculations
415  */
416
417 /* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
418  */
419 static int
420 _gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
421                                     gnutls_pcert_st * cert,
422                                     gnutls_datum_t * signature,
423                                     gnutls_sign_algorithm_t sign_algo)
424 {
425         int ret;
426         uint8_t concat[MAX_HASH_SIZE];
427         gnutls_datum_t dconcat;
428         const version_entry_st *ver = get_version(session);
429         gnutls_pk_algorithm_t pk =
430             gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
431         const mac_entry_st *me;
432
433         ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
434         if (ret < 0)
435                 return gnutls_assert_val(ret);
436
437         gnutls_sign_algorithm_set_client(session, sign_algo);
438
439         me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));
440
441         ret =
442             _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
443                               session->internals.handshake_hash_buffer.
444                               data,
445                               session->internals.
446                               handshake_hash_buffer_prev_len, concat);
447         if (ret < 0)
448                 return gnutls_assert_val(ret);
449
450         dconcat.data = concat;
451         dconcat.size = _gnutls_hash_get_algo_len(me);
452
453         ret =
454             verify_tls_hash(session, ver, cert, &dconcat, signature, 0,
455                             sign_algo, pk);
456         if (ret < 0) {
457                 gnutls_assert();
458                 return ret;
459         }
460
461         return ret;
462
463 }
464
465 /* Verifies a TLS signature (like the one in the client certificate
466  * verify message). 
467  */
468 int
469 _gnutls_handshake_verify_crt_vrfy(gnutls_session_t session,
470                                   gnutls_pcert_st * cert,
471                                   gnutls_datum_t * signature,
472                                   gnutls_sign_algorithm_t sign_algo)
473 {
474         int ret;
475         uint8_t concat[MAX_SIG_SIZE];
476         digest_hd_st td_md5;
477         digest_hd_st td_sha;
478         gnutls_datum_t dconcat;
479         const version_entry_st *ver = get_version(session);
480
481         _gnutls_handshake_log("HSK[%p]: verify cert vrfy: using %s\n",
482                               session,
483                               gnutls_sign_algorithm_get_name(sign_algo));
484
485         if (unlikely(ver == NULL))
486                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
487
488         if (_gnutls_version_has_selectable_sighash(ver))
489                 return _gnutls_handshake_verify_crt_vrfy12(session, cert,
490                                                            signature,
491                                                            sign_algo);
492
493         ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5));
494         if (ret < 0) {
495                 gnutls_assert();
496                 return ret;
497         }
498
499         ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
500         if (ret < 0) {
501                 gnutls_assert();
502                 _gnutls_hash_deinit(&td_md5, NULL);
503                 return GNUTLS_E_HASH_FAILED;
504         }
505
506         _gnutls_hash(&td_sha,
507                      session->internals.handshake_hash_buffer.data,
508                      session->internals.handshake_hash_buffer_prev_len);
509         _gnutls_hash(&td_md5,
510                      session->internals.handshake_hash_buffer.data,
511                      session->internals.handshake_hash_buffer_prev_len);
512
513         if (ver->id == GNUTLS_SSL3) {
514                 ret = _gnutls_generate_master(session, 1);
515                 if (ret < 0) {
516                         _gnutls_hash_deinit(&td_md5, NULL);
517                         _gnutls_hash_deinit(&td_sha, NULL);
518                         return gnutls_assert_val(ret);
519                 }
520
521                 ret = _gnutls_mac_deinit_ssl3_handshake(&td_md5, concat,
522                                                         session->security_parameters.
523                                                         master_secret,
524                                                         GNUTLS_MASTER_SIZE);
525                 if (ret < 0) {
526                         _gnutls_hash_deinit(&td_sha, NULL);
527                         return gnutls_assert_val(ret);
528                 }
529
530                 ret =
531                     _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
532                                                       session->security_parameters.
533                                                       master_secret,
534                                                       GNUTLS_MASTER_SIZE);
535                 if (ret < 0) {
536                         return gnutls_assert_val(ret);
537                 }
538         } else {
539                 _gnutls_hash_deinit(&td_md5, concat);
540                 _gnutls_hash_deinit(&td_sha, &concat[16]);
541         }
542
543         dconcat.data = concat;
544         dconcat.size = 20 + 16; /* md5+ sha */
545
546         ret =
547             verify_tls_hash(session, ver, cert, &dconcat, signature, 16,
548                             GNUTLS_SIGN_UNKNOWN,
549                             gnutls_pubkey_get_pk_algorithm(cert->pubkey,
550                                                            NULL));
551         if (ret < 0) {
552                 gnutls_assert();
553                 return ret;
554         }
555
556         return ret;
557 }
558
559 /* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2
560  */
561 static int
562 _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session,
563                                   gnutls_pcert_st * cert,
564                                   gnutls_privkey_t pkey,
565                                   gnutls_datum_t * signature)
566 {
567         gnutls_datum_t dconcat;
568         int ret;
569         uint8_t concat[MAX_SIG_SIZE];
570         gnutls_sign_algorithm_t sign_algo;
571         const mac_entry_st *me;
572
573         sign_algo = _gnutls_session_get_sign_algo(session, cert);
574         if (sign_algo == GNUTLS_SIGN_UNKNOWN) {
575                 gnutls_assert();
576                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
577         }
578
579         gnutls_sign_algorithm_set_client(session, sign_algo);
580
581         me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));
582
583         _gnutls_debug_log("sign handshake cert vrfy: picked %s with %s\n",
584                           gnutls_sign_algorithm_get_name(sign_algo),
585                           _gnutls_mac_get_name(me));
586
587         ret =
588             _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
589                               session->internals.handshake_hash_buffer.
590                               data,
591                               session->internals.handshake_hash_buffer.
592                               length, concat);
593         if (ret < 0)
594                 return gnutls_assert_val(ret);
595
596         dconcat.data = concat;
597         dconcat.size = _gnutls_hash_get_algo_len(me);
598
599         ret = sign_tls_hash(session, me, cert, pkey, &dconcat, signature);
600         if (ret < 0) {
601                 gnutls_assert();
602                 return ret;
603         }
604
605         return sign_algo;
606 }
607
608
609 /* Generates a signature of all the previous sent packets in the 
610  * handshake procedure. 
611  * 20040227: now it works for SSL 3.0 as well
612  * 20091031: works for TLS 1.2 too!
613  *
614  * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
615  * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
616  */
617 int
618 _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
619                                 gnutls_pcert_st * cert,
620                                 gnutls_privkey_t pkey,
621                                 gnutls_datum_t * signature)
622 {
623         gnutls_datum_t dconcat;
624         int ret;
625         uint8_t concat[MAX_SIG_SIZE];
626         digest_hd_st td_md5;
627         digest_hd_st td_sha;
628         const version_entry_st *ver = get_version(session);
629         gnutls_pk_algorithm_t pk =
630             gnutls_privkey_get_pk_algorithm(pkey, NULL);
631
632         if (unlikely(ver == NULL))
633                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
634
635         if (_gnutls_version_has_selectable_sighash(ver))
636                 return _gnutls_handshake_sign_crt_vrfy12(session, cert,
637                                                          pkey, signature);
638
639         ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
640         if (ret < 0) {
641                 gnutls_assert();
642                 return ret;
643         }
644
645         _gnutls_hash(&td_sha,
646                      session->internals.handshake_hash_buffer.data,
647                      session->internals.handshake_hash_buffer.length);
648
649         if (ver->id == GNUTLS_SSL3) {
650                 ret = _gnutls_generate_master(session, 1);
651                 if (ret < 0) {
652                         gnutls_assert();
653                         _gnutls_hash_deinit(&td_sha, NULL);
654                         return ret;
655                 }
656
657                 ret =
658                     _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
659                                                       session->security_parameters.
660                                                       master_secret,
661                                                       GNUTLS_MASTER_SIZE);
662                 if (ret < 0)
663                         return gnutls_assert_val(ret);
664         } else
665                 _gnutls_hash_deinit(&td_sha, &concat[16]);
666
667         /* ensure 1024 bit DSA keys are used */
668         ret =
669             _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
670                                                GNUTLS_SIGN_UNKNOWN);
671         if (ret < 0)
672                 return gnutls_assert_val(ret);
673
674         switch (pk) {
675         case GNUTLS_PK_RSA:
676                 ret =
677                     _gnutls_hash_init(&td_md5,
678                                       hash_to_entry(GNUTLS_DIG_MD5));
679                 if (ret < 0)
680                         return gnutls_assert_val(ret);
681
682                 _gnutls_hash(&td_md5,
683                              session->internals.handshake_hash_buffer.data,
684                              session->internals.handshake_hash_buffer.
685                              length);
686
687                 if (ver->id == GNUTLS_SSL3) {
688                         ret =
689                             _gnutls_mac_deinit_ssl3_handshake(&td_md5,
690                                                               concat,
691                                                               session->security_parameters.
692                                                               master_secret,
693                                                               GNUTLS_MASTER_SIZE);
694                         if (ret < 0)
695                                 return gnutls_assert_val(ret);
696                 } else
697                         _gnutls_hash_deinit(&td_md5, concat);
698
699                 dconcat.data = concat;
700                 dconcat.size = 36;
701                 break;
702         case GNUTLS_PK_DSA:
703         case GNUTLS_PK_EC:
704
705                 dconcat.data = &concat[16];
706                 dconcat.size = 20;
707                 break;
708
709         default:
710                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
711         }
712         ret =
713             sign_tls_hash(session, NULL, cert, pkey, &dconcat, signature);
714         if (ret < 0) {
715                 gnutls_assert();
716         }
717
718         return ret;
719 }
720
721 int
722 pk_hash_data(gnutls_pk_algorithm_t pk, const mac_entry_st * hash,
723              gnutls_pk_params_st * params,
724              const gnutls_datum_t * data, gnutls_datum_t * digest)
725 {
726         int ret;
727
728         digest->size = _gnutls_hash_get_algo_len(hash);
729         digest->data = gnutls_malloc(digest->size);
730         if (digest->data == NULL) {
731                 gnutls_assert();
732                 return GNUTLS_E_MEMORY_ERROR;
733         }
734
735         ret =
736             _gnutls_hash_fast((gnutls_digest_algorithm_t)hash->id, data->data, data->size,
737                               digest->data);
738         if (ret < 0) {
739                 gnutls_assert();
740                 goto cleanup;
741         }
742
743         return 0;
744
745       cleanup:
746         gnutls_free(digest->data);
747         return ret;
748 }
749
750
751 /* 
752  * This function will do RSA PKCS #1 1.5 encoding
753  * on the given digest. The given digest must be allocated
754  * and will be freed if replacement is required.
755  */
756 int
757 pk_prepare_hash(gnutls_pk_algorithm_t pk,
758                 const mac_entry_st * hash, gnutls_datum_t * digest)
759 {
760         int ret;
761         gnutls_datum_t old_digest = { digest->data, digest->size };
762
763         switch (pk) {
764         case GNUTLS_PK_RSA:
765                 if (unlikely(hash == NULL))
766                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
767                 /* Encode the digest as a DigestInfo
768                  */
769                 if ((ret =
770                      encode_ber_digest_info(hash, &old_digest,
771                                             digest)) != 0) {
772                         gnutls_assert();
773                         return ret;
774                 }
775
776                 _gnutls_free_datum(&old_digest);
777                 break;
778         case GNUTLS_PK_DSA:
779         case GNUTLS_PK_EC:
780                 break;
781         default:
782                 gnutls_assert();
783                 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
784         }
785
786         return 0;
787 }