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.
This commit is contained in:
parent
8b64a80a56
commit
05b8b86699
4 changed files with 312 additions and 354 deletions
128
configure.ac
128
configure.ac
|
|
@ -2832,60 +2832,86 @@ if test "${with_gnutls}" = "yes" ; then
|
|||
EMACS_CHECK_MODULES([LIBGNUTLS3], [gnutls >= 3.0.0],
|
||||
[AC_DEFINE(HAVE_GNUTLS3, 1, [Define if using GnuTLS v3.])], [])
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]],
|
||||
[[
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
gnutls_hmac_hd_t handle;
|
||||
gnutls_hmac_deinit(handle, NULL);
|
||||
}
|
||||
]])],
|
||||
[AC_DEFINE(HAVE_GNUTLS3_HMAC, 1, [Define if using GnuTLS v3 with HMAC support.])])
|
||||
AC_CACHE_CHECK([for GnuTLS v3 with HMAC], [emacs_cv_gnutls3_hmac],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]], [[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
gnutls_hmac_hd_t handle;
|
||||
gnutls_hmac_deinit (handle, NULL);
|
||||
}
|
||||
]])],
|
||||
[emacs_cv_gnutls3_hmac=yes],
|
||||
[emacs_cv_gnutls3_hmac=no])])
|
||||
if test "$emacs_cv_gnutls3_hmac" = yes; then
|
||||
AC_DEFINE([HAVE_GNUTLS3_HMAC], [1],
|
||||
[Define if using GnuTLS v3 with HMAC support.])
|
||||
fi
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]],
|
||||
[[
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
gnutls_aead_cipher_hd_t handle;
|
||||
gnutls_aead_cipher_deinit(handle);
|
||||
}
|
||||
]])],
|
||||
[AC_DEFINE(HAVE_GNUTLS3_AEAD, 1, [Define if using GnuTLS v3 with AEAD support.])])
|
||||
AC_CACHE_CHECK([for GnuTLS v3 with AEAD], [emacs_cv_gnutls3_aead],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]], [[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
gnutls_aead_cipher_hd_t handle;
|
||||
gnutls_aead_cipher_deinit (handle);
|
||||
}
|
||||
]])],
|
||||
[emacs_cv_gnutls3_aead=yes],
|
||||
[emacs_cv_gnutls3_aead=no])])
|
||||
if test "$emacs_cv_gnutls3_aead" = yes; then
|
||||
AC_DEFINE([HAVE_GNUTLS3_AEAD], [1],
|
||||
[Define if using GnuTLS v3 with AEAD support.])
|
||||
fi
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]],
|
||||
[[
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
gnutls_cipher_hd_t handle;
|
||||
gnutls_cipher_encrypt2 (handle,
|
||||
NULL, 0,
|
||||
NULL, 0);
|
||||
gnutls_cipher_deinit(handle);
|
||||
}
|
||||
]])],
|
||||
[AC_DEFINE(HAVE_GNUTLS3_CIPHER, 1, [Define if using GnuTLS v3 with cipher support.])])
|
||||
AC_CACHE_CHECK([for GnuTLS v3 with cipher], [emacs_cv_gnutls3_cipher],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]], [[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
gnutls_cipher_hd_t handle;
|
||||
gnutls_cipher_encrypt2 (handle, NULL, 0, NULL, 0);
|
||||
gnutls_cipher_deinit (handle);
|
||||
}
|
||||
]])],
|
||||
[emacs_cv_gnutls3_cipher=yes],
|
||||
[emacs_cv_gnutls3_cipher=no])])
|
||||
if test "$emacs_cv_gnutls3_cipher" = yes; then
|
||||
AC_DEFINE([HAVE_GNUTLS3_CIPHER], [1],
|
||||
[Define if using GnuTLS v3 with cipher support.])
|
||||
fi
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]],
|
||||
[[
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
gnutls_hash_hd_t handle;
|
||||
gnutls_hash_deinit(handle, NULL);
|
||||
}
|
||||
]])],
|
||||
[AC_DEFINE(HAVE_GNUTLS3_DIGEST, 1, [Define if using GnuTLS v3 with digest support.])])
|
||||
AC_CACHE_CHECK([for GnuTLS v3 with digest], [emacs_cv_gnutls3_digest],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
]], [[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
gnutls_hash_hd_t handle;
|
||||
gnutls_hash_deinit (handle, NULL);
|
||||
}
|
||||
]])],
|
||||
[emacs_cv_gnutls3_digest=yes],
|
||||
[emacs_cv_gnutls3_digest=no])])
|
||||
if test "$emacs_cv_gnutls3_digest" = yes; then
|
||||
AC_DEFINE([HAVE_GNUTLS3_DIGEST], [1],
|
||||
[Define if using GnuTLS v3 with digest support.])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Windows loads GnuTLS dynamically
|
||||
|
|
|
|||
49
src/fns.c
49
src/fns.c
|
|
@ -46,10 +46,6 @@ static void sort_vector_copy (Lisp_Object, ptrdiff_t,
|
|||
enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
|
||||
static bool internal_equal (Lisp_Object, Lisp_Object,
|
||||
enum equal_kind, int, Lisp_Object);
|
||||
static Lisp_Object
|
||||
secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
|
||||
Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror,
|
||||
Lisp_Object binary);
|
||||
|
||||
DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
|
||||
doc: /* Return the argument unchanged. */
|
||||
|
|
@ -4767,29 +4763,24 @@ DEFUN ("secure-hash-algorithms", Fsecure_hash_algorithms,
|
|||
(BUFFER-OR-STRING-OR-SYMBOL START END CODING-SYSTEM NOERROR) which behave as
|
||||
specified with `secure-hash' and in Info node
|
||||
`(elisp)Format of GnuTLS Cryptography Inputs'. */
|
||||
const char*
|
||||
char *
|
||||
extract_data_from_object (Lisp_Object spec,
|
||||
ptrdiff_t *start_byte,
|
||||
ptrdiff_t *end_byte)
|
||||
{
|
||||
ptrdiff_t size, start_char = 0, end_char = 0;
|
||||
register EMACS_INT b, e;
|
||||
register struct buffer *bp;
|
||||
EMACS_INT temp;
|
||||
Lisp_Object object = XCAR (spec);
|
||||
|
||||
Lisp_Object object = XCAR (spec);
|
||||
if (CONSP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object start = CAR_SAFE (spec);
|
||||
|
||||
if (! NILP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object start = (CONSP (spec)) ? XCAR (spec) : Qnil;
|
||||
if (CONSP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object end = CAR_SAFE (spec);
|
||||
|
||||
if (! NILP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object end = (CONSP (spec)) ? XCAR (spec) : Qnil;
|
||||
if (CONSP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object coding_system = CAR_SAFE (spec);
|
||||
|
||||
if (! NILP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object coding_system = (CONSP (spec)) ? XCAR (spec) : Qnil;
|
||||
|
||||
if (! NILP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object noerror = (CONSP (spec)) ? XCAR (spec) : Qnil;
|
||||
if (CONSP (spec)) spec = XCDR (spec);
|
||||
Lisp_Object noerror = CAR_SAFE (spec);
|
||||
|
||||
if (STRINGP (object))
|
||||
{
|
||||
|
|
@ -4817,7 +4808,7 @@ extract_data_from_object (Lisp_Object spec,
|
|||
if (STRING_MULTIBYTE (object))
|
||||
object = code_convert_string (object, coding_system, Qnil, 1, 0, 1);
|
||||
|
||||
size = SCHARS (object);
|
||||
ptrdiff_t size = SCHARS (object), start_char, end_char;
|
||||
validate_subarray (object, start, end, size, &start_char, &end_char);
|
||||
|
||||
*start_byte = !start_char ? 0 : string_char_to_byte (object, start_char);
|
||||
|
|
@ -4828,12 +4819,13 @@ extract_data_from_object (Lisp_Object spec,
|
|||
else if (BUFFERP (object))
|
||||
{
|
||||
struct buffer *prev = current_buffer;
|
||||
EMACS_INT b, e;
|
||||
|
||||
record_unwind_current_buffer ();
|
||||
|
||||
CHECK_BUFFER (object);
|
||||
|
||||
bp = XBUFFER (object);
|
||||
struct buffer *bp = XBUFFER (object);
|
||||
set_buffer_internal (bp);
|
||||
|
||||
if (NILP (start))
|
||||
|
|
@ -4853,7 +4845,11 @@ extract_data_from_object (Lisp_Object spec,
|
|||
}
|
||||
|
||||
if (b > e)
|
||||
temp = b, b = e, e = temp;
|
||||
{
|
||||
EMACS_INT temp = b;
|
||||
b = e;
|
||||
e = temp;
|
||||
}
|
||||
|
||||
if (!(BEGV <= b && e <= ZV))
|
||||
args_out_of_range (start, end);
|
||||
|
|
@ -4932,14 +4928,13 @@ extract_data_from_object (Lisp_Object spec,
|
|||
else if (EQ (object, Qiv_auto))
|
||||
{
|
||||
#ifdef HAVE_GNUTLS3
|
||||
// Format: (iv-auto REQUIRED-LENGTH)
|
||||
/* Format: (iv-auto REQUIRED-LENGTH). */
|
||||
|
||||
if (! INTEGERP (start))
|
||||
if (! NATNUMP (start))
|
||||
error ("Without a length, iv-auto can't be used. See manual.");
|
||||
else
|
||||
{
|
||||
/* Make sure the value of "start" doesn't change. */
|
||||
size_t start_hold = XUINT (start);
|
||||
EMACS_INT start_hold = XFASTINT (start);
|
||||
object = make_uninit_string (start_hold);
|
||||
gnutls_rnd (GNUTLS_RND_NONCE, SSDATA (object), start_hold);
|
||||
|
||||
|
|
@ -4971,7 +4966,7 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start,
|
|||
|
||||
Lisp_Object spec = list5 (object, start, end, coding_system, noerror);
|
||||
|
||||
const char* input = extract_data_from_object (spec, &start_byte, &end_byte);
|
||||
const char *input = extract_data_from_object (spec, &start_byte, &end_byte);
|
||||
|
||||
if (input == NULL)
|
||||
error ("secure_hash: failed to extract data from object, aborting!");
|
||||
|
|
|
|||
485
src/gnutls.c
485
src/gnutls.c
|
|
@ -672,6 +672,13 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte)
|
|||
}
|
||||
}
|
||||
|
||||
static char const *
|
||||
emacs_gnutls_strerror (int err)
|
||||
{
|
||||
char const *str = gnutls_strerror (err);
|
||||
return str ? str : "unknown";
|
||||
}
|
||||
|
||||
/* Report a GnuTLS error to the user.
|
||||
Return true if the error code was successfully handled. */
|
||||
static bool
|
||||
|
|
@ -680,7 +687,6 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
|
|||
int max_log_level = 0;
|
||||
|
||||
bool ret;
|
||||
const char *str;
|
||||
|
||||
/* TODO: use a Lisp_Object generated by gnutls_make_error? */
|
||||
if (err >= 0)
|
||||
|
|
@ -692,9 +698,7 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
|
|||
|
||||
/* TODO: use gnutls-error-fatalp and gnutls-error-string. */
|
||||
|
||||
str = gnutls_strerror (err);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
char const *str = emacs_gnutls_strerror (err);
|
||||
|
||||
if (gnutls_error_is_fatal (err))
|
||||
{
|
||||
|
|
@ -708,11 +712,11 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
|
|||
#endif
|
||||
|
||||
GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
|
||||
ret = 0;
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 1;
|
||||
ret = true;
|
||||
|
||||
switch (err)
|
||||
{
|
||||
|
|
@ -900,7 +904,7 @@ usage: (gnutls-error-string ERROR) */)
|
|||
if (! TYPE_RANGED_INTEGERP (int, err))
|
||||
return build_string ("Not an error symbol or code");
|
||||
|
||||
return build_string (gnutls_strerror (XINT (err)));
|
||||
return build_string (emacs_gnutls_strerror (XINT (err)));
|
||||
}
|
||||
|
||||
DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
|
||||
|
|
@ -1592,9 +1596,9 @@ one trustfile (usually a CA bundle). */)
|
|||
XPROCESS (proc)->gnutls_x509_cred = x509_cred;
|
||||
|
||||
verify_flags = Fplist_get (proplist, QCverify_flags);
|
||||
if (NUMBERP (verify_flags))
|
||||
if (TYPE_RANGED_INTEGERP (unsigned int, verify_flags))
|
||||
{
|
||||
gnutls_verify_flags = XINT (verify_flags);
|
||||
gnutls_verify_flags = XFASTINT (verify_flags);
|
||||
GNUTLS_LOG (2, max_log_level, "setting verification flags");
|
||||
}
|
||||
else if (NILP (verify_flags))
|
||||
|
|
@ -1818,39 +1822,32 @@ This function may also return `gnutls-e-again', or
|
|||
DEFUN ("gnutls-ciphers", Fgnutls_ciphers, Sgnutls_ciphers, 0, 0, 0,
|
||||
doc: /* Return alist of GnuTLS symmetric cipher descriptions as plists.
|
||||
The alist key is the cipher name. */)
|
||||
(void)
|
||||
(void)
|
||||
{
|
||||
Lisp_Object ciphers = Qnil;
|
||||
|
||||
const gnutls_cipher_algorithm_t* gciphers = gnutls_cipher_list ();
|
||||
for (size_t pos = 0; gciphers[pos] != GNUTLS_CIPHER_NULL; pos++)
|
||||
const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
|
||||
for (ptrdiff_t pos = 0; gciphers[pos] != GNUTLS_CIPHER_NULL; pos++)
|
||||
{
|
||||
const gnutls_cipher_algorithm_t gca = gciphers[pos];
|
||||
gnutls_cipher_algorithm_t gca = gciphers[pos];
|
||||
Lisp_Object cipher_symbol = intern (gnutls_cipher_get_name (gca));
|
||||
ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
|
||||
|
||||
Lisp_Object cp = listn (CONSTYPE_HEAP, 15,
|
||||
/* A symbol representing the cipher */
|
||||
intern (gnutls_cipher_get_name (gca)),
|
||||
/* The internally meaningful cipher ID */
|
||||
QCcipher_id,
|
||||
make_number (gca),
|
||||
/* The type (vs. other GnuTLS objects). */
|
||||
QCtype,
|
||||
Qgnutls_type_cipher,
|
||||
/* The tag size (nonzero means AEAD). */
|
||||
QCcipher_aead_capable,
|
||||
(gnutls_cipher_get_tag_size (gca) == 0) ? Qnil : Qt,
|
||||
/* The tag size (nonzero means AEAD). */
|
||||
QCcipher_tagsize,
|
||||
make_number (gnutls_cipher_get_tag_size (gca)),
|
||||
/* The block size */
|
||||
QCcipher_blocksize,
|
||||
make_number (gnutls_cipher_get_block_size (gca)),
|
||||
/* The key size */
|
||||
QCcipher_keysize,
|
||||
make_number (gnutls_cipher_get_key_size (gca)),
|
||||
/* IV size */
|
||||
QCcipher_ivsize,
|
||||
make_number (gnutls_cipher_get_iv_size (gca)));
|
||||
Lisp_Object cp
|
||||
= listn (CONSTYPE_HEAP, 15, cipher_symbol,
|
||||
QCcipher_id, make_number (gca),
|
||||
QCtype, Qgnutls_type_cipher,
|
||||
QCcipher_aead_capable, cipher_tag_size == 0 ? Qnil : Qt,
|
||||
QCcipher_tagsize, make_number (cipher_tag_size),
|
||||
|
||||
QCcipher_blocksize,
|
||||
make_number (gnutls_cipher_get_block_size (gca)),
|
||||
|
||||
QCcipher_keysize,
|
||||
make_number (gnutls_cipher_get_key_size (gca)),
|
||||
|
||||
QCcipher_ivsize,
|
||||
make_number (gnutls_cipher_get_iv_size (gca)));
|
||||
|
||||
ciphers = Fcons (cp, ciphers);
|
||||
}
|
||||
|
|
@ -1861,36 +1858,35 @@ The alist key is the cipher name. */)
|
|||
static Lisp_Object
|
||||
gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
|
||||
Lisp_Object cipher,
|
||||
const char* kdata, size_t ksize,
|
||||
const char* vdata, size_t vsize,
|
||||
const char* idata, size_t isize,
|
||||
const char *kdata, ptrdiff_t ksize,
|
||||
const char *vdata, ptrdiff_t vsize,
|
||||
const char *idata, ptrdiff_t isize,
|
||||
Lisp_Object aead_auth)
|
||||
{
|
||||
#ifdef HAVE_GNUTLS3_AEAD
|
||||
|
||||
const char* desc = (encrypting ? "encrypt" : "decrypt");
|
||||
int ret = GNUTLS_E_SUCCESS;
|
||||
const char *desc = encrypting ? "encrypt" : "decrypt";
|
||||
Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
|
||||
|
||||
gnutls_aead_cipher_hd_t acipher;
|
||||
gnutls_datum_t key_datum = { (unsigned char*) kdata, ksize };
|
||||
ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
|
||||
gnutls_datum_t key_datum = { (unsigned char *) kdata, ksize };
|
||||
int ret = gnutls_aead_cipher_init (&acipher, gca, &key_datum);
|
||||
|
||||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
|
||||
gnutls_cipher_get_name (gca), desc, str);
|
||||
}
|
||||
error ("GnuTLS AEAD cipher %s/%s initialization failed: %s",
|
||||
gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
|
||||
|
||||
size_t storage_length = isize + gnutls_cipher_get_tag_size (gca);
|
||||
ptrdiff_t cipher_tag_size = gnutls_cipher_get_tag_size (gca);
|
||||
ptrdiff_t tagged_size;
|
||||
if (INT_ADD_WRAPV (isize, cipher_tag_size, &tagged_size)
|
||||
|| SIZE_MAX < tagged_size)
|
||||
memory_full (SIZE_MAX);
|
||||
size_t storage_length = tagged_size;
|
||||
USE_SAFE_ALLOCA;
|
||||
unsigned char *storage = SAFE_ALLOCA (storage_length);
|
||||
char *storage = SAFE_ALLOCA (storage_length);
|
||||
|
||||
const char* aead_auth_data = NULL;
|
||||
size_t aead_auth_size = 0;
|
||||
const char *aead_auth_data = NULL;
|
||||
ptrdiff_t aead_auth_size = 0;
|
||||
|
||||
if (!NILP (aead_auth))
|
||||
{
|
||||
|
|
@ -1900,8 +1896,8 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
|
|||
CHECK_CONS (aead_auth);
|
||||
|
||||
ptrdiff_t astart_byte, aend_byte;
|
||||
const char* adata = extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
|
||||
|
||||
const char *adata
|
||||
= extract_data_from_object (aead_auth, &astart_byte, &aend_byte);
|
||||
if (adata == NULL)
|
||||
error ("GnuTLS AEAD cipher auth extraction failed");
|
||||
|
||||
|
|
@ -1909,53 +1905,38 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
|
|||
aead_auth_size = aend_byte - astart_byte;
|
||||
}
|
||||
|
||||
size_t expected_remainder = 0;
|
||||
ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
|
||||
ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
|
||||
|
||||
if (!encrypting)
|
||||
expected_remainder = gnutls_cipher_get_tag_size (gca);
|
||||
|
||||
if ((isize - expected_remainder) % gnutls_cipher_get_block_size (gca) != 0)
|
||||
error ("GnuTLS AEAD cipher %s/%s input block length %ld was not a "
|
||||
"multiple of the required %ld plus the expected tag remainder %ld",
|
||||
if (isize < expected_remainder
|
||||
|| (isize - expected_remainder) % cipher_block_size != 0)
|
||||
error (("GnuTLS AEAD cipher %s/%s input block length %"pD"d "
|
||||
"is not %"pD"d greater than a multiple of the required %"pD"d"),
|
||||
gnutls_cipher_get_name (gca), desc,
|
||||
(long) isize, (long) gnutls_cipher_get_block_size (gca),
|
||||
(long) expected_remainder);
|
||||
isize, expected_remainder, cipher_block_size);
|
||||
|
||||
if (encrypting)
|
||||
ret = gnutls_aead_cipher_encrypt (acipher,
|
||||
vdata, vsize,
|
||||
aead_auth_data, aead_auth_size,
|
||||
gnutls_cipher_get_tag_size (gca),
|
||||
idata, isize,
|
||||
storage, &storage_length);
|
||||
else
|
||||
ret = gnutls_aead_cipher_decrypt (acipher,
|
||||
vdata, vsize,
|
||||
aead_auth_data, aead_auth_size,
|
||||
gnutls_cipher_get_tag_size (gca),
|
||||
idata, isize,
|
||||
storage, &storage_length);
|
||||
ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
|
||||
(acipher, vdata, vsize, aead_auth_data, aead_auth_size,
|
||||
cipher_tag_size, idata, isize, storage, &storage_length));
|
||||
|
||||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
memset (storage, 0, storage_length);
|
||||
SAFE_FREE ();
|
||||
gnutls_aead_cipher_deinit (acipher);
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS AEAD cipher %s %sion failed: %s",
|
||||
gnutls_cipher_get_name (gca), desc, str);
|
||||
gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
|
||||
}
|
||||
|
||||
gnutls_aead_cipher_deinit (acipher);
|
||||
|
||||
Lisp_Object output = make_unibyte_string ((const char *)storage, storage_length);
|
||||
Lisp_Object output = make_unibyte_string (storage, storage_length);
|
||||
memset (storage, 0, storage_length);
|
||||
SAFE_FREE ();
|
||||
return list2 (output, actual_iv);
|
||||
#else
|
||||
error ("GnuTLS AEAD cipher %ld was invalid or not found", (long) gca);
|
||||
printmax_t print_gca = gca;
|
||||
error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1980,9 +1961,7 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
|
|||
CHECK_CONS (iv);
|
||||
|
||||
|
||||
const char* desc = (encrypting ? "encrypt" : "decrypt");
|
||||
|
||||
int ret = GNUTLS_E_SUCCESS;
|
||||
const char *desc = encrypting ? "encrypt" : "decrypt";
|
||||
|
||||
gnutls_cipher_algorithm_t gca = GNUTLS_CIPHER_UNKNOWN;
|
||||
|
||||
|
|
@ -1992,7 +1971,7 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
|
|||
|
||||
if (SYMBOLP (cipher))
|
||||
info = XCDR (Fassq (cipher, Fgnutls_ciphers ()));
|
||||
else if (INTEGERP (cipher))
|
||||
else if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, cipher))
|
||||
gca = XINT (cipher);
|
||||
else
|
||||
info = cipher;
|
||||
|
|
@ -2000,41 +1979,44 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
|
|||
if (!NILP (info) && CONSP (info))
|
||||
{
|
||||
Lisp_Object v = Fplist_get (info, QCcipher_id);
|
||||
if (INTEGERP (v))
|
||||
if (TYPE_RANGED_INTEGERP (gnutls_cipher_algorithm_t, v))
|
||||
gca = XINT (v);
|
||||
}
|
||||
|
||||
if (gca == GNUTLS_CIPHER_UNKNOWN)
|
||||
error ("GnuTLS cipher was invalid or not found");
|
||||
ptrdiff_t key_size = gnutls_cipher_get_key_size (gca);
|
||||
if (key_size == 0)
|
||||
error ("GnuTLS cipher is invalid or not found");
|
||||
|
||||
ptrdiff_t kstart_byte, kend_byte;
|
||||
const char* kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
|
||||
const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
|
||||
|
||||
if (kdata == NULL)
|
||||
error ("GnuTLS cipher key extraction failed");
|
||||
|
||||
if ((kend_byte - kstart_byte) != gnutls_cipher_get_key_size (gca))
|
||||
error ("GnuTLS cipher %s/%s key length %" pD "d was not equal to "
|
||||
"the required %ld",
|
||||
if (kend_byte - kstart_byte != key_size)
|
||||
error (("GnuTLS cipher %s/%s key length %"pD"d is not equal to "
|
||||
"the required %"pD"d"),
|
||||
gnutls_cipher_get_name (gca), desc,
|
||||
kend_byte - kstart_byte, (long) gnutls_cipher_get_key_size (gca));
|
||||
kend_byte - kstart_byte, key_size);
|
||||
|
||||
ptrdiff_t vstart_byte, vend_byte;
|
||||
const char* vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
|
||||
char *vdata = extract_data_from_object (iv, &vstart_byte, &vend_byte);
|
||||
|
||||
if (vdata == NULL)
|
||||
error ("GnuTLS cipher IV extraction failed");
|
||||
|
||||
if ((vend_byte - vstart_byte) != gnutls_cipher_get_iv_size (gca))
|
||||
error ("GnuTLS cipher %s/%s IV length %" pD "d was not equal to "
|
||||
"the required %ld",
|
||||
ptrdiff_t iv_size = gnutls_cipher_get_iv_size (gca);
|
||||
if (vend_byte - vstart_byte != iv_size)
|
||||
error (("GnuTLS cipher %s/%s IV length %"pD"d is not equal to "
|
||||
"the required %"pD"d"),
|
||||
gnutls_cipher_get_name (gca), desc,
|
||||
vend_byte - vstart_byte, (long) gnutls_cipher_get_iv_size (gca));
|
||||
vend_byte - vstart_byte, iv_size);
|
||||
|
||||
Lisp_Object actual_iv = make_unibyte_string (vdata, vend_byte - vstart_byte);
|
||||
|
||||
ptrdiff_t istart_byte, iend_byte;
|
||||
const char* idata = extract_data_from_object (input, &istart_byte, &iend_byte);
|
||||
const char *idata
|
||||
= extract_data_from_object (input, &istart_byte, &iend_byte);
|
||||
|
||||
if (idata == NULL)
|
||||
error ("GnuTLS cipher input extraction failed");
|
||||
|
|
@ -2053,44 +2035,34 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
|
|||
return aead_output;
|
||||
}
|
||||
|
||||
if ((iend_byte - istart_byte) % gnutls_cipher_get_block_size (gca) != 0)
|
||||
error ("GnuTLS cipher %s/%s input block length %" pD "d was not a multiple "
|
||||
"of the required %ld",
|
||||
ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
|
||||
if ((iend_byte - istart_byte) % cipher_block_size != 0)
|
||||
error (("GnuTLS cipher %s/%s input block length %"pD"d is not a multiple "
|
||||
"of the required %"pD"d"),
|
||||
gnutls_cipher_get_name (gca), desc,
|
||||
iend_byte - istart_byte, (long) gnutls_cipher_get_block_size (gca));
|
||||
iend_byte - istart_byte, cipher_block_size);
|
||||
|
||||
gnutls_cipher_hd_t hcipher;
|
||||
gnutls_datum_t key_datum = { (unsigned char*) kdata, kend_byte - kstart_byte };
|
||||
gnutls_datum_t key_datum
|
||||
= { (unsigned char *) kdata, kend_byte - kstart_byte };
|
||||
|
||||
ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
|
||||
int ret = gnutls_cipher_init (&hcipher, gca, &key_datum, NULL);
|
||||
|
||||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS cipher %s/%s initialization failed: %s",
|
||||
gnutls_cipher_get_name (gca), desc, str);
|
||||
}
|
||||
error ("GnuTLS cipher %s/%s initialization failed: %s",
|
||||
gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
|
||||
|
||||
/* Note that this will not support streaming block mode. */
|
||||
gnutls_cipher_set_iv (hcipher, (void*) vdata, vend_byte - vstart_byte);
|
||||
gnutls_cipher_set_iv (hcipher, vdata, vend_byte - vstart_byte);
|
||||
|
||||
/*
|
||||
* GnuTLS docs: "For the supported ciphers the encrypted data length
|
||||
* will equal the plaintext size."
|
||||
*/
|
||||
size_t storage_length = iend_byte - istart_byte;
|
||||
/* GnuTLS docs: "For the supported ciphers the encrypted data length
|
||||
will equal the plaintext size." */
|
||||
ptrdiff_t storage_length = iend_byte - istart_byte;
|
||||
Lisp_Object storage = make_uninit_string (storage_length);
|
||||
|
||||
if (encrypting)
|
||||
ret = gnutls_cipher_encrypt2 (hcipher,
|
||||
idata, iend_byte - istart_byte,
|
||||
SSDATA (storage), storage_length);
|
||||
else
|
||||
ret = gnutls_cipher_decrypt2 (hcipher,
|
||||
idata, iend_byte - istart_byte,
|
||||
SSDATA (storage), storage_length);
|
||||
ret = ((encrypting ? gnutls_cipher_encrypt2 : gnutls_cipher_decrypt2)
|
||||
(hcipher, idata, iend_byte - istart_byte,
|
||||
SSDATA (storage), storage_length));
|
||||
|
||||
if (STRINGP (XCAR (key)))
|
||||
Fclear_string (XCAR (key));
|
||||
|
|
@ -2098,11 +2070,8 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
|
|||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
gnutls_cipher_deinit (hcipher);
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS cipher %s %sion failed: %s",
|
||||
gnutls_cipher_get_name (gca), desc, str);
|
||||
gnutls_cipher_get_name (gca), desc, emacs_gnutls_strerror (ret));
|
||||
}
|
||||
|
||||
gnutls_cipher_deinit (hcipher);
|
||||
|
|
@ -2110,41 +2079,46 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher,
|
|||
return list2 (storage, actual_iv);
|
||||
}
|
||||
|
||||
DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt, Sgnutls_symmetric_encrypt, 4, 5, 0,
|
||||
DEFUN ("gnutls-symmetric-encrypt", Fgnutls_symmetric_encrypt,
|
||||
Sgnutls_symmetric_encrypt, 4, 5, 0,
|
||||
doc: /* Encrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
|
||||
|
||||
Returns nil on error.
|
||||
Return nil on error.
|
||||
|
||||
The KEY can be specified as a buffer or string or in other ways
|
||||
(see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY will be
|
||||
wiped after use if it's a string.
|
||||
The KEY can be specified as a buffer or string or in other ways (see
|
||||
Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
|
||||
will be wiped after use if it's a string.
|
||||
|
||||
The IV and INPUT and the optional AEAD_AUTH can be
|
||||
specified as a buffer or string or in other ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
|
||||
The IV and INPUT and the optional AEAD_AUTH can be specified as a
|
||||
buffer or string or in other ways (see Info node `(elisp)Format of
|
||||
GnuTLS Cryptography Inputs').
|
||||
|
||||
The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
|
||||
The CIPHER may be a string or symbol matching a key in that alist, or
|
||||
a plist with the `:cipher-id' numeric property, or the number itself.
|
||||
a plist with the :cipher-id numeric property, or the number itself.
|
||||
|
||||
AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
|
||||
:cipher-aead-capable set to t. AEAD_AUTH can be supplied for
|
||||
these AEAD ciphers, but it may still be omitted (nil) as well. */)
|
||||
(Lisp_Object cipher, Lisp_Object key, Lisp_Object iv, Lisp_Object input, Lisp_Object aead_auth)
|
||||
(Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
|
||||
Lisp_Object input, Lisp_Object aead_auth)
|
||||
{
|
||||
return gnutls_symmetric (true, cipher, key, iv, input, aead_auth);
|
||||
}
|
||||
|
||||
DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt, Sgnutls_symmetric_decrypt, 4, 5, 0,
|
||||
DEFUN ("gnutls-symmetric-decrypt", Fgnutls_symmetric_decrypt,
|
||||
Sgnutls_symmetric_decrypt, 4, 5, 0,
|
||||
doc: /* Decrypt INPUT with symmetric CIPHER, KEY+AEAD_AUTH, and IV to a unibyte string.
|
||||
|
||||
Returns nil on error.
|
||||
Return nil on error.
|
||||
|
||||
The KEY can be specified as a buffer or string or in other ways
|
||||
(see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY will be
|
||||
wiped after use if it's a string.
|
||||
The KEY can be specified as a buffer or string or in other ways (see
|
||||
Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
|
||||
will be wiped after use if it's a string.
|
||||
|
||||
The IV and INPUT and the optional AEAD_AUTH can be
|
||||
specified as a buffer or string or in other ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
|
||||
The IV and INPUT and the optional AEAD_AUTH can be specified as a
|
||||
buffer or string or in other ways (see Info node `(elisp)Format of
|
||||
GnuTLS Cryptography Inputs').
|
||||
|
||||
The alist of symmetric ciphers can be obtained with `gnutls-ciphers`.
|
||||
The 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.
|
|||
AEAD ciphers: these ciphers will have a `gnutls-ciphers' entry with
|
||||
:cipher-aead-capable set to t. AEAD_AUTH can be supplied for
|
||||
these AEAD ciphers, but it may still be omitted (nil) as well. */)
|
||||
(Lisp_Object cipher, Lisp_Object key, Lisp_Object iv, Lisp_Object input, Lisp_Object aead_auth)
|
||||
(Lisp_Object cipher, Lisp_Object key, Lisp_Object iv,
|
||||
Lisp_Object input, Lisp_Object aead_auth)
|
||||
{
|
||||
return gnutls_symmetric (false, cipher, key, iv, input, aead_auth);
|
||||
}
|
||||
|
|
@ -2164,32 +2139,26 @@ DEFUN ("gnutls-macs", Fgnutls_macs, Sgnutls_macs, 0, 0, 0,
|
|||
Use the value of the alist (extract it with `alist-get' for instance)
|
||||
with `gnutls-hash-mac'. The alist key is the mac-algorithm method
|
||||
name. */)
|
||||
(void)
|
||||
(void)
|
||||
{
|
||||
Lisp_Object mac_algorithms = Qnil;
|
||||
const gnutls_mac_algorithm_t* macs = gnutls_mac_list ();
|
||||
for (size_t pos = 0; macs[pos] != 0; pos++)
|
||||
const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
|
||||
for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
|
||||
{
|
||||
const gnutls_mac_algorithm_t gma = macs[pos];
|
||||
|
||||
const char* name = gnutls_mac_get_name (gma);
|
||||
const char *name = gnutls_mac_get_name (gma);
|
||||
|
||||
Lisp_Object mp = listn (CONSTYPE_HEAP, 11, intern (name),
|
||||
QCmac_algorithm_id, make_number (gma),
|
||||
QCtype, Qgnutls_type_mac_algorithm,
|
||||
|
||||
Lisp_Object mp = listn (CONSTYPE_HEAP, 11,
|
||||
/* A symbol representing the mac-algorithm. */
|
||||
intern (name),
|
||||
/* The internally meaningful mac-algorithm ID. */
|
||||
QCmac_algorithm_id,
|
||||
make_number (gma),
|
||||
/* The type (vs. other GnuTLS objects). */
|
||||
QCtype,
|
||||
Qgnutls_type_mac_algorithm,
|
||||
/* The output length. */
|
||||
QCmac_algorithm_length,
|
||||
make_number (gnutls_hmac_get_len (gma)),
|
||||
/* The key size. */
|
||||
|
||||
QCmac_algorithm_keysize,
|
||||
make_number (gnutls_mac_get_key_size (gma)),
|
||||
/* The nonce size. */
|
||||
|
||||
QCmac_algorithm_noncesize,
|
||||
make_number (gnutls_mac_get_nonce_size (gma)));
|
||||
mac_algorithms = Fcons (mp, mac_algorithms);
|
||||
|
|
@ -2204,25 +2173,20 @@ DEFUN ("gnutls-digests", Fgnutls_digests, Sgnutls_digests, 0, 0, 0,
|
|||
Use the value of the alist (extract it with `alist-get' for instance)
|
||||
with `gnutls-hash-digest'. The alist key is the digest-algorithm
|
||||
method name. */)
|
||||
(void)
|
||||
(void)
|
||||
{
|
||||
Lisp_Object digest_algorithms = Qnil;
|
||||
const gnutls_digest_algorithm_t* digests = gnutls_digest_list ();
|
||||
for (size_t pos = 0; digests[pos] != 0; pos++)
|
||||
const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
|
||||
for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
|
||||
{
|
||||
const gnutls_digest_algorithm_t gda = digests[pos];
|
||||
|
||||
const char* name = gnutls_digest_get_name (gda);
|
||||
const char *name = gnutls_digest_get_name (gda);
|
||||
|
||||
Lisp_Object mp = listn (CONSTYPE_HEAP, 7, intern (name),
|
||||
QCdigest_algorithm_id, make_number (gda),
|
||||
QCtype, Qgnutls_type_digest_algorithm,
|
||||
|
||||
Lisp_Object mp = listn (CONSTYPE_HEAP, 7,
|
||||
/* A symbol representing the digest-algorithm. */
|
||||
intern (name),
|
||||
/* The internally meaningful digest-algorithm ID. */
|
||||
QCdigest_algorithm_id,
|
||||
make_number (gda),
|
||||
QCtype,
|
||||
Qgnutls_type_digest_algorithm,
|
||||
/* The digest length. */
|
||||
QCdigest_algorithm_length,
|
||||
make_number (gnutls_hash_get_len (gda)));
|
||||
|
||||
|
|
@ -2235,11 +2199,11 @@ method name. */)
|
|||
DEFUN ("gnutls-hash-mac", Fgnutls_hash_mac, Sgnutls_hash_mac, 3, 3, 0,
|
||||
doc: /* Hash INPUT with HASH-METHOD and KEY into a unibyte string.
|
||||
|
||||
Returns nil on error.
|
||||
Return nil on error.
|
||||
|
||||
The KEY can be specified as a buffer or string or in other ways
|
||||
(see Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY will be
|
||||
wiped after use if it's a string.
|
||||
The KEY can be specified as a buffer or string or in other ways (see
|
||||
Info node `(elisp)Format of GnuTLS Cryptography Inputs'). The KEY
|
||||
will be wiped after use if it's a string.
|
||||
|
||||
The INPUT can be specified as a buffer or string or in other
|
||||
ways (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
|
|||
HASH-METHOD may be a string or symbol matching a key in that alist, or
|
||||
a plist with the `:mac-algorithm-id' numeric property, or the number
|
||||
itself. */)
|
||||
(Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
|
||||
(Lisp_Object hash_method, Lisp_Object key, Lisp_Object input)
|
||||
{
|
||||
if (BUFFERP (input) || STRINGP (input))
|
||||
input = list1 (input);
|
||||
|
|
@ -2260,8 +2224,6 @@ itself. */)
|
|||
|
||||
CHECK_CONS (key);
|
||||
|
||||
int ret = GNUTLS_E_SUCCESS;
|
||||
|
||||
gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
|
||||
|
||||
Lisp_Object info = Qnil;
|
||||
|
|
@ -2270,7 +2232,7 @@ itself. */)
|
|||
|
||||
if (SYMBOLP (hash_method))
|
||||
info = XCDR (Fassq (hash_method, Fgnutls_macs ()));
|
||||
else if (INTEGERP (hash_method))
|
||||
else if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, hash_method))
|
||||
gma = XINT (hash_method);
|
||||
else
|
||||
info = hash_method;
|
||||
|
|
@ -2278,37 +2240,32 @@ itself. */)
|
|||
if (!NILP (info) && CONSP (info))
|
||||
{
|
||||
Lisp_Object v = Fplist_get (info, QCmac_algorithm_id);
|
||||
if (INTEGERP (v))
|
||||
if (TYPE_RANGED_INTEGERP (gnutls_mac_algorithm_t, v))
|
||||
gma = XINT (v);
|
||||
}
|
||||
|
||||
if (gma == GNUTLS_MAC_UNKNOWN)
|
||||
error ("GnuTLS MAC-method was invalid or not found");
|
||||
ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
|
||||
if (digest_length == 0)
|
||||
error ("GnuTLS MAC-method is invalid or not found");
|
||||
|
||||
ptrdiff_t kstart_byte, kend_byte;
|
||||
const char* kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
|
||||
gnutls_hmac_hd_t hmac;
|
||||
ret = gnutls_hmac_init (&hmac, gma,
|
||||
kdata + kstart_byte, kend_byte - kstart_byte);
|
||||
|
||||
const char *kdata = extract_data_from_object (key, &kstart_byte, &kend_byte);
|
||||
if (kdata == NULL)
|
||||
error ("GnuTLS MAC key extraction failed");
|
||||
|
||||
gnutls_hmac_hd_t hmac;
|
||||
int ret = gnutls_hmac_init (&hmac, gma,
|
||||
kdata + kstart_byte, kend_byte - kstart_byte);
|
||||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS MAC %s initialization failed: %s",
|
||||
gnutls_mac_get_name (gma), str);
|
||||
}
|
||||
error ("GnuTLS MAC %s initialization failed: %s",
|
||||
gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
|
||||
|
||||
ptrdiff_t istart_byte, iend_byte;
|
||||
const char* idata = extract_data_from_object (input, &istart_byte, &iend_byte);
|
||||
const char *idata
|
||||
= extract_data_from_object (input, &istart_byte, &iend_byte);
|
||||
if (idata == NULL)
|
||||
error ("GnuTLS MAC input extraction failed");
|
||||
|
||||
size_t digest_length = gnutls_hmac_get_len (gma);
|
||||
Lisp_Object digest = make_uninit_string (digest_length);
|
||||
|
||||
ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
|
||||
|
|
@ -2319,12 +2276,8 @@ itself. */)
|
|||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
gnutls_hmac_deinit (hmac, NULL);
|
||||
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS MAC %s application failed: %s",
|
||||
gnutls_mac_get_name (gma), str);
|
||||
gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
|
||||
}
|
||||
|
||||
gnutls_hmac_output (hmac, SSDATA (digest));
|
||||
|
|
@ -2336,7 +2289,7 @@ itself. */)
|
|||
DEFUN ("gnutls-hash-digest", Fgnutls_hash_digest, Sgnutls_hash_digest, 2, 2, 0,
|
||||
doc: /* Digest INPUT with DIGEST-METHOD into a unibyte string.
|
||||
|
||||
Returns nil on error.
|
||||
Return nil on error.
|
||||
|
||||
The INPUT can be specified as a buffer or string or in other
|
||||
ways (see Info node `(elisp)Format of GnuTLS Cryptography Inputs').
|
||||
|
|
@ -2345,15 +2298,13 @@ The alist of digest algorithms can be obtained with `gnutls-digests`.
|
|||
The DIGEST-METHOD may be a string or symbol matching a key in that
|
||||
alist, or a plist with the `:digest-algorithm-id' numeric property, or
|
||||
the number itself. */)
|
||||
(Lisp_Object digest_method, Lisp_Object input)
|
||||
(Lisp_Object digest_method, Lisp_Object input)
|
||||
{
|
||||
if (BUFFERP (input) || STRINGP (input))
|
||||
input = list1 (input);
|
||||
|
||||
CHECK_CONS (input);
|
||||
|
||||
int ret = GNUTLS_E_SUCCESS;
|
||||
|
||||
gnutls_digest_algorithm_t gda = GNUTLS_DIG_UNKNOWN;
|
||||
|
||||
Lisp_Object info = Qnil;
|
||||
|
|
@ -2362,7 +2313,7 @@ the number itself. */)
|
|||
|
||||
if (SYMBOLP (digest_method))
|
||||
info = XCDR (Fassq (digest_method, Fgnutls_digests ()));
|
||||
else if (INTEGERP (digest_method))
|
||||
else if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, digest_method))
|
||||
gda = XINT (digest_method);
|
||||
else
|
||||
info = digest_method;
|
||||
|
|
@ -2370,29 +2321,26 @@ the number itself. */)
|
|||
if (!NILP (info) && CONSP (info))
|
||||
{
|
||||
Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id);
|
||||
if (INTEGERP (v))
|
||||
if (TYPE_RANGED_INTEGERP (gnutls_digest_algorithm_t, v))
|
||||
gda = XINT (v);
|
||||
}
|
||||
|
||||
if (gda == GNUTLS_DIG_UNKNOWN)
|
||||
error ("GnuTLS digest-method was invalid or not found");
|
||||
ptrdiff_t digest_length = gnutls_hash_get_len (gda);
|
||||
if (digest_length == 0)
|
||||
error ("GnuTLS digest-method is invalid or not found");
|
||||
|
||||
gnutls_hash_hd_t hash;
|
||||
ret = gnutls_hash_init (&hash, gda);
|
||||
int ret = gnutls_hash_init (&hash, gda);
|
||||
|
||||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS digest initialization failed: %s", str);
|
||||
}
|
||||
error ("GnuTLS digest initialization failed: %s",
|
||||
emacs_gnutls_strerror (ret));
|
||||
|
||||
size_t digest_length = gnutls_hash_get_len (gda);
|
||||
Lisp_Object digest = make_uninit_string (digest_length);
|
||||
|
||||
ptrdiff_t istart_byte, iend_byte;
|
||||
const char* idata = extract_data_from_object (input, &istart_byte, &iend_byte);
|
||||
const char *idata
|
||||
= extract_data_from_object (input, &istart_byte, &iend_byte);
|
||||
if (idata == NULL)
|
||||
error ("GnuTLS digest input extraction failed");
|
||||
|
||||
|
|
@ -2401,11 +2349,8 @@ the number itself. */)
|
|||
if (ret < GNUTLS_E_SUCCESS)
|
||||
{
|
||||
gnutls_hash_deinit (hash, NULL);
|
||||
|
||||
const char* str = gnutls_strerror (ret);
|
||||
if (!str)
|
||||
str = "unknown";
|
||||
error ("GnuTLS digest application failed: %s", str);
|
||||
error ("GnuTLS digest application failed: %s",
|
||||
emacs_gnutls_strerror (ret));
|
||||
}
|
||||
|
||||
gnutls_hash_output (hash, SSDATA (digest));
|
||||
|
|
@ -2420,57 +2365,51 @@ DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
|
|||
doc: /* Return list of capabilities if GnuTLS is available in this instance of Emacs.
|
||||
|
||||
...if supported : then...
|
||||
GnuTLS 3 or higher : the list will contain 'gnutls3.
|
||||
GnuTLS MACs : the list will contain 'macs.
|
||||
GnuTLS digests : the list will contain 'digests.
|
||||
GnuTLS symmetric ciphers: the list will contain 'ciphers.
|
||||
GnuTLS AEAD ciphers : the list will contain 'AEAD-ciphers. */)
|
||||
(void)
|
||||
GnuTLS 3 or higher : the list will contain `gnutls3'.
|
||||
GnuTLS MACs : the list will contain `macs'.
|
||||
GnuTLS digests : the list will contain `digests'.
|
||||
GnuTLS symmetric ciphers: the list will contain `ciphers'.
|
||||
GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'. */)
|
||||
(void)
|
||||
{
|
||||
#ifdef HAVE_GNUTLS
|
||||
Lisp_Object capabilities = Qnil;
|
||||
|
||||
#ifdef HAVE_GNUTLS3
|
||||
|
||||
capabilities = Fcons (intern("gnutls3"), capabilities);
|
||||
|
||||
#ifdef HAVE_GNUTLS3_DIGEST
|
||||
capabilities = Fcons (intern("digests"), capabilities);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GNUTLS3_CIPHER
|
||||
capabilities = Fcons (intern("ciphers"), capabilities);
|
||||
|
||||
#ifdef HAVE_GNUTLS3_AEAD
|
||||
capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GNUTLS3_HMAC
|
||||
capabilities = Fcons (intern("macs"), capabilities);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
# ifdef WINDOWSNT
|
||||
#ifdef WINDOWSNT
|
||||
Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
|
||||
if (CONSP (found))
|
||||
return XCDR (found); // TODO: use capabilities.
|
||||
return XCDR (found); /* TODO: use capabilities. */
|
||||
else
|
||||
{
|
||||
Lisp_Object status;
|
||||
// TODO: should the capabilities be dynamic here?
|
||||
/* TODO: should the capabilities be dynamic here? */
|
||||
status = init_gnutls_functions () ? capabilities : Qnil;
|
||||
Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
|
||||
return status;
|
||||
}
|
||||
# else /* !WINDOWSNT */
|
||||
#else
|
||||
|
||||
Lisp_Object capabilities = Qnil;
|
||||
|
||||
# ifdef HAVE_GNUTLS3
|
||||
capabilities = Fcons (intern("gnutls3"), capabilities);
|
||||
|
||||
# ifdef HAVE_GNUTLS3_DIGEST
|
||||
capabilities = Fcons (intern("digests"), capabilities);
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_GNUTLS3_CIPHER
|
||||
capabilities = Fcons (intern("ciphers"), capabilities);
|
||||
|
||||
# ifdef HAVE_GNUTLS3_AEAD
|
||||
capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_GNUTLS3_HMAC
|
||||
capabilities = Fcons (intern("macs"), capabilities);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
return capabilities;
|
||||
# endif /* !WINDOWSNT */
|
||||
#else /* !HAVE_GNUTLS */
|
||||
return Qnil;
|
||||
#endif /* !HAVE_GNUTLS */
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -3386,9 +3386,7 @@ enum { NEXT_ALMOST_PRIME_LIMIT = 11 };
|
|||
extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST;
|
||||
extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t);
|
||||
extern void sweep_weak_hash_tables (void);
|
||||
extern const char* extract_data_from_object (Lisp_Object spec,
|
||||
ptrdiff_t *start_byte,
|
||||
ptrdiff_t *end_byte);
|
||||
extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *);
|
||||
EMACS_UINT hash_string (char const *, ptrdiff_t);
|
||||
EMACS_UINT sxhash (Lisp_Object, int);
|
||||
Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue