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 <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2024-03-29 15:26:42 +09:00
parent 571a768ac6
commit 1fa24e2841
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
3 changed files with 140 additions and 2 deletions

View File

@ -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

132
common/kmac.c Normal file
View File

@ -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;
}

View File

@ -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