aboutsummaryrefslogtreecommitdiffstats
path: root/src/gnutls.c
diff options
context:
space:
mode:
authorMichael R. Mauger2017-07-24 22:15:04 -0400
committerMichael R. Mauger2017-07-24 22:15:04 -0400
commitdf1a71272e5cdd10b511e2ffd702ca50ddd8a773 (patch)
tree9b9ac725394ee80891e2bff57b6407d0e491e71a /src/gnutls.c
parenteb27fc4d49e8c914cd0e6a8a2d02159601542141 (diff)
parent32daa3cb54523006c88717cbeac87964cd687a1b (diff)
downloademacs-df1a71272e5cdd10b511e2ffd702ca50ddd8a773.tar.gz
emacs-df1a71272e5cdd10b511e2ffd702ca50ddd8a773.zip
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'src/gnutls.c')
-rw-r--r--src/gnutls.c811
1 files changed, 792 insertions, 19 deletions
diff --git a/src/gnutls.c b/src/gnutls.c
index 2078ad88f28..59694074e16 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24#include "process.h" 24#include "process.h"
25#include "gnutls.h" 25#include "gnutls.h"
26#include "coding.h" 26#include "coding.h"
27#include "buffer.h"
27 28
28#ifdef HAVE_GNUTLS 29#ifdef HAVE_GNUTLS
29 30
@@ -171,6 +172,59 @@ DEF_DLL_FN (const char *, gnutls_cipher_get_name,
171DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t)); 172DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
172DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t)); 173DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
173 174
175# ifdef HAVE_GNUTLS3
176DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t));
177DEF_DLL_FN (const gnutls_mac_algorithm_t *, gnutls_mac_list, (void));
178DEF_DLL_FN (size_t, gnutls_mac_get_nonce_size, (gnutls_mac_algorithm_t));
179DEF_DLL_FN (size_t, gnutls_mac_get_key_size, (gnutls_mac_algorithm_t));
180DEF_DLL_FN (const gnutls_digest_algorithm_t *, gnutls_digest_list, (void));
181DEF_DLL_FN (const char *, gnutls_digest_get_name, (gnutls_digest_algorithm_t));
182# ifdef HAVE_GNUTLS3_CIPHER
183DEF_DLL_FN (gnutls_cipher_algorithm_t *, gnutls_cipher_list, (void));
184DEF_DLL_FN (int, gnutls_cipher_get_iv_size, (gnutls_cipher_algorithm_t));
185DEF_DLL_FN (size_t, gnutls_cipher_get_key_size, (gnutls_cipher_algorithm_t));
186DEF_DLL_FN (int, gnutls_cipher_get_block_size, (gnutls_cipher_algorithm_t));
187DEF_DLL_FN (int, gnutls_cipher_get_tag_size, (gnutls_cipher_algorithm_t));
188DEF_DLL_FN (int, gnutls_cipher_init,
189 (gnutls_cipher_hd_t *, gnutls_cipher_algorithm_t,
190 const gnutls_datum_t *, const gnutls_datum_t *));
191DEF_DLL_FN (void, gnutls_cipher_set_iv, (gnutls_cipher_hd_t, void *, size_t));
192DEF_DLL_FN (int, gnutls_cipher_encrypt2,
193 (gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
194DEF_DLL_FN (void, gnutls_cipher_deinit, (gnutls_cipher_hd_t));
195DEF_DLL_FN (int, gnutls_cipher_decrypt2,
196 (gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
197# ifdef HAVE_GNUTLS3_AEAD
198DEF_DLL_FN (int, gnutls_aead_cipher_init,
199 (gnutls_aead_cipher_hd_t *, gnutls_cipher_algorithm_t,
200 const gnutls_datum_t *));
201DEF_DLL_FN (void, gnutls_aead_cipher_deinit, (gnutls_aead_cipher_hd_t));
202DEF_DLL_FN (int, gnutls_aead_cipher_encrypt,
203 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
204 size_t, size_t, const void *, size_t, void *, size_t *));
205DEF_DLL_FN (int, gnutls_aead_cipher_decrypt,
206 (gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
207 size_t, size_t, const void *, size_t, void *, size_t *));
208# endif /* HAVE_GNUTLS3_AEAD */
209# ifdef HAVE_GNUTLS3_HMAC
210DEF_DLL_FN (int, gnutls_hmac_init,
211 (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t));
212DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t));
213DEF_DLL_FN (int, gnutls_hmac, (gnutls_hmac_hd_t, const void *, size_t));
214DEF_DLL_FN (void, gnutls_hmac_deinit, (gnutls_hmac_hd_t, void *));
215DEF_DLL_FN (void, gnutls_hmac_output, (gnutls_hmac_hd_t, void *));
216# endif /* HAVE_GNUTLS3_HMAC */
217# endif /* HAVE_GNUTLS3_CIPHER */
218# ifdef HAVE_GNUTLS3_DIGEST
219 DEF_DLL_FN (int, gnutls_hash_init,
220 (gnutls_hash_hd_t *, gnutls_digest_algorithm_t));
221DEF_DLL_FN (int, gnutls_hash_get_len, (gnutls_digest_algorithm_t));
222DEF_DLL_FN (int, gnutls_hash, (gnutls_hash_hd_t, const void *, size_t));
223DEF_DLL_FN (void, gnutls_hash_deinit, (gnutls_hash_hd_t, void *));
224DEF_DLL_FN (void, gnutls_hash_output, (gnutls_hash_hd_t, void *));
225# endif /* HAVE_GNUTLS3_DIGEST */
226# endif /* HAVE_GNUTLS3 */
227
174 228
175static bool 229static bool
176init_gnutls_functions (void) 230init_gnutls_functions (void)
@@ -255,6 +309,46 @@ init_gnutls_functions (void)
255 LOAD_DLL_FN (library, gnutls_cipher_get_name); 309 LOAD_DLL_FN (library, gnutls_cipher_get_name);
256 LOAD_DLL_FN (library, gnutls_mac_get); 310 LOAD_DLL_FN (library, gnutls_mac_get);
257 LOAD_DLL_FN (library, gnutls_mac_get_name); 311 LOAD_DLL_FN (library, gnutls_mac_get_name);
312# ifdef HAVE_GNUTLS3
313 LOAD_DLL_FN (library, gnutls_rnd);
314 LOAD_DLL_FN (library, gnutls_mac_list);
315 LOAD_DLL_FN (library, gnutls_mac_get_nonce_size);
316 LOAD_DLL_FN (library, gnutls_mac_get_key_size);
317 LOAD_DLL_FN (library, gnutls_digest_list);
318 LOAD_DLL_FN (library, gnutls_digest_get_name);
319# ifdef HAVE_GNUTLS3_CIPHER
320 LOAD_DLL_FN (library, gnutls_cipher_list);
321 LOAD_DLL_FN (library, gnutls_cipher_get_iv_size);
322 LOAD_DLL_FN (library, gnutls_cipher_get_key_size);
323 LOAD_DLL_FN (library, gnutls_cipher_get_block_size);
324 LOAD_DLL_FN (library, gnutls_cipher_get_tag_size);
325 LOAD_DLL_FN (library, gnutls_cipher_init);
326 LOAD_DLL_FN (library, gnutls_cipher_set_iv);
327 LOAD_DLL_FN (library, gnutls_cipher_encrypt2);
328 LOAD_DLL_FN (library, gnutls_cipher_deinit);
329 LOAD_DLL_FN (library, gnutls_cipher_decrypt2);
330# ifdef HAVE_GNUTLS3_AEAD
331 LOAD_DLL_FN (library, gnutls_aead_cipher_init);
332 LOAD_DLL_FN (library, gnutls_aead_cipher_deinit);
333 LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt);
334 LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt);
335# endif
336# ifdef HAVE_GNUTLS3_HMAC
337 LOAD_DLL_FN (library, gnutls_hmac_init);
338 LOAD_DLL_FN (library, gnutls_hmac_get_len);
339 LOAD_DLL_FN (library, gnutls_hmac);
340 LOAD_DLL_FN (library, gnutls_hmac_deinit);
341 LOAD_DLL_FN (library, gnutls_hmac_output);
342# endif /* HAVE_GNUTLS3_HMAC */
343# endif /* HAVE_GNUTLS3_CIPHER */
344# ifdef HAVE_GNUTLS3_DIGEST
345 LOAD_DLL_FN (library, gnutls_hash_init);
346 LOAD_DLL_FN (library, gnutls_hash_get_len);
347 LOAD_DLL_FN (library, gnutls_hash);
348 LOAD_DLL_FN (library, gnutls_hash_deinit);
349 LOAD_DLL_FN (library, gnutls_hash_output);
350# endif
351# endif /* HAVE_GNUTLS3 */
258 352
259 max_log_level = global_gnutls_log_level; 353 max_log_level = global_gnutls_log_level;
260 354
@@ -332,8 +426,56 @@ init_gnutls_functions (void)
332# define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version 426# define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
333# define gnutls_x509_crt_import fn_gnutls_x509_crt_import 427# define gnutls_x509_crt_import fn_gnutls_x509_crt_import
334# define gnutls_x509_crt_init fn_gnutls_x509_crt_init 428# define gnutls_x509_crt_init fn_gnutls_x509_crt_init
429# ifdef HAVE_GNUTLS3
430# define gnutls_rnd fn_gnutls_rnd
431# define gnutls_mac_list fn_gnutls_mac_list
432# define gnutls_mac_get_nonce_size fn_gnutls_mac_get_nonce_size
433# define gnutls_mac_get_key_size fn_gnutls_mac_get_key_size
434# define gnutls_digest_list fn_gnutls_digest_list
435# define gnutls_digest_get_name fn_gnutls_digest_get_name
436# ifdef HAVE_GNUTLS3_CIPHER
437# define gnutls_cipher_list fn_gnutls_cipher_list
438# define gnutls_cipher_get_iv_size fn_gnutls_cipher_get_iv_size
439# define gnutls_cipher_get_key_size fn_gnutls_cipher_get_key_size
440# define gnutls_cipher_get_block_size fn_gnutls_cipher_get_block_size
441# define gnutls_cipher_get_tag_size fn_gnutls_cipher_get_tag_size
442# define gnutls_cipher_init fn_gnutls_cipher_init
443# define gnutls_cipher_set_iv fn_gnutls_cipher_set_iv
444# define gnutls_cipher_encrypt2 fn_gnutls_cipher_encrypt2
445# define gnutls_cipher_decrypt2 fn_gnutls_cipher_decrypt2
446# define gnutls_cipher_deinit fn_gnutls_cipher_deinit
447# ifdef HAVE_GNUTLS3_AEAD
448# define gnutls_aead_cipher_encrypt fn_gnutls_aead_cipher_encrypt
449# define gnutls_aead_cipher_decrypt fn_gnutls_aead_cipher_decrypt
450# define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init
451# define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit
452# endif /* HAVE_GNUTLS3_AEAD */
453# ifdef HAVE_GNUTLS3_HMAC
454# define gnutls_hmac_init fn_gnutls_hmac_init
455# define gnutls_hmac_get_len fn_gnutls_hmac_get_len
456# define gnutls_hmac fn_gnutls_hmac
457# define gnutls_hmac_deinit fn_gnutls_hmac_deinit
458# define gnutls_hmac_output fn_gnutls_hmac_output
459# endif /* HAVE_GNUTLS3_HMAC */
460# endif /* HAVE_GNUTLS3_CIPHER */
461# ifdef HAVE_GNUTLS3_DIGEST
462# define gnutls_hash_init fn_gnutls_hash_init
463# define gnutls_hash_get_len fn_gnutls_hash_get_len
464# define gnutls_hash fn_gnutls_hash
465# define gnutls_hash_deinit fn_gnutls_hash_deinit
466# define gnutls_hash_output fn_gnutls_hash_output
467# endif
468# endif /* HAVE_GNUTLS3 */
469
470/* This wrapper is called from fns.c, which doesn't know about the
471 LOAD_DLL_FN stuff above. */
472int
473w32_gnutls_rnd (gnutls_rnd_level_t level, void *data, size_t len)
474{
475 return gnutls_rnd (level, data, len);
476}
335 477
336#endif 478#endif /* WINDOWSNT */
337 479
338 480
339/* Report memory exhaustion if ERR is an out-of-memory indication. */ 481/* Report memory exhaustion if ERR is an out-of-memory indication. */
@@ -433,7 +575,7 @@ emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
433 return err; 575 return err;
434 } 576 }
435} 577}
436#endif 578#endif /* !WINDOWSNT */
437 579
438static int 580static int
439emacs_gnutls_handshake (struct Lisp_Process *proc) 581emacs_gnutls_handshake (struct Lisp_Process *proc)
@@ -556,6 +698,13 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
556 } 698 }
557} 699}
558 700
701static char const *
702emacs_gnutls_strerror (int err)
703{
704 char const *str = gnutls_strerror (err);
705 return str ? str : "unknown";
706}
707
559/* Report a GnuTLS error to the user. 708/* Report a GnuTLS error to the user.
560 Return true if the error code was successfully handled. */ 709 Return true if the error code was successfully handled. */
561static bool 710static bool
@@ -564,7 +713,6 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
564 int max_log_level = 0; 713 int max_log_level = 0;
565 714
566 bool ret; 715 bool ret;
567 const char *str;
568 716
569 /* TODO: use a Lisp_Object generated by gnutls_make_error? */ 717 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
570 if (err >= 0) 718 if (err >= 0)
@@ -576,9 +724,7 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
576 724
577 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */ 725 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
578 726
579 str = gnutls_strerror (err); 727 char const *str = emacs_gnutls_strerror (err);
580 if (!str)
581 str = "unknown";
582 728
583 if (gnutls_error_is_fatal (err)) 729 if (gnutls_error_is_fatal (err))
584 { 730 {
@@ -592,11 +738,11 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
592#endif 738#endif
593 739
594 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str); 740 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
595 ret = 0; 741 ret = false;
596 } 742 }
597 else 743 else
598 { 744 {
599 ret = 1; 745 ret = true;
600 746
601 switch (err) 747 switch (err)
602 { 748 {
@@ -784,7 +930,7 @@ usage: (gnutls-error-string ERROR) */)
784 if (! TYPE_RANGED_INTEGERP (int, err)) 930 if (! TYPE_RANGED_INTEGERP (int, err))
785 return build_string ("Not an error symbol or code"); 931 return build_string ("Not an error symbol or code");
786 932
787 return build_string (gnutls_strerror (XINT (err))); 933 return build_string (emacs_gnutls_strerror (XINT (err)));
788} 934}
789 935
790DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0, 936DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
@@ -1476,9 +1622,9 @@ one trustfile (usually a CA bundle). */)
1476 XPROCESS (proc)->gnutls_x509_cred = x509_cred; 1622 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1477 1623
1478 verify_flags = Fplist_get (proplist, QCverify_flags); 1624 verify_flags = Fplist_get (proplist, QCverify_flags);
1479 if (NUMBERP (verify_flags)) 1625 if (TYPE_RANGED_INTEGERP (unsigned int, verify_flags))
1480 { 1626 {
1481 gnutls_verify_flags = XINT (verify_flags); 1627 gnutls_verify_flags = XFASTINT (verify_flags);
1482 GNUTLS_LOG (2, max_log_level, "setting verification flags"); 1628 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1483 } 1629 }
1484 else if (NILP (verify_flags)) 1630 else if (NILP (verify_flags))
@@ -1697,28 +1843,624 @@ This function may also return `gnutls-e-again', or
1697 1843
1698#endif /* HAVE_GNUTLS */ 1844#endif /* HAVE_GNUTLS */
1699 1845
1846#ifdef HAVE_GNUTLS3
1847
1848DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0,
1849 doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists.
1850The alist key is the cipher name. */)
1851 (void)
1852{
1853 Lisp_Object ciphers = Qnil;
1854
1855#ifdef HAVE_GNUTLS3_CIPHER
1856 const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
1857 for (ptrdiff_t pos = 0; gciphers[pos] != 0; pos++)
1858 {
1859 gnutls_cipher_algorithm_t gca = gciphers[pos];
1860 if (gca == GNUTLS_CIPHER_NULL)
1861 continue;
1862 char const *cipher_name = gnutls_cipher_get_name (gca);
1863 if (!cipher_name)
1864 continue;
1865
1866 /* A symbol representing the GnuTLS cipher. */
1867 Lisp_Object cipher_symbol = intern (cipher_name);
1868
1869 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1870
1871 Lisp_Object cp
1872 = listn (CONSTYPE_HEAP, 15, cipher_symbol,
1873 QCcipher_id, make_number (gca),
1874 QCtype, Qgnutls_type_cipher,
1875 QCcipher_aead_capable, cipher_tag_size == 0 ? Qnil : Qt,
1876 QCcipher_tagsize, make_number (cipher_tag_size),
1877
1878 QCcipher_blocksize,
1879 make_number (gnutls_cipher_get_block_size (gca)),
1880
1881 QCcipher_keysize,
1882 make_number (gnutls_cipher_get_key_size (gca)),
1883
1884 QCcipher_ivsize,
1885 make_number (gnutls_cipher_get_iv_size (gca)));
1886
1887 ciphers = Fcons (cp, ciphers);
1888 }
1889#endif
1890
1891 return ciphers;
1892}
1893
1894static Lisp_Object
1895gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1896 Lisp_Object cipher,
1897 const char *kdata, ptrdiff_t ksize,
1898 const char *vdata, ptrdiff_t vsize,
1899 const char *idata, ptrdiff_t isize,
1900 Lisp_Object aead_auth)
1901{
1902#ifdef HAVE_GNUTLS3_AEAD
1903
1904 const char *desc = encrypting ? "encrypt" : "decrypt";
1905 Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
1906
1907 gnutls_aead_cipher_hd_t acipher;
1908 gnutls_datum_t key_datum = { (unsigned char *) kdata, ksize };
1909 int ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
1910
1911 if (ret < GNUTLS_E_SUCCESS)
1912 error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
1913 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
1914
1915 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1916 ptrdiff_t tagged_size;
1917 if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
1918 || SIZE_MAX < tagged_size)
1919 memory_full (SIZE_MAX);
1920 size_t storage_length = tagged_size;
1921 USE_SAFE_ALLOCA;
1922 char *storage = SAFE_ALLOCA (storage_length);
1923
1924 const char *aead_auth_data = NULL;
1925 ptrdiff_t aead_auth_size = 0;
1926
1927 if (!NILP (aead_auth))
1928 {
1929 if (BUFFERP (aead_auth) || STRINGP (aead_auth))
1930 aead_auth = list1 (aead_auth);
1931
1932 CHECK_CONS (aead_auth);
1933
1934 ptrdiff_t astart_byte, aend_byte;
1935 const char *adata
1936 = extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
1937 if (adata == NULL)
1938 error ("GnuTLS AEAD cipher auth extraction failed");
1939
1940 aead_auth_data = adata;
1941 aead_auth_size = aend_byte - astart_byte;
1942 }
1943
1944 ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
1945 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
1946
1947 if (isize < expected_remainder
1948 || (isize - expected_remainder) % cipher_block_size != 0)
1949 error (("GnuTLS AEAD cipher %s/%s input block length %"pD"d "
1950 "is not %"pD"d greater than a multiple of the required %"pD"d"),
1951 gnutls_cipher_get_name (gca), desc,
1952 isize, expected_remainder, cipher_block_size);
1953
1954 ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
1955 (acipher, vdata, vsize, aead_auth_data, aead_auth_size,
1956 cipher_tag_size, idata, isize, storage, &storage_length));
1957
1958 Lisp_Object output;
1959 if (GNUTLS_E_SUCCESS <= ret)
1960 output = make_unibyte_string (storage, storage_length);
1961 explicit_bzero (storage, storage_length);
1962 gnutls_aead_cipher_deinit (acipher);
1963
1964 if (ret < GNUTLS_E_SUCCESS)
1965 error ((encrypting
1966 ? "GnuTLS AEAD cipher %s encryption failed: %s"
1967 : "GnuTLS AEAD cipher %s decryption failed: %s"),
1968 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
1969
1970 SAFE_FREE ();
1971 return list2 (output, actual_iv);
1972#else
1973 printmax_t print_gca = gca;
1974 error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
1975#endif
1976}
1977
1978static Lisp_Object
1979gnutls_symmetric (bool encrypting, Lisp_Object cipher,
1980 Lisp_Object key, Lisp_Object iv,
1981 Lisp_Object input, Lisp_Object aead_auth)
1982{
1983 if (BUFFERP (key) || STRINGP (key))
1984 key = list1 (key);
1985
1986 CHECK_CONS (key);
1987
1988 if (BUFFERP (input) || STRINGP (input))
1989 input = list1 (input);
1990
1991 CHECK_CONS (input);
1992
1993 if (BUFFERP (iv) || STRINGP (iv))
1994 iv = list1 (iv);
1995
1996 CHECK_CONS (iv);
1997
1998
1999 const char *desc = encrypting ? "encrypt" : "decrypt";
2000
2001 gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN;
2002
2003 Lisp_Object info = Qnil;
2004 if (STRINGP (cipher))
2005 cipher = intern (SSDATA (cipher));
2006
2007 if (SYMBOLP (cipher))
2008 info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
2009 else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
2010 gca = XINT (cipher);
2011 else
2012 info = cipher;
2013
2014 if (!NILP (info) && CONSP (info))
2015 {
2016 Lisp_Object v = Fplist_get (info, QCcipher_id);
2017 if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, v))
2018 gca = XINT (v);
2019 }
2020
2021 ptrdiff_t key_size = gnutls_cipher_get_key_size (gca);
2022 if (key_size == 0)
2023 error ("GnuTLS cipher is invalid or not found");
2024
2025 ptrdiff_t kstart_byte, kend_byte;
2026 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2027
2028 if (kdata == NULL)
2029 error ("GnuTLS cipher key extraction failed");
2030
2031 if (kend_byte - kstart_byte != key_size)
2032 error (("GnuTLS cipher %s/%s key length %"pD"d is not equal to "
2033 "the required %"pD"d"),
2034 gnutls_cipher_get_name (gca), desc,
2035 kend_byte - kstart_byte, key_size);
2036
2037 ptrdiff_t vstart_byte, vend_byte;
2038 char *vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
2039
2040 if (vdata == NULL)
2041 error ("GnuTLS cipher IV extraction failed");
2042
2043 ptrdiff_t iv_size = gnutls_cipher_get_iv_size (gca);
2044 if (vend_byte - vstart_byte != iv_size)
2045 error (("GnuTLS cipher %s/%s IV length %"pD"d is not equal to "
2046 "the required %"pD"d"),
2047 gnutls_cipher_get_name (gca), desc,
2048 vend_byte - vstart_byte, iv_size);
2049
2050 Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte);
2051
2052 ptrdiff_t istart_byte, iend_byte;
2053 const char *idata
2054 = extract_data_from_object (input, &istart_byte, &iend_byte);
2055
2056 if (idata == NULL)
2057 error ("GnuTLS cipher input extraction failed");
2058
2059 /* Is this an AEAD cipher? */
2060 if (gnutls_cipher_get_tag_size (gca) > 0)
2061 {
2062 Lisp_Object aead_output =
2063 gnutls_symmetric_aead (encrypting, gca, cipher,
2064 kdata, kend_byte - kstart_byte,
2065 vdata, vend_byte - vstart_byte,
2066 idata, iend_byte - istart_byte,
2067 aead_auth);
2068 if (STRINGP (XCAR (key)))
2069 Fclear_string (XCAR (key));
2070 return aead_output;
2071 }
2072
2073 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
2074 if ((iend_byte - istart_byte) % cipher_block_size != 0)
2075 error (("GnuTLS cipher %s/%s input block length %"pD"d is not a multiple "
2076 "of the required %"pD"d"),
2077 gnutls_cipher_get_name (gca), desc,
2078 iend_byte - istart_byte, cipher_block_size);
2079
2080 gnutls_cipher_hd_t hcipher;
2081 gnutls_datum_t key_datum
2082 = { (unsigned char *) kdata, kend_byte - kstart_byte };
2083
2084 int ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
2085
2086 if (ret < GNUTLS_E_SUCCESS)
2087 error ("GnuTLS cipher %s/%s initialization failed: %s",
2088 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
2089
2090 /* Note that this will not support streaming block mode. */
2091 gnutls_cipher_set_iv (hcipher, vdata, vend_byte - vstart_byte);
2092
2093 /* GnuTLS docs: "For the supported ciphers the encrypted data length
2094 will equal the plaintext size." */
2095 ptrdiff_t storage_length = iend_byte - istart_byte;
2096 Lisp_Object storage = make_uninit_string (storage_length);
2097
2098 ret = ((encrypting ? gnutls_cipher_encrypt2 : gnutls_cipher_decrypt2)
2099 (hcipher, idata, iend_byte - istart_byte,
2100 SSDATA (storage), storage_length));
2101
2102 if (STRINGP (XCAR (key)))
2103 Fclear_string (XCAR (key));
2104
2105 if (ret < GNUTLS_E_SUCCESS)
2106 {
2107 gnutls_cipher_deinit (hcipher);
2108 if (encrypting)
2109 error ("GnuTLS cipher %s encryption failed: %s",
2110 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2111 else
2112 error ("GnuTLS cipher %s decryption failed: %s",
2113 gnutls_cipher_get_name (gca), emacs_gnutls_strerror (ret));
2114 }
2115
2116 gnutls_cipher_deinit (hcipher);
2117
2118 return list2 (storage, actual_iv);
2119}
2120
2121DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt,
2122 Sgnutls_symmetric_encrypt, 4, 5, 0,
2123 doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2124
2125Return nil on error.
2126
2127The KEY can be specified as a buffer or string or in other ways (see
2128Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2129will be wiped after use if it's a string.
2130
2131The IV and INPUT and the optional AEAD_AUTH can be specified as a
2132buffer or string or in other ways (see Info node `(elisp)Format of
2133GnuTLS Cryptography Inputs').
2134
2135The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2136The CIPHER may be a string or symbol matching a key in that alist, or
2137a plist with the :cipher-id numeric property, or the number itself.
2138
2139AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2140:cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2141these AEAD ciphers, but it may still be omitted (nil) as well. */)
2142 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2143 Lisp_Object input, Lisp_Object aead_auth)
2144{
2145 return gnutls_symmetric (true, cipher, key, iv, input, aead_auth);
2146}
2147
2148DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt,
2149 Sgnutls_symmetric_decrypt, 4, 5, 0,
2150 doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2151
2152Return nil on error.
2153
2154The KEY can be specified as a buffer or string or in other ways (see
2155Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2156will be wiped after use if it's a string.
2157
2158The IV and INPUT and the optional AEAD_AUTH can be specified as a
2159buffer or string or in other ways (see Info node `(elisp)Format of
2160GnuTLS Cryptography Inputs').
2161
2162The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2163The CIPHER may be a string or symbol matching a key in that alist, or
2164a plist with the `:cipher-id' numeric property, or the number itself.
2165
2166AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2167:cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2168these AEAD ciphers, but it may still be omitted (nil) as well. */)
2169 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2170 Lisp_Object input, Lisp_Object aead_auth)
2171{
2172 return gnutls_symmetric (false, cipher, key, iv, input, aead_auth);
2173}
2174
2175DEFUN ("gnutls-macs", Fgnutls_macs, Sgnutls_macs, 0, 0, 0,
2176 doc: /* Return alist of GnuTLS mac-algorithm method descriptions as plists.
2177
2178Use the value of the alist (extract it with `alist-get' for instance)
2179with `gnutls-hash-mac'. The alist key is the mac-algorithm method
2180name. */)
2181 (void)
2182{
2183 Lisp_Object mac_algorithms = Qnil;
2184#ifdef HAVE_GNUTLS3_HMAC
2185 const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
2186 for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
2187 {
2188 const gnutls_mac_algorithm_t gma = macs[pos];
2189
2190 /* A symbol representing the GnuTLS MAC algorithm. */
2191 Lisp_Object gma_symbol = intern (gnutls_mac_get_name (gma));
2192
2193 Lisp_Object mp = listn (CONSTYPE_HEAP, 11, gma_symbol,
2194 QCmac_algorithm_id, make_number (gma),
2195 QCtype, Qgnutls_type_mac_algorithm,
2196
2197 QCmac_algorithm_length,
2198 make_number (gnutls_hmac_get_len (gma)),
2199
2200 QCmac_algorithm_keysize,
2201 make_number (gnutls_mac_get_key_size (gma)),
2202
2203 QCmac_algorithm_noncesize,
2204 make_number (gnutls_mac_get_nonce_size (gma)));
2205 mac_algorithms = Fcons (mp, mac_algorithms);
2206 }
2207#endif
2208
2209 return mac_algorithms;
2210}
2211
2212DEFUN ("gnutls-digests", Fgnutls_digests, Sgnutls_digests, 0, 0, 0,
2213 doc: /* Return alist of GnuTLS digest-algorithm method descriptions as plists.
2214
2215Use the value of the alist (extract it with `alist-get' for instance)
2216with `gnutls-hash-digest'. The alist key is the digest-algorithm
2217method name. */)
2218 (void)
2219{
2220 Lisp_Object digest_algorithms = Qnil;
2221#ifdef HAVE_GNUTLS3_DIGEST
2222 const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
2223 for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
2224 {
2225 const gnutls_digest_algorithm_t gda = digests[pos];
2226
2227 /* A symbol representing the GnuTLS digest algorithm. */
2228 Lisp_Object gda_symbol = intern (gnutls_digest_get_name (gda));
2229
2230 Lisp_Object mp = listn (CONSTYPE_HEAP, 7, gda_symbol,
2231 QCdigest_algorithm_id, make_number (gda),
2232 QCtype, Qgnutls_type_digest_algorithm,
2233
2234 QCdigest_algorithm_length,
2235 make_number (gnutls_hash_get_len (gda)));
2236
2237 digest_algorithms = Fcons (mp, digest_algorithms);
2238 }
2239#endif
2240
2241 return digest_algorithms;
2242}
2243
2244DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0,
2245 doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string.
2246
2247Return nil on error.
2248
2249The KEY can be specified as a buffer or string or in other ways (see
2250Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2251will be wiped after use if it's a string.
2252
2253The INPUT can be specified as a buffer or string or in other
2254ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2255
2256The alist of MAC algorithms can be obtained with `gnutls-macs`. The
2257HASH-METHOD may be a string or symbol matching a key in that alist, or
2258a plist with the `:mac-algorithm-id' numeric property, or the number
2259itself. */)
2260 (Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
2261{
2262 if (BUFFERP (input) || STRINGP (input))
2263 input = list1 (input);
2264
2265 CHECK_CONS (input);
2266
2267 if (BUFFERP (key) || STRINGP (key))
2268 key = list1 (key);
2269
2270 CHECK_CONS (key);
2271
2272 gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
2273
2274 Lisp_Object info = Qnil;
2275 if (STRINGP (hash_method))
2276 hash_method = intern (SSDATA (hash_method));
2277
2278 if (SYMBOLP (hash_method))
2279 info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
2280 else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
2281 gma = XINT (hash_method);
2282 else
2283 info = hash_method;
2284
2285 if (!NILP (info) && CONSP (info))
2286 {
2287 Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
2288 if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, v))
2289 gma = XINT (v);
2290 }
2291
2292 ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
2293 if (digest_length == 0)
2294 error ("GnuTLS MAC-method is invalid or not found");
2295
2296 ptrdiff_t kstart_byte, kend_byte;
2297 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2298 if (kdata == NULL)
2299 error ("GnuTLS MAC key extraction failed");
2300
2301 gnutls_hmac_hd_t hmac;
2302 int ret = gnutls_hmac_init (&hmac, gma,
2303 kdata + kstart_byte, kend_byte - kstart_byte);
2304 if (ret < GNUTLS_E_SUCCESS)
2305 error ("GnuTLS MAC %s initialization failed: %s",
2306 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2307
2308 ptrdiff_t istart_byte, iend_byte;
2309 const char *idata
2310 = extract_data_from_object (input, &istart_byte, &iend_byte);
2311 if (idata == NULL)
2312 error ("GnuTLS MAC input extraction failed");
2313
2314 Lisp_Object digest = make_uninit_string (digest_length);
2315
2316 ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
2317
2318 if (STRINGP (XCAR (key)))
2319 Fclear_string (XCAR (key));
2320
2321 if (ret < GNUTLS_E_SUCCESS)
2322 {
2323 gnutls_hmac_deinit (hmac, NULL);
2324 error ("GnuTLS MAC %s application failed: %s",
2325 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2326 }
2327
2328 gnutls_hmac_output (hmac, SSDATA (digest));
2329 gnutls_hmac_deinit (hmac, NULL);
2330
2331 return digest;
2332}
2333
2334DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0,
2335 doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string.
2336
2337Return nil on error.
2338
2339The INPUT can be specified as a buffer or string or in other
2340ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
2341
2342The alist of digest algorithms can be obtained with `gnutls-digests`.
2343The DIGEST-METHOD may be a string or symbol matching a key in that
2344alist, or a plist with the `:digest-algorithm-id' numeric property, or
2345the number itself. */)
2346 (Lisp_Object digest_method, Lisp_Object input)
2347{
2348 if (BUFFERP (input) || STRINGP (input))
2349 input = list1 (input);
2350
2351 CHECK_CONS (input);
2352
2353 gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN;
2354
2355 Lisp_Object info = Qnil;
2356 if (STRINGP (digest_method))
2357 digest_method = intern (SSDATA (digest_method));
2358
2359 if (SYMBOLP (digest_method))
2360 info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
2361 else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
2362 gda = XINT (digest_method);
2363 else
2364 info = digest_method;
2365
2366 if (!NILP (info) && CONSP (info))
2367 {
2368 Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
2369 if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, v))
2370 gda = XINT (v);
2371 }
2372
2373 ptrdiff_t digest_length = gnutls_hash_get_len (gda);
2374 if (digest_length == 0)
2375 error ("GnuTLS digest-method is invalid or not found");
2376
2377 gnutls_hash_hd_t hash;
2378 int ret = gnutls_hash_init (&hash, gda);
2379
2380 if (ret < GNUTLS_E_SUCCESS)
2381 error ("GnuTLS digest initialization failed: %s",
2382 emacs_gnutls_strerror (ret));
2383
2384 Lisp_Object digest = make_uninit_string (digest_length);
2385
2386 ptrdiff_t istart_byte, iend_byte;
2387 const char *idata
2388 = extract_data_from_object (input, &istart_byte, &iend_byte);
2389 if (idata == NULL)
2390 error ("GnuTLS digest input extraction failed");
2391
2392 ret = gnutls_hash (hash, idata + istart_byte, iend_byte - istart_byte);
2393
2394 if (ret < GNUTLS_E_SUCCESS)
2395 {
2396 gnutls_hash_deinit (hash, NULL);
2397 error ("GnuTLS digest application failed: %s",
2398 emacs_gnutls_strerror (ret));
2399 }
2400
2401 gnutls_hash_output (hash, SSDATA (digest));
2402 gnutls_hash_deinit (hash, NULL);
2403
2404 return digest;
2405}
2406
2407#endif /* HAVE_GNUTLS3 */
2408
1700DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0, 2409DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
1701 doc: /* Return t if GnuTLS is available in this instance of Emacs. */) 2410 doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs.
1702 (void) 2411
2412...if supported : then...
2413GnuTLS 3 or higher : the list will contain `gnutls3'.
2414GnuTLS MACs : the list will contain `macs'.
2415GnuTLS digests : the list will contain `digests'.
2416GnuTLS symmetric ciphers: the list will contain `ciphers'.
2417GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'. */)
2418 (void)
1703{ 2419{
2420 Lisp_Object capabilities = Qnil;
2421
1704#ifdef HAVE_GNUTLS 2422#ifdef HAVE_GNUTLS
1705# ifdef WINDOWSNT 2423
2424# ifdef HAVE_GNUTLS3
2425 capabilities = Fcons (intern("gnutls3"), capabilities);
2426
2427# ifdef HAVE_GNUTLS3_DIGEST
2428 capabilities = Fcons (intern("digests"), capabilities);
2429# endif
2430
2431# ifdef HAVE_GNUTLS3_CIPHER
2432 capabilities = Fcons (intern("ciphers"), capabilities);
2433
2434# ifdef HAVE_GNUTLS3_AEAD
2435 capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
2436# endif
2437
2438# ifdef HAVE_GNUTLS3_HMAC
2439 capabilities = Fcons (intern("macs"), capabilities);
2440# endif
2441# endif /* HAVE_GNUTLS3_CIPHER */
2442# endif /* HAVE_GNUTLS3 */
2443
2444#ifdef WINDOWSNT
1706 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache); 2445 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
1707 if (CONSP (found)) 2446 if (CONSP (found))
1708 return XCDR (found); 2447 return XCDR (found);
1709 else 2448 else
1710 { 2449 {
1711 Lisp_Object status; 2450 Lisp_Object status;
1712 status = init_gnutls_functions () ? Qt : Qnil; 2451 status = init_gnutls_functions () ? capabilities : Qnil;
1713 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache); 2452 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
1714 return status; 2453 return status;
1715 } 2454 }
1716# else /* !WINDOWSNT */ 2455#else /* !WINDOWSNT */
1717 return Qt; 2456
1718# endif /* !WINDOWSNT */ 2457 return capabilities;
2458
2459#endif /* WINDOWSNT */
2460
1719#else /* !HAVE_GNUTLS */ 2461#else /* !HAVE_GNUTLS */
1720 return Qnil; 2462 return Qnil;
1721#endif /* !HAVE_GNUTLS */ 2463#endif /* HAVE_GNUTLS */
1722} 2464}
1723 2465
1724void 2466void
@@ -1753,6 +2495,27 @@ syms_of_gnutls (void)
1753 DEFSYM (QCverify_flags, ":verify-flags"); 2495 DEFSYM (QCverify_flags, ":verify-flags");
1754 DEFSYM (QCverify_error, ":verify-error"); 2496 DEFSYM (QCverify_error, ":verify-error");
1755 2497
2498 DEFSYM (QCcipher_id, ":cipher-id");
2499 DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable");
2500 DEFSYM (QCcipher_blocksize, ":cipher-blocksize");
2501 DEFSYM (QCcipher_keysize, ":cipher-keysize");
2502 DEFSYM (QCcipher_tagsize, ":cipher-tagsize");
2503 DEFSYM (QCcipher_keysize, ":cipher-keysize");
2504 DEFSYM (QCcipher_ivsize, ":cipher-ivsize");
2505
2506 DEFSYM (QCmac_algorithm_id, ":mac-algorithm-id");
2507 DEFSYM (QCmac_algorithm_noncesize, ":mac-algorithm-noncesize");
2508 DEFSYM (QCmac_algorithm_keysize, ":mac-algorithm-keysize");
2509 DEFSYM (QCmac_algorithm_length, ":mac-algorithm-length");
2510
2511 DEFSYM (QCdigest_algorithm_id, ":digest-algorithm-id");
2512 DEFSYM (QCdigest_algorithm_length, ":digest-algorithm-length");
2513
2514 DEFSYM (QCtype, ":type");
2515 DEFSYM (Qgnutls_type_cipher, "gnutls-symmetric-cipher");
2516 DEFSYM (Qgnutls_type_mac_algorithm, "gnutls-mac-algorithm");
2517 DEFSYM (Qgnutls_type_digest_algorithm, "gnutls-digest-algorithm");
2518
1756 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted"); 2519 DEFSYM (Qgnutls_e_interrupted, "gnutls-e-interrupted");
1757 Fput (Qgnutls_e_interrupted, Qgnutls_code, 2520 Fput (Qgnutls_e_interrupted, Qgnutls_code,
1758 make_number (GNUTLS_E_INTERRUPTED)); 2521 make_number (GNUTLS_E_INTERRUPTED));
@@ -1780,6 +2543,16 @@ syms_of_gnutls (void)
1780 defsubr (&Sgnutls_peer_status); 2543 defsubr (&Sgnutls_peer_status);
1781 defsubr (&Sgnutls_peer_status_warning_describe); 2544 defsubr (&Sgnutls_peer_status_warning_describe);
1782 2545
2546#ifdef HAVE_GNUTLS3
2547 defsubr (&Sgnutls_ciphers);
2548 defsubr (&Sgnutls_macs);
2549 defsubr (&Sgnutls_digests);
2550 defsubr (&Sgnutls_hash_mac);
2551 defsubr (&Sgnutls_hash_digest);
2552 defsubr (&Sgnutls_symmetric_encrypt);
2553 defsubr (&Sgnutls_symmetric_decrypt);
2554#endif
2555
1783 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level, 2556 DEFVAR_INT ("gnutls-log-level", global_gnutls_log_level,
1784 doc: /* Logging level used by the GnuTLS functions. 2557 doc: /* Logging level used by the GnuTLS functions.
1785Set this larger than 0 to get debug output in the *Messages* buffer. 2558Set this larger than 0 to get debug output in the *Messages* buffer.