aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2024-03-29 06:26:42 +0000
committerNIIBE Yutaka <[email protected]>2024-03-29 06:26:42 +0000
commit1fa24e2841dda0b9f7661909077955b0eb96e560 (patch)
tree080181f6a7b622a2135a478aba82aabc4ed0462c
parentgpgsm: Allow to add extensions at the --gen-key prompt. (diff)
downloadgnupg-1fa24e2841dda0b9f7661909077955b0eb96e560.tar.gz
gnupg-1fa24e2841dda0b9f7661909077955b0eb96e560.zip
common: Add KMAC.
* common/Makefile.am (common_sources): Add kmac.c. * common/kmac.c: New. * common/util.h (compute_kmac256): New. -- Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--common/Makefile.am4
-rw-r--r--common/kmac.c132
-rw-r--r--common/util.h6
3 files changed, 140 insertions, 2 deletions
diff --git a/common/Makefile.am b/common/Makefile.am
index d27603f96..e4dcf8ad6 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -97,8 +97,8 @@ common_sources = \
openpgp-fpr.c \
comopt.c comopt.h \
compliance.c compliance.h \
- pkscreening.c pkscreening.h
-
+ pkscreening.c pkscreening.h \
+ kmac.c
if HAVE_W32_SYSTEM
common_sources += w32-reg.c w32-cmdline.c
diff --git a/common/kmac.c b/common/kmac.c
new file mode 100644
index 000000000..8e9a87204
--- /dev/null
+++ b/common/kmac.c
@@ -0,0 +1,132 @@
+/* kmac.c - Keccak based MAC
+ * Copyright (C) 2024 g10 Code GmbH.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute and/or modify this
+ * part of GnuPG under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * GnuPG 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
+ * General Public License for more details.
+ *
+ * You should have received a copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gpg-error.h>
+#include <gcrypt.h>
+#include "mischelp.h"
+
+#define KECCAK512_BLOCKSIZE 136
+gpg_error_t
+compute_kmac256 (void *digest, size_t digestlen,
+ const void *key, size_t keylen,
+ const void *custom, size_t customlen,
+ gcry_buffer_t *data_iov, int data_iovlen)
+{
+ gpg_error_t err;
+ gcry_buffer_t iov[20];
+ const unsigned char headPAD[2] = { 1, KECCAK512_BLOCKSIZE };
+ unsigned char headK[3];
+ const unsigned char pad[KECCAK512_BLOCKSIZE] = { 0 };
+ unsigned char right_encode_L[3];
+ unsigned int len;
+ int iovcnt;
+
+ if (data_iovlen >= DIM(iov) - 6)
+ return gpg_error (GPG_ERR_TOO_LARGE);
+
+ /* Check the validity conditions of NIST SP 800-185 */
+ if (keylen >= 255 || customlen >= 255 || digestlen >= 255)
+ return gpg_error (GPG_ERR_TOO_LARGE);
+
+ iovcnt = 0;
+ iov[iovcnt].data = "KMAC";
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = 4;
+ iovcnt++;
+
+ iov[iovcnt].data = (void *)custom;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = customlen;
+ iovcnt++;
+
+ iov[iovcnt].data = (void *)headPAD;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = sizeof (headPAD);
+ iovcnt++;
+
+ if (keylen < 32)
+ {
+ headK[0] = 1;
+ headK[1] = (keylen*8)&0xff;
+ iov[iovcnt].data = headK;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = 2;
+ }
+ else
+ {
+ headK[0] = 2;
+ headK[1] = (keylen*8)>>8;
+ headK[2] = (keylen*8)&0xff;
+ iov[iovcnt].data = headK;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = 3;
+ }
+ iovcnt++;
+
+ iov[iovcnt].data = (void *)key;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = keylen;
+ iovcnt++;
+
+ len = iov[2].len + iov[3].len + iov[4].len;
+ len %= KECCAK512_BLOCKSIZE;
+
+ iov[iovcnt].data = (unsigned char *)pad;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = sizeof (pad) - len;
+ iovcnt++;
+
+ memcpy (&iov[iovcnt], data_iov, data_iovlen * sizeof (gcry_buffer_t));
+ iovcnt += data_iovlen;
+
+ if (digestlen < 32)
+ {
+ right_encode_L[0] = (digestlen * 8) & 0xff;
+ right_encode_L[1] = 1;
+ }
+ else
+ {
+ right_encode_L[0] = (digestlen * 8) >> 8;
+ right_encode_L[1] = (digestlen * 8) & 0xff;
+ right_encode_L[2] = 2;
+ }
+
+ iov[iovcnt].data = right_encode_L;
+ iov[iovcnt].off = 0;
+ iov[iovcnt].len = 3;
+ iovcnt++;
+
+ err = gcry_md_hash_buffers_ext (GCRY_MD_CSHAKE256, 0,
+ digest, digestlen, iov, iovcnt);
+ return err;
+}
diff --git a/common/util.h b/common/util.h
index 851b392a5..7948b5d82 100644
--- a/common/util.h
+++ b/common/util.h
@@ -299,6 +299,12 @@ char *gnupg_get_help_string (const char *key, int only_current_locale);
/*-- localename.c --*/
const char *gnupg_messages_locale_name (void);
+/*-- kmac.c --*/
+gpg_error_t compute_kmac256 (void *digest, size_t digestlen,
+ const void *key, size_t keylen,
+ const void *custom, size_t customlen,
+ gcry_buffer_t *data_iov, int data_iovlen);
+
/*-- miscellaneous.c --*/
/* This function is called at startup to tell libgcrypt to use our own