summary refs log tree commit diff stats
path: root/libotr/libgcrypt-1.8.7/cipher/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'libotr/libgcrypt-1.8.7/cipher/mac.c')
-rw-r--r--libotr/libgcrypt-1.8.7/cipher/mac.c502
1 files changed, 502 insertions, 0 deletions
diff --git a/libotr/libgcrypt-1.8.7/cipher/mac.c b/libotr/libgcrypt-1.8.7/cipher/mac.c
new file mode 100644
index 0000000..46be7b7
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/cipher/mac.c
@@ -0,0 +1,502 @@
+/* mac.c  -  message authentication code dispatcher
+ * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mac-internal.h"
+
+
+/* This is the list of the digest implementations included in
+   libgcrypt.  */
+static gcry_mac_spec_t *mac_list[] = {
+#if USE_SHA1
+  &_gcry_mac_type_spec_hmac_sha1,
+#endif
+#if USE_SHA256
+  &_gcry_mac_type_spec_hmac_sha256,
+  &_gcry_mac_type_spec_hmac_sha224,
+#endif
+#if USE_SHA512
+  &_gcry_mac_type_spec_hmac_sha512,
+  &_gcry_mac_type_spec_hmac_sha384,
+#endif
+#if USE_SHA3
+  &_gcry_mac_type_spec_hmac_sha3_224,
+  &_gcry_mac_type_spec_hmac_sha3_256,
+  &_gcry_mac_type_spec_hmac_sha3_384,
+  &_gcry_mac_type_spec_hmac_sha3_512,
+#endif
+#ifdef USE_GOST_R_3411_94
+  &_gcry_mac_type_spec_hmac_gost3411_94,
+#endif
+#ifdef USE_GOST_R_3411_12
+  &_gcry_mac_type_spec_hmac_stribog256,
+  &_gcry_mac_type_spec_hmac_stribog512,
+#endif
+#if USE_WHIRLPOOL
+  &_gcry_mac_type_spec_hmac_whirlpool,
+#endif
+#if USE_RMD160
+  &_gcry_mac_type_spec_hmac_rmd160,
+#endif
+#if USE_TIGER
+  &_gcry_mac_type_spec_hmac_tiger1,
+#endif
+#if USE_MD5
+  &_gcry_mac_type_spec_hmac_md5,
+#endif
+#if USE_MD4
+  &_gcry_mac_type_spec_hmac_md4,
+#endif
+#if USE_BLOWFISH
+  &_gcry_mac_type_spec_cmac_blowfish,
+#endif
+#if USE_DES
+  &_gcry_mac_type_spec_cmac_tripledes,
+#endif
+#if USE_CAST5
+  &_gcry_mac_type_spec_cmac_cast5,
+#endif
+#if USE_AES
+  &_gcry_mac_type_spec_cmac_aes,
+  &_gcry_mac_type_spec_gmac_aes,
+  &_gcry_mac_type_spec_poly1305mac_aes,
+#endif
+#if USE_TWOFISH
+  &_gcry_mac_type_spec_cmac_twofish,
+  &_gcry_mac_type_spec_gmac_twofish,
+  &_gcry_mac_type_spec_poly1305mac_twofish,
+#endif
+#if USE_SERPENT
+  &_gcry_mac_type_spec_cmac_serpent,
+  &_gcry_mac_type_spec_gmac_serpent,
+  &_gcry_mac_type_spec_poly1305mac_serpent,
+#endif
+#if USE_RFC2268
+  &_gcry_mac_type_spec_cmac_rfc2268,
+#endif
+#if USE_SEED
+  &_gcry_mac_type_spec_cmac_seed,
+  &_gcry_mac_type_spec_gmac_seed,
+  &_gcry_mac_type_spec_poly1305mac_seed,
+#endif
+#if USE_CAMELLIA
+  &_gcry_mac_type_spec_cmac_camellia,
+  &_gcry_mac_type_spec_gmac_camellia,
+  &_gcry_mac_type_spec_poly1305mac_camellia,
+#endif
+#ifdef USE_IDEA
+  &_gcry_mac_type_spec_cmac_idea,
+#endif
+#if USE_GOST28147
+  &_gcry_mac_type_spec_cmac_gost28147,
+#endif
+  &_gcry_mac_type_spec_poly1305mac,
+  NULL,
+};
+
+/* Explicitly initialize this module.  */
+gcry_err_code_t
+_gcry_mac_init (void)
+{
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_mac_spec_t *spec;
+
+      for (idx = 0; (spec = mac_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
+  return 0;
+}
+
+
+/* Return the spec structure for the MAC algorithm ALGO.  For an
+   unknown algorithm NULL is returned.  */
+static gcry_mac_spec_t *
+spec_from_algo (int algo)
+{
+  gcry_mac_spec_t *spec;
+  int idx;
+
+  for (idx = 0; (spec = mac_list[idx]); idx++)
+    if (algo == spec->algo)
+      return spec;
+  return NULL;
+}
+
+
+/* Lookup a mac's spec by its name.  */
+static gcry_mac_spec_t *
+spec_from_name (const char *name)
+{
+  gcry_mac_spec_t *spec;
+  int idx;
+
+  for (idx = 0; (spec = mac_list[idx]); idx++)
+    if (!stricmp (name, spec->name))
+      return spec;
+
+  return NULL;
+}
+
+
+/****************
+ * Map a string to the mac algo
+ */
+int
+_gcry_mac_map_name (const char *string)
+{
+  gcry_mac_spec_t *spec;
+
+  if (!string)
+    return 0;
+
+  /* Not found, search a matching mac name.  */
+  spec = spec_from_name (string);
+  if (spec)
+    return spec->algo;
+
+  return 0;
+}
+
+
+/****************
+ * This function simply returns the name of the algorithm or some constant
+ * string when there is no algo.  It will never return NULL.
+ * Use the macro gcry_mac_test_algo() to check whether the algorithm
+ * is valid.
+ */
+const char *
+_gcry_mac_algo_name (int algorithm)
+{
+  gcry_mac_spec_t *spec;
+
+  spec = spec_from_algo (algorithm);
+  return spec ? spec->name : "?";
+}
+
+
+static gcry_err_code_t
+check_mac_algo (int algorithm)
+{
+  gcry_mac_spec_t *spec;
+
+  spec = spec_from_algo (algorithm);
+  if (spec && !spec->flags.disabled)
+    return 0;
+
+  return GPG_ERR_MAC_ALGO;
+}
+
+
+/****************
+ * Open a message digest handle for use with algorithm ALGO.
+ */
+static gcry_err_code_t
+mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
+{
+  gcry_mac_spec_t *spec;
+  gcry_err_code_t err;
+  gcry_mac_hd_t h;
+
+  spec = spec_from_algo (algo);
+  if (!spec)
+    return GPG_ERR_MAC_ALGO;
+  else if (spec->flags.disabled)
+    return GPG_ERR_MAC_ALGO;
+  else if (!spec->ops)
+    return GPG_ERR_MAC_ALGO;
+  else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey ||
+           !spec->ops->read || !spec->ops->verify || !spec->ops->reset)
+    return GPG_ERR_MAC_ALGO;
+
+  if (secure)
+    h = xtrycalloc_secure (1, sizeof (*h));
+  else
+    h = xtrycalloc (1, sizeof (*h));
+
+  if (!h)
+    return gpg_err_code_from_syserror ();
+
+  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
+  h->spec = spec;
+  h->algo = algo;
+  h->gcry_ctx = ctx;
+
+  err = h->spec->ops->open (h);
+  if (err)
+    xfree (h);
+  else
+    *hd = h;
+
+  return err;
+}
+
+
+static gcry_err_code_t
+mac_reset (gcry_mac_hd_t hd)
+{
+  if (hd->spec->ops->reset)
+    return hd->spec->ops->reset (hd);
+
+  return 0;
+}
+
+
+static void
+mac_close (gcry_mac_hd_t hd)
+{
+  if (hd->spec->ops->close)
+    hd->spec->ops->close (hd);
+
+  wipememory (hd, sizeof (*hd));
+
+  xfree (hd);
+}
+
+
+static gcry_err_code_t
+mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
+{
+  if (!hd->spec->ops->setkey)
+    return GPG_ERR_INV_ARG;
+  if (keylen > 0 && !key)
+    return GPG_ERR_INV_ARG;
+
+  return hd->spec->ops->setkey (hd, key, keylen);
+}
+
+
+static gcry_err_code_t
+mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
+{
+  if (!hd->spec->ops->setiv)
+    return GPG_ERR_INV_ARG;
+  if (ivlen > 0 && !iv)
+    return GPG_ERR_INV_ARG;
+
+  return hd->spec->ops->setiv (hd, iv, ivlen);
+}
+
+
+static gcry_err_code_t
+mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
+{
+  if (!hd->spec->ops->write)
+    return GPG_ERR_INV_ARG;
+  if (inlen > 0 && !inbuf)
+    return GPG_ERR_INV_ARG;
+
+  return hd->spec->ops->write (hd, inbuf, inlen);
+}
+
+
+static gcry_err_code_t
+mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
+{
+  if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read)
+    return GPG_ERR_INV_ARG;
+
+  return hd->spec->ops->read (hd, outbuf, outlen);
+}
+
+
+static gcry_err_code_t
+mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
+{
+  if (!buf || buflen == 0 || !hd->spec->ops->verify)
+    return GPG_ERR_INV_ARG;
+
+  return hd->spec->ops->verify (hd, buf, buflen);
+}
+
+
+/* Create a MAC object for algorithm ALGO.  FLAGS may be
+   given as an bitwise OR of the gcry_mac_flags values.
+   H is guaranteed to be a valid handle or NULL on error.  */
+gpg_err_code_t
+_gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags,
+                gcry_ctx_t ctx)
+{
+  gcry_err_code_t rc;
+  gcry_mac_hd_t hd = NULL;
+
+  if ((flags & ~GCRY_MAC_FLAG_SECURE))
+    rc = GPG_ERR_INV_ARG;
+  else
+    rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx);
+
+  *h = rc ? NULL : hd;
+  return rc;
+}
+
+
+void
+_gcry_mac_close (gcry_mac_hd_t hd)
+{
+  if (hd)
+    mac_close (hd);
+}
+
+
+gcry_err_code_t
+_gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
+{
+  return mac_setkey (hd, key, keylen);
+}
+
+
+gcry_err_code_t
+_gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
+{
+  return mac_setiv (hd, iv, ivlen);
+}
+
+
+gcry_err_code_t
+_gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
+{
+  return mac_write (hd, inbuf, inlen);
+}
+
+
+gcry_err_code_t
+_gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
+{
+  return mac_read (hd, outbuf, outlen);
+}
+
+
+gcry_err_code_t
+_gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
+{
+  return mac_verify (hd, buf, buflen);
+}
+
+
+int
+_gcry_mac_get_algo (gcry_mac_hd_t hd)
+{
+  return hd->algo;
+}
+
+
+unsigned int
+_gcry_mac_get_algo_maclen (int algo)
+{
+  gcry_mac_spec_t *spec;
+
+  spec = spec_from_algo (algo);
+  if (!spec || !spec->ops || !spec->ops->get_maclen)
+    return 0;
+
+  return spec->ops->get_maclen (algo);
+}
+
+
+unsigned int
+_gcry_mac_get_algo_keylen (int algo)
+{
+  gcry_mac_spec_t *spec;
+
+  spec = spec_from_algo (algo);
+  if (!spec || !spec->ops || !spec->ops->get_keylen)
+    return 0;
+
+  return spec->ops->get_keylen (algo);
+}
+
+
+gcry_err_code_t
+_gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen)
+{
+  gcry_err_code_t rc;
+
+  /* Currently not used.  */
+  (void) hd;
+  (void) buffer;
+  (void) buflen;
+
+  switch (cmd)
+    {
+    case GCRYCTL_RESET:
+      rc = mac_reset (hd);
+      break;
+    default:
+      rc = GPG_ERR_INV_OP;
+    }
+  return rc;
+}
+
+
+/* Return information about the given MAC algorithm ALGO.
+
+    GCRYCTL_TEST_ALGO:
+        Returns 0 if the specified algorithm ALGO is available for use.
+        BUFFER and NBYTES must be zero.
+
+   Note: Because this function is in most cases used to return an
+   integer value, we can make it easier for the caller to just look at
+   the return value.  The caller will in all cases consult the value
+   and thereby detecting whether a error occurred or not (i.e. while
+   checking the block size)
+ */
+gcry_err_code_t
+_gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
+{
+  gcry_err_code_t rc = 0;
+  unsigned int ui;
+
+  switch (what)
+    {
+    case GCRYCTL_GET_KEYLEN:
+      if (buffer || (!nbytes))
+        rc = GPG_ERR_INV_ARG;
+      else
+        {
+          ui = _gcry_mac_get_algo_keylen (algo);
+          if (ui > 0)
+            *nbytes = (size_t) ui;
+          else
+            /* The only reason for an error is an invalid algo.  */
+            rc = GPG_ERR_MAC_ALGO;
+        }
+      break;
+    case GCRYCTL_TEST_ALGO:
+      if (buffer || nbytes)
+        rc = GPG_ERR_INV_ARG;
+      else
+        rc = check_mac_algo (algo);
+      break;
+
+    default:
+      rc = GPG_ERR_INV_OP;
+    }
+
+  return rc;
+}