+2020-11-26 Niels Möller <nisse@lysator.liu.se>
+
+ Enable powerpc64 gcm code in fat builds. Based on patch
+ contributed by Mamone Tarsha:
+ * powerpc64/fat/gcm-hash.asm: New file.
+ * configure.ac: Add HAVE_NATIVE_fat_gcm_init_key and
+ HAVE_NATIVE_fat_gcm_hash.
+ * gcm.c (gcm_init_key): Renamed, to ...
+ (_nettle_gcm_init_key_c): ... new name. Add fat setup conditionals.
+ (gcm_hash): Renamed, to...
+ (_nettle_gcm_hash_c): ... new name. Add fat setup conditionals.
+ * fat-setup.h (gcm_init_key_func, gcm_hash_func): New typedefs.
+ * fat-ppc.c: Select implementations of _nettle_gcm_init_key and _nettle_gcm_hash.
+ * gcm-internal.h: New file.
+ * Makefile.in (DISTFILES): Add gcm-internal.h.
+
2020-10-21 Niels Möller <nisse@lysator.liu.se>
* ecc-secp384r1.c (ecc_secp384r1_inv): New function, modular
nettle.pc.in hogweed.pc.in \
desdata.stamp $(des_headers) descore.README \
aes-internal.h block-internal.h blowfish-internal.h camellia-internal.h \
- gost28147-internal.h poly1305-internal.h serpent-internal.h \
- cast128_sboxes.h desinfo.h desCode.h \
+ gcm-internal.h gost28147-internal.h poly1305-internal.h \
+ serpent-internal.h cast128_sboxes.h desinfo.h desCode.h \
ripemd160-internal.h sha2-internal.h \
memxor-internal.h nettle-internal.h nettle-write.h \
ctr-internal.h chacha-internal.h sha3-internal.h \
#undef HAVE_NATIVE_ecc_secp521r1_modp
#undef HAVE_NATIVE_ecc_secp521r1_redc
#undef HAVE_NATIVE_gcm_init_key
+#undef HAVE_NATIVE_fat_gcm_init_key
#undef HAVE_NATIVE_gcm_hash
+#undef HAVE_NATIVE_fat_gcm_hash
#undef HAVE_NATIVE_gcm_hash8
#undef HAVE_NATIVE_salsa20_core
#undef HAVE_NATIVE_salsa20_2core
#include "aes-internal.h"
#include "gcm.h"
+#include "gcm-internal.h"
#include "fat-setup.h"
/* Defines from arch/powerpc/include/uapi/asm/cputable.h in Linux kernel */
{
#if defined(_AIX)
features->have_crypto_ext
- = _system_configuration.implementation >= 0x10000u;
+ = _system_configuration.implementation >= 0x10000u;
features->have_altivec = _system_configuration.vmx_version > 1;
#else
unsigned long hwcap = 0;
DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, c)
DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, ppc64)
+#if GCM_TABLE_BITS == 8
+DECLARE_FAT_FUNC(_nettle_gcm_init_key, gcm_init_key_func)
+DECLARE_FAT_FUNC_VAR(gcm_init_key, gcm_init_key_func, c)
+DECLARE_FAT_FUNC_VAR(gcm_init_key, gcm_init_key_func, ppc64)
+
+DECLARE_FAT_FUNC(_nettle_gcm_hash, gcm_hash_func)
+DECLARE_FAT_FUNC_VAR(gcm_hash, gcm_hash_func, c)
+DECLARE_FAT_FUNC_VAR(gcm_hash, gcm_hash_func, ppc64)
+#endif /* GCM_TABLE_BITS == 8 */
+
DECLARE_FAT_FUNC(_nettle_chacha_core, chacha_core_func)
DECLARE_FAT_FUNC_VAR(chacha_core, chacha_core_func, c);
DECLARE_FAT_FUNC_VAR(chacha_core, chacha_core_func, altivec);
fprintf (stderr, "libnettle: enabling arch 2.07 code.\n");
_nettle_aes_encrypt_vec = _nettle_aes_encrypt_ppc64;
_nettle_aes_decrypt_vec = _nettle_aes_decrypt_ppc64;
+#if GCM_TABLE_BITS == 8
+ /* Make sure _nettle_gcm_init_key_vec function is compatible
+ with _nettle_gcm_hash_vec function e.g. _nettle_gcm_init_key_c()
+ fills gcm_key table with values that are incompatible with
+ _nettle_gcm_hash_ppc64() */
+ _nettle_gcm_init_key_vec = _nettle_gcm_init_key_ppc64;
+ _nettle_gcm_hash_vec = _nettle_gcm_hash_ppc64;
+#endif /* GCM_TABLE_BITS == 8 */
}
else
{
_nettle_aes_encrypt_vec = _nettle_aes_encrypt_c;
_nettle_aes_decrypt_vec = _nettle_aes_decrypt_c;
+#if GCM_TABLE_BITS == 8
+ _nettle_gcm_init_key_vec = _nettle_gcm_init_key_c;
+ _nettle_gcm_hash_vec = _nettle_gcm_hash_c;
+#endif /* GCM_TABLE_BITS == 8 */
}
if (features.have_altivec)
{
const uint8_t *src),
(rounds, keys, T, length, dst, src))
+#if GCM_TABLE_BITS == 8
+DEFINE_FAT_FUNC(_nettle_gcm_init_key, void,
+ (union nettle_block16 *table),
+ (table))
+
+DEFINE_FAT_FUNC(_nettle_gcm_hash, void,
+ (const struct gcm_key *key, union nettle_block16 *x,
+ size_t length, const uint8_t *data),
+ (key, x, length, data))
+#endif /* GCM_TABLE_BITS == 8 */
+
DEFINE_FAT_FUNC(_nettle_chacha_core, void,
(uint32_t *dst, const uint32_t *src, unsigned rounds),
(dst, src, rounds))
size_t length, uint8_t *dst,
const uint8_t *src);
+typedef void gcm_init_key_func (union nettle_block16 *table);
+
+typedef void gcm_hash_func (const struct gcm_key *key, union nettle_block16 *x,
+ size_t length, const uint8_t *data);
+
typedef void *(memxor_func)(void *dst, const void *src, size_t n);
typedef void salsa20_core_func (uint32_t *dst, const uint32_t *src, unsigned rounds);
--- /dev/null
+/* gcm-internal.h
+
+ Copyright (C) 2020 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it 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.
+
+ GNU Nettle 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 copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_GCM_INTERNAL_H_INCLUDED
+#define NETTLE_GCM_INTERNAL_H_INCLUDED
+
+/* Functions available only in some configurations */
+#if HAVE_NATIVE_fat_gcm_init_key
+void
+_nettle_gcm_init_key (union nettle_block16 *table);
+
+void
+_nettle_gcm_init_key_c (union nettle_block16 *table);
+#endif
+
+#if HAVE_NATIVE_fat_gcm_hash
+void
+_nettle_gcm_hash(const struct gcm_key *key, union nettle_block16 *x,
+ size_t length, const uint8_t *data);
+void
+_nettle_gcm_hash_c (const struct gcm_key *key, union nettle_block16 *x,
+ size_t length, const uint8_t *data);
+#endif
+
+#endif /* NETTLE_GCM_INTERNAL_H_INCLUDED */
#include "gcm.h"
+#include "gcm-internal.h"
#include "memxor.h"
#include "nettle-internal.h"
#include "macros.h"
#include "ctr-internal.h"
#include "block-internal.h"
-#if GCM_TABLE_BITS == 0
+#if GCM_TABLE_BITS != 8
+/* The native implementations (currently ppc64 only) depend on the
+ GCM_TABLE_BITS == 8 layout */
+#undef HAVE_NATIVE_gcm_hash
+#undef HAVE_NATIVE_gcm_init_key
+#undef HAVE_NATIVE_fat_gcm_hash
+#undef HAVE_NATIVE_fat_gcm_init_key
+#endif
+
+#if !HAVE_NATIVE_gcm_hash
+# if GCM_TABLE_BITS == 0
/* Sets x <- x * y mod r, using the plain bitwise algorithm from the
specification. y may be shorter than a full block, missing bytes
are assumed zero. */
}
memcpy (x->b, Z.b, sizeof(Z));
}
-#else /* GCM_TABLE_BITS != 0 */
+# else /* GCM_TABLE_BITS != 0 */
-# if WORDS_BIGENDIAN
-# define W(left,right) (0x##left##right)
-# else
-# define W(left,right) (0x##right##left)
-# endif
+# if WORDS_BIGENDIAN
+# define W(left,right) (0x##left##right)
+# else
+# define W(left,right) (0x##right##left)
+# endif
-# if GCM_TABLE_BITS == 4
+# if GCM_TABLE_BITS == 4
static const uint16_t
shift_table[0x10] = {
W(00,00),W(1c,20),W(38,40),W(24,60),W(70,80),W(6c,a0),W(48,c0),W(54,e0),
u64[1] = (u64[1] >> 4) | ((u64[0] & 0xf) << 60);
u64[0] = (u64[0] >> 4) ^ (reduce << 48);
#else /* ! WORDS_BIGENDIAN */
-#define RSHIFT_WORD_4(x) \
+# define RSHIFT_WORD_4(x) \
((((x) & UINT64_C(0xf0f0f0f0f0f0f0f0)) >> 4) \
| (((x) & UINT64_C(0x000f0f0f0f0f0f0f)) << 12))
reduce = shift_table[(u64[1] >> 56) & 0xf];
}
memcpy (x->b, Z.b, sizeof(Z));
}
-# elif GCM_TABLE_BITS == 8
-# if HAVE_NATIVE_gcm_init_key
-# define gcm_init_key _nettle_gcm_init_key
-void
-_nettle_gcm_init_key (union nettle_block16 *table);
-# endif /* HAVE_NATIVE_gcm_init_key */
-
-# if HAVE_NATIVE_gcm_hash
-# define gcm_hash _nettle_gcm_hash
-void
-_nettle_gcm_hash (const struct gcm_key *key, union nettle_block16 *x,
- size_t length, const uint8_t *data);
-# else /* !HAVE_NATIVE_gcm_hash */
-
+# elif GCM_TABLE_BITS == 8
# if HAVE_NATIVE_gcm_hash8
#define gcm_hash _nettle_gcm_hash8
block16_xor3(x, &Z, &table[x->b[0]]);
}
# endif /* ! HAVE_NATIVE_gcm_hash8 */
-# endif /* !HAVE_NATIVE_gcm_hash */
-# else /* GCM_TABLE_BITS != 8 */
-# error Unsupported table size.
-# endif /* GCM_TABLE_BITS != 8 */
+# else /* GCM_TABLE_BITS != 8 */
+# error Unsupported table size.
+# endif /* GCM_TABLE_BITS != 8 */
-#undef W
+# undef W
+# endif /* GCM_TABLE_BITS != 0 */
+#endif /* !HAVE_NATIVE_gcm_hash */
-#endif /* GCM_TABLE_BITS */
/* Increment the rightmost 32 bits. */
#define INC32(block) INCREMENT(4, (block.b) + GCM_BLOCK_SIZE - 4)
-#ifndef gcm_init_key
-static void
-gcm_init_key(union nettle_block16 *table)
+#if !HAVE_NATIVE_gcm_init_key
+# if !HAVE_NATIVE_fat_gcm_hash
+# define _nettle_gcm_init_key _nettle_gcm_init_key_c
+static
+# endif
+void
+_nettle_gcm_init_key_c(union nettle_block16 *table)
{
#if GCM_TABLE_BITS
/* Middle element if GCM_TABLE_BITS > 0, otherwise the first
}
#endif
}
-#endif /* !gcm_init_key */
+#endif /* !HAVE_NATIVE_gcm_init_key */
/* Initialization of GCM.
* @ctx: The context of GCM
/* H */
memset(key->h[0].b, 0, GCM_BLOCK_SIZE);
f (cipher, GCM_BLOCK_SIZE, key->h[i].b, key->h[0].b);
-
- gcm_init_key(key->h);
+
+ _nettle_gcm_init_key(key->h);
}
-#ifndef gcm_hash
-static void
-gcm_hash(const struct gcm_key *key, union nettle_block16 *x,
- size_t length, const uint8_t *data)
+#if !(HAVE_NATIVE_gcm_hash || HAVE_NATIVE_gcm_hash8)
+# if !HAVE_NATIVE_fat_gcm_hash
+# define _nettle_gcm_hash _nettle_gcm_hash_c
+static
+# endif
+void
+_nettle_gcm_hash_c(const struct gcm_key *key, union nettle_block16 *x,
+ size_t length, const uint8_t *data)
{
for (; length >= GCM_BLOCK_SIZE;
length -= GCM_BLOCK_SIZE, data += GCM_BLOCK_SIZE)
gcm_gf_mul (x, key->h);
}
}
-#endif /* !gcm_hash */
+#endif /* !(HAVE_NATIVE_gcm_hash || HAVE_NATIVE_gcm_hash8) */
static void
gcm_hash_sizes(const struct gcm_key *key, union nettle_block16 *x,
WRITE_UINT64 (buffer, auth_size);
WRITE_UINT64 (buffer + 8, data_size);
- gcm_hash(key, x, GCM_BLOCK_SIZE, buffer);
+ _nettle_gcm_hash(key, x, GCM_BLOCK_SIZE, buffer);
}
/* NOTE: The key is needed only if length != GCM_IV_SIZE */
else
{
memset(ctx->iv.b, 0, GCM_BLOCK_SIZE);
- gcm_hash(key, &ctx->iv, length, iv);
+ _nettle_gcm_hash(key, &ctx->iv, length, iv);
gcm_hash_sizes(key, &ctx->iv, 0, length);
}
assert(ctx->auth_size % GCM_BLOCK_SIZE == 0);
assert(ctx->data_size == 0);
- gcm_hash(key, &ctx->x, length, data);
+ _nettle_gcm_hash(key, &ctx->x, length, data);
ctx->auth_size += length;
}
assert(ctx->data_size % GCM_BLOCK_SIZE == 0);
_ctr_crypt16(cipher, f, gcm_fill, ctx->ctr.b, length, dst, src);
- gcm_hash(key, &ctx->x, length, dst);
+ _nettle_gcm_hash(key, &ctx->x, length, dst);
ctx->data_size += length;
}
{
assert(ctx->data_size % GCM_BLOCK_SIZE == 0);
- gcm_hash(key, &ctx->x, length, src);
+ _nettle_gcm_hash(key, &ctx->x, length, src);
_ctr_crypt16(cipher, f, gcm_fill, ctx->ctr.b, length, dst, src);
ctx->data_size += length;
--- /dev/null
+C powerpc64/fat/gcm-hash.asm
+
+
+ifelse(`
+ Copyright (C) 2020 Mamone Tarsha
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it 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.
+
+ GNU Nettle 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 copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+')
+
+dnl picked up by configure
+dnl PROLOGUE(_nettle_fat_gcm_init_key)
+dnl PROLOGUE(_nettle_fat_gcm_hash)
+
+define(`fat_transform', `$1_ppc64')
+include_src(`powerpc64/p8/gcm-hash.asm')