aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-07-14 16:18:37 -0700
committerPaul Eggert2017-07-14 16:36:18 -0700
commit05b8b866993b957f5fd575846cf8ea3035e60f7e (patch)
tree7d25217ee1f4c409cb217c52a6bd152dda675b8a /src
parent8b64a80a56c0e15d3313a45022ae60b33dbb4bff (diff)
downloademacs-05b8b866993b957f5fd575846cf8ea3035e60f7e.tar.gz
emacs-05b8b866993b957f5fd575846cf8ea3035e60f7e.zip
GnuTLS integer-overflow and style fixes
This tweaks the recently-added GnuTLS improvements so that they avoid some integer-overflow problems and follow typical Emacs style a bit better. * configure.ac (HAVE_GNUTLS3_HMAC, HAVE_GNUTLS3_AEAD) (HAVE_GNUTLS3_CIPHER): Use AC_CACHE_CHECK so that the configure-time results are displayed. * src/fns.c (extract_data_from_object): Return char *, not char const *, since one gnutls caller wants a non-const pointer. Use CONSP rather than !NILP when testing for conses. Use CAR_SAFE instead of rolling our own code. Prefer signed types to unsigned when either will do. Report problems for lengths out of range, instead of silently mishandling them. * src/gnutls.c (emacs_gnutls_strerror): New function, to simplify callers. All callers of gnutls_sterror changed. (Fgnutls_boot): Check for integers out of range rather than silently truncating them. (gnutls_symmetric_aead): Check for integer overflow in size calculations. (gnutls_symmetric_aead, Fgnutls_macs, Fgnutls_digests): Prefer signed to unsigned integers where either will do. (gnutls_symmetric_aead, gnutls_symmetric): Work even if ptrdiff_t is wider than ‘long’. (gnutls_symmetric, Fgnutls_hash_mac, Fgnutls_hash_digest): Check for integer overflow in algorithm selection.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c49
-rw-r--r--src/gnutls.c489
-rw-r--r--src/lisp.h4
3 files changed, 237 insertions, 305 deletions
diff --git a/src/fns.c b/src/fns.c
index b678a482bbc..fb1296bc6f0 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -46,10 +46,6 @@ static void sort_vector_copy (Lisp_Object, ptrdiff_t,
46enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; 46enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
47static bool internal_equal (Lisp_Object, Lisp_Object, 47static bool internal_equal (Lisp_Object, Lisp_Object,
48 enum equal_kind, int, Lisp_Object); 48 enum equal_kind, int, Lisp_Object);
49static Lisp_Object
50secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
51 Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror,
52 Lisp_Object binary);
53 49
54DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, 50DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
55 doc: /* Return the argument unchanged. */ 51 doc: /* Return the argument unchanged. */
@@ -4767,29 +4763,24 @@ DEFUN ("secure-hash-algorithms", Fsecure_hash_algorithms,
4767(BUFFER-OR-STRING-OR-SYMBOL START END CODING-SYSTEM NOERROR) which behave as 4763(BUFFER-OR-STRING-OR-SYMBOL START END CODING-SYSTEM NOERROR) which behave as
4768specified with `secure-hash' and in Info node 4764specified with `secure-hash' and in Info node
4769`(elisp)Format of GnuTLS Cryptography Inputs'. */ 4765`(elisp)Format of GnuTLS Cryptography Inputs'. */
4770const char* 4766char *
4771extract_data_from_object (Lisp_Object spec, 4767extract_data_from_object (Lisp_Object spec,
4772 ptrdiff_t *start_byte, 4768 ptrdiff_t *start_byte,
4773 ptrdiff_t *end_byte) 4769 ptrdiff_t *end_byte)
4774{ 4770{
4775 ptrdiff_t size, start_char = 0, end_char = 0; 4771 Lisp_Object object = XCAR (spec);
4776 register EMACS_INT b, e;
4777 register struct buffer *bp;
4778 EMACS_INT temp;
4779 4772
4780 Lisp_Object object = XCAR (spec); 4773 if (CONSP (spec)) spec = XCDR (spec);
4774 Lisp_Object start = CAR_SAFE (spec);
4781 4775
4782 if (! NILP (spec)) spec = XCDR (spec); 4776 if (CONSP (spec)) spec = XCDR (spec);
4783 Lisp_Object start = (CONSP (spec)) ? XCAR (spec) : Qnil; 4777 Lisp_Object end = CAR_SAFE (spec);
4784 4778
4785 if (! NILP (spec)) spec = XCDR (spec); 4779 if (CONSP (spec)) spec = XCDR (spec);
4786 Lisp_Object end = (CONSP (spec)) ? XCAR (spec) : Qnil; 4780 Lisp_Object coding_system = CAR_SAFE (spec);
4787 4781
4788 if (! NILP (spec)) spec = XCDR (spec); 4782 if (CONSP (spec)) spec = XCDR (spec);
4789 Lisp_Object coding_system = (CONSP (spec)) ? XCAR (spec) : Qnil; 4783 Lisp_Object noerror = CAR_SAFE (spec);
4790
4791 if (! NILP (spec)) spec = XCDR (spec);
4792 Lisp_Object noerror = (CONSP (spec)) ? XCAR (spec) : Qnil;
4793 4784
4794 if (STRINGP (object)) 4785 if (STRINGP (object))
4795 { 4786 {
@@ -4817,7 +4808,7 @@ extract_data_from_object (Lisp_Object spec,
4817 if (STRING_MULTIBYTE (object)) 4808 if (STRING_MULTIBYTE (object))
4818 object = code_convert_string (object, coding_system, Qnil, 1, 0, 1); 4809 object = code_convert_string (object, coding_system, Qnil, 1, 0, 1);
4819 4810
4820 size = SCHARS (object); 4811 ptrdiff_t size = SCHARS (object), start_char, end_char;
4821 validate_subarray (object, start, end, size, &start_char, &end_char); 4812 validate_subarray (object, start, end, size, &start_char, &end_char);
4822 4813
4823 *start_byte = !start_char ? 0 : string_char_to_byte (object, start_char); 4814 *start_byte = !start_char ? 0 : string_char_to_byte (object, start_char);
@@ -4828,12 +4819,13 @@ extract_data_from_object (Lisp_Object spec,
4828 else if (BUFFERP (object)) 4819 else if (BUFFERP (object))
4829 { 4820 {
4830 struct buffer *prev = current_buffer; 4821 struct buffer *prev = current_buffer;
4822 EMACS_INT b, e;
4831 4823
4832 record_unwind_current_buffer (); 4824 record_unwind_current_buffer ();
4833 4825
4834 CHECK_BUFFER (object); 4826 CHECK_BUFFER (object);
4835 4827
4836 bp = XBUFFER (object); 4828 struct buffer *bp = XBUFFER (object);
4837 set_buffer_internal (bp); 4829 set_buffer_internal (bp);
4838 4830
4839 if (NILP (start)) 4831 if (NILP (start))
@@ -4853,7 +4845,11 @@ extract_data_from_object (Lisp_Object spec,
4853 } 4845 }
4854 4846
4855 if (b > e) 4847 if (b > e)
4856 temp = b, b = e, e = temp; 4848 {
4849 EMACS_INT temp = b;
4850 b = e;
4851 e = temp;
4852 }
4857 4853
4858 if (!(BEGV <= b && e <= ZV)) 4854 if (!(BEGV <= b && e <= ZV))
4859 args_out_of_range (start, end); 4855 args_out_of_range (start, end);
@@ -4932,14 +4928,13 @@ extract_data_from_object (Lisp_Object spec,
4932 else if (EQ (object, Qiv_auto)) 4928 else if (EQ (object, Qiv_auto))
4933 { 4929 {
4934#ifdef HAVE_GNUTLS3 4930#ifdef HAVE_GNUTLS3
4935 // Format: (iv-auto REQUIRED-LENGTH) 4931 /* Format: (iv-auto REQUIRED-LENGTH). */
4936 4932
4937 if (! INTEGERP (start)) 4933 if (! NATNUMP (start))
4938 error ("Without a length, iv-auto can't be used. See manual."); 4934 error ("Without a length, iv-auto can't be used. See manual.");
4939 else 4935 else
4940 { 4936 {
4941 /* Make sure the value of "start" doesn't change. */ 4937 EMACS_INT start_hold = XFASTINT (start);
4942 size_t start_hold = XUINT (start);
4943 object = make_uninit_string (start_hold); 4938 object = make_uninit_string (start_hold);
4944 gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold); 4939 gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold);
4945 4940
@@ -4971,7 +4966,7 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
4971 4966
4972 Lisp_Object spec = list5 (object, start, end, coding_system, noerror); 4967 Lisp_Object spec = list5 (object, start, end, coding_system, noerror);
4973 4968
4974 const char* input = extract_data_from_object (spec, &start_byte, &end_byte); 4969 const char *input = extract_data_from_object (spec, &start_byte, &end_byte);
4975 4970
4976 if (input == NULL) 4971 if (input == NULL)
4977 error ("secure_hash: failed to extract data from object, aborting!"); 4972 error ("secure_hash: failed to extract data from object, aborting!");
diff --git a/src/gnutls.c b/src/gnutls.c
index 761fe7df3ac..5717b3075c1 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -672,6 +672,13 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
672 } 672 }
673} 673}
674 674
675static char const *
676emacs_gnutls_strerror (int err)
677{
678 char const *str = gnutls_strerror (err);
679 return str ? str : "unknown";
680}
681
675/* Report a GnuTLS error to the user. 682/* Report a GnuTLS error to the user.
676 Return true if the error code was successfully handled. */ 683 Return true if the error code was successfully handled. */
677static bool 684static bool
@@ -680,7 +687,6 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
680 int max_log_level = 0; 687 int max_log_level = 0;
681 688
682 bool ret; 689 bool ret;
683 const char *str;
684 690
685 /* TODO: use a Lisp_Object generated by gnutls_make_error? */ 691 /* TODO: use a Lisp_Object generated by gnutls_make_error? */
686 if (err >= 0) 692 if (err >= 0)
@@ -692,9 +698,7 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
692 698
693 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */ 699 /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
694 700
695 str = gnutls_strerror (err); 701 char const *str = emacs_gnutls_strerror (err);
696 if (!str)
697 str = "unknown";
698 702
699 if (gnutls_error_is_fatal (err)) 703 if (gnutls_error_is_fatal (err))
700 { 704 {
@@ -708,11 +712,11 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
708#endif 712#endif
709 713
710 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str); 714 GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
711 ret = 0; 715 ret = false;
712 } 716 }
713 else 717 else
714 { 718 {
715 ret = 1; 719 ret = true;
716 720
717 switch (err) 721 switch (err)
718 { 722 {
@@ -900,7 +904,7 @@ usage: (gnutls-error-string ERROR) */)
900 if (! TYPE_RANGED_INTEGERP (int, err)) 904 if (! TYPE_RANGED_INTEGERP (int, err))
901 return build_string ("Not an error symbol or code"); 905 return build_string ("Not an error symbol or code");
902 906
903 return build_string (gnutls_strerror (XINT (err))); 907 return build_string (emacs_gnutls_strerror (XINT (err)));
904} 908}
905 909
906DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0, 910DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
@@ -1592,9 +1596,9 @@ one trustfile (usually a CA bundle). */)
1592 XPROCESS (proc)->gnutls_x509_cred = x509_cred; 1596 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
1593 1597
1594 verify_flags = Fplist_get (proplist, QCverify_flags); 1598 verify_flags = Fplist_get (proplist, QCverify_flags);
1595 if (NUMBERP (verify_flags)) 1599 if (TYPE_RANGED_INTEGERP (unsigned int, verify_flags))
1596 { 1600 {
1597 gnutls_verify_flags = XINT (verify_flags); 1601 gnutls_verify_flags = XFASTINT (verify_flags);
1598 GNUTLS_LOG (2, max_log_level, "setting verification flags"); 1602 GNUTLS_LOG (2, max_log_level, "setting verification flags");
1599 } 1603 }
1600 else if (NILP (verify_flags)) 1604 else if (NILP (verify_flags))
@@ -1818,39 +1822,32 @@ This function may also return `gnutls-e-again', or
1818DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0, 1822DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0,
1819 doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists. 1823 doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists.
1820The alist key is the cipher name. */) 1824The alist key is the cipher name. */)
1821 (void) 1825 (void)
1822{ 1826{
1823 Lisp_Object ciphers = Qnil; 1827 Lisp_Object ciphers = Qnil;
1824 1828
1825 const gnutls_cipher_algorithm_t* gciphers = gnutls_cipher_list (); 1829 const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
1826 for (size_t pos = 0; gciphers[pos] != GNUTLS_CIPHER_NULL; pos++) 1830 for (ptrdiff_t pos = 0; gciphers[pos] != GNUTLS_CIPHER_NULL; pos++)
1827 { 1831 {
1828 const gnutls_cipher_algorithm_t gca = gciphers[pos]; 1832 gnutls_cipher_algorithm_t gca = gciphers[pos];
1829 1833 Lisp_Object cipher_symbol = intern (gnutls_cipher_get_name (gca));
1830 Lisp_Object cp = listn (CONSTYPE_HEAP, 15, 1834 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1831 /* A symbol representing the cipher */ 1835
1832 intern (gnutls_cipher_get_name (gca)), 1836 Lisp_Object cp
1833 /* The internally meaningful cipher ID */ 1837 = listn (CONSTYPE_HEAP, 15, cipher_symbol,
1834 QCcipher_id, 1838 QCcipher_id, make_number (gca),
1835 make_number (gca), 1839 QCtype, Qgnutls_type_cipher,
1836 /* The type (vs. other GnuTLS objects). */ 1840 QCcipher_aead_capable, cipher_tag_size == 0 ? Qnil : Qt,
1837 QCtype, 1841 QCcipher_tagsize, make_number (cipher_tag_size),
1838 Qgnutls_type_cipher, 1842
1839 /* The tag size (nonzero means AEAD). */ 1843 QCcipher_blocksize,
1840 QCcipher_aead_capable, 1844 make_number (gnutls_cipher_get_block_size (gca)),
1841 (gnutls_cipher_get_tag_size (gca) == 0) ? Qnil : Qt, 1845
1842 /* The tag size (nonzero means AEAD). */ 1846 QCcipher_keysize,
1843 QCcipher_tagsize, 1847 make_number (gnutls_cipher_get_key_size (gca)),
1844 make_number (gnutls_cipher_get_tag_size (gca)), 1848
1845 /* The block size */ 1849 QCcipher_ivsize,
1846 QCcipher_blocksize, 1850 make_number (gnutls_cipher_get_iv_size (gca)));
1847 make_number (gnutls_cipher_get_block_size (gca)),
1848 /* The key size */
1849 QCcipher_keysize,
1850 make_number (gnutls_cipher_get_key_size (gca)),
1851 /* IV size */
1852 QCcipher_ivsize,
1853 make_number (gnutls_cipher_get_iv_size (gca)));
1854 1851
1855 ciphers = Fcons (cp, ciphers); 1852 ciphers = Fcons (cp, ciphers);
1856 } 1853 }
@@ -1861,36 +1858,35 @@ The alist key is the cipher name. */)
1861static Lisp_Object 1858static Lisp_Object
1862gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca, 1859gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1863 Lisp_Object cipher, 1860 Lisp_Object cipher,
1864 const char* kdata, size_t ksize, 1861 const char *kdata, ptrdiff_t ksize,
1865 const char* vdata, size_t vsize, 1862 const char *vdata, ptrdiff_t vsize,
1866 const char* idata, size_t isize, 1863 const char *idata, ptrdiff_t isize,
1867 Lisp_Object aead_auth) 1864 Lisp_Object aead_auth)
1868{ 1865{
1869#ifdef HAVE_GNUTLS3_AEAD 1866#ifdef HAVE_GNUTLS3_AEAD
1870 1867
1871 const char* desc = (encrypting ? "encrypt" : "decrypt"); 1868 const char *desc = encrypting ? "encrypt" : "decrypt";
1872 int ret = GNUTLS_E_SUCCESS;
1873 Lisp_Object actual_iv = make_unibyte_string (vdata, vsize); 1869 Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
1874 1870
1875 gnutls_aead_cipher_hd_t acipher; 1871 gnutls_aead_cipher_hd_t acipher;
1876 gnutls_datum_t key_datum = { (unsigned char*) kdata, ksize }; 1872 gnutls_datum_t key_datum = { (unsigned char *) kdata, ksize };
1877 ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum); 1873 int ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
1878 1874
1879 if (ret < GNUTLS_E_SUCCESS) 1875 if (ret < GNUTLS_E_SUCCESS)
1880 { 1876 error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
1881 const char* str = gnutls_strerror (ret); 1877 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
1882 if (!str) 1878
1883 str = "unknown"; 1879 ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
1884 error ("GnuTLS AEAD cipher %s/%s initialization failed: %s", 1880 ptrdiff_t tagged_size;
1885 gnutls_cipher_get_name (gca), desc, str); 1881 if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
1886 } 1882 || SIZE_MAX < tagged_size)
1887 1883 memory_full (SIZE_MAX);
1888 size_t storage_length = isize + gnutls_cipher_get_tag_size (gca); 1884 size_t storage_length = tagged_size;
1889 USE_SAFE_ALLOCA; 1885 USE_SAFE_ALLOCA;
1890 unsigned char *storage = SAFE_ALLOCA (storage_length); 1886 char *storage = SAFE_ALLOCA (storage_length);
1891 1887
1892 const char* aead_auth_data = NULL; 1888 const char *aead_auth_data = NULL;
1893 size_t aead_auth_size = 0; 1889 ptrdiff_t aead_auth_size = 0;
1894 1890
1895 if (!NILP (aead_auth)) 1891 if (!NILP (aead_auth))
1896 { 1892 {
@@ -1900,8 +1896,8 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1900 CHECK_CONS (aead_auth); 1896 CHECK_CONS (aead_auth);
1901 1897
1902 ptrdiff_t astart_byte, aend_byte; 1898 ptrdiff_t astart_byte, aend_byte;
1903 const char* adata = extract_data_from_object (aead_auth, &astart_byte, &aend_byte); 1899 const char *adata
1904 1900 = extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
1905 if (adata == NULL) 1901 if (adata == NULL)
1906 error ("GnuTLS AEAD cipher auth extraction failed"); 1902 error ("GnuTLS AEAD cipher auth extraction failed");
1907 1903
@@ -1909,53 +1905,38 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
1909 aead_auth_size = aend_byte - astart_byte; 1905 aead_auth_size = aend_byte - astart_byte;
1910 } 1906 }
1911 1907
1912 size_t expected_remainder = 0; 1908 ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
1913 1909 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
1914 if (!encrypting)
1915 expected_remainder = gnutls_cipher_get_tag_size (gca);
1916 1910
1917 if ((isize - expected_remainder) % gnutls_cipher_get_block_size (gca) != 0) 1911 if (isize < expected_remainder
1918 error ("GnuTLS AEAD cipher %s/%s input block length %ld was not a " 1912 || (isize - expected_remainder) % cipher_block_size != 0)
1919 "multiple of the required %ld plus the expected tag remainder %ld", 1913 error (("GnuTLS AEAD cipher %s/%s input block length %"pD"d "
1914 "is not %"pD"d greater than a multiple of the required %"pD"d"),
1920 gnutls_cipher_get_name (gca), desc, 1915 gnutls_cipher_get_name (gca), desc,
1921 (long) isize, (long) gnutls_cipher_get_block_size (gca), 1916 isize, expected_remainder, cipher_block_size);
1922 (long) expected_remainder); 1917
1923 1918 ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
1924 if (encrypting) 1919 (acipher, vdata, vsize, aead_auth_data, aead_auth_size,
1925 ret = gnutls_aead_cipher_encrypt (acipher, 1920 cipher_tag_size, idata, isize, storage, &storage_length));
1926 vdata, vsize,
1927 aead_auth_data, aead_auth_size,
1928 gnutls_cipher_get_tag_size (gca),
1929 idata, isize,
1930 storage, &storage_length);
1931 else
1932 ret = gnutls_aead_cipher_decrypt (acipher,
1933 vdata, vsize,
1934 aead_auth_data, aead_auth_size,
1935 gnutls_cipher_get_tag_size (gca),
1936 idata, isize,
1937 storage, &storage_length);
1938 1921
1939 if (ret < GNUTLS_E_SUCCESS) 1922 if (ret < GNUTLS_E_SUCCESS)
1940 { 1923 {
1941 memset (storage, 0, storage_length); 1924 memset (storage, 0, storage_length);
1942 SAFE_FREE (); 1925 SAFE_FREE ();
1943 gnutls_aead_cipher_deinit (acipher); 1926 gnutls_aead_cipher_deinit (acipher);
1944 const char* str = gnutls_strerror (ret);
1945 if (!str)
1946 str = "unknown";
1947 error ("GnuTLS AEAD cipher %s %sion failed: %s", 1927 error ("GnuTLS AEAD cipher %s %sion failed: %s",
1948 gnutls_cipher_get_name (gca), desc, str); 1928 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
1949 } 1929 }
1950 1930
1951 gnutls_aead_cipher_deinit (acipher); 1931 gnutls_aead_cipher_deinit (acipher);
1952 1932
1953 Lisp_Object output = make_unibyte_string ((const char *)storage, storage_length); 1933 Lisp_Object output = make_unibyte_string (storage, storage_length);
1954 memset (storage, 0, storage_length); 1934 memset (storage, 0, storage_length);
1955 SAFE_FREE (); 1935 SAFE_FREE ();
1956 return list2 (output, actual_iv); 1936 return list2 (output, actual_iv);
1957#else 1937#else
1958 error ("GnuTLS AEAD cipher %ld was invalid or not found", (long) gca); 1938 printmax_t print_gca = gca;
1939 error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
1959#endif 1940#endif
1960} 1941}
1961 1942
@@ -1980,9 +1961,7 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
1980 CHECK_CONS (iv); 1961 CHECK_CONS (iv);
1981 1962
1982 1963
1983 const char* desc = (encrypting ? "encrypt" : "decrypt"); 1964 const char *desc = encrypting ? "encrypt" : "decrypt";
1984
1985 int ret = GNUTLS_E_SUCCESS;
1986 1965
1987 gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN; 1966 gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN;
1988 1967
@@ -1992,7 +1971,7 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
1992 1971
1993 if (SYMBOLP (cipher)) 1972 if (SYMBOLP (cipher))
1994 info = XCDR (Fassq (cipher, Fgnutls_ciphers ())); 1973 info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
1995 else if (INTEGERP (cipher)) 1974 else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
1996 gca = XINT (cipher); 1975 gca = XINT (cipher);
1997 else 1976 else
1998 info = cipher; 1977 info = cipher;
@@ -2000,41 +1979,44 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
2000 if (!NILP (info) && CONSP (info)) 1979 if (!NILP (info) && CONSP (info))
2001 { 1980 {
2002 Lisp_Object v = Fplist_get (info, QCcipher_id); 1981 Lisp_Object v = Fplist_get (info, QCcipher_id);
2003 if (INTEGERP (v)) 1982 if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, v))
2004 gca = XINT (v); 1983 gca = XINT (v);
2005 } 1984 }
2006 1985
2007 if (gca == GNUTLS_CIPHER_UNKNOWN) 1986 ptrdiff_t key_size = gnutls_cipher_get_key_size (gca);
2008 error ("GnuTLS cipher was invalid or not found"); 1987 if (key_size == 0)
1988 error ("GnuTLS cipher is invalid or not found");
2009 1989
2010 ptrdiff_t kstart_byte, kend_byte; 1990 ptrdiff_t kstart_byte, kend_byte;
2011 const char* kdata = extract_data_from_object (key, &kstart_byte, &kend_byte); 1991 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2012 1992
2013 if (kdata == NULL) 1993 if (kdata == NULL)
2014 error ("GnuTLS cipher key extraction failed"); 1994 error ("GnuTLS cipher key extraction failed");
2015 1995
2016 if ((kend_byte - kstart_byte) != gnutls_cipher_get_key_size (gca)) 1996 if (kend_byte - kstart_byte != key_size)
2017 error ("GnuTLS cipher %s/%s key length %" pD "d was not equal to " 1997 error (("GnuTLS cipher %s/%s key length %"pD"d is not equal to "
2018 "the required %ld", 1998 "the required %"pD"d"),
2019 gnutls_cipher_get_name (gca), desc, 1999 gnutls_cipher_get_name (gca), desc,
2020 kend_byte - kstart_byte, (long) gnutls_cipher_get_key_size (gca)); 2000 kend_byte - kstart_byte, key_size);
2021 2001
2022 ptrdiff_t vstart_byte, vend_byte; 2002 ptrdiff_t vstart_byte, vend_byte;
2023 const char* vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte); 2003 char *vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
2024 2004
2025 if (vdata == NULL) 2005 if (vdata == NULL)
2026 error ("GnuTLS cipher IV extraction failed"); 2006 error ("GnuTLS cipher IV extraction failed");
2027 2007
2028 if ((vend_byte - vstart_byte) != gnutls_cipher_get_iv_size (gca)) 2008 ptrdiff_t iv_size = gnutls_cipher_get_iv_size (gca);
2029 error ("GnuTLS cipher %s/%s IV length %" pD "d was not equal to " 2009 if (vend_byte - vstart_byte != iv_size)
2030 "the required %ld", 2010 error (("GnuTLS cipher %s/%s IV length %"pD"d is not equal to "
2011 "the required %"pD"d"),
2031 gnutls_cipher_get_name (gca), desc, 2012 gnutls_cipher_get_name (gca), desc,
2032 vend_byte - vstart_byte, (long) gnutls_cipher_get_iv_size (gca)); 2013 vend_byte - vstart_byte, iv_size);
2033 2014
2034 Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte); 2015 Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte);
2035 2016
2036 ptrdiff_t istart_byte, iend_byte; 2017 ptrdiff_t istart_byte, iend_byte;
2037 const char* idata = extract_data_from_object (input, &istart_byte, &iend_byte); 2018 const char *idata
2019 = extract_data_from_object (input, &istart_byte, &iend_byte);
2038 2020
2039 if (idata == NULL) 2021 if (idata == NULL)
2040 error ("GnuTLS cipher input extraction failed"); 2022 error ("GnuTLS cipher input extraction failed");
@@ -2053,44 +2035,34 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
2053 return aead_output; 2035 return aead_output;
2054 } 2036 }
2055 2037
2056 if ((iend_byte - istart_byte) % gnutls_cipher_get_block_size (gca) != 0) 2038 ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
2057 error ("GnuTLS cipher %s/%s input block length %" pD "d was not a multiple " 2039 if ((iend_byte - istart_byte) % cipher_block_size != 0)
2058 "of the required %ld", 2040 error (("GnuTLS cipher %s/%s input block length %"pD"d is not a multiple "
2041 "of the required %"pD"d"),
2059 gnutls_cipher_get_name (gca), desc, 2042 gnutls_cipher_get_name (gca), desc,
2060 iend_byte - istart_byte, (long) gnutls_cipher_get_block_size (gca)); 2043 iend_byte - istart_byte, cipher_block_size);
2061 2044
2062 gnutls_cipher_hd_t hcipher; 2045 gnutls_cipher_hd_t hcipher;
2063 gnutls_datum_t key_datum = { (unsigned char*) kdata, kend_byte - kstart_byte }; 2046 gnutls_datum_t key_datum
2047 = { (unsigned char *) kdata, kend_byte - kstart_byte };
2064 2048
2065 ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL); 2049 int ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
2066 2050
2067 if (ret < GNUTLS_E_SUCCESS) 2051 if (ret < GNUTLS_E_SUCCESS)
2068 { 2052 error ("GnuTLS cipher %s/%s initialization failed: %s",
2069 const char* str = gnutls_strerror (ret); 2053 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
2070 if (!str)
2071 str = "unknown";
2072 error ("GnuTLS cipher %s/%s initialization failed: %s",
2073 gnutls_cipher_get_name (gca), desc, str);
2074 }
2075 2054
2076 /* Note that this will not support streaming block mode. */ 2055 /* Note that this will not support streaming block mode. */
2077 gnutls_cipher_set_iv (hcipher, (void*) vdata, vend_byte - vstart_byte); 2056 gnutls_cipher_set_iv (hcipher, vdata, vend_byte - vstart_byte);
2078 2057
2079 /* 2058 /* GnuTLS docs: "For the supported ciphers the encrypted data length
2080 * GnuTLS docs: "For the supported ciphers the encrypted data length 2059 will equal the plaintext size." */
2081 * will equal the plaintext size." 2060 ptrdiff_t storage_length = iend_byte - istart_byte;
2082 */
2083 size_t storage_length = iend_byte - istart_byte;
2084 Lisp_Object storage = make_uninit_string (storage_length); 2061 Lisp_Object storage = make_uninit_string (storage_length);
2085 2062
2086 if (encrypting) 2063 ret = ((encrypting ? gnutls_cipher_encrypt2 : gnutls_cipher_decrypt2)
2087 ret = gnutls_cipher_encrypt2 (hcipher, 2064 (hcipher, idata, iend_byte - istart_byte,
2088 idata, iend_byte - istart_byte, 2065 SSDATA (storage), storage_length));
2089 SSDATA (storage), storage_length);
2090 else
2091 ret = gnutls_cipher_decrypt2 (hcipher,
2092 idata, iend_byte - istart_byte,
2093 SSDATA (storage), storage_length);
2094 2066
2095 if (STRINGP (XCAR (key))) 2067 if (STRINGP (XCAR (key)))
2096 Fclear_string (XCAR (key)); 2068 Fclear_string (XCAR (key));
@@ -2098,11 +2070,8 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
2098 if (ret < GNUTLS_E_SUCCESS) 2070 if (ret < GNUTLS_E_SUCCESS)
2099 { 2071 {
2100 gnutls_cipher_deinit (hcipher); 2072 gnutls_cipher_deinit (hcipher);
2101 const char* str = gnutls_strerror (ret);
2102 if (!str)
2103 str = "unknown";
2104 error ("GnuTLS cipher %s %sion failed: %s", 2073 error ("GnuTLS cipher %s %sion failed: %s",
2105 gnutls_cipher_get_name (gca), desc, str); 2074 gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
2106 } 2075 }
2107 2076
2108 gnutls_cipher_deinit (hcipher); 2077 gnutls_cipher_deinit (hcipher);
@@ -2110,41 +2079,46 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
2110 return list2 (storage, actual_iv); 2079 return list2 (storage, actual_iv);
2111} 2080}
2112 2081
2113DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt, Sgnutls_symmetric_encrypt, 4, 5, 0, 2082DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt,
2083 Sgnutls_symmetric_encrypt, 4, 5, 0,
2114 doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string. 2084 doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2115 2085
2116Returns nil on error. 2086Return nil on error.
2117 2087
2118The KEY can be specified as a buffer or string or in other ways 2088The KEY can be specified as a buffer or string or in other ways (see
2119(see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY will be 2089Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2120wiped after use if it's a string. 2090will be wiped after use if it's a string.
2121 2091
2122The IV and INPUT and the optional AEAD_AUTH can be 2092The IV and INPUT and the optional AEAD_AUTH can be specified as a
2123specified as a buffer or string or in other ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). 2093buffer or string or in other ways (see Info node `(elisp)Format of
2094GnuTLS Cryptography Inputs').
2124 2095
2125The alist of symmetric ciphers can be obtained with `gnutls-ciphers`. 2096The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2126The CIPHER may be a string or symbol matching a key in that alist, or 2097The CIPHER may be a string or symbol matching a key in that alist, or
2127a plist with the `:cipher-id' numeric property, or the number itself. 2098a plist with the :cipher-id numeric property, or the number itself.
2128 2099
2129AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with 2100AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2130:cipher-aead-capable set to t. AEAD_AUTH can be supplied for 2101:cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2131these AEAD ciphers, but it may still be omitted (nil) as well. */) 2102these AEAD ciphers, but it may still be omitted (nil) as well. */)
2132 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv, Lisp_Object input, Lisp_Object aead_auth) 2103 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2104 Lisp_Object input, Lisp_Object aead_auth)
2133{ 2105{
2134 return gnutls_symmetric (true, cipher, key, iv, input, aead_auth); 2106 return gnutls_symmetric (true, cipher, key, iv, input, aead_auth);
2135} 2107}
2136 2108
2137DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt, Sgnutls_symmetric_decrypt, 4, 5, 0, 2109DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt,
2110 Sgnutls_symmetric_decrypt, 4, 5, 0,
2138 doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string. 2111 doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
2139 2112
2140Returns nil on error. 2113Return nil on error.
2141 2114
2142The KEY can be specified as a buffer or string or in other ways 2115The KEY can be specified as a buffer or string or in other ways (see
2143(see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY will be 2116Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2144wiped after use if it's a string. 2117will be wiped after use if it's a string.
2145 2118
2146The IV and INPUT and the optional AEAD_AUTH can be 2119The IV and INPUT and the optional AEAD_AUTH can be specified as a
2147specified as a buffer or string or in other ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). 2120buffer or string or in other ways (see Info node `(elisp)Format of
2121GnuTLS Cryptography Inputs').
2148 2122
2149The alist of symmetric ciphers can be obtained with `gnutls-ciphers`. 2123The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
2150The CIPHER may be a string or symbol matching a key in that alist, or 2124The CIPHER may be a string or symbol matching a key in that alist, or
@@ -2153,7 +2127,8 @@ a plist with the `:cipher-id' numeric property, or the number itself.
2153AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with 2127AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
2154:cipher-aead-capable set to t. AEAD_AUTH can be supplied for 2128:cipher-aead-capable set to t. AEAD_AUTH can be supplied for
2155these AEAD ciphers, but it may still be omitted (nil) as well. */) 2129these AEAD ciphers, but it may still be omitted (nil) as well. */)
2156 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv, Lisp_Object input, Lisp_Object aead_auth) 2130 (Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
2131 Lisp_Object input, Lisp_Object aead_auth)
2157{ 2132{
2158 return gnutls_symmetric (false, cipher, key, iv, input, aead_auth); 2133 return gnutls_symmetric (false, cipher, key, iv, input, aead_auth);
2159} 2134}
@@ -2164,32 +2139,26 @@ DEFUN ("gnutls-macs", Fgnutls_macs, Sgnutls_macs, 0, 0, 0,
2164Use the value of the alist (extract it with `alist-get' for instance) 2139Use the value of the alist (extract it with `alist-get' for instance)
2165with `gnutls-hash-mac'. The alist key is the mac-algorithm method 2140with `gnutls-hash-mac'. The alist key is the mac-algorithm method
2166name. */) 2141name. */)
2167 (void) 2142 (void)
2168{ 2143{
2169 Lisp_Object mac_algorithms = Qnil; 2144 Lisp_Object mac_algorithms = Qnil;
2170 const gnutls_mac_algorithm_t* macs = gnutls_mac_list (); 2145 const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
2171 for (size_t pos = 0; macs[pos] != 0; pos++) 2146 for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
2172 { 2147 {
2173 const gnutls_mac_algorithm_t gma = macs[pos]; 2148 const gnutls_mac_algorithm_t gma = macs[pos];
2174 2149
2175 const char* name = gnutls_mac_get_name (gma); 2150 const char *name = gnutls_mac_get_name (gma);
2176 2151
2177 Lisp_Object mp = listn (CONSTYPE_HEAP, 11, 2152 Lisp_Object mp = listn (CONSTYPE_HEAP, 11, intern (name),
2178 /* A symbol representing the mac-algorithm. */ 2153 QCmac_algorithm_id, make_number (gma),
2179 intern (name), 2154 QCtype, Qgnutls_type_mac_algorithm,
2180 /* The internally meaningful mac-algorithm ID. */ 2155
2181 QCmac_algorithm_id,
2182 make_number (gma),
2183 /* The type (vs. other GnuTLS objects). */
2184 QCtype,
2185 Qgnutls_type_mac_algorithm,
2186 /* The output length. */
2187 QCmac_algorithm_length, 2156 QCmac_algorithm_length,
2188 make_number (gnutls_hmac_get_len (gma)), 2157 make_number (gnutls_hmac_get_len (gma)),
2189 /* The key size. */ 2158
2190 QCmac_algorithm_keysize, 2159 QCmac_algorithm_keysize,
2191 make_number (gnutls_mac_get_key_size (gma)), 2160 make_number (gnutls_mac_get_key_size (gma)),
2192 /* The nonce size. */ 2161
2193 QCmac_algorithm_noncesize, 2162 QCmac_algorithm_noncesize,
2194 make_number (gnutls_mac_get_nonce_size (gma))); 2163 make_number (gnutls_mac_get_nonce_size (gma)));
2195 mac_algorithms = Fcons (mp, mac_algorithms); 2164 mac_algorithms = Fcons (mp, mac_algorithms);
@@ -2204,25 +2173,20 @@ DEFUN ("gnutls-digests", Fgnutls_digests, Sgnutls_digests, 0, 0, 0,
2204Use the value of the alist (extract it with `alist-get' for instance) 2173Use the value of the alist (extract it with `alist-get' for instance)
2205with `gnutls-hash-digest'. The alist key is the digest-algorithm 2174with `gnutls-hash-digest'. The alist key is the digest-algorithm
2206method name. */) 2175method name. */)
2207 (void) 2176 (void)
2208{ 2177{
2209 Lisp_Object digest_algorithms = Qnil; 2178 Lisp_Object digest_algorithms = Qnil;
2210 const gnutls_digest_algorithm_t* digests = gnutls_digest_list (); 2179 const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
2211 for (size_t pos = 0; digests[pos] != 0; pos++) 2180 for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
2212 { 2181 {
2213 const gnutls_digest_algorithm_t gda = digests[pos]; 2182 const gnutls_digest_algorithm_t gda = digests[pos];
2214 2183
2215 const char* name = gnutls_digest_get_name (gda); 2184 const char *name = gnutls_digest_get_name (gda);
2216 2185
2217 Lisp_Object mp = listn (CONSTYPE_HEAP, 7, 2186 Lisp_Object mp = listn (CONSTYPE_HEAP, 7, intern (name),
2218 /* A symbol representing the digest-algorithm. */ 2187 QCdigest_algorithm_id, make_number (gda),
2219 intern (name), 2188 QCtype, Qgnutls_type_digest_algorithm,
2220 /* The internally meaningful digest-algorithm ID. */ 2189
2221 QCdigest_algorithm_id,
2222 make_number (gda),
2223 QCtype,
2224 Qgnutls_type_digest_algorithm,
2225 /* The digest length. */
2226 QCdigest_algorithm_length, 2190 QCdigest_algorithm_length,
2227 make_number (gnutls_hash_get_len (gda))); 2191 make_number (gnutls_hash_get_len (gda)));
2228 2192
@@ -2235,11 +2199,11 @@ method name. */)
2235DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0, 2199DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0,
2236 doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string. 2200 doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string.
2237 2201
2238Returns nil on error. 2202Return nil on error.
2239 2203
2240The KEY can be specified as a buffer or string or in other ways 2204The KEY can be specified as a buffer or string or in other ways (see
2241(see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY will be 2205Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
2242wiped after use if it's a string. 2206will be wiped after use if it's a string.
2243 2207
2244The INPUT can be specified as a buffer or string or in other 2208The INPUT can be specified as a buffer or string or in other
2245ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). 2209ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
@@ -2248,7 +2212,7 @@ The alist of MAC algorithms can be obtained with `gnutls-macs`. The
2248HASH-METHOD may be a string or symbol matching a key in that alist, or 2212HASH-METHOD may be a string or symbol matching a key in that alist, or
2249a plist with the `:mac-algorithm-id' numeric property, or the number 2213a plist with the `:mac-algorithm-id' numeric property, or the number
2250itself. */) 2214itself. */)
2251 (Lisp_Object hash_method, Lisp_Object key, Lisp_Object input) 2215 (Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
2252{ 2216{
2253 if (BUFFERP (input) || STRINGP (input)) 2217 if (BUFFERP (input) || STRINGP (input))
2254 input = list1 (input); 2218 input = list1 (input);
@@ -2260,8 +2224,6 @@ itself. */)
2260 2224
2261 CHECK_CONS (key); 2225 CHECK_CONS (key);
2262 2226
2263 int ret = GNUTLS_E_SUCCESS;
2264
2265 gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN; 2227 gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
2266 2228
2267 Lisp_Object info = Qnil; 2229 Lisp_Object info = Qnil;
@@ -2270,7 +2232,7 @@ itself. */)
2270 2232
2271 if (SYMBOLP (hash_method)) 2233 if (SYMBOLP (hash_method))
2272 info = XCDR (Fassq (hash_method, Fgnutls_macs ())); 2234 info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
2273 else if (INTEGERP (hash_method)) 2235 else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
2274 gma = XINT (hash_method); 2236 gma = XINT (hash_method);
2275 else 2237 else
2276 info = hash_method; 2238 info = hash_method;
@@ -2278,37 +2240,32 @@ itself. */)
2278 if (!NILP (info) && CONSP (info)) 2240 if (!NILP (info) && CONSP (info))
2279 { 2241 {
2280 Lisp_Object v = Fplist_get (info, QCmac_algorithm_id); 2242 Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
2281 if (INTEGERP (v)) 2243 if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, v))
2282 gma = XINT (v); 2244 gma = XINT (v);
2283 } 2245 }
2284 2246
2285 if (gma == GNUTLS_MAC_UNKNOWN) 2247 ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
2286 error ("GnuTLS MAC-method was invalid or not found"); 2248 if (digest_length == 0)
2249 error ("GnuTLS MAC-method is invalid or not found");
2287 2250
2288 ptrdiff_t kstart_byte, kend_byte; 2251 ptrdiff_t kstart_byte, kend_byte;
2289 const char* kdata = extract_data_from_object (key, &kstart_byte, &kend_byte); 2252 const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
2290 gnutls_hmac_hd_t hmac;
2291 ret = gnutls_hmac_init (&hmac, gma,
2292 kdata + kstart_byte, kend_byte - kstart_byte);
2293
2294 if (kdata == NULL) 2253 if (kdata == NULL)
2295 error ("GnuTLS MAC key extraction failed"); 2254 error ("GnuTLS MAC key extraction failed");
2296 2255
2256 gnutls_hmac_hd_t hmac;
2257 int ret = gnutls_hmac_init (&hmac, gma,
2258 kdata + kstart_byte, kend_byte - kstart_byte);
2297 if (ret < GNUTLS_E_SUCCESS) 2259 if (ret < GNUTLS_E_SUCCESS)
2298 { 2260 error ("GnuTLS MAC %s initialization failed: %s",
2299 const char* str = gnutls_strerror (ret); 2261 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2300 if (!str)
2301 str = "unknown";
2302 error ("GnuTLS MAC %s initialization failed: %s",
2303 gnutls_mac_get_name (gma), str);
2304 }
2305 2262
2306 ptrdiff_t istart_byte, iend_byte; 2263 ptrdiff_t istart_byte, iend_byte;
2307 const char* idata = extract_data_from_object (input, &istart_byte, &iend_byte); 2264 const char *idata
2265 = extract_data_from_object (input, &istart_byte, &iend_byte);
2308 if (idata == NULL) 2266 if (idata == NULL)
2309 error ("GnuTLS MAC input extraction failed"); 2267 error ("GnuTLS MAC input extraction failed");
2310 2268
2311 size_t digest_length = gnutls_hmac_get_len (gma);
2312 Lisp_Object digest = make_uninit_string (digest_length); 2269 Lisp_Object digest = make_uninit_string (digest_length);
2313 2270
2314 ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte); 2271 ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
@@ -2319,12 +2276,8 @@ itself. */)
2319 if (ret < GNUTLS_E_SUCCESS) 2276 if (ret < GNUTLS_E_SUCCESS)
2320 { 2277 {
2321 gnutls_hmac_deinit (hmac, NULL); 2278 gnutls_hmac_deinit (hmac, NULL);
2322
2323 const char* str = gnutls_strerror (ret);
2324 if (!str)
2325 str = "unknown";
2326 error ("GnuTLS MAC %s application failed: %s", 2279 error ("GnuTLS MAC %s application failed: %s",
2327 gnutls_mac_get_name (gma), str); 2280 gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
2328 } 2281 }
2329 2282
2330 gnutls_hmac_output (hmac, SSDATA (digest)); 2283 gnutls_hmac_output (hmac, SSDATA (digest));
@@ -2336,7 +2289,7 @@ itself. */)
2336DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0, 2289DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0,
2337 doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string. 2290 doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string.
2338 2291
2339Returns nil on error. 2292Return nil on error.
2340 2293
2341The INPUT can be specified as a buffer or string or in other 2294The INPUT can be specified as a buffer or string or in other
2342ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). 2295ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
@@ -2345,15 +2298,13 @@ The alist of digest algorithms can be obtained with `gnutls-digests`.
2345The DIGEST-METHOD may be a string or symbol matching a key in that 2298The DIGEST-METHOD may be a string or symbol matching a key in that
2346alist, or a plist with the `:digest-algorithm-id' numeric property, or 2299alist, or a plist with the `:digest-algorithm-id' numeric property, or
2347the number itself. */) 2300the number itself. */)
2348 (Lisp_Object digest_method, Lisp_Object input) 2301 (Lisp_Object digest_method, Lisp_Object input)
2349{ 2302{
2350 if (BUFFERP (input) || STRINGP (input)) 2303 if (BUFFERP (input) || STRINGP (input))
2351 input = list1 (input); 2304 input = list1 (input);
2352 2305
2353 CHECK_CONS (input); 2306 CHECK_CONS (input);
2354 2307
2355 int ret = GNUTLS_E_SUCCESS;
2356
2357 gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN; 2308 gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN;
2358 2309
2359 Lisp_Object info = Qnil; 2310 Lisp_Object info = Qnil;
@@ -2362,7 +2313,7 @@ the number itself. */)
2362 2313
2363 if (SYMBOLP (digest_method)) 2314 if (SYMBOLP (digest_method))
2364 info = XCDR (Fassq (digest_method, Fgnutls_digests ())); 2315 info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
2365 else if (INTEGERP (digest_method)) 2316 else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
2366 gda = XINT (digest_method); 2317 gda = XINT (digest_method);
2367 else 2318 else
2368 info = digest_method; 2319 info = digest_method;
@@ -2370,29 +2321,26 @@ the number itself. */)
2370 if (!NILP (info) && CONSP (info)) 2321 if (!NILP (info) && CONSP (info))
2371 { 2322 {
2372 Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id); 2323 Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
2373 if (INTEGERP (v)) 2324 if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, v))
2374 gda = XINT (v); 2325 gda = XINT (v);
2375 } 2326 }
2376 2327
2377 if (gda == GNUTLS_DIG_UNKNOWN) 2328 ptrdiff_t digest_length = gnutls_hash_get_len (gda);
2378 error ("GnuTLS digest-method was invalid or not found"); 2329 if (digest_length == 0)
2330 error ("GnuTLS digest-method is invalid or not found");
2379 2331
2380 gnutls_hash_hd_t hash; 2332 gnutls_hash_hd_t hash;
2381 ret = gnutls_hash_init (&hash, gda); 2333 int ret = gnutls_hash_init (&hash, gda);
2382 2334
2383 if (ret < GNUTLS_E_SUCCESS) 2335 if (ret < GNUTLS_E_SUCCESS)
2384 { 2336 error ("GnuTLS digest initialization failed: %s",
2385 const char* str = gnutls_strerror (ret); 2337 emacs_gnutls_strerror (ret));
2386 if (!str)
2387 str = "unknown";
2388 error ("GnuTLS digest initialization failed: %s", str);
2389 }
2390 2338
2391 size_t digest_length = gnutls_hash_get_len (gda);
2392 Lisp_Object digest = make_uninit_string (digest_length); 2339 Lisp_Object digest = make_uninit_string (digest_length);
2393 2340
2394 ptrdiff_t istart_byte, iend_byte; 2341 ptrdiff_t istart_byte, iend_byte;
2395 const char* idata = extract_data_from_object (input, &istart_byte, &iend_byte); 2342 const char *idata
2343 = extract_data_from_object (input, &istart_byte, &iend_byte);
2396 if (idata == NULL) 2344 if (idata == NULL)
2397 error ("GnuTLS digest input extraction failed"); 2345 error ("GnuTLS digest input extraction failed");
2398 2346
@@ -2401,11 +2349,8 @@ the number itself. */)
2401 if (ret < GNUTLS_E_SUCCESS) 2349 if (ret < GNUTLS_E_SUCCESS)
2402 { 2350 {
2403 gnutls_hash_deinit (hash, NULL); 2351 gnutls_hash_deinit (hash, NULL);
2404 2352 error ("GnuTLS digest application failed: %s",
2405 const char* str = gnutls_strerror (ret); 2353 emacs_gnutls_strerror (ret));
2406 if (!str)
2407 str = "unknown";
2408 error ("GnuTLS digest application failed: %s", str);
2409 } 2354 }
2410 2355
2411 gnutls_hash_output (hash, SSDATA (digest)); 2356 gnutls_hash_output (hash, SSDATA (digest));
@@ -2420,57 +2365,51 @@ DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
2420 doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs. 2365 doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs.
2421 2366
2422...if supported : then... 2367...if supported : then...
2423GnuTLS 3 or higher : the list will contain 'gnutls3. 2368GnuTLS 3 or higher : the list will contain `gnutls3'.
2424GnuTLS MACs : the list will contain 'macs. 2369GnuTLS MACs : the list will contain `macs'.
2425GnuTLS digests : the list will contain 'digests. 2370GnuTLS digests : the list will contain `digests'.
2426GnuTLS symmetric ciphers: the list will contain 'ciphers. 2371GnuTLS symmetric ciphers: the list will contain `ciphers'.
2427GnuTLS AEAD ciphers : the list will contain 'AEAD-ciphers. */) 2372GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'. */)
2428 (void) 2373 (void)
2429{ 2374{
2430#ifdef HAVE_GNUTLS 2375#ifdef WINDOWSNT
2431 Lisp_Object capabilities = Qnil; 2376 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
2377 if (CONSP (found))
2378 return XCDR (found); /* TODO: use capabilities. */
2379 else
2380 {
2381 Lisp_Object status;
2382 /* TODO: should the capabilities be dynamic here? */
2383 status = init_gnutls_functions () ? capabilities : Qnil;
2384 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
2385 return status;
2386 }
2387#else
2432 2388
2433#ifdef HAVE_GNUTLS3 2389 Lisp_Object capabilities = Qnil;
2434 2390
2391# ifdef HAVE_GNUTLS3
2435 capabilities = Fcons (intern("gnutls3"), capabilities); 2392 capabilities = Fcons (intern("gnutls3"), capabilities);
2436 2393
2437#ifdef HAVE_GNUTLS3_DIGEST 2394# ifdef HAVE_GNUTLS3_DIGEST
2438 capabilities = Fcons (intern("digests"), capabilities); 2395 capabilities = Fcons (intern("digests"), capabilities);
2439#endif 2396# endif
2440 2397
2441#ifdef HAVE_GNUTLS3_CIPHER 2398# ifdef HAVE_GNUTLS3_CIPHER
2442 capabilities = Fcons (intern("ciphers"), capabilities); 2399 capabilities = Fcons (intern("ciphers"), capabilities);
2443 2400
2444#ifdef HAVE_GNUTLS3_AEAD 2401# ifdef HAVE_GNUTLS3_AEAD
2445 capabilities = Fcons (intern("AEAD-ciphers"), capabilities); 2402 capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
2446#endif 2403# endif
2447 2404
2448#ifdef HAVE_GNUTLS3_HMAC 2405# ifdef HAVE_GNUTLS3_HMAC
2449 capabilities = Fcons (intern("macs"), capabilities); 2406 capabilities = Fcons (intern("macs"), capabilities);
2450#endif 2407# endif
2451 2408# endif
2452#endif 2409# endif
2453
2454#endif
2455 2410
2456# ifdef WINDOWSNT
2457 Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
2458 if (CONSP (found))
2459 return XCDR (found); // TODO: use capabilities.
2460 else
2461 {
2462 Lisp_Object status;
2463 // TODO: should the capabilities be dynamic here?
2464 status = init_gnutls_functions () ? capabilities : Qnil;
2465 Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
2466 return status;
2467 }
2468# else /* !WINDOWSNT */
2469 return capabilities; 2411 return capabilities;
2470# endif /* !WINDOWSNT */ 2412#endif
2471#else /* !HAVE_GNUTLS */
2472 return Qnil;
2473#endif /* !HAVE_GNUTLS */
2474} 2413}
2475 2414
2476void 2415void
diff --git a/src/lisp.h b/src/lisp.h
index a5134a9532c..9464bf8559f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3386,9 +3386,7 @@ enum { NEXT_ALMOST_PRIME_LIMIT = 11 };
3386extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST; 3386extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST;
3387extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t); 3387extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t);
3388extern void sweep_weak_hash_tables (void); 3388extern void sweep_weak_hash_tables (void);
3389extern const char* extract_data_from_object (Lisp_Object spec, 3389extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *);
3390 ptrdiff_t *start_byte,
3391 ptrdiff_t *end_byte);
3392EMACS_UINT hash_string (char const *, ptrdiff_t); 3390EMACS_UINT hash_string (char const *, ptrdiff_t);
3393EMACS_UINT sxhash (Lisp_Object, int); 3391EMACS_UINT sxhash (Lisp_Object, int);
3394Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float, 3392Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float,