aboutsummaryrefslogtreecommitdiffstats
path: root/src/fns.c
diff options
context:
space:
mode:
authorTed Zlatanov2017-07-14 11:04:19 -0400
committerTed Zlatanov2017-07-14 11:06:16 -0400
commit583995c62dd424775dda33d5134ce04bee2ae685 (patch)
tree732251c7c468b20a70d20578b778946cf49f77fe /src/fns.c
parent0f3cc0b8245dfd7a9f6fcc95ec148be03fde8931 (diff)
downloademacs-583995c62dd424775dda33d5134ce04bee2ae685.tar.gz
emacs-583995c62dd424775dda33d5134ce04bee2ae685.zip
GnuTLS HMAC and symmetric cipher support
* etc/NEWS: Add news for new feature. * doc/lispref/text.texi (GnuTLS Cryptography): Add documentation. * configure.ac: Add macros HAVE_GNUTLS3_DIGEST, HAVE_GNUTLS3_CIPHER, HAVE_GNUTLS3_AEAD, HAVE_GNUTLS3_HMAC. * src/fns.c (Fsecure_hash_algorithms): Add function to list supported `secure-hash' algorithms. (extract_data_from_object): Add data extraction function that can operate on buffers and strings. (secure_hash): Use it. (Fsecure_hash): Mention `secure-hash-algorithms'. * src/gnutls.h: Include gnutls/crypto.h. * src/gnutls.c (Fgnutls_ciphers, gnutls_symmetric_aead) (gnutls_symmetric, Fgnutls_symmetric_encrypt, Fgnutls_symmetric_decrypt) (Fgnutls_macs, Fgnutls_digests, Fgnutls_hash_mac, Fgnutls_hash_digest) (Fgnutls_available_p): Implement GnuTLS cryptographic integration. * test/lisp/net/gnutls-tests.el: Add tests.
Diffstat (limited to 'src/fns.c')
-rw-r--r--src/fns.c134
1 files changed, 109 insertions, 25 deletions
diff --git a/src/fns.c b/src/fns.c
index f0e10e311f5..8b7fc0f89d8 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -35,12 +35,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
35#include "intervals.h" 35#include "intervals.h"
36#include "window.h" 36#include "window.h"
37#include "puresize.h" 37#include "puresize.h"
38#include "gnutls.h"
38 39
39static void sort_vector_copy (Lisp_Object, ptrdiff_t, 40static void sort_vector_copy (Lisp_Object, ptrdiff_t,
40 Lisp_Object *restrict, Lisp_Object *restrict); 41 Lisp_Object *restrict, Lisp_Object *restrict);
41enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; 42enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
42static bool internal_equal (Lisp_Object, Lisp_Object, 43static bool internal_equal (Lisp_Object, Lisp_Object,
43 enum equal_kind, int, Lisp_Object); 44 enum equal_kind, int, Lisp_Object);
45static Lisp_Object
46secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
47 Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror,
48 Lisp_Object binary);
44 49
45DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, 50DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
46 doc: /* Return the argument unchanged. */ 51 doc: /* Return the argument unchanged. */
@@ -4740,22 +4745,47 @@ make_digest_string (Lisp_Object digest, int digest_size)
4740 return digest; 4745 return digest;
4741} 4746}
4742 4747
4743/* ALGORITHM is a symbol: md5, sha1, sha224 and so on. */ 4748DEFUN ("secure-hash-algorithms", Fsecure_hash_algorithms,
4749 Ssecure_hash_algorithms, 0, 0, 0,
4750 doc: /* Return a list of all the supported `secure_hash' algorithms. */)
4751 (void)
4752{
4753 return listn (CONSTYPE_HEAP, 6,
4754 Qmd5,
4755 Qsha1,
4756 Qsha224,
4757 Qsha256,
4758 Qsha384,
4759 Qsha512);
4760}
4744 4761
4745static Lisp_Object 4762/* Extract data from a string or a buffer. SPEC is a list of
4746secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, 4763(BUFFER-OR-STRING-OR-SYMBOL START END CODING-SYSTEM NOERROR) which behave as
4747 Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror, 4764specified with `secure-hash' and in Info node
4748 Lisp_Object binary) 4765`(elisp)Format of GnuTLS Cryptography Inputs'. */
4766const char*
4767extract_data_from_object (Lisp_Object spec,
4768 ptrdiff_t *start_byte,
4769 ptrdiff_t *end_byte)
4749{ 4770{
4750 ptrdiff_t size, start_char = 0, start_byte, end_char = 0, end_byte; 4771 ptrdiff_t size, start_char = 0, end_char = 0;
4751 register EMACS_INT b, e; 4772 register EMACS_INT b, e;
4752 register struct buffer *bp; 4773 register struct buffer *bp;
4753 EMACS_INT temp; 4774 EMACS_INT temp;
4754 int digest_size;
4755 void *(*hash_func) (const char *, size_t, void *);
4756 Lisp_Object digest;
4757 4775
4758 CHECK_SYMBOL (algorithm); 4776 Lisp_Object object = XCAR (spec);
4777
4778 if (! NILP (spec)) spec = XCDR (spec);
4779 Lisp_Object start = (CONSP (spec)) ? XCAR (spec) : Qnil;
4780
4781 if (! NILP (spec)) spec = XCDR (spec);
4782 Lisp_Object end = (CONSP (spec)) ? XCAR (spec) : Qnil;
4783
4784 if (! NILP (spec)) spec = XCDR (spec);
4785 Lisp_Object coding_system = (CONSP (spec)) ? XCAR (spec) : Qnil;
4786
4787 if (! NILP (spec)) spec = XCDR (spec);
4788 Lisp_Object noerror = (CONSP (spec)) ? XCAR (spec) : Qnil;
4759 4789
4760 if (STRINGP (object)) 4790 if (STRINGP (object))
4761 { 4791 {
@@ -4786,12 +4816,12 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
4786 size = SCHARS (object); 4816 size = SCHARS (object);
4787 validate_subarray (object, start, end, size, &start_char, &end_char); 4817 validate_subarray (object, start, end, size, &start_char, &end_char);
4788 4818
4789 start_byte = !start_char ? 0 : string_char_to_byte (object, start_char); 4819 *start_byte = !start_char ? 0 : string_char_to_byte (object, start_char);
4790 end_byte = (end_char == size 4820 *end_byte = (end_char == size
4791 ? SBYTES (object) 4821 ? SBYTES (object)
4792 : string_char_to_byte (object, end_char)); 4822 : string_char_to_byte (object, end_char));
4793 } 4823 }
4794 else 4824 else if (BUFFERP (object))
4795 { 4825 {
4796 struct buffer *prev = current_buffer; 4826 struct buffer *prev = current_buffer;
4797 4827
@@ -4892,10 +4922,56 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
4892 4922
4893 if (STRING_MULTIBYTE (object)) 4923 if (STRING_MULTIBYTE (object))
4894 object = code_convert_string (object, coding_system, Qnil, 1, 0, 0); 4924 object = code_convert_string (object, coding_system, Qnil, 1, 0, 0);
4895 start_byte = 0; 4925 *start_byte = 0;
4896 end_byte = SBYTES (object); 4926 *end_byte = SBYTES (object);
4927 }
4928 else if (EQ (object, Qiv_auto))
4929 {
4930#ifdef HAVE_GNUTLS3
4931 // Format: (iv-auto REQUIRED-LENGTH)
4932
4933 if (! INTEGERP (start))
4934 error ("Without a length, iv-auto can't be used. See manual.");
4935 else
4936 {
4937 /* Make sure the value of "start" doesn't change. */
4938 size_t start_hold = XUINT (start);
4939 object = make_uninit_string (start_hold);
4940 gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold);
4941
4942 *start_byte = 0;
4943 *end_byte = start_hold;
4944 }
4945#else
4946 error ("GnuTLS integration is not available, so iv-auto can't be used.");
4947#endif
4897 } 4948 }
4898 4949
4950 return SSDATA (object);
4951}
4952
4953
4954/* ALGORITHM is a symbol: md5, sha1, sha224 and so on. */
4955
4956static Lisp_Object
4957secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
4958 Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror,
4959 Lisp_Object binary)
4960{
4961 ptrdiff_t start_byte, end_byte;
4962 int digest_size;
4963 void *(*hash_func) (const char *, size_t, void *);
4964 Lisp_Object digest;
4965
4966 CHECK_SYMBOL (algorithm);
4967
4968 Lisp_Object spec = list5 (object, start, end, coding_system, noerror);
4969
4970 const char* input = extract_data_from_object (spec, &start_byte, &end_byte);
4971
4972 if (input == NULL)
4973 error ("secure_hash: failed to extract data from object, aborting!");
4974
4899 if (EQ (algorithm, Qmd5)) 4975 if (EQ (algorithm, Qmd5))
4900 { 4976 {
4901 digest_size = MD5_DIGEST_SIZE; 4977 digest_size = MD5_DIGEST_SIZE;
@@ -4933,7 +5009,7 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
4933 hexified value */ 5009 hexified value */
4934 digest = make_uninit_string (digest_size * 2); 5010 digest = make_uninit_string (digest_size * 2);
4935 5011
4936 hash_func (SSDATA (object) + start_byte, 5012 hash_func (input + start_byte,
4937 end_byte - start_byte, 5013 end_byte - start_byte,
4938 SSDATA (digest)); 5014 SSDATA (digest));
4939 5015
@@ -4984,6 +5060,8 @@ The two optional arguments START and END are positions specifying for
4984which part of OBJECT to compute the hash. If nil or omitted, uses the 5060which part of OBJECT to compute the hash. If nil or omitted, uses the
4985whole OBJECT. 5061whole OBJECT.
4986 5062
5063The full list of algorithms can be obtained with `secure-hash-algorithms'.
5064
4987If BINARY is non-nil, returns a string in binary form. */) 5065If BINARY is non-nil, returns a string in binary form. */)
4988 (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object binary) 5066 (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object binary)
4989{ 5067{
@@ -5031,13 +5109,6 @@ disregarding any coding systems. If nil, use the current buffer. */ )
5031void 5109void
5032syms_of_fns (void) 5110syms_of_fns (void)
5033{ 5111{
5034 DEFSYM (Qmd5, "md5");
5035 DEFSYM (Qsha1, "sha1");
5036 DEFSYM (Qsha224, "sha224");
5037 DEFSYM (Qsha256, "sha256");
5038 DEFSYM (Qsha384, "sha384");
5039 DEFSYM (Qsha512, "sha512");
5040
5041 /* Hash table stuff. */ 5112 /* Hash table stuff. */
5042 DEFSYM (Qhash_table_p, "hash-table-p"); 5113 DEFSYM (Qhash_table_p, "hash-table-p");
5043 DEFSYM (Qeq, "eq"); 5114 DEFSYM (Qeq, "eq");
@@ -5074,6 +5145,18 @@ syms_of_fns (void)
5074 defsubr (&Smaphash); 5145 defsubr (&Smaphash);
5075 defsubr (&Sdefine_hash_table_test); 5146 defsubr (&Sdefine_hash_table_test);
5076 5147
5148 /* Crypto and hashing stuff. */
5149 DEFSYM (Qiv_auto, "iv-auto");
5150
5151 DEFSYM (Qmd5, "md5");
5152 DEFSYM (Qsha1, "sha1");
5153 DEFSYM (Qsha224, "sha224");
5154 DEFSYM (Qsha256, "sha256");
5155 DEFSYM (Qsha384, "sha384");
5156 DEFSYM (Qsha512, "sha512");
5157
5158 /* Miscellaneous stuff. */
5159
5077 DEFSYM (Qstring_lessp, "string-lessp"); 5160 DEFSYM (Qstring_lessp, "string-lessp");
5078 DEFSYM (Qprovide, "provide"); 5161 DEFSYM (Qprovide, "provide");
5079 DEFSYM (Qrequire, "require"); 5162 DEFSYM (Qrequire, "require");
@@ -5192,6 +5275,7 @@ this variable. */);
5192 defsubr (&Sbase64_encode_string); 5275 defsubr (&Sbase64_encode_string);
5193 defsubr (&Sbase64_decode_string); 5276 defsubr (&Sbase64_decode_string);
5194 defsubr (&Smd5); 5277 defsubr (&Smd5);
5278 defsubr (&Ssecure_hash_algorithms);
5195 defsubr (&Ssecure_hash); 5279 defsubr (&Ssecure_hash);
5196 defsubr (&Sbuffer_hash); 5280 defsubr (&Sbuffer_hash);
5197 defsubr (&Slocale_info); 5281 defsubr (&Slocale_info);