diff options
| author | Ted Zlatanov | 2017-07-14 11:04:19 -0400 |
|---|---|---|
| committer | Ted Zlatanov | 2017-07-14 11:06:16 -0400 |
| commit | 583995c62dd424775dda33d5134ce04bee2ae685 (patch) | |
| tree | 732251c7c468b20a70d20578b778946cf49f77fe /src/fns.c | |
| parent | 0f3cc0b8245dfd7a9f6fcc95ec148be03fde8931 (diff) | |
| download | emacs-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.c | 134 |
1 files changed, 109 insertions, 25 deletions
| @@ -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 | ||
| 39 | static void sort_vector_copy (Lisp_Object, ptrdiff_t, | 40 | static void sort_vector_copy (Lisp_Object, ptrdiff_t, |
| 40 | Lisp_Object *restrict, Lisp_Object *restrict); | 41 | Lisp_Object *restrict, Lisp_Object *restrict); |
| 41 | enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; | 42 | enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; |
| 42 | static bool internal_equal (Lisp_Object, Lisp_Object, | 43 | static bool internal_equal (Lisp_Object, Lisp_Object, |
| 43 | enum equal_kind, int, Lisp_Object); | 44 | enum equal_kind, int, Lisp_Object); |
| 45 | static Lisp_Object | ||
| 46 | secure_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 | ||
| 45 | DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, | 50 | DEFUN ("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. */ | 4748 | DEFUN ("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 | ||
| 4745 | static Lisp_Object | 4762 | /* Extract data from a string or a buffer. SPEC is a list of |
| 4746 | secure_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, | 4764 | specified with `secure-hash' and in Info node |
| 4748 | Lisp_Object binary) | 4765 | `(elisp)Format of GnuTLS Cryptography Inputs'. */ |
| 4766 | const char* | ||
| 4767 | extract_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 | |||
| 4956 | static Lisp_Object | ||
| 4957 | secure_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 | |||
| 4984 | which part of OBJECT to compute the hash. If nil or omitted, uses the | 5060 | which part of OBJECT to compute the hash. If nil or omitted, uses the |
| 4985 | whole OBJECT. | 5061 | whole OBJECT. |
| 4986 | 5062 | ||
| 5063 | The full list of algorithms can be obtained with `secure-hash-algorithms'. | ||
| 5064 | |||
| 4987 | If BINARY is non-nil, returns a string in binary form. */) | 5065 | If 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. */ ) | |||
| 5031 | void | 5109 | void |
| 5032 | syms_of_fns (void) | 5110 | syms_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); |