Documented gnutls_certificate_verification_status_print().
[gnutls.git] / lib / gnutls_sig.c
blobc3665c6b76504f9c0aca7d6d7b5fc0c331edf585
1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <x509_b64.h>
26 #include <auth/cert.h>
27 #include <algorithms.h>
28 #include <gnutls_datum.h>
29 #include <gnutls_mpi.h>
30 #include <gnutls_global.h>
31 #include <gnutls_pk.h>
32 #include <debug.h>
33 #include <gnutls_buffers.h>
34 #include <gnutls_sig.h>
35 #include <gnutls_kx.h>
36 #include <libtasn1.h>
37 #include <ext/signature.h>
38 #include <gnutls_state.h>
39 #include <x509/common.h>
40 #include <abstract_int.h>
42 static int
43 sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
44 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
45 const gnutls_datum_t * hash_concat,
46 gnutls_datum_t * signature);
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.
54 #define MAX_SIG_SIZE 19 + MAX_HASH_SIZE
56 /* Generates a signature of all the random data and the parameters.
57 * Used in DHE_* ciphersuites.
59 int
60 _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_pcert_st* cert,
61 gnutls_privkey_t pkey, gnutls_datum_t * params,
62 gnutls_datum_t * signature,
63 gnutls_sign_algorithm_t * sign_algo)
65 gnutls_datum_t dconcat;
66 int ret;
67 digest_hd_st td_sha;
68 uint8_t concat[MAX_SIG_SIZE];
69 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
70 gnutls_digest_algorithm_t hash_algo;
72 *sign_algo =
73 _gnutls_session_get_sign_algo (session, cert);
74 if (*sign_algo == GNUTLS_SIGN_UNKNOWN)
76 gnutls_assert ();
77 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
80 gnutls_sign_algorithm_set(session, *sign_algo);
82 hash_algo = gnutls_sign_get_hash_algorithm (*sign_algo);
84 _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n",
85 session, gnutls_sign_algorithm_get_name (*sign_algo));
87 ret = _gnutls_hash_init (&td_sha, hash_algo);
88 if (ret < 0)
90 gnutls_assert ();
91 return ret;
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);
100 switch (gnutls_privkey_get_pk_algorithm(pkey, NULL))
102 case GNUTLS_PK_RSA:
103 if (!_gnutls_version_has_selectable_sighash (ver))
105 digest_hd_st td_md5;
107 ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
108 if (ret < 0)
110 gnutls_assert ();
111 return ret;
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);
120 _gnutls_hash_deinit (&td_md5, concat);
121 _gnutls_hash_deinit (&td_sha, &concat[16]);
123 dconcat.data = concat;
124 dconcat.size = 36;
126 else
127 { /* TLS 1.2 way */
129 _gnutls_hash_deinit (&td_sha, concat);
131 dconcat.data = concat;
132 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
134 break;
135 case GNUTLS_PK_DSA:
136 case GNUTLS_PK_EC:
137 _gnutls_hash_deinit (&td_sha, concat);
139 if (!IS_SHA(hash_algo))
141 gnutls_assert ();
142 return GNUTLS_E_INTERNAL_ERROR;
144 dconcat.data = concat;
145 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
146 break;
148 default:
149 gnutls_assert ();
150 _gnutls_hash_deinit (&td_sha, NULL);
151 return GNUTLS_E_INTERNAL_ERROR;
154 ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
155 if (ret < 0)
157 gnutls_assert ();
160 return ret;
164 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
165 * Cert is the certificate of the corresponding private key. It is only checked if
166 * it supports signing.
168 static int
169 sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
170 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
171 const gnutls_datum_t * hash_concat,
172 gnutls_datum_t * signature)
174 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
175 unsigned int key_usage = 0;
176 /* If our certificate supports signing
179 if (cert != NULL)
181 gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
183 if (key_usage != 0)
184 if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
186 gnutls_assert ();
187 if (session->internals.priorities.allow_key_usage_violation == 0)
188 return GNUTLS_E_KEY_USAGE_VIOLATION;
189 else
190 _gnutls_audit_log(session, "Key usage violation was detected (ignored).\n");
193 /* External signing. Deprecated. To be removed. */
194 if (!pkey)
196 int ret;
198 if (!session->internals.sign_func)
199 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
201 if (!_gnutls_version_has_selectable_sighash (ver))
202 return (*session->internals.sign_func)
203 (session, session->internals.sign_func_userdata,
204 cert->type, &cert->cert, hash_concat, signature);
205 else
207 gnutls_datum_t digest;
209 ret = _gnutls_set_datum(&digest, hash_concat->data, hash_concat->size);
210 if (ret < 0)
211 return gnutls_assert_val(ret);
213 ret = pk_prepare_hash (gnutls_privkey_get_pk_algorithm(pkey, NULL), hash_algo, &digest);
214 if (ret < 0)
216 gnutls_assert ();
217 goto es_cleanup;
220 ret = (*session->internals.sign_func)
221 (session, session->internals.sign_func_userdata,
222 cert->type, &cert->cert, &digest, signature);
223 es_cleanup:
224 gnutls_free(digest.data);
226 return ret;
231 if (!_gnutls_version_has_selectable_sighash (ver))
232 return _gnutls_privkey_sign_hash (pkey, hash_concat, signature);
233 else
234 return gnutls_privkey_sign_hash (pkey, hash_algo, 0, hash_concat, signature);
237 static int
238 verify_tls_hash (gnutls_session_t session,
239 gnutls_protocol_t ver, gnutls_pcert_st* cert,
240 const gnutls_datum_t * hash_concat,
241 gnutls_datum_t * signature, size_t sha1pos,
242 gnutls_sign_algorithm_t sign_algo,
243 gnutls_pk_algorithm_t pk_algo)
245 int ret;
246 gnutls_datum_t vdata;
247 unsigned int key_usage = 0, flags;
249 if (cert == NULL)
251 gnutls_assert ();
252 return GNUTLS_E_CERTIFICATE_ERROR;
255 gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
257 /* If the certificate supports signing continue.
259 if (key_usage != 0)
260 if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE))
262 gnutls_assert ();
263 if (session->internals.priorities.allow_key_usage_violation == 0)
264 return GNUTLS_E_KEY_USAGE_VIOLATION;
265 else
266 _gnutls_audit_log(session, "Key usage violation was detected (ignored).\n");
269 if (pk_algo == GNUTLS_PK_UNKNOWN)
270 pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
271 switch (pk_algo)
273 case GNUTLS_PK_RSA:
275 vdata.data = hash_concat->data;
276 vdata.size = hash_concat->size;
278 /* verify signature */
279 if (!_gnutls_version_has_selectable_sighash (ver))
280 flags = GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA;
281 else
282 flags = 0;
283 break;
284 case GNUTLS_PK_DSA:
285 case GNUTLS_PK_EC:
286 vdata.data = &hash_concat->data[sha1pos];
287 vdata.size = hash_concat->size - sha1pos;
289 flags = 0;
291 break;
292 default:
293 gnutls_assert ();
294 return GNUTLS_E_INTERNAL_ERROR;
297 ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags,
298 &vdata, signature);
300 if (ret < 0)
301 return gnutls_assert_val(ret);
304 return 0;
308 /* Generates a signature of all the random data and the parameters.
309 * Used in DHE_* ciphersuites.
312 _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert,
313 const gnutls_datum_t * params,
314 gnutls_datum_t * signature,
315 gnutls_sign_algorithm_t sign_algo)
317 gnutls_datum_t dconcat;
318 int ret;
319 digest_hd_st td_md5;
320 digest_hd_st td_sha;
321 uint8_t concat[MAX_SIG_SIZE];
322 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
323 gnutls_digest_algorithm_t hash_algo;
325 if (_gnutls_version_has_selectable_sighash (ver))
327 _gnutls_handshake_log ("HSK[%p]: verify handshake data: using %s\n",
328 session, gnutls_sign_algorithm_get_name (sign_algo));
330 ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, sign_algo);
331 if (ret < 0)
332 return gnutls_assert_val(ret);
334 ret = _gnutls_session_sign_algo_enabled (session, sign_algo);
335 if (ret < 0)
336 return gnutls_assert_val(ret);
338 hash_algo = gnutls_sign_get_hash_algorithm (sign_algo);
340 else
342 ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
343 if (ret < 0)
345 gnutls_assert ();
346 return ret;
349 _gnutls_hash (&td_md5, session->security_parameters.client_random,
350 GNUTLS_RANDOM_SIZE);
351 _gnutls_hash (&td_md5, session->security_parameters.server_random,
352 GNUTLS_RANDOM_SIZE);
353 _gnutls_hash (&td_md5, params->data, params->size);
355 hash_algo = GNUTLS_DIG_SHA1;
358 ret = _gnutls_hash_init (&td_sha, hash_algo);
359 if (ret < 0)
361 gnutls_assert ();
362 if (!_gnutls_version_has_selectable_sighash (ver))
363 _gnutls_hash_deinit (&td_md5, NULL);
364 return ret;
367 _gnutls_hash (&td_sha, session->security_parameters.client_random,
368 GNUTLS_RANDOM_SIZE);
369 _gnutls_hash (&td_sha, session->security_parameters.server_random,
370 GNUTLS_RANDOM_SIZE);
371 _gnutls_hash (&td_sha, params->data, params->size);
373 if (!_gnutls_version_has_selectable_sighash (ver))
375 _gnutls_hash_deinit (&td_md5, concat);
376 _gnutls_hash_deinit (&td_sha, &concat[16]);
377 dconcat.data = concat;
378 dconcat.size = 36;
380 else
382 _gnutls_hash_deinit (&td_sha, concat);
384 dconcat.data = concat;
385 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
388 ret = verify_tls_hash (session, ver, cert, &dconcat, signature,
389 dconcat.size - _gnutls_hash_get_algo_len (hash_algo),
390 sign_algo, gnutls_sign_get_pk_algorithm (sign_algo));
391 if (ret < 0)
393 gnutls_assert ();
394 return ret;
397 return ret;
401 /* Client certificate verify calculations
404 /* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
406 static int
407 _gnutls_handshake_verify_crt_vrfy12 (gnutls_session_t session,
408 gnutls_pcert_st* cert,
409 gnutls_datum_t * signature,
410 gnutls_sign_algorithm_t sign_algo)
412 int ret;
413 uint8_t concat[MAX_HASH_SIZE];
414 gnutls_datum_t dconcat;
415 gnutls_digest_algorithm_t hash_algo;
416 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
417 gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
419 ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
420 if (ret < 0)
421 return gnutls_assert_val(ret);
423 hash_algo = gnutls_sign_get_hash_algorithm(sign_algo);
425 ret = _gnutls_hash_fast(hash_algo, session->internals.handshake_hash_buffer.data,
426 session->internals.handshake_hash_buffer_prev_len,
427 concat);
428 if (ret < 0)
429 return gnutls_assert_val(ret);
431 dconcat.data = concat;
432 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
434 ret =
435 verify_tls_hash (session, ver, cert, &dconcat, signature, 0, sign_algo, pk);
436 if (ret < 0)
438 gnutls_assert ();
439 return ret;
442 return ret;
446 /* Verifies a TLS signature (like the one in the client certificate
447 * verify message).
450 _gnutls_handshake_verify_crt_vrfy (gnutls_session_t session,
451 gnutls_pcert_st *cert,
452 gnutls_datum_t * signature,
453 gnutls_sign_algorithm_t sign_algo)
455 int ret;
456 uint8_t concat[MAX_SIG_SIZE];
457 digest_hd_st td_md5;
458 digest_hd_st td_sha;
459 gnutls_datum_t dconcat;
460 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
462 _gnutls_handshake_log ("HSK[%p]: verify cert vrfy: using %s\n",
463 session, gnutls_sign_algorithm_get_name (sign_algo));
466 if (_gnutls_version_has_selectable_sighash(ver))
467 return _gnutls_handshake_verify_crt_vrfy12 (session, cert, signature,
468 sign_algo);
470 ret =
471 _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
472 if (ret < 0)
474 gnutls_assert ();
475 return ret;
478 ret =
479 _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
480 if (ret < 0)
482 gnutls_assert ();
483 _gnutls_hash_deinit (&td_md5, NULL);
484 return GNUTLS_E_HASH_FAILED;
487 _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
488 _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
490 if (ver == GNUTLS_SSL3)
492 ret = _gnutls_generate_master (session, 1);
493 if (ret < 0)
495 _gnutls_hash_deinit (&td_md5, NULL);
496 _gnutls_hash_deinit (&td_sha, NULL);
497 return gnutls_assert_val(ret);
500 ret = _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
501 session->
502 security_parameters.master_secret,
503 GNUTLS_MASTER_SIZE);
504 if (ret < 0)
506 _gnutls_hash_deinit (&td_sha, NULL);
507 return gnutls_assert_val(ret);
510 ret = _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
511 session->
512 security_parameters.master_secret,
513 GNUTLS_MASTER_SIZE);
514 if (ret < 0)
516 return gnutls_assert_val(ret);
519 else
521 _gnutls_hash_deinit (&td_md5, concat);
522 _gnutls_hash_deinit (&td_sha, &concat[16]);
525 dconcat.data = concat;
526 dconcat.size = 20 + 16; /* md5+ sha */
528 ret =
529 verify_tls_hash (session, ver, cert, &dconcat, signature, 16,
530 GNUTLS_SIGN_UNKNOWN,
531 gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL));
532 if (ret < 0)
534 gnutls_assert ();
535 return ret;
538 return ret;
542 /* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2
544 static int
545 _gnutls_handshake_sign_crt_vrfy12 (gnutls_session_t session,
546 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
547 gnutls_datum_t * signature)
549 gnutls_datum_t dconcat;
550 int ret;
551 uint8_t concat[MAX_SIG_SIZE];
552 gnutls_sign_algorithm_t sign_algo;
553 gnutls_digest_algorithm_t hash_algo;
555 sign_algo =
556 _gnutls_session_get_sign_algo (session, cert);
557 if (sign_algo == GNUTLS_SIGN_UNKNOWN)
559 gnutls_assert ();
560 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
563 gnutls_sign_algorithm_set(session, sign_algo);
565 hash_algo = gnutls_sign_get_hash_algorithm (sign_algo);
567 _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n",
568 gnutls_sign_algorithm_get_name (sign_algo),
569 gnutls_mac_get_name ((gnutls_mac_algorithm_t)hash_algo));
571 ret = _gnutls_hash_fast (hash_algo, session->internals.handshake_hash_buffer.data,
572 session->internals.handshake_hash_buffer.length,
573 concat);
574 if (ret < 0)
575 return gnutls_assert_val(ret);
577 dconcat.data = concat;
578 dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
580 ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
581 if (ret < 0)
583 gnutls_assert ();
584 return ret;
587 return sign_algo;
591 /* Generates a signature of all the previous sent packets in the
592 * handshake procedure.
593 * 20040227: now it works for SSL 3.0 as well
594 * 20091031: works for TLS 1.2 too!
596 * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
597 * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
600 _gnutls_handshake_sign_crt_vrfy (gnutls_session_t session,
601 gnutls_pcert_st* cert, gnutls_privkey_t pkey,
602 gnutls_datum_t * signature)
604 gnutls_datum_t dconcat;
605 int ret;
606 uint8_t concat[MAX_SIG_SIZE];
607 digest_hd_st td_md5;
608 digest_hd_st td_sha;
609 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
610 gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL);
612 if (_gnutls_version_has_selectable_sighash(ver))
613 return _gnutls_handshake_sign_crt_vrfy12 (session, cert, pkey,
614 signature);
616 ret =
617 _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
618 if (ret < 0)
620 gnutls_assert ();
621 return ret;
624 _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length);
626 if (ver == GNUTLS_SSL3)
628 ret = _gnutls_generate_master (session, 1);
629 if (ret < 0)
631 gnutls_assert ();
632 _gnutls_hash_deinit (&td_sha, NULL);
633 return ret;
636 ret = _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
637 session->
638 security_parameters.master_secret,
639 GNUTLS_MASTER_SIZE);
640 if (ret < 0)
641 return gnutls_assert_val(ret);
643 else
644 _gnutls_hash_deinit (&td_sha, &concat[16]);
646 /* ensure 1024 bit DSA keys are used */
647 ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN);
648 if (ret < 0)
649 return gnutls_assert_val(ret);
651 switch (pk)
653 case GNUTLS_PK_RSA:
654 ret =
655 _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
656 if (ret < 0)
657 return gnutls_assert_val(ret);
659 _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length);
661 if (ver == GNUTLS_SSL3)
663 ret = _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
664 session->
665 security_parameters.master_secret,
666 GNUTLS_MASTER_SIZE);
667 if (ret < 0)
668 return gnutls_assert_val(ret);
670 else
671 _gnutls_hash_deinit (&td_md5, concat);
673 dconcat.data = concat;
674 dconcat.size = 36;
675 break;
676 case GNUTLS_PK_DSA:
677 case GNUTLS_PK_EC:
679 dconcat.data = &concat[16];
680 dconcat.size = 20;
681 break;
683 default:
684 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
686 ret = sign_tls_hash (session, GNUTLS_DIG_NULL, cert, pkey, &dconcat, signature);
687 if (ret < 0)
689 gnutls_assert ();
692 return ret;
696 pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
697 gnutls_pk_params_st* params,
698 const gnutls_datum_t * data, gnutls_datum_t * digest)
700 int ret;
702 digest->size = _gnutls_hash_get_algo_len (hash);
703 digest->data = gnutls_malloc (digest->size);
704 if (digest->data == NULL)
706 gnutls_assert ();
707 return GNUTLS_E_MEMORY_ERROR;
710 ret = _gnutls_hash_fast (hash, data->data, data->size, digest->data);
711 if (ret < 0)
713 gnutls_assert ();
714 goto cleanup;
717 return 0;
719 cleanup:
720 gnutls_free (digest->data);
721 return ret;
726 * This function will do RSA PKCS #1 1.5 encoding
727 * on the given digest. The given digest must be allocated
728 * and will be freed if replacement is required.
731 pk_prepare_hash (gnutls_pk_algorithm_t pk,
732 gnutls_digest_algorithm_t hash, gnutls_datum_t * digest)
734 int ret;
735 gnutls_datum_t old_digest = { digest->data, digest->size };
737 switch (pk)
739 case GNUTLS_PK_RSA:
740 /* Encode the digest as a DigestInfo
742 if ((ret = encode_ber_digest_info (hash, &old_digest, digest)) != 0)
744 gnutls_assert ();
745 return ret;
748 _gnutls_free_datum (&old_digest);
749 break;
750 case GNUTLS_PK_DSA:
751 case GNUTLS_PK_EC:
752 break;
753 default:
754 gnutls_assert ();
755 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
758 return 0;