Function: gnutls-hash-mac
gnutls-hash-mac is a function defined in gnutls.c.
Signature
(gnutls-hash-mac HASH-METHOD KEY INPUT)
Documentation
Hash INPUT with HASH-METHOD and KEY into a unibyte string.
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 INPUT can also be specified as a buffer or string or in other ways.
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.
Probably introduced at or before Emacs version 26.1.
Source Code
// Defined in /usr/src/emacs/src/gnutls.c
{
if (BUFFERP (input) || STRINGP (input))
input = list1 (input);
CHECK_CONS (input);
if (BUFFERP (key) || STRINGP (key))
key = list1 (key);
CHECK_CONS (key);
gnutls_mac_algorithm_t gma = GNUTLS_MAC_UNKNOWN;
Lisp_Object info = Qnil;
if (STRINGP (hash_method))
hash_method = intern (SSDATA (hash_method));
if (SYMBOLP (hash_method))
{
info = Fassq (hash_method, Fgnutls_macs ());
if (!CONSP (info))
xsignal2 (Qerror,
build_string ("GnuTLS MAC-method is invalid or not found"),
hash_method);
info = XCDR (info);
}
else if (TYPE_RANGED_FIXNUMP (gnutls_mac_algorithm_t, hash_method))
gma = XFIXNUM (hash_method);
else
info = hash_method;
if (!NILP (info) && CONSP (info))
{
Lisp_Object v = plist_get (info, QCmac_algorithm_id);
if (TYPE_RANGED_FIXNUMP (gnutls_mac_algorithm_t, v))
gma = XFIXNUM (v);
}
ptrdiff_t digest_length = gnutls_hmac_get_len (gma);
if (digest_length == 0)
xsignal2 (Qerror,
build_string ("GnuTLS MAC-method is invalid or not found"),
hash_method);
ptrdiff_t kstart_byte, kend_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)
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);
if (idata == NULL)
error ("GnuTLS MAC input extraction failed");
Lisp_Object digest = make_uninit_string (digest_length);
ret = gnutls_hmac (hmac, idata + istart_byte, iend_byte - istart_byte);
if (STRINGP (XCAR (key)))
Fclear_string (XCAR (key));
if (ret < GNUTLS_E_SUCCESS)
{
gnutls_hmac_deinit (hmac, NULL);
error ("GnuTLS MAC %s application failed: %s",
gnutls_mac_get_name (gma), emacs_gnutls_strerror (ret));
}
gnutls_hmac_output (hmac, SSDATA (digest));
gnutls_hmac_deinit (hmac, NULL);
return digest;
}