diff --git a/cipher/blake2.c b/cipher/blake2.c index 750c00c3..642c5bfd 100644 --- a/cipher/blake2.c +++ b/cipher/blake2.c @@ -1,986 +1,986 @@ /* blake2.c - BLAKE2b and BLAKE2s hash functions (RFC 7693) * Copyright (C) 2017 Jussi Kivilinna * * 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 . */ /* The code is based on public-domain/CC0 BLAKE2 reference implementation * by Samual Neves, at https://github.com/BLAKE2/BLAKE2/tree/master/ref * Copyright 2012, Samuel Neves */ #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* USE_AVX indicates whether to compile with Intel AVX code. */ #undef USE_AVX #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX 1 #endif /* USE_AVX2 indicates whether to compile with Intel AVX2 code. */ #undef USE_AVX2 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX2 1 #endif /* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #undef ASM_EXTRA_STACK #if defined(USE_AVX2) && defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS) # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16) #else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 #endif #define BLAKE2B_BLOCKBYTES 128 #define BLAKE2B_OUTBYTES 64 #define BLAKE2B_KEYBYTES 64 #define BLAKE2S_BLOCKBYTES 64 #define BLAKE2S_OUTBYTES 32 #define BLAKE2S_KEYBYTES 32 typedef struct { u64 h[8]; u64 t[2]; u64 f[2]; } BLAKE2B_STATE; struct blake2b_param_s { byte digest_length; byte key_length; byte fanout; byte depth; byte leaf_length[4]; byte node_offset[4]; byte xof_length[4]; byte node_depth; byte inner_length; byte reserved[14]; byte salt[16]; byte personal[16]; }; typedef struct BLAKE2B_CONTEXT_S { BLAKE2B_STATE state; byte buf[BLAKE2B_BLOCKBYTES]; size_t buflen; size_t outlen; #ifdef USE_AVX2 unsigned int use_avx2:1; #endif } BLAKE2B_CONTEXT; typedef struct { u32 h[8]; u32 t[2]; u32 f[2]; } BLAKE2S_STATE; struct blake2s_param_s { byte digest_length; byte key_length; byte fanout; byte depth; byte leaf_length[4]; byte node_offset[4]; byte xof_length[2]; byte node_depth; byte inner_length; /* byte reserved[0]; */ byte salt[8]; byte personal[8]; }; typedef struct BLAKE2S_CONTEXT_S { BLAKE2S_STATE state; byte buf[BLAKE2S_BLOCKBYTES]; size_t buflen; size_t outlen; #ifdef USE_AVX unsigned int use_avx:1; #endif } BLAKE2S_CONTEXT; typedef unsigned int (*blake2_transform_t)(void *S, const void *inblk, size_t nblks); static const u64 blake2b_IV[8] = { U64_C(0x6a09e667f3bcc908), U64_C(0xbb67ae8584caa73b), U64_C(0x3c6ef372fe94f82b), U64_C(0xa54ff53a5f1d36f1), U64_C(0x510e527fade682d1), U64_C(0x9b05688c2b3e6c1f), U64_C(0x1f83d9abfb41bd6b), U64_C(0x5be0cd19137e2179) }; static const u32 blake2s_IV[8] = { 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL }; static byte zero_block[BLAKE2B_BLOCKBYTES] = { 0, }; static void blake2_write(void *S, const void *inbuf, size_t inlen, byte *tmpbuf, size_t *tmpbuflen, size_t blkbytes, blake2_transform_t transform_fn) { const byte* in = inbuf; unsigned int burn = 0; if (inlen > 0) { size_t left = *tmpbuflen; size_t fill = blkbytes - left; size_t nblks; if (inlen > fill) { if (fill > 0) buf_cpy (tmpbuf + left, in, fill); /* Fill buffer */ left = 0; burn = transform_fn (S, tmpbuf, 1); /* Increment counter + Compress */ in += fill; inlen -= fill; nblks = inlen / blkbytes - !(inlen % blkbytes); if (nblks) { burn = transform_fn(S, in, nblks); in += blkbytes * nblks; inlen -= blkbytes * nblks; } } gcry_assert (inlen > 0); buf_cpy (tmpbuf + left, in, inlen); *tmpbuflen = left + inlen; } if (burn) _gcry_burn_stack (burn); return; } static inline void blake2b_set_lastblock(BLAKE2B_STATE *S) { S->f[0] = U64_C(0xffffffffffffffff); } static inline int blake2b_is_lastblock(const BLAKE2B_STATE *S) { return S->f[0] != 0; } static inline void blake2b_increment_counter(BLAKE2B_STATE *S, const int inc) { S->t[0] += (u64)inc; S->t[1] += (S->t[0] < (u64)inc) - (inc < 0); } static inline u64 rotr64(u64 x, u64 n) { return ((x >> (n & 63)) | (x << ((64 - n) & 63))); } static unsigned int blake2b_transform_generic(BLAKE2B_STATE *S, const void *inblks, size_t nblks) { static const byte blake2b_sigma[12][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } }; const byte* in = inblks; u64 m[16]; u64 v[16]; while (nblks--) { /* Increment counter */ blake2b_increment_counter (S, BLAKE2B_BLOCKBYTES); /* Compress */ m[0] = buf_get_le64 (in + 0 * sizeof(m[0])); m[1] = buf_get_le64 (in + 1 * sizeof(m[0])); m[2] = buf_get_le64 (in + 2 * sizeof(m[0])); m[3] = buf_get_le64 (in + 3 * sizeof(m[0])); m[4] = buf_get_le64 (in + 4 * sizeof(m[0])); m[5] = buf_get_le64 (in + 5 * sizeof(m[0])); m[6] = buf_get_le64 (in + 6 * sizeof(m[0])); m[7] = buf_get_le64 (in + 7 * sizeof(m[0])); m[8] = buf_get_le64 (in + 8 * sizeof(m[0])); m[9] = buf_get_le64 (in + 9 * sizeof(m[0])); m[10] = buf_get_le64 (in + 10 * sizeof(m[0])); m[11] = buf_get_le64 (in + 11 * sizeof(m[0])); m[12] = buf_get_le64 (in + 12 * sizeof(m[0])); m[13] = buf_get_le64 (in + 13 * sizeof(m[0])); m[14] = buf_get_le64 (in + 14 * sizeof(m[0])); m[15] = buf_get_le64 (in + 15 * sizeof(m[0])); v[ 0] = S->h[0]; v[ 1] = S->h[1]; v[ 2] = S->h[2]; v[ 3] = S->h[3]; v[ 4] = S->h[4]; v[ 5] = S->h[5]; v[ 6] = S->h[6]; v[ 7] = S->h[7]; v[ 8] = blake2b_IV[0]; v[ 9] = blake2b_IV[1]; v[10] = blake2b_IV[2]; v[11] = blake2b_IV[3]; v[12] = blake2b_IV[4] ^ S->t[0]; v[13] = blake2b_IV[5] ^ S->t[1]; v[14] = blake2b_IV[6] ^ S->f[0]; v[15] = blake2b_IV[7] ^ S->f[1]; #define G(r,i,a,b,c,d) \ do { \ a = a + b + m[blake2b_sigma[r][2*i+0]]; \ d = rotr64(d ^ a, 32); \ c = c + d; \ b = rotr64(b ^ c, 24); \ a = a + b + m[blake2b_sigma[r][2*i+1]]; \ d = rotr64(d ^ a, 16); \ c = c + d; \ b = rotr64(b ^ c, 63); \ } while(0) #define ROUND(r) \ do { \ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ G(r,2,v[ 2],v[ 6],v[10],v[14]); \ G(r,3,v[ 3],v[ 7],v[11],v[15]); \ G(r,4,v[ 0],v[ 5],v[10],v[15]); \ G(r,5,v[ 1],v[ 6],v[11],v[12]); \ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ } while(0) ROUND(0); ROUND(1); ROUND(2); ROUND(3); ROUND(4); ROUND(5); ROUND(6); ROUND(7); ROUND(8); ROUND(9); ROUND(10); ROUND(11); #undef G #undef ROUND S->h[0] = S->h[0] ^ v[0] ^ v[0 + 8]; S->h[1] = S->h[1] ^ v[1] ^ v[1 + 8]; S->h[2] = S->h[2] ^ v[2] ^ v[2 + 8]; S->h[3] = S->h[3] ^ v[3] ^ v[3 + 8]; S->h[4] = S->h[4] ^ v[4] ^ v[4 + 8]; S->h[5] = S->h[5] ^ v[5] ^ v[5 + 8]; S->h[6] = S->h[6] ^ v[6] ^ v[6 + 8]; S->h[7] = S->h[7] ^ v[7] ^ v[7 + 8]; in += BLAKE2B_BLOCKBYTES; } return sizeof(void *) * 4 + sizeof(u64) * 16 * 2; } #ifdef USE_AVX2 unsigned int _gcry_blake2b_transform_amd64_avx2(BLAKE2B_STATE *S, const void *inblks, size_t nblks) ASM_FUNC_ABI; #endif static unsigned int blake2b_transform(void *ctx, const void *inblks, size_t nblks) { BLAKE2B_CONTEXT *c = ctx; unsigned int nburn; if (0) {} #ifdef USE_AVX2 if (c->use_avx2) nburn = _gcry_blake2b_transform_amd64_avx2(&c->state, inblks, nblks); #endif else nburn = blake2b_transform_generic(&c->state, inblks, nblks); if (nburn) nburn += ASM_EXTRA_STACK; return nburn; } static void blake2b_final(void *ctx) { BLAKE2B_CONTEXT *c = ctx; BLAKE2B_STATE *S = &c->state; unsigned int burn; size_t i; gcry_assert (sizeof(c->buf) >= c->outlen); if (blake2b_is_lastblock(S)) return; if (c->buflen < BLAKE2B_BLOCKBYTES) memset (c->buf + c->buflen, 0, BLAKE2B_BLOCKBYTES - c->buflen); /* Padding */ blake2b_set_lastblock (S); blake2b_increment_counter (S, (int)c->buflen - BLAKE2B_BLOCKBYTES); burn = blake2b_transform (ctx, c->buf, 1); /* Output full hash to buffer */ for (i = 0; i < 8; ++i) buf_put_le64 (c->buf + sizeof(S->h[i]) * i, S->h[i]); /* Zero out extra buffer bytes. */ if (c->outlen < sizeof(c->buf)) memset (c->buf + c->outlen, 0, sizeof(c->buf) - c->outlen); if (burn) _gcry_burn_stack (burn); } static byte *blake2b_read(void *ctx) { BLAKE2B_CONTEXT *c = ctx; return c->buf; } static void blake2b_write(void *ctx, const void *inbuf, size_t inlen) { BLAKE2B_CONTEXT *c = ctx; BLAKE2B_STATE *S = &c->state; blake2_write(S, inbuf, inlen, c->buf, &c->buflen, BLAKE2B_BLOCKBYTES, blake2b_transform); } static inline void blake2b_init_param(BLAKE2B_STATE *S, const struct blake2b_param_s *P) { const byte *p = (const byte *)P; size_t i; /* init xors IV with input parameter block */ /* IV XOR ParamBlock */ for (i = 0; i < 8; ++i) S->h[i] = blake2b_IV[i] ^ buf_get_le64(p + sizeof(S->h[i]) * i); } static inline gcry_err_code_t blake2b_init(BLAKE2B_CONTEXT *ctx, const byte *key, size_t keylen) { struct blake2b_param_s P[1] = { { 0, } }; BLAKE2B_STATE *S = &ctx->state; if (!ctx->outlen || ctx->outlen > BLAKE2B_OUTBYTES) return GPG_ERR_INV_ARG; if (sizeof(P[0]) != sizeof(u64) * 8) return GPG_ERR_INTERNAL; if (keylen && (!key || keylen > BLAKE2B_KEYBYTES)) return GPG_ERR_INV_KEYLEN; P->digest_length = ctx->outlen; P->key_length = keylen; P->fanout = 1; P->depth = 1; blake2b_init_param (S, P); wipememory (P, sizeof(P)); if (key) { blake2b_write (ctx, key, keylen); blake2b_write (ctx, zero_block, BLAKE2B_BLOCKBYTES - keylen); } return 0; } static gcry_err_code_t blake2b_init_ctx(void *ctx, unsigned int flags, const byte *key, size_t keylen, unsigned int dbits) { BLAKE2B_CONTEXT *c = ctx; unsigned int features = _gcry_get_hw_features (); (void)features; (void)flags; memset (c, 0, sizeof (*c)); #ifdef USE_AVX2 c->use_avx2 = !!(features & HWF_INTEL_AVX2); #endif c->outlen = dbits / 8; c->buflen = 0; return blake2b_init(c, key, keylen); } static inline void blake2s_set_lastblock(BLAKE2S_STATE *S) { S->f[0] = 0xFFFFFFFFUL; } static inline int blake2s_is_lastblock(BLAKE2S_STATE *S) { return S->f[0] != 0; } static inline void blake2s_increment_counter(BLAKE2S_STATE *S, const int inc) { S->t[0] += (u32)inc; S->t[1] += (S->t[0] < (u32)inc) - (inc < 0); } static unsigned int blake2s_transform_generic(BLAKE2S_STATE *S, const void *inblks, size_t nblks) { static const byte blake2s_sigma[10][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, }; unsigned int burn = 0; const byte* in = inblks; u32 m[16]; u32 v[16]; while (nblks--) { /* Increment counter */ blake2s_increment_counter (S, BLAKE2S_BLOCKBYTES); /* Compress */ m[0] = buf_get_le32 (in + 0 * sizeof(m[0])); m[1] = buf_get_le32 (in + 1 * sizeof(m[0])); m[2] = buf_get_le32 (in + 2 * sizeof(m[0])); m[3] = buf_get_le32 (in + 3 * sizeof(m[0])); m[4] = buf_get_le32 (in + 4 * sizeof(m[0])); m[5] = buf_get_le32 (in + 5 * sizeof(m[0])); m[6] = buf_get_le32 (in + 6 * sizeof(m[0])); m[7] = buf_get_le32 (in + 7 * sizeof(m[0])); m[8] = buf_get_le32 (in + 8 * sizeof(m[0])); m[9] = buf_get_le32 (in + 9 * sizeof(m[0])); m[10] = buf_get_le32 (in + 10 * sizeof(m[0])); m[11] = buf_get_le32 (in + 11 * sizeof(m[0])); m[12] = buf_get_le32 (in + 12 * sizeof(m[0])); m[13] = buf_get_le32 (in + 13 * sizeof(m[0])); m[14] = buf_get_le32 (in + 14 * sizeof(m[0])); m[15] = buf_get_le32 (in + 15 * sizeof(m[0])); v[ 0] = S->h[0]; v[ 1] = S->h[1]; v[ 2] = S->h[2]; v[ 3] = S->h[3]; v[ 4] = S->h[4]; v[ 5] = S->h[5]; v[ 6] = S->h[6]; v[ 7] = S->h[7]; v[ 8] = blake2s_IV[0]; v[ 9] = blake2s_IV[1]; v[10] = blake2s_IV[2]; v[11] = blake2s_IV[3]; v[12] = S->t[0] ^ blake2s_IV[4]; v[13] = S->t[1] ^ blake2s_IV[5]; v[14] = S->f[0] ^ blake2s_IV[6]; v[15] = S->f[1] ^ blake2s_IV[7]; #define G(r,i,a,b,c,d) \ do { \ a = a + b + m[blake2s_sigma[r][2*i+0]]; \ d = ror(d ^ a, 16); \ c = c + d; \ b = ror(b ^ c, 12); \ a = a + b + m[blake2s_sigma[r][2*i+1]]; \ d = ror(d ^ a, 8); \ c = c + d; \ b = ror(b ^ c, 7); \ } while(0) #define ROUND(r) \ do { \ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ G(r,2,v[ 2],v[ 6],v[10],v[14]); \ G(r,3,v[ 3],v[ 7],v[11],v[15]); \ G(r,4,v[ 0],v[ 5],v[10],v[15]); \ G(r,5,v[ 1],v[ 6],v[11],v[12]); \ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ } while(0) ROUND(0); ROUND(1); ROUND(2); ROUND(3); ROUND(4); ROUND(5); ROUND(6); ROUND(7); ROUND(8); ROUND(9); #undef G #undef ROUND S->h[0] = S->h[0] ^ v[0] ^ v[0 + 8]; S->h[1] = S->h[1] ^ v[1] ^ v[1 + 8]; S->h[2] = S->h[2] ^ v[2] ^ v[2 + 8]; S->h[3] = S->h[3] ^ v[3] ^ v[3 + 8]; S->h[4] = S->h[4] ^ v[4] ^ v[4 + 8]; S->h[5] = S->h[5] ^ v[5] ^ v[5 + 8]; S->h[6] = S->h[6] ^ v[6] ^ v[6 + 8]; S->h[7] = S->h[7] ^ v[7] ^ v[7 + 8]; in += BLAKE2S_BLOCKBYTES; } return burn; } #ifdef USE_AVX unsigned int _gcry_blake2s_transform_amd64_avx(BLAKE2S_STATE *S, const void *inblks, size_t nblks) ASM_FUNC_ABI; #endif static unsigned int blake2s_transform(void *ctx, const void *inblks, size_t nblks) { BLAKE2S_CONTEXT *c = ctx; unsigned int nburn; if (0) {} #ifdef USE_AVX if (c->use_avx) nburn = _gcry_blake2s_transform_amd64_avx(&c->state, inblks, nblks); #endif else nburn = blake2s_transform_generic(&c->state, inblks, nblks); if (nburn) nburn += ASM_EXTRA_STACK; return nburn; } static void blake2s_final(void *ctx) { BLAKE2S_CONTEXT *c = ctx; BLAKE2S_STATE *S = &c->state; unsigned int burn; size_t i; gcry_assert (sizeof(c->buf) >= c->outlen); if (blake2s_is_lastblock(S)) return; if (c->buflen < BLAKE2S_BLOCKBYTES) memset (c->buf + c->buflen, 0, BLAKE2S_BLOCKBYTES - c->buflen); /* Padding */ blake2s_set_lastblock (S); blake2s_increment_counter (S, (int)c->buflen - BLAKE2S_BLOCKBYTES); burn = blake2s_transform (ctx, c->buf, 1); /* Output full hash to buffer */ for (i = 0; i < 8; ++i) buf_put_le32 (c->buf + sizeof(S->h[i]) * i, S->h[i]); /* Zero out extra buffer bytes. */ if (c->outlen < sizeof(c->buf)) memset (c->buf + c->outlen, 0, sizeof(c->buf) - c->outlen); if (burn) _gcry_burn_stack (burn); } static byte *blake2s_read(void *ctx) { BLAKE2S_CONTEXT *c = ctx; return c->buf; } static void blake2s_write(void *ctx, const void *inbuf, size_t inlen) { BLAKE2S_CONTEXT *c = ctx; BLAKE2S_STATE *S = &c->state; blake2_write(S, inbuf, inlen, c->buf, &c->buflen, BLAKE2S_BLOCKBYTES, blake2s_transform); } static inline void blake2s_init_param(BLAKE2S_STATE *S, const struct blake2s_param_s *P) { const byte *p = (const byte *)P; size_t i; /* init2 xors IV with input parameter block */ /* IV XOR ParamBlock */ for (i = 0; i < 8; ++i) S->h[i] ^= blake2s_IV[i] ^ buf_get_le32(&p[i * 4]); } static inline gcry_err_code_t blake2s_init(BLAKE2S_CONTEXT *ctx, const byte *key, size_t keylen) { struct blake2s_param_s P[1] = { { 0, } }; BLAKE2S_STATE *S = &ctx->state; if (!ctx->outlen || ctx->outlen > BLAKE2S_OUTBYTES) return GPG_ERR_INV_ARG; if (sizeof(P[0]) != sizeof(u32) * 8) return GPG_ERR_INTERNAL; if (keylen && (!key || keylen > BLAKE2S_KEYBYTES)) return GPG_ERR_INV_KEYLEN; P->digest_length = ctx->outlen; P->key_length = keylen; P->fanout = 1; P->depth = 1; blake2s_init_param (S, P); wipememory (P, sizeof(P)); if (key) { blake2s_write (ctx, key, keylen); blake2s_write (ctx, zero_block, BLAKE2S_BLOCKBYTES - keylen); } return 0; } static gcry_err_code_t blake2s_init_ctx(void *ctx, unsigned int flags, const byte *key, size_t keylen, unsigned int dbits) { BLAKE2S_CONTEXT *c = ctx; unsigned int features = _gcry_get_hw_features (); (void)features; (void)flags; memset (c, 0, sizeof (*c)); #ifdef USE_AVX c->use_avx = !!(features & HWF_INTEL_AVX); #endif c->outlen = dbits / 8; c->buflen = 0; return blake2s_init(c, key, keylen); } /* Selftests from "RFC 7693, Appendix E. BLAKE2b and BLAKE2s Self-Test * Module C Source". */ static void selftest_seq(byte *out, size_t len, u32 seed) { size_t i; u32 t, a, b; a = 0xDEAD4BAD * seed; b = 1; for (i = 0; i < len; i++) { t = a + b; a = b; b = t; out[i] = (t >> 24) & 0xFF; } } static gpg_err_code_t selftests_blake2b (int algo, int extended, selftest_report_func_t report) { static const byte blake2b_res[32] = { 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75 }; static const size_t b2b_md_len[4] = { 20, 32, 48, 64 }; static const size_t b2b_in_len[6] = { 0, 3, 128, 129, 255, 1024 }; size_t i, j, outlen, inlen; byte in[1024], key[64]; BLAKE2B_CONTEXT ctx; BLAKE2B_CONTEXT ctx2; const char *what; const char *errtxt; (void)extended; what = "rfc7693 BLAKE2b selftest"; /* 256-bit hash for testing */ if (blake2b_init_ctx(&ctx, 0, NULL, 0, 32 * 8)) { errtxt = "init failed"; goto failed; } for (i = 0; i < 4; i++) { outlen = b2b_md_len[i]; for (j = 0; j < 6; j++) { inlen = b2b_in_len[j]; selftest_seq(in, inlen, inlen); /* unkeyed hash */ blake2b_init_ctx(&ctx2, 0, NULL, 0, outlen * 8); blake2b_write(&ctx2, in, inlen); blake2b_final(&ctx2); blake2b_write(&ctx, ctx2.buf, outlen); /* hash the hash */ selftest_seq(key, outlen, outlen); /* keyed hash */ blake2b_init_ctx(&ctx2, 0, key, outlen, outlen * 8); blake2b_write(&ctx2, in, inlen); blake2b_final(&ctx2); blake2b_write(&ctx, ctx2.buf, outlen); /* hash the hash */ } } /* compute and compare the hash of hashes */ blake2b_final(&ctx); for (i = 0; i < 32; i++) { if (ctx.buf[i] != blake2b_res[i]) { errtxt = "digest mismatch"; goto failed; } } return 0; failed: if (report) report ("digest", algo, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_blake2s (int algo, int extended, selftest_report_func_t report) { static const byte blake2s_res[32] = { 0x6A, 0x41, 0x1F, 0x08, 0xCE, 0x25, 0xAD, 0xCD, 0xFB, 0x02, 0xAB, 0xA6, 0x41, 0x45, 0x1C, 0xEC, 0x53, 0xC5, 0x98, 0xB2, 0x4F, 0x4F, 0xC7, 0x87, 0xFB, 0xDC, 0x88, 0x79, 0x7F, 0x4C, 0x1D, 0xFE }; static const size_t b2s_md_len[4] = { 16, 20, 28, 32 }; static const size_t b2s_in_len[6] = { 0, 3, 64, 65, 255, 1024 }; size_t i, j, outlen, inlen; byte in[1024], key[32]; BLAKE2S_CONTEXT ctx; BLAKE2S_CONTEXT ctx2; const char *what; const char *errtxt; (void)extended; what = "rfc7693 BLAKE2s selftest"; /* 256-bit hash for testing */ if (blake2s_init_ctx(&ctx, 0, NULL, 0, 32 * 8)) { errtxt = "init failed"; goto failed; } for (i = 0; i < 4; i++) { outlen = b2s_md_len[i]; for (j = 0; j < 6; j++) { inlen = b2s_in_len[j]; selftest_seq(in, inlen, inlen); /* unkeyed hash */ blake2s_init_ctx(&ctx2, 0, NULL, 0, outlen * 8); blake2s_write(&ctx2, in, inlen); blake2s_final(&ctx2); blake2s_write(&ctx, ctx2.buf, outlen); /* hash the hash */ selftest_seq(key, outlen, outlen); /* keyed hash */ blake2s_init_ctx(&ctx2, 0, key, outlen, outlen * 8); blake2s_write(&ctx2, in, inlen); blake2s_final(&ctx2); blake2s_write(&ctx, ctx2.buf, outlen); /* hash the hash */ } } /* compute and compare the hash of hashes */ blake2s_final(&ctx); for (i = 0; i < 32; i++) { if (ctx.buf[i] != blake2s_res[i]) { errtxt = "digest mismatch"; goto failed; } } return 0; failed: if (report) report ("digest", algo, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags, const unsigned char *key, size_t keylen, int algo) { gcry_err_code_t rc; switch (algo) { case GCRY_MD_BLAKE2B_512: rc = blake2b_init_ctx (ctx, flags, key, keylen, 512); break; case GCRY_MD_BLAKE2B_384: rc = blake2b_init_ctx (ctx, flags, key, keylen, 384); break; case GCRY_MD_BLAKE2B_256: rc = blake2b_init_ctx (ctx, flags, key, keylen, 256); break; case GCRY_MD_BLAKE2B_160: rc = blake2b_init_ctx (ctx, flags, key, keylen, 160); break; case GCRY_MD_BLAKE2S_256: rc = blake2s_init_ctx (ctx, flags, key, keylen, 256); break; case GCRY_MD_BLAKE2S_224: rc = blake2s_init_ctx (ctx, flags, key, keylen, 224); break; case GCRY_MD_BLAKE2S_160: rc = blake2s_init_ctx (ctx, flags, key, keylen, 160); break; case GCRY_MD_BLAKE2S_128: rc = blake2s_init_ctx (ctx, flags, key, keylen, 128); break; default: rc = GPG_ERR_DIGEST_ALGO; break; } return rc; } #define DEFINE_BLAKE2_VARIANT(bs, BS, dbits, oid_branch) \ static void blake2##bs##_##dbits##_init(void *ctx, unsigned int flags) \ { \ int err = blake2##bs##_init_ctx (ctx, flags, NULL, 0, dbits); \ gcry_assert (err == 0); \ } \ static void \ _gcry_blake2##bs##_##dbits##_hash_buffers(void *outbuf, size_t nbytes, \ const gcry_buffer_t *iov, int iovcnt) \ { \ BLAKE2##BS##_CONTEXT hd; \ (void)nbytes; \ blake2##bs##_##dbits##_init (&hd, 0); \ for (;iovcnt > 0; iov++, iovcnt--) \ blake2##bs##_write (&hd, (const char*)iov[0].data + iov[0].off, \ iov[0].len); \ blake2##bs##_final (&hd); \ memcpy (outbuf, blake2##bs##_read (&hd), dbits / 8); \ } \ - static byte blake2##bs##_##dbits##_asn[] = { 0x30 }; \ - static gcry_md_oid_spec_t oid_spec_blake2##bs##_##dbits[] = \ + static const byte blake2##bs##_##dbits##_asn[] = { 0x30 }; \ + static const gcry_md_oid_spec_t oid_spec_blake2##bs##_##dbits[] = \ { \ { " 1.3.6.1.4.1.1722.12.2." oid_branch }, \ { NULL } \ }; \ - gcry_md_spec_t _gcry_digest_spec_blake2##bs##_##dbits = \ + const gcry_md_spec_t _gcry_digest_spec_blake2##bs##_##dbits = \ { \ GCRY_MD_BLAKE2##BS##_##dbits, {0, 0}, \ "BLAKE2" #BS "_" #dbits, blake2##bs##_##dbits##_asn, \ DIM (blake2##bs##_##dbits##_asn), oid_spec_blake2##bs##_##dbits, \ dbits / 8, blake2##bs##_##dbits##_init, blake2##bs##_write, \ blake2##bs##_final, blake2##bs##_read, NULL, \ _gcry_blake2##bs##_##dbits##_hash_buffers, \ sizeof (BLAKE2##BS##_CONTEXT), selftests_blake2##bs \ }; DEFINE_BLAKE2_VARIANT(b, B, 512, "1.16") DEFINE_BLAKE2_VARIANT(b, B, 384, "1.12") DEFINE_BLAKE2_VARIANT(b, B, 256, "1.8") DEFINE_BLAKE2_VARIANT(b, B, 160, "1.5") DEFINE_BLAKE2_VARIANT(s, S, 256, "2.8") DEFINE_BLAKE2_VARIANT(s, S, 224, "2.7") DEFINE_BLAKE2_VARIANT(s, S, 160, "2.5") DEFINE_BLAKE2_VARIANT(s, S, 128, "2.4") diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 23cbec81..72c02d77 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -1,1195 +1,1195 @@ /* camellia-glue.c - Glue for the Camellia cipher * Copyright (C) 2007 Free Software Foundation, Inc. * * 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 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ /* I put all the libgcrypt-specific stuff in this file to keep the camellia.c/camellia.h files exactly as provided by NTT. If they update their code, this should make it easier to bring the changes in. - dshaw There is one small change which needs to be done: Include the following code at the top of camellia.h: */ #if 0 /* To use Camellia with libraries it is often useful to keep the name * space of the library clean. The following macro is thus useful: * * #define CAMELLIA_EXT_SYM_PREFIX foo_ * * This prefixes all external symbols with "foo_". */ #ifdef HAVE_CONFIG_H #include #endif #ifdef CAMELLIA_EXT_SYM_PREFIX #define CAMELLIA_PREFIX1(x,y) x ## y #define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y) #define CAMELLIA_PREFIX(x) CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x) #define Camellia_Ekeygen CAMELLIA_PREFIX(Camellia_Ekeygen) #define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock) #define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock) #define camellia_decrypt128 CAMELLIA_PREFIX(camellia_decrypt128) #define camellia_decrypt256 CAMELLIA_PREFIX(camellia_decrypt256) #define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) #define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) #define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) #define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) #define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) #endif /*CAMELLIA_EXT_SYM_PREFIX*/ #endif /* Code sample. */ #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "camellia.h" #include "bufhelp.h" #include "cipher-internal.h" #include "cipher-selftest.h" /* Helper macro to force alignment to 16 bytes. */ #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED # define ATTR_ALIGNED_16 __attribute__ ((aligned (16))) #else # define ATTR_ALIGNED_16 #endif /* USE_AESNI inidicates whether to compile with Intel AES-NI/AVX code. */ #undef USE_AESNI_AVX #if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT) # if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AESNI_AVX 1 # endif #endif /* USE_AESNI_AVX2 inidicates whether to compile with Intel AES-NI/AVX2 code. */ #undef USE_AESNI_AVX2 #if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) # if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AESNI_AVX2 1 # endif #endif /* USE_VAES_AVX2 inidicates whether to compile with Intel VAES/AVX2 code. */ #undef USE_VAES_AVX2 #if defined(USE_AESNI_AVX2) && defined(HAVE_GCC_INLINE_ASM_VAES_VPCLMUL) # define USE_VAES_AVX2 1 #endif typedef struct { KEY_TABLE_TYPE keytable; int keybitlength; #ifdef USE_AESNI_AVX unsigned int use_aesni_avx:1; /* AES-NI/AVX implementation shall be used. */ #endif /*USE_AESNI_AVX*/ #ifdef USE_AESNI_AVX2 unsigned int use_aesni_avx2:1;/* AES-NI/AVX2 implementation shall be used. */ unsigned int use_vaes_avx2:1; /* VAES/AVX2 implementation shall be used. */ #endif /*USE_AESNI_AVX2*/ } CAMELLIA_context; /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #undef ASM_EXTRA_STACK #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16) # else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 # endif #endif #ifdef USE_AESNI_AVX /* Assembler implementations of Camellia using AES-NI and AVX. Process data in 16 block same time. */ extern void _gcry_camellia_aesni_avx_ctr_enc(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx_cbc_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx_cfb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx_ocb_enc(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx_ocb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx_ocb_auth(CAMELLIA_context *ctx, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx_keygen(CAMELLIA_context *ctx, const unsigned char *key, unsigned int keylen) ASM_FUNC_ABI; #endif #ifdef USE_AESNI_AVX2 /* Assembler implementations of Camellia using AES-NI and AVX2. Process data in 32 block same time. */ extern void _gcry_camellia_aesni_avx2_ctr_enc(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx2_cbc_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx2_cfb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx2_ocb_enc(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[32]) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx2_ocb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[32]) ASM_FUNC_ABI; extern void _gcry_camellia_aesni_avx2_ocb_auth(CAMELLIA_context *ctx, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[32]) ASM_FUNC_ABI; #endif #ifdef USE_VAES_AVX2 /* Assembler implementations of Camellia using VAES and AVX2. Process data in 32 block same time. */ extern void _gcry_camellia_vaes_avx2_ctr_enc(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr) ASM_FUNC_ABI; extern void _gcry_camellia_vaes_avx2_cbc_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_camellia_vaes_avx2_cfb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_camellia_vaes_avx2_ocb_enc(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[32]) ASM_FUNC_ABI; extern void _gcry_camellia_vaes_avx2_ocb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[32]) ASM_FUNC_ABI; extern void _gcry_camellia_vaes_avx2_ocb_auth(CAMELLIA_context *ctx, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[32]) ASM_FUNC_ABI; #endif static const char *selftest(void); static void _gcry_camellia_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_camellia_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_camellia_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static size_t _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); static size_t _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); static gcry_err_code_t camellia_setkey(void *c, const byte *key, unsigned keylen, cipher_bulk_ops_t *bulk_ops) { CAMELLIA_context *ctx=c; static int initialized=0; static const char *selftest_failed=NULL; #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) || defined(USE_VAES_AVX2) unsigned int hwf = _gcry_get_hw_features (); #endif if(keylen!=16 && keylen!=24 && keylen!=32) return GPG_ERR_INV_KEYLEN; if(!initialized) { initialized=1; selftest_failed=selftest(); if(selftest_failed) log_error("%s\n",selftest_failed); } if(selftest_failed) return GPG_ERR_SELFTEST_FAILED; #ifdef USE_AESNI_AVX ctx->use_aesni_avx = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX); #endif #ifdef USE_AESNI_AVX2 ctx->use_aesni_avx2 = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX2); ctx->use_vaes_avx2 = 0; #endif #ifdef USE_VAES_AVX2 ctx->use_vaes_avx2 = (hwf & HWF_INTEL_VAES_VPCLMUL) && (hwf & HWF_INTEL_AVX2); #endif ctx->keybitlength=keylen*8; /* Setup bulk encryption routines. */ memset (bulk_ops, 0, sizeof(*bulk_ops)); bulk_ops->cbc_dec = _gcry_camellia_cbc_dec; bulk_ops->cfb_dec = _gcry_camellia_cfb_dec; bulk_ops->ctr_enc = _gcry_camellia_ctr_enc; bulk_ops->ocb_crypt = _gcry_camellia_ocb_crypt; bulk_ops->ocb_auth = _gcry_camellia_ocb_auth; if (0) { } #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) _gcry_camellia_aesni_avx_keygen(ctx, key, keylen); else #endif { Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); _gcry_burn_stack ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ +3*2*sizeof(void*) /* Function calls. */ ); } return 0; } #ifdef USE_ARM_ASM /* Assembly implementations of Camellia. */ extern void _gcry_camellia_arm_encrypt_block(const KEY_TABLE_TYPE keyTable, byte *outbuf, const byte *inbuf, const int keybits); extern void _gcry_camellia_arm_decrypt_block(const KEY_TABLE_TYPE keyTable, byte *outbuf, const byte *inbuf, const int keybits); static void Camellia_EncryptBlock(const int keyBitLength, const unsigned char *plaintext, const KEY_TABLE_TYPE keyTable, unsigned char *cipherText) { _gcry_camellia_arm_encrypt_block(keyTable, cipherText, plaintext, keyBitLength); } static void Camellia_DecryptBlock(const int keyBitLength, const unsigned char *cipherText, const KEY_TABLE_TYPE keyTable, unsigned char *plaintext) { _gcry_camellia_arm_decrypt_block(keyTable, plaintext, cipherText, keyBitLength); } #ifdef __aarch64__ # define CAMELLIA_encrypt_stack_burn_size (0) # define CAMELLIA_decrypt_stack_burn_size (0) #else # define CAMELLIA_encrypt_stack_burn_size (15*4) # define CAMELLIA_decrypt_stack_burn_size (15*4) #endif static unsigned int camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx = c; Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size); } static unsigned int camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size); } #else /*USE_ARM_ASM*/ static unsigned int camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); #define CAMELLIA_encrypt_stack_burn_size \ (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \ +4*sizeof(u32)+4*sizeof(u32) \ +2*sizeof(u32*)+4*sizeof(u32) \ +2*2*sizeof(void*) /* Function calls. */ \ ) return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size); } static unsigned int camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) { CAMELLIA_context *ctx=c; Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); #define CAMELLIA_decrypt_stack_burn_size \ (sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \ +4*sizeof(u32)+4*sizeof(u32) \ +2*sizeof(u32*)+4*sizeof(u32) \ +2*2*sizeof(void*) /* Function calls. */ \ ) return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size); } #endif /*!USE_ARM_ASM*/ /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size CAMELLIA_BLOCK_SIZE. */ static void _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[CAMELLIA_BLOCK_SIZE]; int burn_stack_depth = CAMELLIA_encrypt_stack_burn_size; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { int did_use_aesni_avx2 = 0; #ifdef USE_VAES_AVX2 int use_vaes = ctx->use_vaes_avx2; #endif /* Process data in 32 block chunks. */ while (nblocks >= 32) { #ifdef USE_VAES_AVX2 if (use_vaes) _gcry_camellia_vaes_avx2_ctr_enc(ctx, outbuf, inbuf, ctr); else #endif _gcry_camellia_aesni_avx2_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 32; outbuf += 32 * CAMELLIA_BLOCK_SIZE; inbuf += 32 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx2 = 1; } if (did_use_aesni_avx2) { int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { int did_use_aesni_avx = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_camellia_aesni_avx_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 16; outbuf += 16 * CAMELLIA_BLOCK_SIZE; inbuf += 16 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx = 1; } if (did_use_aesni_avx) { int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx_burn_stack_depth) burn_stack_depth = avx_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ cipher_block_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE); outbuf += CAMELLIA_BLOCK_SIZE; inbuf += CAMELLIA_BLOCK_SIZE; /* Increment the counter. */ cipher_block_add(ctr, 1, CAMELLIA_BLOCK_SIZE); } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_camellia_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[CAMELLIA_BLOCK_SIZE]; int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { int did_use_aesni_avx2 = 0; #ifdef USE_VAES_AVX2 int use_vaes = ctx->use_vaes_avx2; #endif /* Process data in 32 block chunks. */ while (nblocks >= 32) { #ifdef USE_VAES_AVX2 if (use_vaes) _gcry_camellia_vaes_avx2_cbc_dec(ctx, outbuf, inbuf, iv); else #endif _gcry_camellia_aesni_avx2_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 32; outbuf += 32 * CAMELLIA_BLOCK_SIZE; inbuf += 32 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx2 = 1; } if (did_use_aesni_avx2) { int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 + 2 * sizeof(void *) + ASM_EXTRA_STACK;; if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { int did_use_aesni_avx = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_camellia_aesni_avx_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * CAMELLIA_BLOCK_SIZE; inbuf += 16 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx = 1; } if (did_use_aesni_avx) { int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx_burn_stack_depth) burn_stack_depth = avx_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* INBUF is needed later and it may be identical to OUTBUF, so store the intermediate result to SAVEBUF. */ Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, savebuf); cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); inbuf += CAMELLIA_BLOCK_SIZE; outbuf += CAMELLIA_BLOCK_SIZE; } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_camellia_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { int did_use_aesni_avx2 = 0; #ifdef USE_VAES_AVX2 int use_vaes = ctx->use_vaes_avx2; #endif /* Process data in 32 block chunks. */ while (nblocks >= 32) { #ifdef USE_VAES_AVX2 if (use_vaes) _gcry_camellia_vaes_avx2_cfb_dec(ctx, outbuf, inbuf, iv); else #endif _gcry_camellia_aesni_avx2_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 32; outbuf += 32 * CAMELLIA_BLOCK_SIZE; inbuf += 32 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx2 = 1; } if (did_use_aesni_avx2) { int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { int did_use_aesni_avx = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_camellia_aesni_avx_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * CAMELLIA_BLOCK_SIZE; inbuf += 16 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx = 1; } if (did_use_aesni_avx) { int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx_burn_stack_depth) burn_stack_depth = avx_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { Camellia_EncryptBlock(ctx->keybitlength, iv, ctx->keytable, iv); cipher_block_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); outbuf += CAMELLIA_BLOCK_SIZE; inbuf += CAMELLIA_BLOCK_SIZE; } _gcry_burn_stack(burn_stack_depth); } /* Bulk encryption/decryption of complete blocks in OCB mode. */ static size_t _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt) { #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) CAMELLIA_context *ctx = (void *)&c->context.c; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth; u64 blkn = c->u_mode.ocb.data_nblocks; burn_stack_depth = encrypt ? CAMELLIA_encrypt_stack_burn_size : CAMELLIA_decrypt_stack_burn_size; #else (void)c; (void)outbuf_arg; (void)inbuf_arg; (void)encrypt; #endif #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { int did_use_aesni_avx2 = 0; #ifdef USE_VAES_AVX2 int encrypt_use_vaes = encrypt && ctx->use_vaes_avx2; int decrypt_use_vaes = !encrypt && ctx->use_vaes_avx2; #endif u64 Ls[32]; unsigned int n = 32 - (blkn % 32); u64 *l; int i; if (nblocks >= 32) { for (i = 0; i < 32; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; Ls[(15 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[4]; Ls[(23 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(31 + n) % 32]; /* Process data in 32 block chunks. */ while (nblocks >= 32) { blkn += 32; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 32); if (0) {} #ifdef USE_VAES_AVX2 else if (encrypt_use_vaes) _gcry_camellia_vaes_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else if (decrypt_use_vaes) _gcry_camellia_vaes_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); #endif else if (encrypt) _gcry_camellia_aesni_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_camellia_aesni_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 32; outbuf += 32 * CAMELLIA_BLOCK_SIZE; inbuf += 32 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx2 = 1; } } if (did_use_aesni_avx2) { int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { int did_use_aesni_avx = 0; u64 Ls[16]; unsigned int n = 16 - (blkn % 16); u64 *l; int i; if (nblocks >= 16) { for (i = 0; i < 16; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(15 + n) % 16]; /* Process data in 16 block chunks. */ while (nblocks >= 16) { blkn += 16; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16); if (encrypt) _gcry_camellia_aesni_avx_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_camellia_aesni_avx_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 16; outbuf += 16 * CAMELLIA_BLOCK_SIZE; inbuf += 16 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx = 1; } } if (did_use_aesni_avx) { int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx_burn_stack_depth) burn_stack_depth = avx_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) c->u_mode.ocb.data_nblocks = blkn; if (burn_stack_depth) _gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *)); #endif return nblocks; } /* Bulk authentication of complete blocks in OCB mode. */ static size_t _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks) { #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) CAMELLIA_context *ctx = (void *)&c->context.c; const unsigned char *abuf = abuf_arg; int burn_stack_depth; u64 blkn = c->u_mode.ocb.aad_nblocks; burn_stack_depth = CAMELLIA_encrypt_stack_burn_size; #else (void)c; (void)abuf_arg; #endif #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { int did_use_aesni_avx2 = 0; #ifdef USE_VAES_AVX2 int use_vaes = ctx->use_vaes_avx2; #endif u64 Ls[32]; unsigned int n = 32 - (blkn % 32); u64 *l; int i; if (nblocks >= 32) { for (i = 0; i < 32; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; Ls[(15 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[4]; Ls[(23 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(31 + n) % 32]; /* Process data in 32 block chunks. */ while (nblocks >= 32) { blkn += 32; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 32); #ifdef USE_VAES_AVX2 if (use_vaes) _gcry_camellia_vaes_avx2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); else #endif _gcry_camellia_aesni_avx2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 32; abuf += 32 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx2 = 1; } } if (did_use_aesni_avx2) { int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx2_burn_stack_depth) burn_stack_depth = avx2_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { int did_use_aesni_avx = 0; u64 Ls[16]; unsigned int n = 16 - (blkn % 16); u64 *l; int i; if (nblocks >= 16) { for (i = 0; i < 16; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(15 + n) % 16]; /* Process data in 16 block chunks. */ while (nblocks >= 16) { blkn += 16; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16); _gcry_camellia_aesni_avx_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 16; abuf += 16 * CAMELLIA_BLOCK_SIZE; did_use_aesni_avx = 1; } } if (did_use_aesni_avx) { int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE + 2 * sizeof(void *) + ASM_EXTRA_STACK; if (burn_stack_depth < avx_burn_stack_depth) burn_stack_depth = avx_burn_stack_depth; } /* Use generic code to handle smaller chunks... */ } #endif #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) c->u_mode.ocb.aad_nblocks = blkn; if (burn_stack_depth) _gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *)); #endif return nblocks; } /* Run the self-tests for CAMELLIA-CTR-128, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char* selftest_ctr_128 (void) { const int nblocks = 32+16+1; const int blocksize = CAMELLIA_BLOCK_SIZE; const int context_size = sizeof(CAMELLIA_context); return _gcry_selftest_helper_ctr("CAMELLIA", &camellia_setkey, &camellia_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for CAMELLIA-CBC-128, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cbc_128 (void) { const int nblocks = 32+16+2; const int blocksize = CAMELLIA_BLOCK_SIZE; const int context_size = sizeof(CAMELLIA_context); return _gcry_selftest_helper_cbc("CAMELLIA", &camellia_setkey, &camellia_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for CAMELLIA-CFB-128, tests bulk CFB decryption. Returns NULL on success. */ static const char* selftest_cfb_128 (void) { const int nblocks = 32+16+2; const int blocksize = CAMELLIA_BLOCK_SIZE; const int context_size = sizeof(CAMELLIA_context); return _gcry_selftest_helper_cfb("CAMELLIA", &camellia_setkey, &camellia_encrypt, nblocks, blocksize, context_size); } static const char * selftest(void) { CAMELLIA_context ctx; byte scratch[16]; cipher_bulk_ops_t bulk_ops; const char *r; /* These test vectors are from RFC-3713 */ static const byte plaintext[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; static const byte key_128[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; static const byte ciphertext_128[]= { 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 }; static const byte key_192[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98, 0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77 }; static const byte ciphertext_192[]= { 0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8, 0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9 }; static const byte key_256[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba, 0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55, 0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; static const byte ciphertext_256[]= { 0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c, 0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09 }; camellia_setkey(&ctx,key_128,sizeof(key_128),&bulk_ops); camellia_encrypt(&ctx,scratch,plaintext); if(memcmp(scratch,ciphertext_128,sizeof(ciphertext_128))!=0) return "CAMELLIA-128 test encryption failed."; camellia_decrypt(&ctx,scratch,scratch); if(memcmp(scratch,plaintext,sizeof(plaintext))!=0) return "CAMELLIA-128 test decryption failed."; camellia_setkey(&ctx,key_192,sizeof(key_192),&bulk_ops); camellia_encrypt(&ctx,scratch,plaintext); if(memcmp(scratch,ciphertext_192,sizeof(ciphertext_192))!=0) return "CAMELLIA-192 test encryption failed."; camellia_decrypt(&ctx,scratch,scratch); if(memcmp(scratch,plaintext,sizeof(plaintext))!=0) return "CAMELLIA-192 test decryption failed."; camellia_setkey(&ctx,key_256,sizeof(key_256),&bulk_ops); camellia_encrypt(&ctx,scratch,plaintext); if(memcmp(scratch,ciphertext_256,sizeof(ciphertext_256))!=0) return "CAMELLIA-256 test encryption failed."; camellia_decrypt(&ctx,scratch,scratch); if(memcmp(scratch,plaintext,sizeof(plaintext))!=0) return "CAMELLIA-256 test decryption failed."; if ( (r = selftest_ctr_128 ()) ) return r; if ( (r = selftest_cbc_128 ()) ) return r; if ( (r = selftest_cfb_128 ()) ) return r; return NULL; } /* These oids are from , retrieved May 1, 2007. */ -static gcry_cipher_oid_spec_t camellia128_oids[] = +static const gcry_cipher_oid_spec_t camellia128_oids[] = { {"1.2.392.200011.61.1.1.1.2", GCRY_CIPHER_MODE_CBC}, {"0.3.4401.5.3.1.9.1", GCRY_CIPHER_MODE_ECB}, {"0.3.4401.5.3.1.9.3", GCRY_CIPHER_MODE_OFB}, {"0.3.4401.5.3.1.9.4", GCRY_CIPHER_MODE_CFB}, { NULL } }; -static gcry_cipher_oid_spec_t camellia192_oids[] = +static const gcry_cipher_oid_spec_t camellia192_oids[] = { {"1.2.392.200011.61.1.1.1.3", GCRY_CIPHER_MODE_CBC}, {"0.3.4401.5.3.1.9.21", GCRY_CIPHER_MODE_ECB}, {"0.3.4401.5.3.1.9.23", GCRY_CIPHER_MODE_OFB}, {"0.3.4401.5.3.1.9.24", GCRY_CIPHER_MODE_CFB}, { NULL } }; -static gcry_cipher_oid_spec_t camellia256_oids[] = +static const gcry_cipher_oid_spec_t camellia256_oids[] = { {"1.2.392.200011.61.1.1.1.4", GCRY_CIPHER_MODE_CBC}, {"0.3.4401.5.3.1.9.41", GCRY_CIPHER_MODE_ECB}, {"0.3.4401.5.3.1.9.43", GCRY_CIPHER_MODE_OFB}, {"0.3.4401.5.3.1.9.44", GCRY_CIPHER_MODE_CFB}, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_camellia128 = { GCRY_CIPHER_CAMELLIA128, {0, 0}, "CAMELLIA128",NULL,camellia128_oids,CAMELLIA_BLOCK_SIZE,128, sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_camellia192 = { GCRY_CIPHER_CAMELLIA192, {0, 0}, "CAMELLIA192",NULL,camellia192_oids,CAMELLIA_BLOCK_SIZE,192, sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_camellia256 = { GCRY_CIPHER_CAMELLIA256, {0, 0}, "CAMELLIA256",NULL,camellia256_oids,CAMELLIA_BLOCK_SIZE,256, sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt }; diff --git a/cipher/cipher.c b/cipher/cipher.c index 4890777d..3e2b70a5 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1,1898 +1,1898 @@ /* cipher.c - cipher dispatcher * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. * Copyright (C) 2013 g10 Code GmbH * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "../src/gcrypt-testapi.h" #include "cipher.h" #include "./cipher-internal.h" /* This is the list of the default ciphers, which are included in libgcrypt. */ static gcry_cipher_spec_t * const cipher_list[] = { #if USE_BLOWFISH &_gcry_cipher_spec_blowfish, #endif #if USE_DES &_gcry_cipher_spec_des, &_gcry_cipher_spec_tripledes, #endif #if USE_ARCFOUR &_gcry_cipher_spec_arcfour, #endif #if USE_CAST5 &_gcry_cipher_spec_cast5, #endif #if USE_AES &_gcry_cipher_spec_aes, &_gcry_cipher_spec_aes192, &_gcry_cipher_spec_aes256, #endif #if USE_TWOFISH &_gcry_cipher_spec_twofish, &_gcry_cipher_spec_twofish128, #endif #if USE_SERPENT &_gcry_cipher_spec_serpent128, &_gcry_cipher_spec_serpent192, &_gcry_cipher_spec_serpent256, #endif #if USE_RFC2268 &_gcry_cipher_spec_rfc2268_40, &_gcry_cipher_spec_rfc2268_128, #endif #if USE_SEED &_gcry_cipher_spec_seed, #endif #if USE_CAMELLIA &_gcry_cipher_spec_camellia128, &_gcry_cipher_spec_camellia192, &_gcry_cipher_spec_camellia256, #endif #if USE_IDEA &_gcry_cipher_spec_idea, #endif #if USE_SALSA20 &_gcry_cipher_spec_salsa20, &_gcry_cipher_spec_salsa20r12, #endif #if USE_GOST28147 &_gcry_cipher_spec_gost28147, &_gcry_cipher_spec_gost28147_mesh, #endif #if USE_CHACHA20 &_gcry_cipher_spec_chacha20, #endif #if USE_SM4 &_gcry_cipher_spec_sm4, #endif NULL }; /* Cipher implementations starting with index 0 (enum gcry_cipher_algos) */ static gcry_cipher_spec_t * const cipher_list_algo0[] = { NULL, /* GCRY_CIPHER_NONE */ #if USE_IDEA &_gcry_cipher_spec_idea, #else NULL, #endif #if USE_DES &_gcry_cipher_spec_tripledes, #else NULL, #endif #if USE_CAST5 &_gcry_cipher_spec_cast5, #else NULL, #endif #if USE_BLOWFISH &_gcry_cipher_spec_blowfish, #else NULL, #endif NULL, /* GCRY_CIPHER_SAFER_SK128 */ NULL, /* GCRY_CIPHER_DES_SK */ #if USE_AES &_gcry_cipher_spec_aes, &_gcry_cipher_spec_aes192, &_gcry_cipher_spec_aes256, #else NULL, NULL, NULL, #endif #if USE_TWOFISH &_gcry_cipher_spec_twofish #else NULL #endif }; /* Cipher implementations starting with index 301 (enum gcry_cipher_algos) */ static gcry_cipher_spec_t * const cipher_list_algo301[] = { #if USE_ARCFOUR &_gcry_cipher_spec_arcfour, #else NULL, #endif #if USE_DES &_gcry_cipher_spec_des, #else NULL, #endif #if USE_TWOFISH &_gcry_cipher_spec_twofish128, #else NULL, #endif #if USE_SERPENT &_gcry_cipher_spec_serpent128, &_gcry_cipher_spec_serpent192, &_gcry_cipher_spec_serpent256, #else NULL, NULL, NULL, #endif #if USE_RFC2268 &_gcry_cipher_spec_rfc2268_40, &_gcry_cipher_spec_rfc2268_128, #else NULL, NULL, #endif #if USE_SEED &_gcry_cipher_spec_seed, #else NULL, #endif #if USE_CAMELLIA &_gcry_cipher_spec_camellia128, &_gcry_cipher_spec_camellia192, &_gcry_cipher_spec_camellia256, #else NULL, NULL, NULL, #endif #if USE_SALSA20 &_gcry_cipher_spec_salsa20, &_gcry_cipher_spec_salsa20r12, #else NULL, NULL, #endif #if USE_GOST28147 &_gcry_cipher_spec_gost28147, #else NULL, #endif #if USE_CHACHA20 &_gcry_cipher_spec_chacha20, #else NULL, #endif #if USE_GOST28147 &_gcry_cipher_spec_gost28147_mesh, #else NULL, #endif #if USE_SM4 &_gcry_cipher_spec_sm4, #else NULL, #endif }; static void _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode); static int map_algo (int algo) { return algo; } /* Return the spec structure for the cipher algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_cipher_spec_t * spec_from_algo (int algo) { gcry_cipher_spec_t *spec = NULL; algo = map_algo (algo); if (algo >= 0 && algo < DIM(cipher_list_algo0)) spec = cipher_list_algo0[algo]; else if (algo >= 301 && algo < 301 + DIM(cipher_list_algo301)) spec = cipher_list_algo301[algo - 301]; if (spec) gcry_assert (spec->algo == algo); return spec; } /* Lookup a cipher's spec by its name. */ static gcry_cipher_spec_t * spec_from_name (const char *name) { gcry_cipher_spec_t *spec; int idx; const char **aliases; for (idx=0; (spec = cipher_list[idx]); idx++) { if (!stricmp (name, spec->name)) return spec; if (spec->aliases) { for (aliases = spec->aliases; *aliases; aliases++) if (!stricmp (name, *aliases)) return spec; } } return NULL; } /* Lookup a cipher's spec by its OID. */ static gcry_cipher_spec_t * spec_from_oid (const char *oid) { gcry_cipher_spec_t *spec; - gcry_cipher_oid_spec_t *oid_specs; + const gcry_cipher_oid_spec_t *oid_specs; int idx, j; for (idx=0; (spec = cipher_list[idx]); idx++) { oid_specs = spec->oids; if (oid_specs) { for (j = 0; oid_specs[j].oid; j++) if (!stricmp (oid, oid_specs[j].oid)) return spec; } } return NULL; } /* Locate the OID in the oid table and return the spec or NULL if not found. An optional "oid." or "OID." prefix in OID is ignored, the OID is expected to be in standard IETF dotted notation. A pointer to the OID specification of the module implementing this algorithm is return in OID_SPEC unless passed as NULL.*/ static gcry_cipher_spec_t * search_oid (const char *oid, gcry_cipher_oid_spec_t *oid_spec) { gcry_cipher_spec_t *spec; int i; if (!oid) return NULL; if (!strncmp (oid, "oid.", 4) || !strncmp (oid, "OID.", 4)) oid += 4; spec = spec_from_oid (oid); if (spec && spec->oids) { for (i = 0; spec->oids[i].oid; i++) if (!stricmp (oid, spec->oids[i].oid)) { if (oid_spec) *oid_spec = spec->oids[i]; return spec; } } return NULL; } /* Map STRING to the cipher algorithm identifier. Returns the algorithm ID of the cipher for the given name or 0 if the name is not known. It is valid to pass NULL for STRING which results in a return value of 0. */ int _gcry_cipher_map_name (const char *string) { gcry_cipher_spec_t *spec; if (!string) return 0; /* If the string starts with a digit (optionally prefixed with either "OID." or "oid."), we first look into our table of ASN.1 object identifiers to figure out the algorithm */ spec = search_oid (string, NULL); if (spec) return spec->algo; spec = spec_from_name (string); if (spec) return spec->algo; return 0; } /* Given a STRING with an OID in dotted decimal notation, this function returns the cipher mode (GCRY_CIPHER_MODE_*) associated with that OID or 0 if no mode is known. Passing NULL for string yields a return value of 0. */ int _gcry_cipher_mode_from_oid (const char *string) { gcry_cipher_spec_t *spec; gcry_cipher_oid_spec_t oid_spec; if (!string) return 0; spec = search_oid (string, &oid_spec); if (spec) return oid_spec.mode; return 0; } /* Map the cipher algorithm identifier ALGORITHM to a string representing this algorithm. This string is the default name as used by Libgcrypt. A "?" is returned for an unknown algorithm. NULL is never returned. */ const char * _gcry_cipher_algo_name (int algorithm) { gcry_cipher_spec_t *spec; spec = spec_from_algo (algorithm); return spec? spec->name : "?"; } /* Flag the cipher algorithm with the identifier ALGORITHM as disabled. There is no error return, the function does nothing for unknown algorithms. Disabled algorithms are virtually not available in Libgcrypt. This is not thread safe and should thus be called early. */ static void disable_cipher_algo (int algo) { gcry_cipher_spec_t *spec = spec_from_algo (algo); if (spec) spec->flags.disabled = 1; } /* Return 0 if the cipher algorithm with identifier ALGORITHM is available. Returns a basic error code value if it is not available. */ static gcry_err_code_t check_cipher_algo (int algorithm) { gcry_cipher_spec_t *spec; spec = spec_from_algo (algorithm); if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())) return 0; return GPG_ERR_CIPHER_ALGO; } /* Return the standard length in bits of the key for the cipher algorithm with the identifier ALGORITHM. */ static unsigned int cipher_get_keylen (int algorithm) { gcry_cipher_spec_t *spec; unsigned len = 0; spec = spec_from_algo (algorithm); if (spec) { len = spec->keylen; if (!len) log_bug ("cipher %d w/o key length\n", algorithm); } return len; } /* Return the block length of the cipher algorithm with the identifier ALGORITHM. This function return 0 for an invalid algorithm. */ static unsigned int cipher_get_blocksize (int algorithm) { gcry_cipher_spec_t *spec; unsigned len = 0; spec = spec_from_algo (algorithm); if (spec) { len = spec->blocksize; if (!len) log_bug ("cipher %d w/o blocksize\n", algorithm); } return len; } /* Open a cipher handle for use with cipher algorithm ALGORITHM, using the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a handle in HANDLE. Put NULL into HANDLE and return an error code if something goes wrong. FLAGS may be used to modify the operation. The defined flags are: GCRY_CIPHER_SECURE: allocate all internal buffers in secure memory. GCRY_CIPHER_ENABLE_SYNC: Enable the sync operation as used in OpenPGP. GCRY_CIPHER_CBC_CTS: Enable CTS mode. GCRY_CIPHER_CBC_MAC: Enable MAC mode. Values for these flags may be combined using OR. */ gcry_err_code_t _gcry_cipher_open (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags) { gcry_err_code_t rc; gcry_cipher_hd_t h = NULL; if (mode >= GCRY_CIPHER_MODE_INTERNAL) rc = GPG_ERR_INV_CIPHER_MODE; else rc = _gcry_cipher_open_internal (&h, algo, mode, flags); *handle = rc ? NULL : h; return rc; } gcry_err_code_t _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags) { int secure = (flags & GCRY_CIPHER_SECURE); gcry_cipher_spec_t *spec; gcry_cipher_hd_t h = NULL; gcry_err_code_t err; /* If the application missed to call the random poll function, we do it here to ensure that it is used once in a while. */ _gcry_fast_random_poll (); spec = spec_from_algo (algo); if (!spec) err = GPG_ERR_CIPHER_ALGO; else if (spec->flags.disabled) err = GPG_ERR_CIPHER_ALGO; else if (!spec->flags.fips && fips_mode ()) err = GPG_ERR_CIPHER_ALGO; else err = 0; /* check flags */ if ((! err) && ((flags & ~(0 | GCRY_CIPHER_SECURE | GCRY_CIPHER_ENABLE_SYNC | GCRY_CIPHER_CBC_CTS | GCRY_CIPHER_CBC_MAC | GCRY_CIPHER_EXTENDED)) || ((flags & GCRY_CIPHER_CBC_CTS) && (flags & GCRY_CIPHER_CBC_MAC)))) err = GPG_ERR_CIPHER_ALGO; /* check that a valid mode has been requested */ if (! err) switch (mode) { case GCRY_CIPHER_MODE_ECB: case GCRY_CIPHER_MODE_CBC: case GCRY_CIPHER_MODE_CFB: case GCRY_CIPHER_MODE_CFB8: case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: case GCRY_CIPHER_MODE_AESWRAP: case GCRY_CIPHER_MODE_CMAC: case GCRY_CIPHER_MODE_EAX: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_CCM: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; else if (spec->blocksize != GCRY_CCM_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_XTS: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; else if (spec->blocksize != GCRY_XTS_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_GCM: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; else if (spec->blocksize != GCRY_GCM_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_SIV: case GCRY_CIPHER_MODE_GCM_SIV: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; else if (spec->blocksize != GCRY_SIV_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_POLY1305: if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv) err = GPG_ERR_INV_CIPHER_MODE; else if (spec->algo != GCRY_CIPHER_CHACHA20) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_OCB: /* Note that our implementation allows only for 128 bit block length algorithms. Lower block lengths would be possible but we do not implement them because they limit the security too much. */ if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; else if (spec->blocksize != GCRY_OCB_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_STREAM: if (!spec->stencrypt || !spec->stdecrypt) err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_NONE: /* This mode may be used for debugging. It copies the main text verbatim to the ciphertext. We do not allow this in fips mode or if no debug flag has been set. */ if (fips_mode () || !_gcry_get_debug_flag (0)) err = GPG_ERR_INV_CIPHER_MODE; break; default: err = GPG_ERR_INV_CIPHER_MODE; } /* Perform selftest here and mark this with a flag in cipher_table? No, we should not do this as it takes too long. Further it does not make sense to exclude algorithms with failing selftests at runtime: If a selftest fails there is something seriously wrong with the system and thus we better die immediately. */ if (! err) { size_t size = (sizeof (*h) + 2 * spec->contextsize - sizeof (cipher_context_alignment_t) #ifdef NEED_16BYTE_ALIGNED_CONTEXT + 15 /* Space for leading alignment gap. */ #endif /*NEED_16BYTE_ALIGNED_CONTEXT*/ ); /* Space needed per mode. */ switch (mode) { case GCRY_CIPHER_MODE_XTS: case GCRY_CIPHER_MODE_SIV: /* Additional cipher context for tweak. */ size += 2 * spec->contextsize + 15; break; default: break; } if (secure) h = xtrycalloc_secure (1, size); else h = xtrycalloc (1, size); if (! h) err = gpg_err_code_from_syserror (); else { size_t off = 0; char *tc; #ifdef NEED_16BYTE_ALIGNED_CONTEXT if ( ((uintptr_t)h & 0x0f) ) { /* The malloced block is not aligned on a 16 byte boundary. Correct for this. */ off = 16 - ((uintptr_t)h & 0x0f); h = (void*)((char*)h + off); } #endif /*NEED_16BYTE_ALIGNED_CONTEXT*/ h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; h->actual_handle_size = size - off; h->handle_offset = off; h->spec = spec; h->algo = algo; h->mode = mode; h->flags = flags; /* Setup mode routines. */ _gcry_cipher_setup_mode_ops(h, mode); /* Setup defaults depending on the mode. */ switch (mode) { case GCRY_CIPHER_MODE_OCB: h->u_mode.ocb.taglen = 16; /* Bytes. */ break; case GCRY_CIPHER_MODE_XTS: tc = h->context.c + spec->contextsize * 2; tc += (16 - (uintptr_t)tc % 16) % 16; h->u_mode.xts.tweak_context = tc; break; case GCRY_CIPHER_MODE_SIV: tc = h->context.c + spec->contextsize * 2; tc += (16 - (uintptr_t)tc % 16) % 16; h->u_mode.siv.ctr_context = tc; break; default: break; } } } /* Done. */ *handle = err ? NULL : h; return err; } /* Release all resources associated with the cipher handle H. H may be NULL in which case this is a no-operation. */ void _gcry_cipher_close (gcry_cipher_hd_t h) { size_t off; if (!h) return; if ((h->magic != CTX_MAGIC_SECURE) && (h->magic != CTX_MAGIC_NORMAL)) _gcry_fatal_error(GPG_ERR_INTERNAL, "gcry_cipher_close: already closed/invalid handle"); else h->magic = 0; /* We always want to wipe out the memory even when the context has been allocated in secure memory. The user might have disabled secure memory or is using his own implementation which does not do the wiping. To accomplish this we need to keep track of the actual size of this structure because we have no way to known how large the allocated area was when using a standard malloc. */ off = h->handle_offset; wipememory (h, h->actual_handle_size); xfree ((char*)h - off); } /* Set the key to be used for the encryption context C to KEY with length KEYLEN. The length should match the required length. */ static gcry_err_code_t cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) { gcry_err_code_t rc; if (c->mode == GCRY_CIPHER_MODE_XTS) { /* XTS uses two keys. */ if (keylen % 2) return GPG_ERR_INV_KEYLEN; keylen /= 2; if (fips_mode ()) { /* Reject key if subkeys Key_1 and Key_2 are equal. See "Implementation Guidance for FIPS 140-2, A.9 XTS-AES Key Generation Requirements" for details. */ if (buf_eq_const (key, key + keylen, keylen)) return GPG_ERR_WEAK_KEY; } } else if (c->mode == GCRY_CIPHER_MODE_SIV) { /* SIV uses two keys. */ if (keylen % 2) return GPG_ERR_INV_KEYLEN; keylen /= 2; } rc = c->spec->setkey (&c->context.c, key, keylen, &c->bulk); if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY)) { /* Duplicate initial context. */ memcpy ((void *) ((char *) &c->context.c + c->spec->contextsize), (void *) &c->context.c, c->spec->contextsize); c->marks.key = 1; switch (c->mode) { case GCRY_CIPHER_MODE_CMAC: rc = _gcry_cipher_cmac_set_subkeys (c); break; case GCRY_CIPHER_MODE_EAX: rc = _gcry_cipher_eax_setkey (c); break; case GCRY_CIPHER_MODE_GCM: _gcry_cipher_gcm_setkey (c); break; case GCRY_CIPHER_MODE_GCM_SIV: rc = _gcry_cipher_gcm_siv_setkey (c, keylen); if (rc) c->marks.key = 0; break; case GCRY_CIPHER_MODE_OCB: _gcry_cipher_ocb_setkey (c); break; case GCRY_CIPHER_MODE_POLY1305: _gcry_cipher_poly1305_setkey (c); break; case GCRY_CIPHER_MODE_XTS: /* Setup tweak cipher with second part of XTS key. */ rc = c->spec->setkey (c->u_mode.xts.tweak_context, key + keylen, keylen, &c->bulk); if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY)) { /* Duplicate initial tweak context. */ memcpy (c->u_mode.xts.tweak_context + c->spec->contextsize, c->u_mode.xts.tweak_context, c->spec->contextsize); } else c->marks.key = 0; break; case GCRY_CIPHER_MODE_SIV: /* Setup CTR cipher with second part of SIV key. */ rc = _gcry_cipher_siv_setkey (c, key + keylen, keylen); if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY)) { /* Duplicate initial CTR context. */ memcpy (c->u_mode.siv.ctr_context + c->spec->contextsize, c->u_mode.siv.ctr_context, c->spec->contextsize); } else c->marks.key = 0; break; default: break; } } else c->marks.key = 0; return rc; } /* Set the IV to be used for the encryption context C to IV with length IVLEN. The length should match the required length. */ static gcry_err_code_t cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ if (c->spec->setiv) { c->spec->setiv (&c->context.c, iv, ivlen); return 0; } memset (c->u_iv.iv, 0, c->spec->blocksize); if (iv) { if (ivlen != c->spec->blocksize) { log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n", (unsigned int)ivlen, (unsigned int)c->spec->blocksize); fips_signal_error ("IV length does not match blocklength"); } if (ivlen > c->spec->blocksize) ivlen = c->spec->blocksize; memcpy (c->u_iv.iv, iv, ivlen); c->marks.iv = 1; } else c->marks.iv = 0; c->unused = 0; return 0; } /* Reset the cipher context to the initial context. This is basically the same as an release followed by a new. */ static void cipher_reset (gcry_cipher_hd_t c) { unsigned int marks_key, marks_allow_weak_key; marks_key = c->marks.key; marks_allow_weak_key = c->marks.allow_weak_key; memcpy (&c->context.c, (char *) &c->context.c + c->spec->contextsize, c->spec->contextsize); memset (&c->marks, 0, sizeof c->marks); memset (c->u_iv.iv, 0, c->spec->blocksize); memset (c->lastiv, 0, c->spec->blocksize); memset (c->u_ctr.ctr, 0, c->spec->blocksize); c->unused = 0; c->marks.key = marks_key; c->marks.allow_weak_key = marks_allow_weak_key; switch (c->mode) { case GCRY_CIPHER_MODE_CMAC: _gcry_cmac_reset(&c->u_mode.cmac); break; case GCRY_CIPHER_MODE_EAX: _gcry_cmac_reset(&c->u_mode.eax.cmac_header); _gcry_cmac_reset(&c->u_mode.eax.cmac_ciphertext); break; case GCRY_CIPHER_MODE_GCM: case GCRY_CIPHER_MODE_GCM_SIV: /* Only clear head of u_mode, keep ghash_key and gcm_table. */ { byte *u_mode_pos = (void *)&c->u_mode; byte *ghash_key_pos = c->u_mode.gcm.u_ghash_key.key; size_t u_mode_head_length = ghash_key_pos - u_mode_pos; memset (&c->u_mode, 0, u_mode_head_length); } break; case GCRY_CIPHER_MODE_POLY1305: memset (&c->u_mode.poly1305, 0, sizeof c->u_mode.poly1305); break; case GCRY_CIPHER_MODE_CCM: memset (&c->u_mode.ccm, 0, sizeof c->u_mode.ccm); break; case GCRY_CIPHER_MODE_OCB: { const size_t table_maxblks = 1 << OCB_L_TABLE_SIZE; byte *u_mode_head_pos = (void *)&c->u_mode.ocb; byte *u_mode_tail_pos = (void *)&c->u_mode.ocb.tag; size_t u_mode_head_length = u_mode_tail_pos - u_mode_head_pos; size_t u_mode_tail_length = sizeof(c->u_mode.ocb) - u_mode_head_length; if (c->u_mode.ocb.aad_nblocks < table_maxblks) { /* Precalculated L-values are still ok after reset, no need * to clear. */ memset (u_mode_tail_pos, 0, u_mode_tail_length); } else { /* Reinitialize L table. */ memset (&c->u_mode.ocb, 0, sizeof(c->u_mode.ocb)); _gcry_cipher_ocb_setkey (c); } /* Setup default taglen. */ c->u_mode.ocb.taglen = 16; } break; case GCRY_CIPHER_MODE_XTS: memcpy (c->u_mode.xts.tweak_context, c->u_mode.xts.tweak_context + c->spec->contextsize, c->spec->contextsize); break; case GCRY_CIPHER_MODE_SIV: /* Only clear head of u_mode, keep s2v_cmac and ctr_context. */ { byte *u_mode_pos = (void *)&c->u_mode; byte *tail_pos = (void *)&c->u_mode.siv.s2v_cmac; size_t u_mode_head_length = tail_pos - u_mode_pos; memset (&c->u_mode, 0, u_mode_head_length); memcpy (c->u_mode.siv.ctr_context, c->u_mode.siv.ctr_context + c->spec->contextsize, c->spec->contextsize); memcpy (c->u_mode.siv.s2v_d, c->u_mode.siv.s2v_zero_block, GCRY_SIV_BLOCK_LEN); } break; default: break; /* u_mode unused by other modes. */ } } static gcry_err_code_t do_ecb_crypt (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen, const unsigned char *inbuf, size_t inbuflen, gcry_cipher_encrypt_t crypt_fn) { unsigned int blocksize = c->spec->blocksize; size_t n, nblocks; unsigned int burn, nburn; if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; if ((inbuflen % blocksize)) return GPG_ERR_INV_LENGTH; nblocks = inbuflen / blocksize; burn = 0; for (n=0; n < nblocks; n++ ) { nburn = crypt_fn (&c->context.c, outbuf, inbuf); burn = nburn > burn ? nburn : burn; inbuf += blocksize; outbuf += blocksize; } if (burn > 0) _gcry_burn_stack (burn + 4 * sizeof(void *)); return 0; } static gcry_err_code_t do_ecb_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen, const unsigned char *inbuf, size_t inbuflen) { return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->encrypt); } static gcry_err_code_t do_ecb_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen, const unsigned char *inbuf, size_t inbuflen) { return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->decrypt); } static gcry_err_code_t do_stream_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen, const unsigned char *inbuf, size_t inbuflen) { (void)outbuflen; c->spec->stencrypt (&c->context.c, outbuf, (void *)inbuf, inbuflen); return 0; } static gcry_err_code_t do_stream_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen, const unsigned char *inbuf, size_t inbuflen) { (void)outbuflen; c->spec->stdecrypt (&c->context.c, outbuf, (void *)inbuf, inbuflen); return 0; } static gcry_err_code_t do_encrypt_none_unknown (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, const byte *inbuf, size_t inbuflen) { gcry_err_code_t rc; (void)outbuflen; switch (c->mode) { case GCRY_CIPHER_MODE_CMAC: rc = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_NONE: if (fips_mode () || !_gcry_get_debug_flag (0)) { fips_signal_error ("cipher mode NONE used"); rc = GPG_ERR_INV_CIPHER_MODE; } else { if (inbuf != outbuf) memmove (outbuf, inbuf, inbuflen); rc = 0; } break; default: log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode ); rc = GPG_ERR_INV_CIPHER_MODE; break; } return rc; } static gcry_err_code_t do_decrypt_none_unknown (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, const byte *inbuf, size_t inbuflen) { gcry_err_code_t rc; (void)outbuflen; switch (c->mode) { case GCRY_CIPHER_MODE_CMAC: rc = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_NONE: if (fips_mode () || !_gcry_get_debug_flag (0)) { fips_signal_error ("cipher mode NONE used"); rc = GPG_ERR_INV_CIPHER_MODE; } else { if (inbuf != outbuf) memmove (outbuf, inbuf, inbuflen); rc = 0; } break; default: log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); rc = GPG_ERR_INV_CIPHER_MODE; break; } return rc; } /**************** * Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has * been requested. */ gcry_err_code_t _gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, const void *in, size_t inlen) { gcry_err_code_t rc; if (!in) /* Caller requested in-place encryption. */ { in = out; inlen = outsize; } if (h->mode != GCRY_CIPHER_MODE_NONE && !h->marks.key) { log_error ("cipher_encrypt: key not set\n"); return GPG_ERR_MISSING_KEY; } rc = h->mode_ops.encrypt (h, out, outsize, in, inlen); /* Failsafe: Make sure that the plaintext will never make it into OUT if the encryption returned an error. */ if (rc && out) memset (out, 0x42, outsize); return rc; } /**************** * Decrypt IN and write it to OUT. If IN is NULL, in-place encryption has * been requested. */ gcry_err_code_t _gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize, const void *in, size_t inlen) { if (!in) /* Caller requested in-place encryption. */ { in = out; inlen = outsize; } if (h->mode != GCRY_CIPHER_MODE_NONE && !h->marks.key) { log_error ("cipher_decrypt: key not set\n"); return GPG_ERR_MISSING_KEY; } return h->mode_ops.decrypt (h, out, outsize, in, inlen); } /**************** * Used for PGP's somewhat strange CFB mode. Only works if * the corresponding flag is set. */ static void cipher_sync (gcry_cipher_hd_t c) { if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused) { memmove (c->u_iv.iv + c->unused, c->u_iv.iv, c->spec->blocksize - c->unused); memcpy (c->u_iv.iv, c->lastiv + c->spec->blocksize - c->unused, c->unused); c->unused = 0; } } gcry_err_code_t _gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen) { return cipher_setkey (hd, (void*)key, keylen); } gcry_err_code_t _gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen) { return hd->mode_ops.setiv (hd, iv, ivlen); } /* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of block size length, or (NULL,0) to set the CTR to the all-zero block. */ gpg_err_code_t _gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen) { if (ctr && ctrlen == hd->spec->blocksize) { memcpy (hd->u_ctr.ctr, ctr, hd->spec->blocksize); hd->unused = 0; } else if (!ctr || !ctrlen) { memset (hd->u_ctr.ctr, 0, hd->spec->blocksize); hd->unused = 0; } else return GPG_ERR_INV_ARG; return 0; } gpg_err_code_t _gcry_cipher_getctr (gcry_cipher_hd_t hd, void *ctr, size_t ctrlen) { if (ctr && ctrlen == hd->spec->blocksize) memcpy (ctr, hd->u_ctr.ctr, hd->spec->blocksize); else return GPG_ERR_INV_ARG; return 0; } gcry_err_code_t _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, size_t abuflen) { gcry_err_code_t rc; if (hd->mode_ops.authenticate) { rc = hd->mode_ops.authenticate (hd, abuf, abuflen); } else { log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; } return rc; } gcry_err_code_t _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen) { gcry_err_code_t rc; if (hd->mode_ops.get_tag) { rc = hd->mode_ops.get_tag (hd, outtag, taglen); } else { log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; } return rc; } gcry_err_code_t _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen) { gcry_err_code_t rc; if (hd->mode_ops.check_tag) { rc = hd->mode_ops.check_tag (hd, intag, taglen); } else { log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; } return rc; } static void _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode) { /* Setup encryption and decryption routines. */ switch (mode) { case GCRY_CIPHER_MODE_STREAM: c->mode_ops.encrypt = do_stream_encrypt; c->mode_ops.decrypt = do_stream_decrypt; break; case GCRY_CIPHER_MODE_ECB: c->mode_ops.encrypt = do_ecb_encrypt; c->mode_ops.decrypt = do_ecb_decrypt; break; case GCRY_CIPHER_MODE_CBC: if (!(c->flags & GCRY_CIPHER_CBC_CTS)) { c->mode_ops.encrypt = _gcry_cipher_cbc_encrypt; c->mode_ops.decrypt = _gcry_cipher_cbc_decrypt; } else { c->mode_ops.encrypt = _gcry_cipher_cbc_cts_encrypt; c->mode_ops.decrypt = _gcry_cipher_cbc_cts_decrypt; } break; case GCRY_CIPHER_MODE_CFB: c->mode_ops.encrypt = _gcry_cipher_cfb_encrypt; c->mode_ops.decrypt = _gcry_cipher_cfb_decrypt; break; case GCRY_CIPHER_MODE_CFB8: c->mode_ops.encrypt = _gcry_cipher_cfb8_encrypt; c->mode_ops.decrypt = _gcry_cipher_cfb8_decrypt; break; case GCRY_CIPHER_MODE_OFB: c->mode_ops.encrypt = _gcry_cipher_ofb_encrypt; c->mode_ops.decrypt = _gcry_cipher_ofb_encrypt; break; case GCRY_CIPHER_MODE_CTR: c->mode_ops.encrypt = _gcry_cipher_ctr_encrypt; c->mode_ops.decrypt = _gcry_cipher_ctr_encrypt; break; case GCRY_CIPHER_MODE_AESWRAP: if (!(c->flags & GCRY_CIPHER_EXTENDED)) { c->mode_ops.encrypt = _gcry_cipher_keywrap_encrypt; c->mode_ops.decrypt = _gcry_cipher_keywrap_decrypt; } else { c->mode_ops.encrypt = _gcry_cipher_keywrap_encrypt_padding; c->mode_ops.decrypt = _gcry_cipher_keywrap_decrypt_padding; } break; case GCRY_CIPHER_MODE_CCM: c->mode_ops.encrypt = _gcry_cipher_ccm_encrypt; c->mode_ops.decrypt = _gcry_cipher_ccm_decrypt; break; case GCRY_CIPHER_MODE_EAX: c->mode_ops.encrypt = _gcry_cipher_eax_encrypt; c->mode_ops.decrypt = _gcry_cipher_eax_decrypt; break; case GCRY_CIPHER_MODE_GCM: c->mode_ops.encrypt = _gcry_cipher_gcm_encrypt; c->mode_ops.decrypt = _gcry_cipher_gcm_decrypt; break; case GCRY_CIPHER_MODE_POLY1305: c->mode_ops.encrypt = _gcry_cipher_poly1305_encrypt; c->mode_ops.decrypt = _gcry_cipher_poly1305_decrypt; break; case GCRY_CIPHER_MODE_OCB: c->mode_ops.encrypt = _gcry_cipher_ocb_encrypt; c->mode_ops.decrypt = _gcry_cipher_ocb_decrypt; break; case GCRY_CIPHER_MODE_XTS: c->mode_ops.encrypt = _gcry_cipher_xts_encrypt; c->mode_ops.decrypt = _gcry_cipher_xts_decrypt; break; case GCRY_CIPHER_MODE_SIV: c->mode_ops.encrypt = _gcry_cipher_siv_encrypt; c->mode_ops.decrypt = _gcry_cipher_siv_decrypt; break; case GCRY_CIPHER_MODE_GCM_SIV: c->mode_ops.encrypt = _gcry_cipher_gcm_siv_encrypt; c->mode_ops.decrypt = _gcry_cipher_gcm_siv_decrypt; break; default: c->mode_ops.encrypt = do_encrypt_none_unknown; c->mode_ops.decrypt = do_decrypt_none_unknown; break; } /* Setup IV setting routine. */ switch (mode) { case GCRY_CIPHER_MODE_CCM: c->mode_ops.setiv = _gcry_cipher_ccm_set_nonce; break; case GCRY_CIPHER_MODE_EAX: c->mode_ops.setiv = _gcry_cipher_eax_set_nonce; break; case GCRY_CIPHER_MODE_GCM: c->mode_ops.setiv = _gcry_cipher_gcm_setiv; break; case GCRY_CIPHER_MODE_POLY1305: c->mode_ops.setiv = _gcry_cipher_poly1305_setiv; break; case GCRY_CIPHER_MODE_OCB: c->mode_ops.setiv = _gcry_cipher_ocb_set_nonce; break; case GCRY_CIPHER_MODE_SIV: c->mode_ops.setiv = _gcry_cipher_siv_set_nonce; break; case GCRY_CIPHER_MODE_GCM_SIV: c->mode_ops.setiv = _gcry_cipher_gcm_siv_set_nonce; break; default: c->mode_ops.setiv = cipher_setiv; break; } /* Setup authentication routines for AEAD modes. */ switch (mode) { case GCRY_CIPHER_MODE_CCM: c->mode_ops.authenticate = _gcry_cipher_ccm_authenticate; c->mode_ops.get_tag = _gcry_cipher_ccm_get_tag; c->mode_ops.check_tag = _gcry_cipher_ccm_check_tag; break; case GCRY_CIPHER_MODE_CMAC: c->mode_ops.authenticate = _gcry_cipher_cmac_authenticate; c->mode_ops.get_tag = _gcry_cipher_cmac_get_tag; c->mode_ops.check_tag = _gcry_cipher_cmac_check_tag; break; case GCRY_CIPHER_MODE_EAX: c->mode_ops.authenticate = _gcry_cipher_eax_authenticate; c->mode_ops.get_tag = _gcry_cipher_eax_get_tag; c->mode_ops.check_tag = _gcry_cipher_eax_check_tag; break; case GCRY_CIPHER_MODE_GCM: c->mode_ops.authenticate = _gcry_cipher_gcm_authenticate; c->mode_ops.get_tag = _gcry_cipher_gcm_get_tag; c->mode_ops.check_tag = _gcry_cipher_gcm_check_tag; break; case GCRY_CIPHER_MODE_POLY1305: c->mode_ops.authenticate = _gcry_cipher_poly1305_authenticate; c->mode_ops.get_tag = _gcry_cipher_poly1305_get_tag; c->mode_ops.check_tag = _gcry_cipher_poly1305_check_tag; break; case GCRY_CIPHER_MODE_OCB: c->mode_ops.authenticate = _gcry_cipher_ocb_authenticate; c->mode_ops.get_tag = _gcry_cipher_ocb_get_tag; c->mode_ops.check_tag = _gcry_cipher_ocb_check_tag; break; case GCRY_CIPHER_MODE_SIV: c->mode_ops.authenticate = _gcry_cipher_siv_authenticate; c->mode_ops.get_tag = _gcry_cipher_siv_get_tag; c->mode_ops.check_tag = _gcry_cipher_siv_check_tag; break; case GCRY_CIPHER_MODE_GCM_SIV: c->mode_ops.authenticate = _gcry_cipher_gcm_siv_authenticate; c->mode_ops.get_tag = _gcry_cipher_gcm_siv_get_tag; c->mode_ops.check_tag = _gcry_cipher_gcm_siv_check_tag; break; default: c->mode_ops.authenticate = NULL; c->mode_ops.get_tag = NULL; c->mode_ops.check_tag = NULL; break; } } gcry_err_code_t _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc = 0; switch (cmd) { case GCRYCTL_RESET: cipher_reset (h); break; case GCRYCTL_FINALIZE: if (!h || buffer || buflen) return GPG_ERR_INV_ARG; h->marks.finalize = 1; break; case GCRYCTL_CFB_SYNC: cipher_sync( h ); break; case GCRYCTL_SET_CBC_CTS: if (buflen) if (h->flags & GCRY_CIPHER_CBC_MAC) rc = GPG_ERR_INV_FLAG; else h->flags |= GCRY_CIPHER_CBC_CTS; else h->flags &= ~GCRY_CIPHER_CBC_CTS; break; case GCRYCTL_SET_CBC_MAC: if (buflen) if (h->flags & GCRY_CIPHER_CBC_CTS) rc = GPG_ERR_INV_FLAG; else h->flags |= GCRY_CIPHER_CBC_MAC; else h->flags &= ~GCRY_CIPHER_CBC_MAC; break; case GCRYCTL_SET_CCM_LENGTHS: { u64 params[3]; size_t encryptedlen; size_t aadlen; size_t authtaglen; if (h->mode != GCRY_CIPHER_MODE_CCM) return GPG_ERR_INV_CIPHER_MODE; if (!buffer || buflen != 3 * sizeof(u64)) return GPG_ERR_INV_ARG; /* This command is used to pass additional length parameters needed by CCM mode to initialize CBC-MAC. */ memcpy (params, buffer, sizeof(params)); encryptedlen = params[0]; aadlen = params[1]; authtaglen = params[2]; rc = _gcry_cipher_ccm_set_lengths (h, encryptedlen, aadlen, authtaglen); } break; case GCRYCTL_SET_DECRYPTION_TAG: { if (!buffer) return GPG_ERR_INV_ARG; if (h->mode == GCRY_CIPHER_MODE_SIV) rc = _gcry_cipher_siv_set_decryption_tag (h, buffer, buflen); else if (h->mode == GCRY_CIPHER_MODE_GCM_SIV) rc = _gcry_cipher_gcm_siv_set_decryption_tag (h, buffer, buflen); else rc = GPG_ERR_INV_CIPHER_MODE; } break; case GCRYCTL_SET_TAGLEN: if (!h || !buffer || buflen != sizeof(int) ) return GPG_ERR_INV_ARG; switch (h->mode) { case GCRY_CIPHER_MODE_OCB: switch (*(int*)buffer) { case 8: case 12: case 16: h->u_mode.ocb.taglen = *(int*)buffer; break; default: rc = GPG_ERR_INV_LENGTH; /* Invalid tag length. */ break; } break; default: rc =GPG_ERR_INV_CIPHER_MODE; break; } break; case GCRYCTL_DISABLE_ALGO: /* This command expects NULL for H and BUFFER to point to an integer with the algo number. */ if( h || !buffer || buflen != sizeof(int) ) return GPG_ERR_CIPHER_ALGO; disable_cipher_algo( *(int*)buffer ); break; case PRIV_CIPHERCTL_DISABLE_WEAK_KEY: /* (private) */ if (h->spec->set_extra_info) rc = h->spec->set_extra_info (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0); else rc = GPG_ERR_NOT_SUPPORTED; break; case PRIV_CIPHERCTL_GET_INPUT_VECTOR: /* (private) */ /* This is the input block as used in CFB and OFB mode which has initially been set as IV. The returned format is: 1 byte Actual length of the block in bytes. n byte The block. If the provided buffer is too short, an error is returned. */ if (buflen < (1 + h->spec->blocksize)) rc = GPG_ERR_TOO_SHORT; else { unsigned char *ivp; unsigned char *dst = buffer; int n = h->unused; if (!n) n = h->spec->blocksize; gcry_assert (n <= h->spec->blocksize); *dst++ = n; ivp = h->u_iv.iv + h->spec->blocksize - n; while (n--) *dst++ = *ivp++; } break; case GCRYCTL_SET_SBOX: if (h->spec->set_extra_info) rc = h->spec->set_extra_info (&h->context.c, GCRYCTL_SET_SBOX, buffer, buflen); else rc = GPG_ERR_NOT_SUPPORTED; break; case GCRYCTL_SET_ALLOW_WEAK_KEY: /* Expecting BUFFER to be NULL and buflen to be on/off flag (0 or 1). */ if (!h || buffer || buflen > 1) return GPG_ERR_CIPHER_ALGO; h->marks.allow_weak_key = buflen ? 1 : 0; break; default: rc = GPG_ERR_INV_OP; } return rc; } /* Return information about the cipher handle H. CMD is the kind of * information requested. * * CMD may be one of: * * GCRYCTL_GET_TAGLEN: * Return the length of the tag for an AE algorithm mode. An * error is returned for modes which do not support a tag. * BUFFER must be given as NULL. On success the result is stored * at NBYTES. The taglen is returned in bytes. * * The function returns 0 on success or an error code. */ gcry_err_code_t _gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) { gcry_err_code_t rc = 0; switch (cmd) { case GCRYCTL_GET_TAGLEN: if (!h || buffer || !nbytes) rc = GPG_ERR_INV_ARG; else { switch (h->mode) { case GCRY_CIPHER_MODE_OCB: *nbytes = h->u_mode.ocb.taglen; break; case GCRY_CIPHER_MODE_CCM: *nbytes = h->u_mode.ccm.authlen; break; case GCRY_CIPHER_MODE_EAX: *nbytes = h->spec->blocksize; break; case GCRY_CIPHER_MODE_GCM: *nbytes = GCRY_GCM_BLOCK_LEN; break; case GCRY_CIPHER_MODE_POLY1305: *nbytes = POLY1305_TAGLEN; break; case GCRY_CIPHER_MODE_SIV: *nbytes = GCRY_SIV_BLOCK_LEN; break; case GCRY_CIPHER_MODE_GCM_SIV: *nbytes = GCRY_SIV_BLOCK_LEN; break; default: rc = GPG_ERR_INV_CIPHER_MODE; break; } } break; default: rc = GPG_ERR_INV_OP; } return rc; } /* Return information about the given cipher algorithm ALGO. WHAT select the kind of information returned: GCRYCTL_GET_KEYLEN: Return the length of the key. If the algorithm ALGO supports multiple key lengths, the maximum supported key length is returned. The key length is returned as number of octets. BUFFER and NBYTES must be zero. GCRYCTL_GET_BLKLEN: Return the blocklength of the algorithm ALGO counted in octets. BUFFER and NBYTES must be zero. 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_cipher_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_CIPHER_ALGO; else { ui = cipher_get_keylen (algo); if ((ui > 0) && (ui <= 512)) *nbytes = (size_t) ui / 8; else /* The only reason for an error is an invalid algo. */ rc = GPG_ERR_CIPHER_ALGO; } break; case GCRYCTL_GET_BLKLEN: if (buffer || (! nbytes)) rc = GPG_ERR_CIPHER_ALGO; else { ui = cipher_get_blocksize (algo); if ((ui > 0) && (ui < 10000)) *nbytes = ui; else { /* The only reason is an invalid algo or a strange blocksize. */ rc = GPG_ERR_CIPHER_ALGO; } } break; case GCRYCTL_TEST_ALGO: if (buffer || nbytes) rc = GPG_ERR_INV_ARG; else rc = check_cipher_algo (algo); break; default: rc = GPG_ERR_INV_OP; } return rc; } /* This function returns length of the key for algorithm ALGO. If the algorithm supports multiple key lengths, the maximum supported key length is returned. On error 0 is returned. The key length is returned as number of octets. This is a convenience functions which should be preferred over gcry_cipher_algo_info because it allows for proper type checking. */ size_t _gcry_cipher_get_algo_keylen (int algo) { size_t n; if (_gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n)) n = 0; return n; } /* This functions returns the blocklength of the algorithm ALGO counted in octets. On error 0 is returned. This is a convenience functions which should be preferred over gcry_cipher_algo_info because it allows for proper type checking. */ size_t _gcry_cipher_get_algo_blklen (int algo) { size_t n; if (_gcry_cipher_algo_info( algo, GCRYCTL_GET_BLKLEN, NULL, &n)) n = 0; return n; } /* Explicitly initialize this module. */ gcry_err_code_t _gcry_cipher_init (void) { return 0; } /* Run the selftests for cipher algorithm ALGO with optional reporting function REPORT. */ gpg_error_t _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec = 0; gcry_cipher_spec_t *spec; spec = spec_from_algo (algo); if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()) && spec->selftest) ec = spec->selftest (algo, extended, report); else { ec = GPG_ERR_CIPHER_ALGO; if (report) report ("cipher", algo, "module", spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())? "no selftest available" : spec? "algorithm disabled" : "algorithm not found"); } return gpg_error (ec); } diff --git a/cipher/crc.c b/cipher/crc.c index db8d8dc9..b38869ec 100644 --- a/cipher/crc.c +++ b/cipher/crc.c @@ -1,955 +1,955 @@ /* crc.c - Cyclic redundancy checks. * Copyright (C) 2003 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" /* USE_INTEL_PCLMUL indicates whether to compile CRC with Intel PCLMUL/SSE4.1 * code. */ #undef USE_INTEL_PCLMUL #if defined(ENABLE_PCLMUL_SUPPORT) && defined(ENABLE_SSE41_SUPPORT) # if ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)) # if __GNUC__ >= 4 # define USE_INTEL_PCLMUL 1 # endif # endif #endif /* USE_INTEL_PCLMUL */ /* USE_ARM_PMULL indicates whether to compile GCM with ARMv8 PMULL code. */ #undef USE_ARM_PMULL #if defined(ENABLE_ARM_CRYPTO_SUPPORT) # if defined(__AARCH64EL__) && \ defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \ defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO) # define USE_ARM_PMULL 1 # endif #endif /* USE_ARM_PMULL */ /* USE_PPC_VPMSUM indicates whether to enable PowerPC vector * accelerated code. */ #undef USE_PPC_VPMSUM #ifdef ENABLE_PPC_CRYPTO_SUPPORT # if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) # if __GNUC__ >= 4 # define USE_PPC_VPMSUM 1 # endif # endif #endif /* USE_PPC_VPMSUM */ typedef struct { u32 CRC; #ifdef USE_INTEL_PCLMUL unsigned int use_pclmul:1; /* Intel PCLMUL shall be used. */ #endif #ifdef USE_ARM_PMULL unsigned int use_pmull:1; /* ARMv8 PMULL shall be used. */ #endif #ifdef USE_PPC_VPMSUM unsigned int use_vpmsum:1; /* POWER vpmsum shall be used. */ #endif byte buf[4]; } CRC_CONTEXT; #ifdef USE_INTEL_PCLMUL /*-- crc-intel-pclmul.c --*/ void _gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen); void _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen); #endif #ifdef USE_ARM_PMULL /*-- crc-armv8-ce.c --*/ void _gcry_crc32_armv8_ce_pmull (u32 *pcrc, const byte *inbuf, size_t inlen); void _gcry_crc24rfc2440_armv8_ce_pmull (u32 *pcrc, const byte *inbuf, size_t inlen); #endif #ifdef USE_PPC_VPMSUM /*-- crc-ppc.c --*/ void _gcry_crc32_ppc8_vpmsum (u32 *pcrc, const byte *inbuf, size_t inlen); void _gcry_crc24rfc2440_ppc8_vpmsum (u32 *pcrc, const byte *inbuf, size_t inlen); #endif /* * Code generated by universal_crc by Danjel McGougan * * CRC parameters used: * bits: 32 * poly: 0x04c11db7 * init: 0xffffffff * xor: 0xffffffff * reverse: true * non-direct: false * * CRC of the string "123456789" is 0xcbf43926 */ static const u32 crc32_table[1024] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72, 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed, 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1 }; /* CRC32 */ static inline u32 crc32_next (u32 crc, byte data) { return (crc >> 8) ^ crc32_table[(crc & 0xff) ^ data]; } /* * Process 4 bytes in one go */ static inline u32 crc32_next4 (u32 crc, u32 data) { crc ^= data; crc = crc32_table[(crc & 0xff) + 0x300] ^ crc32_table[((crc >> 8) & 0xff) + 0x200] ^ crc32_table[((crc >> 16) & 0xff) + 0x100] ^ crc32_table[(crc >> 24) & 0xff]; return crc; } static void crc32_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; u32 hwf = _gcry_get_hw_features (); #ifdef USE_INTEL_PCLMUL ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); #endif #ifdef USE_ARM_PMULL ctx->use_pmull = (hwf & HWF_ARM_NEON) && (hwf & HWF_ARM_PMULL); #endif #ifdef USE_PPC_VPMSUM ctx->use_vpmsum = !!(hwf & HWF_PPC_ARCH_2_07); #endif (void)flags; (void)hwf; ctx->CRC = 0 ^ 0xffffffffL; } static void crc32_write (void *context, const void *inbuf_arg, size_t inlen) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; const byte *inbuf = inbuf_arg; u32 crc; #ifdef USE_INTEL_PCLMUL if (ctx->use_pclmul) { _gcry_crc32_intel_pclmul(&ctx->CRC, inbuf, inlen); return; } #endif #ifdef USE_ARM_PMULL if (ctx->use_pmull) { _gcry_crc32_armv8_ce_pmull(&ctx->CRC, inbuf, inlen); return; } #endif #ifdef USE_PPC_VPMSUM if (ctx->use_vpmsum) { _gcry_crc32_ppc8_vpmsum(&ctx->CRC, inbuf, inlen); return; } #endif if (!inbuf || !inlen) return; crc = ctx->CRC; while (inlen >= 16) { inlen -= 16; crc = crc32_next4(crc, buf_get_le32(&inbuf[0])); crc = crc32_next4(crc, buf_get_le32(&inbuf[4])); crc = crc32_next4(crc, buf_get_le32(&inbuf[8])); crc = crc32_next4(crc, buf_get_le32(&inbuf[12])); inbuf += 16; } while (inlen >= 4) { inlen -= 4; crc = crc32_next4(crc, buf_get_le32(inbuf)); inbuf += 4; } while (inlen--) { crc = crc32_next(crc, *inbuf++); } ctx->CRC = crc; } static byte * crc32_read (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; return ctx->buf; } static void crc32_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; ctx->CRC ^= 0xffffffffL; buf_put_be32 (ctx->buf, ctx->CRC); } /* CRC32 a'la RFC 1510 */ /* CRC of the string "123456789" is 0x2dfd2d88 */ static void crc32rfc1510_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; u32 hwf = _gcry_get_hw_features (); #ifdef USE_INTEL_PCLMUL ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); #endif #ifdef USE_ARM_PMULL ctx->use_pmull = (hwf & HWF_ARM_NEON) && (hwf & HWF_ARM_PMULL); #endif #ifdef USE_PPC_VPMSUM ctx->use_vpmsum = !!(hwf & HWF_PPC_ARCH_2_07); #endif (void)flags; (void)hwf; ctx->CRC = 0; } static void crc32rfc1510_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; buf_put_be32(ctx->buf, ctx->CRC); } /* CRC24 a'la RFC 2440 */ /* * Code generated by universal_crc by Danjel McGougan * * CRC parameters used: * bits: 24 * poly: 0x864cfb * init: 0xb704ce * xor: 0x000000 * reverse: false * non-direct: false * * CRC of the string "123456789" is 0x21cf02 */ static const u32 crc24_table[1024] = { 0x00000000, 0x00fb4c86, 0x000dd58a, 0x00f6990c, 0x00e1e693, 0x001aaa15, 0x00ec3319, 0x00177f9f, 0x003981a1, 0x00c2cd27, 0x0034542b, 0x00cf18ad, 0x00d86732, 0x00232bb4, 0x00d5b2b8, 0x002efe3e, 0x00894ec5, 0x00720243, 0x00849b4f, 0x007fd7c9, 0x0068a856, 0x0093e4d0, 0x00657ddc, 0x009e315a, 0x00b0cf64, 0x004b83e2, 0x00bd1aee, 0x00465668, 0x005129f7, 0x00aa6571, 0x005cfc7d, 0x00a7b0fb, 0x00e9d10c, 0x00129d8a, 0x00e40486, 0x001f4800, 0x0008379f, 0x00f37b19, 0x0005e215, 0x00feae93, 0x00d050ad, 0x002b1c2b, 0x00dd8527, 0x0026c9a1, 0x0031b63e, 0x00cafab8, 0x003c63b4, 0x00c72f32, 0x00609fc9, 0x009bd34f, 0x006d4a43, 0x009606c5, 0x0081795a, 0x007a35dc, 0x008cacd0, 0x0077e056, 0x00591e68, 0x00a252ee, 0x0054cbe2, 0x00af8764, 0x00b8f8fb, 0x0043b47d, 0x00b52d71, 0x004e61f7, 0x00d2a319, 0x0029ef9f, 0x00df7693, 0x00243a15, 0x0033458a, 0x00c8090c, 0x003e9000, 0x00c5dc86, 0x00eb22b8, 0x00106e3e, 0x00e6f732, 0x001dbbb4, 0x000ac42b, 0x00f188ad, 0x000711a1, 0x00fc5d27, 0x005beddc, 0x00a0a15a, 0x00563856, 0x00ad74d0, 0x00ba0b4f, 0x004147c9, 0x00b7dec5, 0x004c9243, 0x00626c7d, 0x009920fb, 0x006fb9f7, 0x0094f571, 0x00838aee, 0x0078c668, 0x008e5f64, 0x007513e2, 0x003b7215, 0x00c03e93, 0x0036a79f, 0x00cdeb19, 0x00da9486, 0x0021d800, 0x00d7410c, 0x002c0d8a, 0x0002f3b4, 0x00f9bf32, 0x000f263e, 0x00f46ab8, 0x00e31527, 0x001859a1, 0x00eec0ad, 0x00158c2b, 0x00b23cd0, 0x00497056, 0x00bfe95a, 0x0044a5dc, 0x0053da43, 0x00a896c5, 0x005e0fc9, 0x00a5434f, 0x008bbd71, 0x0070f1f7, 0x008668fb, 0x007d247d, 0x006a5be2, 0x00911764, 0x00678e68, 0x009cc2ee, 0x00a44733, 0x005f0bb5, 0x00a992b9, 0x0052de3f, 0x0045a1a0, 0x00beed26, 0x0048742a, 0x00b338ac, 0x009dc692, 0x00668a14, 0x00901318, 0x006b5f9e, 0x007c2001, 0x00876c87, 0x0071f58b, 0x008ab90d, 0x002d09f6, 0x00d64570, 0x0020dc7c, 0x00db90fa, 0x00ccef65, 0x0037a3e3, 0x00c13aef, 0x003a7669, 0x00148857, 0x00efc4d1, 0x00195ddd, 0x00e2115b, 0x00f56ec4, 0x000e2242, 0x00f8bb4e, 0x0003f7c8, 0x004d963f, 0x00b6dab9, 0x004043b5, 0x00bb0f33, 0x00ac70ac, 0x00573c2a, 0x00a1a526, 0x005ae9a0, 0x0074179e, 0x008f5b18, 0x0079c214, 0x00828e92, 0x0095f10d, 0x006ebd8b, 0x00982487, 0x00636801, 0x00c4d8fa, 0x003f947c, 0x00c90d70, 0x003241f6, 0x00253e69, 0x00de72ef, 0x0028ebe3, 0x00d3a765, 0x00fd595b, 0x000615dd, 0x00f08cd1, 0x000bc057, 0x001cbfc8, 0x00e7f34e, 0x00116a42, 0x00ea26c4, 0x0076e42a, 0x008da8ac, 0x007b31a0, 0x00807d26, 0x009702b9, 0x006c4e3f, 0x009ad733, 0x00619bb5, 0x004f658b, 0x00b4290d, 0x0042b001, 0x00b9fc87, 0x00ae8318, 0x0055cf9e, 0x00a35692, 0x00581a14, 0x00ffaaef, 0x0004e669, 0x00f27f65, 0x000933e3, 0x001e4c7c, 0x00e500fa, 0x001399f6, 0x00e8d570, 0x00c62b4e, 0x003d67c8, 0x00cbfec4, 0x0030b242, 0x0027cddd, 0x00dc815b, 0x002a1857, 0x00d154d1, 0x009f3526, 0x006479a0, 0x0092e0ac, 0x0069ac2a, 0x007ed3b5, 0x00859f33, 0x0073063f, 0x00884ab9, 0x00a6b487, 0x005df801, 0x00ab610d, 0x00502d8b, 0x00475214, 0x00bc1e92, 0x004a879e, 0x00b1cb18, 0x00167be3, 0x00ed3765, 0x001bae69, 0x00e0e2ef, 0x00f79d70, 0x000cd1f6, 0x00fa48fa, 0x0001047c, 0x002ffa42, 0x00d4b6c4, 0x00222fc8, 0x00d9634e, 0x00ce1cd1, 0x00355057, 0x00c3c95b, 0x003885dd, 0x00000000, 0x00488f66, 0x00901ecd, 0x00d891ab, 0x00db711c, 0x0093fe7a, 0x004b6fd1, 0x0003e0b7, 0x00b6e338, 0x00fe6c5e, 0x0026fdf5, 0x006e7293, 0x006d9224, 0x00251d42, 0x00fd8ce9, 0x00b5038f, 0x006cc771, 0x00244817, 0x00fcd9bc, 0x00b456da, 0x00b7b66d, 0x00ff390b, 0x0027a8a0, 0x006f27c6, 0x00da2449, 0x0092ab2f, 0x004a3a84, 0x0002b5e2, 0x00015555, 0x0049da33, 0x00914b98, 0x00d9c4fe, 0x00d88ee3, 0x00900185, 0x0048902e, 0x00001f48, 0x0003ffff, 0x004b7099, 0x0093e132, 0x00db6e54, 0x006e6ddb, 0x0026e2bd, 0x00fe7316, 0x00b6fc70, 0x00b51cc7, 0x00fd93a1, 0x0025020a, 0x006d8d6c, 0x00b44992, 0x00fcc6f4, 0x0024575f, 0x006cd839, 0x006f388e, 0x0027b7e8, 0x00ff2643, 0x00b7a925, 0x0002aaaa, 0x004a25cc, 0x0092b467, 0x00da3b01, 0x00d9dbb6, 0x009154d0, 0x0049c57b, 0x00014a1d, 0x004b5141, 0x0003de27, 0x00db4f8c, 0x0093c0ea, 0x0090205d, 0x00d8af3b, 0x00003e90, 0x0048b1f6, 0x00fdb279, 0x00b53d1f, 0x006dacb4, 0x002523d2, 0x0026c365, 0x006e4c03, 0x00b6dda8, 0x00fe52ce, 0x00279630, 0x006f1956, 0x00b788fd, 0x00ff079b, 0x00fce72c, 0x00b4684a, 0x006cf9e1, 0x00247687, 0x00917508, 0x00d9fa6e, 0x00016bc5, 0x0049e4a3, 0x004a0414, 0x00028b72, 0x00da1ad9, 0x009295bf, 0x0093dfa2, 0x00db50c4, 0x0003c16f, 0x004b4e09, 0x0048aebe, 0x000021d8, 0x00d8b073, 0x00903f15, 0x00253c9a, 0x006db3fc, 0x00b52257, 0x00fdad31, 0x00fe4d86, 0x00b6c2e0, 0x006e534b, 0x0026dc2d, 0x00ff18d3, 0x00b797b5, 0x006f061e, 0x00278978, 0x002469cf, 0x006ce6a9, 0x00b47702, 0x00fcf864, 0x0049fbeb, 0x0001748d, 0x00d9e526, 0x00916a40, 0x00928af7, 0x00da0591, 0x0002943a, 0x004a1b5c, 0x0096a282, 0x00de2de4, 0x0006bc4f, 0x004e3329, 0x004dd39e, 0x00055cf8, 0x00ddcd53, 0x00954235, 0x002041ba, 0x0068cedc, 0x00b05f77, 0x00f8d011, 0x00fb30a6, 0x00b3bfc0, 0x006b2e6b, 0x0023a10d, 0x00fa65f3, 0x00b2ea95, 0x006a7b3e, 0x0022f458, 0x002114ef, 0x00699b89, 0x00b10a22, 0x00f98544, 0x004c86cb, 0x000409ad, 0x00dc9806, 0x00941760, 0x0097f7d7, 0x00df78b1, 0x0007e91a, 0x004f667c, 0x004e2c61, 0x0006a307, 0x00de32ac, 0x0096bdca, 0x00955d7d, 0x00ddd21b, 0x000543b0, 0x004dccd6, 0x00f8cf59, 0x00b0403f, 0x0068d194, 0x00205ef2, 0x0023be45, 0x006b3123, 0x00b3a088, 0x00fb2fee, 0x0022eb10, 0x006a6476, 0x00b2f5dd, 0x00fa7abb, 0x00f99a0c, 0x00b1156a, 0x006984c1, 0x00210ba7, 0x00940828, 0x00dc874e, 0x000416e5, 0x004c9983, 0x004f7934, 0x0007f652, 0x00df67f9, 0x0097e89f, 0x00ddf3c3, 0x00957ca5, 0x004ded0e, 0x00056268, 0x000682df, 0x004e0db9, 0x00969c12, 0x00de1374, 0x006b10fb, 0x00239f9d, 0x00fb0e36, 0x00b38150, 0x00b061e7, 0x00f8ee81, 0x00207f2a, 0x0068f04c, 0x00b134b2, 0x00f9bbd4, 0x00212a7f, 0x0069a519, 0x006a45ae, 0x0022cac8, 0x00fa5b63, 0x00b2d405, 0x0007d78a, 0x004f58ec, 0x0097c947, 0x00df4621, 0x00dca696, 0x009429f0, 0x004cb85b, 0x0004373d, 0x00057d20, 0x004df246, 0x009563ed, 0x00ddec8b, 0x00de0c3c, 0x0096835a, 0x004e12f1, 0x00069d97, 0x00b39e18, 0x00fb117e, 0x002380d5, 0x006b0fb3, 0x0068ef04, 0x00206062, 0x00f8f1c9, 0x00b07eaf, 0x0069ba51, 0x00213537, 0x00f9a49c, 0x00b12bfa, 0x00b2cb4d, 0x00fa442b, 0x0022d580, 0x006a5ae6, 0x00df5969, 0x0097d60f, 0x004f47a4, 0x0007c8c2, 0x00042875, 0x004ca713, 0x009436b8, 0x00dcb9de, 0x00000000, 0x00d70983, 0x00555f80, 0x00825603, 0x0051f286, 0x0086fb05, 0x0004ad06, 0x00d3a485, 0x0059a88b, 0x008ea108, 0x000cf70b, 0x00dbfe88, 0x00085a0d, 0x00df538e, 0x005d058d, 0x008a0c0e, 0x00491c91, 0x009e1512, 0x001c4311, 0x00cb4a92, 0x0018ee17, 0x00cfe794, 0x004db197, 0x009ab814, 0x0010b41a, 0x00c7bd99, 0x0045eb9a, 0x0092e219, 0x0041469c, 0x00964f1f, 0x0014191c, 0x00c3109f, 0x006974a4, 0x00be7d27, 0x003c2b24, 0x00eb22a7, 0x00388622, 0x00ef8fa1, 0x006dd9a2, 0x00bad021, 0x0030dc2f, 0x00e7d5ac, 0x006583af, 0x00b28a2c, 0x00612ea9, 0x00b6272a, 0x00347129, 0x00e378aa, 0x00206835, 0x00f761b6, 0x007537b5, 0x00a23e36, 0x00719ab3, 0x00a69330, 0x0024c533, 0x00f3ccb0, 0x0079c0be, 0x00aec93d, 0x002c9f3e, 0x00fb96bd, 0x00283238, 0x00ff3bbb, 0x007d6db8, 0x00aa643b, 0x0029a4ce, 0x00fead4d, 0x007cfb4e, 0x00abf2cd, 0x00785648, 0x00af5fcb, 0x002d09c8, 0x00fa004b, 0x00700c45, 0x00a705c6, 0x002553c5, 0x00f25a46, 0x0021fec3, 0x00f6f740, 0x0074a143, 0x00a3a8c0, 0x0060b85f, 0x00b7b1dc, 0x0035e7df, 0x00e2ee5c, 0x00314ad9, 0x00e6435a, 0x00641559, 0x00b31cda, 0x003910d4, 0x00ee1957, 0x006c4f54, 0x00bb46d7, 0x0068e252, 0x00bfebd1, 0x003dbdd2, 0x00eab451, 0x0040d06a, 0x0097d9e9, 0x00158fea, 0x00c28669, 0x001122ec, 0x00c62b6f, 0x00447d6c, 0x009374ef, 0x001978e1, 0x00ce7162, 0x004c2761, 0x009b2ee2, 0x00488a67, 0x009f83e4, 0x001dd5e7, 0x00cadc64, 0x0009ccfb, 0x00dec578, 0x005c937b, 0x008b9af8, 0x00583e7d, 0x008f37fe, 0x000d61fd, 0x00da687e, 0x00506470, 0x00876df3, 0x00053bf0, 0x00d23273, 0x000196f6, 0x00d69f75, 0x0054c976, 0x0083c0f5, 0x00a9041b, 0x007e0d98, 0x00fc5b9b, 0x002b5218, 0x00f8f69d, 0x002fff1e, 0x00ada91d, 0x007aa09e, 0x00f0ac90, 0x0027a513, 0x00a5f310, 0x0072fa93, 0x00a15e16, 0x00765795, 0x00f40196, 0x00230815, 0x00e0188a, 0x00371109, 0x00b5470a, 0x00624e89, 0x00b1ea0c, 0x0066e38f, 0x00e4b58c, 0x0033bc0f, 0x00b9b001, 0x006eb982, 0x00ecef81, 0x003be602, 0x00e84287, 0x003f4b04, 0x00bd1d07, 0x006a1484, 0x00c070bf, 0x0017793c, 0x00952f3f, 0x004226bc, 0x00918239, 0x00468bba, 0x00c4ddb9, 0x0013d43a, 0x0099d834, 0x004ed1b7, 0x00cc87b4, 0x001b8e37, 0x00c82ab2, 0x001f2331, 0x009d7532, 0x004a7cb1, 0x00896c2e, 0x005e65ad, 0x00dc33ae, 0x000b3a2d, 0x00d89ea8, 0x000f972b, 0x008dc128, 0x005ac8ab, 0x00d0c4a5, 0x0007cd26, 0x00859b25, 0x005292a6, 0x00813623, 0x00563fa0, 0x00d469a3, 0x00036020, 0x0080a0d5, 0x0057a956, 0x00d5ff55, 0x0002f6d6, 0x00d15253, 0x00065bd0, 0x00840dd3, 0x00530450, 0x00d9085e, 0x000e01dd, 0x008c57de, 0x005b5e5d, 0x0088fad8, 0x005ff35b, 0x00dda558, 0x000aacdb, 0x00c9bc44, 0x001eb5c7, 0x009ce3c4, 0x004bea47, 0x00984ec2, 0x004f4741, 0x00cd1142, 0x001a18c1, 0x009014cf, 0x00471d4c, 0x00c54b4f, 0x001242cc, 0x00c1e649, 0x0016efca, 0x0094b9c9, 0x0043b04a, 0x00e9d471, 0x003eddf2, 0x00bc8bf1, 0x006b8272, 0x00b826f7, 0x006f2f74, 0x00ed7977, 0x003a70f4, 0x00b07cfa, 0x00677579, 0x00e5237a, 0x00322af9, 0x00e18e7c, 0x003687ff, 0x00b4d1fc, 0x0063d87f, 0x00a0c8e0, 0x0077c163, 0x00f59760, 0x00229ee3, 0x00f13a66, 0x002633e5, 0x00a465e6, 0x00736c65, 0x00f9606b, 0x002e69e8, 0x00ac3feb, 0x007b3668, 0x00a892ed, 0x007f9b6e, 0x00fdcd6d, 0x002ac4ee, 0x00000000, 0x00520936, 0x00a4126c, 0x00f61b5a, 0x004825d8, 0x001a2cee, 0x00ec37b4, 0x00be3e82, 0x006b0636, 0x00390f00, 0x00cf145a, 0x009d1d6c, 0x002323ee, 0x00712ad8, 0x00873182, 0x00d538b4, 0x00d60c6c, 0x0084055a, 0x00721e00, 0x00201736, 0x009e29b4, 0x00cc2082, 0x003a3bd8, 0x006832ee, 0x00bd0a5a, 0x00ef036c, 0x00191836, 0x004b1100, 0x00f52f82, 0x00a726b4, 0x00513dee, 0x000334d8, 0x00ac19d8, 0x00fe10ee, 0x00080bb4, 0x005a0282, 0x00e43c00, 0x00b63536, 0x00402e6c, 0x0012275a, 0x00c71fee, 0x009516d8, 0x00630d82, 0x003104b4, 0x008f3a36, 0x00dd3300, 0x002b285a, 0x0079216c, 0x007a15b4, 0x00281c82, 0x00de07d8, 0x008c0eee, 0x0032306c, 0x0060395a, 0x00962200, 0x00c42b36, 0x00111382, 0x00431ab4, 0x00b501ee, 0x00e708d8, 0x0059365a, 0x000b3f6c, 0x00fd2436, 0x00af2d00, 0x00a37f36, 0x00f17600, 0x00076d5a, 0x0055646c, 0x00eb5aee, 0x00b953d8, 0x004f4882, 0x001d41b4, 0x00c87900, 0x009a7036, 0x006c6b6c, 0x003e625a, 0x00805cd8, 0x00d255ee, 0x00244eb4, 0x00764782, 0x0075735a, 0x00277a6c, 0x00d16136, 0x00836800, 0x003d5682, 0x006f5fb4, 0x009944ee, 0x00cb4dd8, 0x001e756c, 0x004c7c5a, 0x00ba6700, 0x00e86e36, 0x005650b4, 0x00045982, 0x00f242d8, 0x00a04bee, 0x000f66ee, 0x005d6fd8, 0x00ab7482, 0x00f97db4, 0x00474336, 0x00154a00, 0x00e3515a, 0x00b1586c, 0x006460d8, 0x003669ee, 0x00c072b4, 0x00927b82, 0x002c4500, 0x007e4c36, 0x0088576c, 0x00da5e5a, 0x00d96a82, 0x008b63b4, 0x007d78ee, 0x002f71d8, 0x00914f5a, 0x00c3466c, 0x00355d36, 0x00675400, 0x00b26cb4, 0x00e06582, 0x00167ed8, 0x004477ee, 0x00fa496c, 0x00a8405a, 0x005e5b00, 0x000c5236, 0x0046ff6c, 0x0014f65a, 0x00e2ed00, 0x00b0e436, 0x000edab4, 0x005cd382, 0x00aac8d8, 0x00f8c1ee, 0x002df95a, 0x007ff06c, 0x0089eb36, 0x00dbe200, 0x0065dc82, 0x0037d5b4, 0x00c1ceee, 0x0093c7d8, 0x0090f300, 0x00c2fa36, 0x0034e16c, 0x0066e85a, 0x00d8d6d8, 0x008adfee, 0x007cc4b4, 0x002ecd82, 0x00fbf536, 0x00a9fc00, 0x005fe75a, 0x000dee6c, 0x00b3d0ee, 0x00e1d9d8, 0x0017c282, 0x0045cbb4, 0x00eae6b4, 0x00b8ef82, 0x004ef4d8, 0x001cfdee, 0x00a2c36c, 0x00f0ca5a, 0x0006d100, 0x0054d836, 0x0081e082, 0x00d3e9b4, 0x0025f2ee, 0x0077fbd8, 0x00c9c55a, 0x009bcc6c, 0x006dd736, 0x003fde00, 0x003cead8, 0x006ee3ee, 0x0098f8b4, 0x00caf182, 0x0074cf00, 0x0026c636, 0x00d0dd6c, 0x0082d45a, 0x0057ecee, 0x0005e5d8, 0x00f3fe82, 0x00a1f7b4, 0x001fc936, 0x004dc000, 0x00bbdb5a, 0x00e9d26c, 0x00e5805a, 0x00b7896c, 0x00419236, 0x00139b00, 0x00ada582, 0x00ffacb4, 0x0009b7ee, 0x005bbed8, 0x008e866c, 0x00dc8f5a, 0x002a9400, 0x00789d36, 0x00c6a3b4, 0x0094aa82, 0x0062b1d8, 0x0030b8ee, 0x00338c36, 0x00618500, 0x00979e5a, 0x00c5976c, 0x007ba9ee, 0x0029a0d8, 0x00dfbb82, 0x008db2b4, 0x00588a00, 0x000a8336, 0x00fc986c, 0x00ae915a, 0x0010afd8, 0x0042a6ee, 0x00b4bdb4, 0x00e6b482, 0x00499982, 0x001b90b4, 0x00ed8bee, 0x00bf82d8, 0x0001bc5a, 0x0053b56c, 0x00a5ae36, 0x00f7a700, 0x00229fb4, 0x00709682, 0x00868dd8, 0x00d484ee, 0x006aba6c, 0x0038b35a, 0x00cea800, 0x009ca136, 0x009f95ee, 0x00cd9cd8, 0x003b8782, 0x00698eb4, 0x00d7b036, 0x0085b900, 0x0073a25a, 0x0021ab6c, 0x00f493d8, 0x00a69aee, 0x005081b4, 0x00028882, 0x00bcb600, 0x00eebf36, 0x0018a46c, 0x004aad5a }; static inline u32 crc24_init (void) { /* Transformed to 32-bit CRC by multiplied by x⁸ and then byte swapped. */ return 0xce04b7; /* _gcry_bswap(0xb704ce << 8) */ } static inline u32 crc24_next (u32 crc, byte data) { return (crc >> 8) ^ crc24_table[(crc & 0xff) ^ data]; } /* * Process 4 bytes in one go */ static inline u32 crc24_next4 (u32 crc, u32 data) { crc ^= data; crc = crc24_table[(crc & 0xff) + 0x300] ^ crc24_table[((crc >> 8) & 0xff) + 0x200] ^ crc24_table[((crc >> 16) & 0xff) + 0x100] ^ crc24_table[(data >> 24) & 0xff]; return crc; } static inline u32 crc24_final (u32 crc) { return crc & 0xffffff; } static void crc24rfc2440_init (void *context, unsigned int flags) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; u32 hwf = _gcry_get_hw_features (); #ifdef USE_INTEL_PCLMUL ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL); #endif #ifdef USE_ARM_PMULL ctx->use_pmull = (hwf & HWF_ARM_NEON) && (hwf & HWF_ARM_PMULL); #endif #ifdef USE_PPC_VPMSUM ctx->use_vpmsum = !!(hwf & HWF_PPC_ARCH_2_07); #endif (void)hwf; (void)flags; ctx->CRC = crc24_init(); } static void crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen) { const unsigned char *inbuf = inbuf_arg; CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; u32 crc; #ifdef USE_INTEL_PCLMUL if (ctx->use_pclmul) { _gcry_crc24rfc2440_intel_pclmul(&ctx->CRC, inbuf, inlen); return; } #endif #ifdef USE_ARM_PMULL if (ctx->use_pmull) { _gcry_crc24rfc2440_armv8_ce_pmull(&ctx->CRC, inbuf, inlen); return; } #endif #ifdef USE_PPC_VPMSUM if (ctx->use_vpmsum) { _gcry_crc24rfc2440_ppc8_vpmsum(&ctx->CRC, inbuf, inlen); return; } #endif if (!inbuf || !inlen) return; crc = ctx->CRC; while (inlen >= 16) { inlen -= 16; crc = crc24_next4(crc, buf_get_le32(&inbuf[0])); crc = crc24_next4(crc, buf_get_le32(&inbuf[4])); crc = crc24_next4(crc, buf_get_le32(&inbuf[8])); crc = crc24_next4(crc, buf_get_le32(&inbuf[12])); inbuf += 16; } while (inlen >= 4) { inlen -= 4; crc = crc24_next4(crc, buf_get_le32(inbuf)); inbuf += 4; } while (inlen--) { crc = crc24_next(crc, *inbuf++); } ctx->CRC = crc; } static void crc24rfc2440_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; ctx->CRC = crc24_final(ctx->CRC); buf_put_le32 (ctx->buf, ctx->CRC); } /* We allow the CRC algorithms even in FIPS mode because they are actually no cryptographic primitives. */ -gcry_md_spec_t _gcry_digest_spec_crc32 = +const gcry_md_spec_t _gcry_digest_spec_crc32 = { GCRY_MD_CRC32, {0, 1}, "CRC32", NULL, 0, NULL, 4, crc32_init, crc32_write, crc32_final, crc32_read, NULL, NULL, sizeof (CRC_CONTEXT) }; -gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 = +const gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 = { GCRY_MD_CRC32_RFC1510, {0, 1}, "CRC32RFC1510", NULL, 0, NULL, 4, crc32rfc1510_init, crc32_write, crc32rfc1510_final, crc32_read, NULL, NULL, sizeof (CRC_CONTEXT) }; -gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 = +const gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 = { GCRY_MD_CRC24_RFC2440, {0, 1}, "CRC24RFC2440", NULL, 0, NULL, 3, crc24rfc2440_init, crc24rfc2440_write, crc24rfc2440_final, crc32_read, NULL, NULL, sizeof (CRC_CONTEXT) }; diff --git a/cipher/des.c b/cipher/des.c index ddab0e45..51116fcf 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -1,1507 +1,1507 @@ /* des.c - DES and Triple-DES encryption/decryption Algorithm * Copyright (C) 1998, 1999, 2001, 2002, 2003, * 2008 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * For a description of triple encryption, see: * Bruce Schneier: Applied Cryptography. Second Edition. * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. * This implementation is according to the definition of DES in FIPS * PUB 46-2 from December 1993. */ /* * Written by Michael Roth , September 1998 */ /* * U S A G E * =========== * * For DES or Triple-DES encryption/decryption you must initialize a proper * encryption context with a key. * * A DES key is 64bit wide but only 56bits of the key are used. The remaining * bits are parity bits and they will _not_ checked in this implementation, but * simply ignored. * * For Triple-DES you could use either two 64bit keys or three 64bit keys. * The parity bits will _not_ checked, too. * * After initializing a context with a key you could use this context to * encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode. * * (In the examples below the slashes at the beginning and ending of comments * are omitted.) * * DES Example * ----------- * unsigned char key[8]; * unsigned char plaintext[8]; * unsigned char ciphertext[8]; * unsigned char recoverd[8]; * des_ctx context; * * * Fill 'key' and 'plaintext' with some data * * .... * * * Set up the DES encryption context * * des_setkey(context, key); * * * Encrypt the plaintext * * des_ecb_encrypt(context, plaintext, ciphertext); * * * To recover the original plaintext from ciphertext use: * * des_ecb_decrypt(context, ciphertext, recoverd); * * * Triple-DES Example * ------------------ * unsigned char key1[8]; * unsigned char key2[8]; * unsigned char key3[8]; * unsigned char plaintext[8]; * unsigned char ciphertext[8]; * unsigned char recoverd[8]; * tripledes_ctx context; * * * If you would like to use two 64bit keys, fill 'key1' and'key2' * then setup the encryption context: * * tripledes_set2keys(context, key1, key2); * * * To use three 64bit keys with Triple-DES use: * * tripledes_set3keys(context, key1, key2, key3); * * * Encrypting plaintext with Triple-DES * * tripledes_ecb_encrypt(context, plaintext, ciphertext); * * * Decrypting ciphertext to recover the plaintext with Triple-DES * * tripledes_ecb_decrypt(context, ciphertext, recoverd); * * * Selftest * -------- * char *error_msg; * * * To perform a selftest of this DES/Triple-DES implementation use the * function selftest(). It will return an error string if there are * some problems with this library. * * * if ( (error_msg = selftest()) ) * { * fprintf(stderr, "An error in the DES/Triple-DES implementation occurred: %s\n", error_msg); * abort(); * } */ #include #include #include /* memcpy, memcmp */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "cipher-internal.h" #include "cipher-selftest.h" #define DES_BLOCKSIZE 8 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AMD64_ASM 1 #endif /* Helper macro to force alignment to 16 bytes. */ #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED # define ATTR_ALIGNED_16 __attribute__ ((aligned (16))) #else # define ATTR_ALIGNED_16 #endif #if defined(__GNUC__) && defined(__GNU_LIBRARY__) # define working_memcmp memcmp #else /* * According to the SunOS man page, memcmp returns indeterminate sign * depending on whether characters are signed or not. */ static int working_memcmp( const void *_a, const void *_b, size_t n ) { const char *a = _a; const char *b = _b; for( ; n; n--, a++, b++ ) if( *a != *b ) return (int)(*(byte*)a) - (int)(*(byte*)b); return 0; } #endif /* * Encryption/Decryption context of DES */ typedef struct _des_ctx { u32 encrypt_subkeys[32]; u32 decrypt_subkeys[32]; } des_ctx[1]; /* * Encryption/Decryption context of Triple-DES */ typedef struct _tripledes_ctx { u32 encrypt_subkeys[96]; u32 decrypt_subkeys[96]; struct { int no_weak_key; } flags; } tripledes_ctx[1]; static void des_key_schedule (const byte *, u32 *); static int des_setkey (struct _des_ctx *, const byte *); static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int); static int tripledes_set2keys (struct _tripledes_ctx *, const byte *, const byte *); static int tripledes_set3keys (struct _tripledes_ctx *, const byte *, const byte *, const byte *); static int tripledes_ecb_crypt (struct _tripledes_ctx *, const byte *, byte *, int); static int is_weak_key ( const byte *key ); static const char *selftest (void); static unsigned int do_tripledes_encrypt(void *context, byte *outbuf, const byte *inbuf ); static unsigned int do_tripledes_decrypt(void *context, byte *outbuf, const byte *inbuf ); static gcry_err_code_t do_tripledes_setkey(void *context, const byte *key, unsigned keylen, cipher_bulk_ops_t *bulk_ops); static int initialized; /* * The s-box values are permuted according to the 'primitive function P' * and are rotated one bit to the left. */ static u32 sbox1[64] = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; static u32 sbox2[64] = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; static u32 sbox3[64] = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; static u32 sbox4[64] = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; static u32 sbox5[64] = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; static u32 sbox6[64] = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; static u32 sbox7[64] = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; static u32 sbox8[64] = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; /* * These two tables are part of the 'permuted choice 1' function. * In this implementation several speed improvements are done. */ static u32 leftkey_swap[16] = { 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, 0x01010000, 0x01010001, 0x01010100, 0x01010101 }; static u32 rightkey_swap[16] = { 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, 0x01010101, }; /* * Numbers of left shifts per round for encryption subkeys. * To calculate the decryption subkeys we just reverse the * ordering of the calculated encryption subkeys. So their * is no need for a decryption rotate tab. */ static byte encrypt_rotate_tab[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; /* * Table with weak DES keys sorted in ascending order. * In DES their are 64 known keys which are weak. They are weak * because they produce only one, two or four different * subkeys in the subkey scheduling process. * The keys in this table have all their parity bits cleared. */ static byte weak_keys[64][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*w*/ { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e }, { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe }, { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, /*sw*/ { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 }, { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 }, { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, /*sw*/ { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe }, { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e }, { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, /*sw*/ { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 }, { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 }, { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e }, { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, /*sw*/ { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe }, { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 }, { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, /*w*/ { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 }, { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe }, { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, /*sw*/ { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e }, { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 }, { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, /*sw*/ { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 }, { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 }, { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, /*sw*/ { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe }, { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, /*sw*/ { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 }, { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, /*w*/ { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe }, { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 }, { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, /*sw*/ { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 }, { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 }, { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, /*sw*/ { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe }, { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, /*sw*/ { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 }, { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, /*sw*/ { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e }, { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe } /*w*/ }; static unsigned char weak_keys_chksum[20] = { 0xD0, 0xCF, 0x07, 0x38, 0x93, 0x70, 0x8A, 0x83, 0x7D, 0xD7, 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 }; /* * Macro to swap bits across two words. */ #define DO_PERMUTATION(a, temp, b, offset, mask) \ temp = ((a>>offset) ^ b) & mask; \ b ^= temp; \ a ^= temp<> 31); \ temp = (left ^ right) & 0xaaaaaaaa; \ right ^= temp; \ left ^= temp; \ left = (left << 1) | (left >> 31); /* * The 'inverse initial permutation'. */ #define FINAL_PERMUTATION(left, temp, right) \ left = (left << 31) | (left >> 1); \ temp = (left ^ right) & 0xaaaaaaaa; \ left ^= temp; \ right ^= temp; \ right = (right << 31) | (right >> 1); \ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) /* * A full DES round including 'expansion function', 'sbox substitution' * and 'primitive function P' but without swapping the left and right word. * Please note: The data in 'from' and 'to' is already rotated one bit to * the left, done in the initial permutation. */ #define DES_ROUND(from, to, work, subkey) \ work = from ^ *subkey++; \ to ^= sbox8[ work & 0x3f ]; \ to ^= sbox6[ (work>>8) & 0x3f ]; \ to ^= sbox4[ (work>>16) & 0x3f ]; \ to ^= sbox2[ (work>>24) & 0x3f ]; \ work = ((from << 28) | (from >> 4)) ^ *subkey++; \ to ^= sbox7[ work & 0x3f ]; \ to ^= sbox5[ (work>>8) & 0x3f ]; \ to ^= sbox3[ (work>>16) & 0x3f ]; \ to ^= sbox1[ (work>>24) & 0x3f ]; /* * Macros to convert 8 bytes from/to 32bit words. */ #define READ_64BIT_DATA(data, left, right) \ left = buf_get_be32(data + 0); \ right = buf_get_be32(data + 4); #define WRITE_64BIT_DATA(data, left, right) \ buf_put_be32(data + 0, left); \ buf_put_be32(data + 4, right); /* * Handy macros for encryption and decryption of data */ #define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0) #define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1) #define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,0) #define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,1) /* * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for * 16 encryption rounds. * To calculate subkeys for decryption the caller * have to reorder the generated subkeys. * * rawkey: 8 Bytes of key data * subkey: Array of at least 32 u32s. Will be filled * with calculated subkeys. * */ static void des_key_schedule (const byte * rawkey, u32 * subkey) { u32 left, right, work; int round; READ_64BIT_DATA (rawkey, left, right) DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) DO_PERMUTATION (right, work, left, 0, 0x10101010) left = ((leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4)); left &= 0x0fffffff; right = ((rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4)); right &= 0x0fffffff; for (round = 0; round < 16; ++round) { left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; *subkey++ = (((left << 4) & 0x24000000) | ((left << 28) & 0x10000000) | ((left << 14) & 0x08000000) | ((left << 18) & 0x02080000) | ((left << 6) & 0x01000000) | ((left << 9) & 0x00200000) | ((left >> 1) & 0x00100000) | ((left << 10) & 0x00040000) | ((left << 2) & 0x00020000) | ((left >> 10) & 0x00010000) | ((right >> 13) & 0x00002000) | ((right >> 4) & 0x00001000) | ((right << 6) & 0x00000800) | ((right >> 1) & 0x00000400) | ((right >> 14) & 0x00000200) | (right & 0x00000100) | ((right >> 5) & 0x00000020) | ((right >> 10) & 0x00000010) | ((right >> 3) & 0x00000008) | ((right >> 18) & 0x00000004) | ((right >> 26) & 0x00000002) | ((right >> 24) & 0x00000001)); *subkey++ = (((left << 15) & 0x20000000) | ((left << 17) & 0x10000000) | ((left << 10) & 0x08000000) | ((left << 22) & 0x04000000) | ((left >> 2) & 0x02000000) | ((left << 1) & 0x01000000) | ((left << 16) & 0x00200000) | ((left << 11) & 0x00100000) | ((left << 3) & 0x00080000) | ((left >> 6) & 0x00040000) | ((left << 15) & 0x00020000) | ((left >> 4) & 0x00010000) | ((right >> 2) & 0x00002000) | ((right << 8) & 0x00001000) | ((right >> 14) & 0x00000808) | ((right >> 9) & 0x00000400) | ((right) & 0x00000200) | ((right << 7) & 0x00000100) | ((right >> 7) & 0x00000020) | ((right >> 3) & 0x00000011) | ((right << 2) & 0x00000004) | ((right >> 21) & 0x00000002)); } } /* * Fill a DES context with subkeys calculated from a 64bit key. * Does not check parity bits, but simply ignore them. * Does not check for weak keys. */ static int des_setkey (struct _des_ctx *ctx, const byte * key) { static const char *selftest_failed; int i; if (!fips_mode () && !initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("%s\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; des_key_schedule (key, ctx->encrypt_subkeys); _gcry_burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; } return 0; } /* * Electronic Codebook Mode DES encryption/decryption of data according * to 'mode'. */ static int des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode) { u32 left, right, work; u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; READ_64BIT_DATA (from, left, right) INITIAL_PERMUTATION (left, work, right) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) FINAL_PERMUTATION (right, work, left) WRITE_64BIT_DATA (to, right, left) return 0; } /* * Fill a Triple-DES context with subkeys calculated from two 64bit keys. * Does not check the parity bits of the keys, but simply ignore them. * Does not check for weak keys. */ static int tripledes_set2keys (struct _tripledes_ctx *ctx, const byte * key1, const byte * key2) { int i; des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); _gcry_burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i]; ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1]; ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i]; ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1]; } return 0; } /* * Fill a Triple-DES context with subkeys calculated from three 64bit keys. * Does not check the parity bits of the keys, but simply ignore them. * Does not check for weak keys. */ static int tripledes_set3keys (struct _tripledes_ctx *ctx, const byte * key1, const byte * key2, const byte * key3) { static const char *selftest_failed; int i; if (!fips_mode () && !initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("%s\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); _gcry_burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i]; ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i]; } return 0; } #ifdef USE_AMD64_ASM /* Assembly implementation of triple-DES. */ extern void _gcry_3des_amd64_crypt_block(const void *keys, byte *out, const byte *in); /* These assembly implementations process three blocks in parallel. */ extern void _gcry_3des_amd64_ctr_enc(const void *keys, byte *out, const byte *in, byte *ctr); extern void _gcry_3des_amd64_cbc_dec(const void *keys, byte *out, const byte *in, byte *iv); extern void _gcry_3des_amd64_cfb_dec(const void *keys, byte *out, const byte *in, byte *iv); #define TRIPLEDES_ECB_BURN_STACK (8 * sizeof(void *)) /* * Electronic Codebook Mode Triple-DES encryption/decryption of data * according to 'mode'. Sometimes this mode is named 'EDE' mode * (Encryption-Decryption-Encryption). */ static inline int tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, byte * to, int mode) { u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; _gcry_3des_amd64_crypt_block(keys, to, from); return 0; } static inline void tripledes_amd64_ctr_enc(const void *keys, byte *out, const byte *in, byte *ctr) { _gcry_3des_amd64_ctr_enc(keys, out, in, ctr); } static inline void tripledes_amd64_cbc_dec(const void *keys, byte *out, const byte *in, byte *iv) { _gcry_3des_amd64_cbc_dec(keys, out, in, iv); } static inline void tripledes_amd64_cfb_dec(const void *keys, byte *out, const byte *in, byte *iv) { _gcry_3des_amd64_cfb_dec(keys, out, in, iv); } #else /*USE_AMD64_ASM*/ #define TRIPLEDES_ECB_BURN_STACK 32 /* * Electronic Codebook Mode Triple-DES encryption/decryption of data * according to 'mode'. Sometimes this mode is named 'EDE' mode * (Encryption-Decryption-Encryption). */ static int tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, byte * to, int mode) { u32 left, right, work; u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; READ_64BIT_DATA (from, left, right) INITIAL_PERMUTATION (left, work, right) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) FINAL_PERMUTATION (right, work, left) WRITE_64BIT_DATA (to, right, left) return 0; } #endif /*!USE_AMD64_ASM*/ /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size DES_BLOCKSIZE. */ static void _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { struct _tripledes_ctx *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[DES_BLOCKSIZE]; int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK; #ifdef USE_AMD64_ASM { int asm_burn_depth = 9 * sizeof(void *); if (nblocks >= 3 && burn_stack_depth < asm_burn_depth) burn_stack_depth = asm_burn_depth; /* Process data in 3 block chunks. */ while (nblocks >= 3) { tripledes_amd64_ctr_enc(ctx->encrypt_subkeys, outbuf, inbuf, ctr); nblocks -= 3; outbuf += 3 * DES_BLOCKSIZE; inbuf += 3 * DES_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ tripledes_ecb_encrypt (ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ cipher_block_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE); outbuf += DES_BLOCKSIZE; inbuf += DES_BLOCKSIZE; /* Increment the counter. */ cipher_block_add(ctr, 1, DES_BLOCKSIZE); } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { struct _tripledes_ctx *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[DES_BLOCKSIZE]; int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK; #ifdef USE_AMD64_ASM { int asm_burn_depth = 10 * sizeof(void *); if (nblocks >= 3 && burn_stack_depth < asm_burn_depth) burn_stack_depth = asm_burn_depth; /* Process data in 3 block chunks. */ while (nblocks >= 3) { tripledes_amd64_cbc_dec(ctx->decrypt_subkeys, outbuf, inbuf, iv); nblocks -= 3; outbuf += 3 * DES_BLOCKSIZE; inbuf += 3 * DES_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* INBUF is needed later and it may be identical to OUTBUF, so store the intermediate result to SAVEBUF. */ tripledes_ecb_decrypt (ctx, inbuf, savebuf); cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE); inbuf += DES_BLOCKSIZE; outbuf += DES_BLOCKSIZE; } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { struct _tripledes_ctx *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK; #ifdef USE_AMD64_ASM { int asm_burn_depth = 9 * sizeof(void *); if (nblocks >= 3 && burn_stack_depth < asm_burn_depth) burn_stack_depth = asm_burn_depth; /* Process data in 3 block chunks. */ while (nblocks >= 3) { tripledes_amd64_cfb_dec(ctx->encrypt_subkeys, outbuf, inbuf, iv); nblocks -= 3; outbuf += 3 * DES_BLOCKSIZE; inbuf += 3 * DES_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { tripledes_ecb_encrypt (ctx, iv, iv); cipher_block_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE); outbuf += DES_BLOCKSIZE; inbuf += DES_BLOCKSIZE; } _gcry_burn_stack(burn_stack_depth); } /* * Check whether the 8 byte key is weak. * Does not check the parity bits of the key but simple ignore them. */ static int is_weak_key ( const byte *key ) { byte work[8]; int i, left, right, middle, cmp_result; /* clear parity bits */ for(i=0; i<8; ++i) work[i] = key[i] & 0xfe; /* binary search in the weak key table */ left = 0; right = 63; while(left <= right) { middle = (left + right) / 2; if ( !(cmp_result=working_memcmp(work, weak_keys[middle], 8)) ) return -1; if ( cmp_result > 0 ) left = middle + 1; else right = middle - 1; } return 0; } /* Alternative setkey for selftests; need larger key than default. */ static gcry_err_code_t bulk_selftest_setkey (void *context, const byte *__key, unsigned __keylen, cipher_bulk_ops_t *bulk_ops) { static const unsigned char key[24] ATTR_ALIGNED_16 = { 0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22, 0x18,0x2A,0x39,0x47,0x5E,0x6F,0x75,0x82 }; (void)__key; (void)__keylen; return do_tripledes_setkey(context, key, sizeof(key), bulk_ops); } /* Run the self-tests for DES-CTR, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char * selftest_ctr (void) { const int nblocks = 3+1; const int blocksize = DES_BLOCKSIZE; const int context_size = sizeof(struct _tripledes_ctx); return _gcry_selftest_helper_ctr("3DES", &bulk_selftest_setkey, &do_tripledes_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for DES-CBC, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cbc (void) { const int nblocks = 3+2; const int blocksize = DES_BLOCKSIZE; const int context_size = sizeof(struct _tripledes_ctx); return _gcry_selftest_helper_cbc("3DES", &bulk_selftest_setkey, &do_tripledes_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for DES-CFB, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cfb (void) { const int nblocks = 3+2; const int blocksize = DES_BLOCKSIZE; const int context_size = sizeof(struct _tripledes_ctx); return _gcry_selftest_helper_cfb("3DES", &bulk_selftest_setkey, &do_tripledes_encrypt, nblocks, blocksize, context_size); } /* * Performs a selftest of this DES/Triple-DES implementation. * Returns an string with the error text on failure. * Returns NULL if all is ok. */ static const char * selftest (void) { const char *r; /* * Check if 'u32' is really 32 bits wide. This DES / 3DES implementation * need this. */ if (sizeof (u32) != 4) return "Wrong word size for DES configured."; /* * DES Maintenance Test */ { int i; byte key[8] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; byte input[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; byte result[8] = {0x24, 0x6e, 0x9d, 0xb9, 0xc5, 0x50, 0x38, 0x1a}; byte temp1[8], temp2[8], temp3[8]; des_ctx des; for (i = 0; i < 64; ++i) { des_setkey (des, key); des_ecb_encrypt (des, input, temp1); des_ecb_encrypt (des, temp1, temp2); des_setkey (des, temp2); des_ecb_decrypt (des, temp1, temp3); memcpy (key, temp3, 8); memcpy (input, temp1, 8); } if (memcmp (temp3, result, 8)) return "DES maintenance test failed."; } /* * Self made Triple-DES test (Does somebody know an official test?) */ { int i; byte input[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; byte key1[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; byte key2[8] = {0x11, 0x22, 0x33, 0x44, 0xff, 0xaa, 0xcc, 0xdd}; byte result[8] = {0x7b, 0x38, 0x3b, 0x23, 0xa2, 0x7d, 0x26, 0xd3}; tripledes_ctx des3; for (i = 0; i < 16; ++i) { tripledes_set2keys (des3, key1, key2); tripledes_ecb_encrypt (des3, input, key1); tripledes_ecb_decrypt (des3, input, key2); tripledes_set3keys (des3, key1, input, key2); tripledes_ecb_encrypt (des3, input, input); } if (memcmp (input, result, 8)) return "Triple-DES test failed."; } /* * More Triple-DES test. These are testvectors as used by SSLeay, * thanks to Jeroen C. van Gelderen. */ { static const struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, { 0x9D,0x64,0x55,0x5A,0x9A,0x10,0xB8,0x52, }, { 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00 } }, { { 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E }, { 0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A }, { 0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A } }, { { 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6 }, { 0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2 }, { 0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0x3D,0x12,0x4F,0xE2,0x19,0x8B,0xA3,0x18 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0xFB,0xAB,0xA1,0xFF,0x9D,0x05,0xE9,0xB1 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0x18,0xd7,0x48,0xe5,0x63,0x62,0x05,0x72 } }, { { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 } }, { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0xe6,0xe6,0xdd,0x5b,0x7e,0x72,0x29,0x74 } }, { { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } } }; byte result[8]; int i; tripledes_ctx des3; for (i=0; icbc_dec = _gcry_3des_cbc_dec; bulk_ops->cfb_dec = _gcry_3des_cfb_dec; bulk_ops->ctr_enc = _gcry_3des_ctr_enc; tripledes_set3keys ( ctx, key, key+8, key+16); if (ctx->flags.no_weak_key) ; /* Detection has been disabled. */ else if (is_weak_key (key) || is_weak_key (key+8) || is_weak_key (key+16)) { _gcry_burn_stack (64); return GPG_ERR_WEAK_KEY; } _gcry_burn_stack (64); return GPG_ERR_NO_ERROR; } static gcry_err_code_t do_tripledes_set_extra_info (void *context, int what, const void *buffer, size_t buflen) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *)context; gpg_err_code_t ec = 0; (void)buffer; (void)buflen; switch (what) { case CIPHER_INFO_NO_WEAK_KEY: ctx->flags.no_weak_key = 1; break; default: ec = GPG_ERR_INV_OP; break; } return ec; } static unsigned int do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ TRIPLEDES_ECB_BURN_STACK; } static unsigned int do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ TRIPLEDES_ECB_BURN_STACK; } static gcry_err_code_t do_des_setkey (void *context, const byte *key, unsigned keylen, cipher_bulk_ops_t *bulk_ops) { struct _des_ctx *ctx = (struct _des_ctx *) context; (void)bulk_ops; if (keylen != 8) return GPG_ERR_INV_KEYLEN; des_setkey (ctx, key); if (is_weak_key (key)) { _gcry_burn_stack (64); return GPG_ERR_WEAK_KEY; } _gcry_burn_stack (64); return GPG_ERR_NO_ERROR; } static unsigned int do_des_encrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _des_ctx *ctx = (struct _des_ctx *) context; des_ecb_encrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ (32); } static unsigned int do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _des_ctx *ctx = (struct _des_ctx *) context; des_ecb_decrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ (32); } /* Self-test section. */ /* Selftest for TripleDES. */ static gpg_err_code_t selftest_fips (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; (void)extended; /* No extended tests available. */ what = "low-level"; errtxt = selftest (); if (errtxt) goto failed; /* The low-level self-tests are quite extensive and thus we can do without high level tests. This is also justified because we have no custom block code implementation for 3des but always use the standard high level block code. */ return 0; /* Succeeded. */ failed: if (report) report ("cipher", GCRY_CIPHER_3DES, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_CIPHER_3DES: ec = selftest_fips (extended, report); break; default: ec = GPG_ERR_CIPHER_ALGO; break; } return ec; } gcry_cipher_spec_t _gcry_cipher_spec_des = { GCRY_CIPHER_DES, {0, 0}, "DES", NULL, NULL, 8, 64, sizeof (struct _des_ctx), do_des_setkey, do_des_encrypt, do_des_decrypt }; -static gcry_cipher_oid_spec_t oids_tripledes[] = +static const gcry_cipher_oid_spec_t oids_tripledes[] = { { "1.2.840.113549.3.7", GCRY_CIPHER_MODE_CBC }, /* Teletrust specific OID for 3DES. */ { "1.3.36.3.1.3.2.1", GCRY_CIPHER_MODE_CBC }, /* pbeWithSHAAnd3_KeyTripleDES_CBC */ { "1.2.840.113549.1.12.1.3", GCRY_CIPHER_MODE_CBC }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_tripledes = { GCRY_CIPHER_3DES, {0, 0}, "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx), do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt, NULL, NULL, run_selftests, do_tripledes_set_extra_info }; diff --git a/cipher/gost28147.c b/cipher/gost28147.c index 9445b378..f094d5ba 100644 --- a/cipher/gost28147.c +++ b/cipher/gost28147.c @@ -1,553 +1,553 @@ /* gost28147.c - GOST 28147-89 implementation for Libgcrypt * Copyright (C) 2012 Free Software Foundation, Inc. * * 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 . */ /* GOST 28147-89 defines several modes of encryption: * - ECB which should be used only for key transfer * - CFB mode * - OFB-like mode with additional transformation on keystream * RFC 5830 names this 'counter encryption' mode * Original GOST text uses the term 'gammirovanie' * - MAC mode ('imitovstavka') * * This implementation handles ECB and CFB modes via usual libgcrypt handling. * OFB-like modes are unsupported. */ #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "mac-internal.h" #include "bufhelp.h" #include "cipher-internal.h" #include "gost.h" #include "gost-sb.h" static void gost_do_set_sbox (GOST28147_context *ctx, unsigned int index) { ctx->sbox = gost_oid_map[index].sbox; ctx->mesh_limit = gost_oid_map[index].keymeshing ? 1024 : 0; } static gcry_err_code_t gost_setkey (void *c, const byte *key, unsigned keylen, cipher_bulk_ops_t *bulk_ops) { int i; GOST28147_context *ctx = c; (void)bulk_ops; if (keylen != 256 / 8) return GPG_ERR_INV_KEYLEN; if (!ctx->sbox) gost_do_set_sbox (ctx, 0); for (i = 0; i < 8; i++) { ctx->key[i] = buf_get_le32(&key[4*i]); } ctx->mesh_counter = 0; return GPG_ERR_NO_ERROR; } static inline u32 gost_val (u32 subkey, u32 cm1, const u32 *sbox) { cm1 += subkey; cm1 = sbox[0*256 + ((cm1 >> 0) & 0xff)] | sbox[1*256 + ((cm1 >> 8) & 0xff)] | sbox[2*256 + ((cm1 >> 16) & 0xff)] | sbox[3*256 + ((cm1 >> 24) & 0xff)]; return cm1; } static unsigned int _gost_encrypt_data (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2) { n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[7], n1, sbox); n1 ^= gost_val (key[6], n2, sbox); n2 ^= gost_val (key[5], n1, sbox); n1 ^= gost_val (key[4], n2, sbox); n2 ^= gost_val (key[3], n1, sbox); n1 ^= gost_val (key[2], n2, sbox); n2 ^= gost_val (key[1], n1, sbox); n1 ^= gost_val (key[0], n2, sbox); *o1 = n2; *o2 = n1; return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + 4*sizeof(void*) /* gost_val call */; } static unsigned int gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; u32 n1, n2; unsigned int burn; n1 = buf_get_le32 (inbuf); n2 = buf_get_le32 (inbuf+4); burn = _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2); buf_put_le32 (outbuf+0, n1); buf_put_le32 (outbuf+4, n2); return /* burn_stack */ burn + 6*sizeof(void*) /* func call */; } unsigned int _gcry_gost_enc_data (const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro) { const u32 *sbox; if (cryptopro) sbox = sbox_CryptoPro_3411; else sbox = sbox_test_3411; return _gost_encrypt_data (sbox, key, o1, o2, n1, n2) + 7 * sizeof(void *); } static unsigned int gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; u32 n1, n2; const u32 *sbox = ctx->sbox; n1 = buf_get_le32 (inbuf); n2 = buf_get_le32 (inbuf+4); n2 ^= gost_val (ctx->key[0], n1, sbox); n1 ^= gost_val (ctx->key[1], n2, sbox); n2 ^= gost_val (ctx->key[2], n1, sbox); n1 ^= gost_val (ctx->key[3], n2, sbox); n2 ^= gost_val (ctx->key[4], n1, sbox); n1 ^= gost_val (ctx->key[5], n2, sbox); n2 ^= gost_val (ctx->key[6], n1, sbox); n1 ^= gost_val (ctx->key[7], n2, sbox); n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox); n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox); n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox); n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox); n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox); n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox); n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox); n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox); n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox); n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox); n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox); n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox); buf_put_le32 (outbuf+0, n2); buf_put_le32 (outbuf+4, n1); return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + 4*sizeof(void*) /* gost_val call */; } static gpg_err_code_t gost_set_sbox (GOST28147_context *ctx, const char *oid) { int i; for (i = 0; gost_oid_map[i].oid; i++) { if (!strcmp(gost_oid_map[i].oid, oid)) { gost_do_set_sbox (ctx, i); return 0; } } return GPG_ERR_VALUE_NOT_FOUND; } static gpg_err_code_t gost_set_extra_info (void *c, int what, const void *buffer, size_t buflen) { GOST28147_context *ctx = c; gpg_err_code_t ec = 0; (void)buffer; (void)buflen; switch (what) { case GCRYCTL_SET_SBOX: ec = gost_set_sbox (ctx, buffer); break; default: ec = GPG_ERR_INV_OP; break; } return ec; } static const byte CryptoProKeyMeshingKey[] = { 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B }; /* Implements key meshing algorithm by modifing ctx and returning new IV. Thanks to Dmitry Belyavskiy. */ static void cryptopro_key_meshing (GOST28147_context *ctx) { unsigned char newkey[32]; unsigned int i; /* "Decrypt" the static keymeshing key */ for (i = 0; i < 4; i++) { gost_decrypt_block (ctx, newkey + i*8, CryptoProKeyMeshingKey + i*8); } /* Set new key */ for (i = 0; i < 8; i++) { ctx->key[i] = buf_get_le32(&newkey[4*i]); } ctx->mesh_counter = 0; } static unsigned int gost_encrypt_block_mesh (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; u32 n1, n2; unsigned int burn; n1 = buf_get_le32 (inbuf); n2 = buf_get_le32 (inbuf+4); if (ctx->mesh_limit && (ctx->mesh_counter == ctx->mesh_limit)) { cryptopro_key_meshing (ctx); /* Yes, encrypt twice: once for KeyMeshing procedure per RFC 4357, * once for block encryption */ _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2); } burn = _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2); ctx->mesh_counter += 8; buf_put_le32 (outbuf+0, n1); buf_put_le32 (outbuf+4, n2); return /* burn_stack */ burn + 6*sizeof(void*) /* func call */; } -static gcry_cipher_oid_spec_t oids_gost28147_mesh[] = +static const gcry_cipher_oid_spec_t oids_gost28147_mesh[] = { { "1.2.643.2.2.21", GCRY_CIPHER_MODE_CFB }, /* { "1.2.643.2.2.31.0", GCRY_CIPHER_MODE_CNTGOST }, */ { "1.2.643.2.2.31.1", GCRY_CIPHER_MODE_CFB }, { "1.2.643.2.2.31.2", GCRY_CIPHER_MODE_CFB }, { "1.2.643.2.2.31.3", GCRY_CIPHER_MODE_CFB }, { "1.2.643.2.2.31.4", GCRY_CIPHER_MODE_CFB }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_gost28147 = { GCRY_CIPHER_GOST28147, {0, 0}, "GOST28147", NULL, NULL, 8, 256, sizeof (GOST28147_context), gost_setkey, gost_encrypt_block, gost_decrypt_block, NULL, NULL, NULL, gost_set_extra_info, }; /* Meshing is used only for CFB, so no need to have separate * gost_decrypt_block_mesh. * Moreover key meshing is specified as encrypting the block (IV). Decrypting * it afterwards would be meaningless. */ gcry_cipher_spec_t _gcry_cipher_spec_gost28147_mesh = { GCRY_CIPHER_GOST28147_MESH, {0, 0}, "GOST28147_MESH", NULL, oids_gost28147_mesh, 8, 256, sizeof (GOST28147_context), gost_setkey, gost_encrypt_block_mesh, gost_decrypt_block, NULL, NULL, NULL, gost_set_extra_info, }; static gcry_err_code_t gost_imit_open (gcry_mac_hd_t h) { memset(&h->u.imit, 0, sizeof(h->u.imit)); return 0; } static void gost_imit_close (gcry_mac_hd_t h) { (void) h; } static gcry_err_code_t gost_imit_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { int i; if (keylen != 256 / 8) return GPG_ERR_INV_KEYLEN; if (!h->u.imit.ctx.sbox) h->u.imit.ctx.sbox = sbox_CryptoPro_A; for (i = 0; i < 8; i++) { h->u.imit.ctx.key[i] = buf_get_le32(&key[4*i]); } return 0; } static gcry_err_code_t gost_imit_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { if (ivlen != 8) return GPG_ERR_INV_LENGTH; h->u.imit.n1 = buf_get_le32 (iv + 0); h->u.imit.n2 = buf_get_le32 (iv + 4); return 0; } static gcry_err_code_t gost_imit_reset (gcry_mac_hd_t h) { h->u.imit.n1 = h->u.imit.n2 = 0; h->u.imit.unused = 0; return 0; } static unsigned int _gost_imit_block (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2) { n1 ^= *o1; n2 ^= *o2; n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); *o1 = n1; *o2 = n2; return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + 4*sizeof(void*) /* gost_val call */; } static inline unsigned int gost_imit_block (GOST28147_context *ctx, u32 *n1, u32 *n2, const unsigned char *buf) { if (ctx->mesh_limit && (ctx->mesh_counter == ctx->mesh_limit)) cryptopro_key_meshing (ctx); return _gost_imit_block (ctx->sbox, ctx->key, n1, n2, buf_get_le32 (buf+0), buf_get_le32 (buf+4)); } static gcry_err_code_t gost_imit_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { const int blocksize = 8; unsigned int burn = 0; if (!buflen || !buf) return GPG_ERR_NO_ERROR; if (h->u.imit.unused) { for (; buflen && h->u.imit.unused < blocksize; buflen --) h->u.imit.lastiv[h->u.imit.unused++] = *buf++; if (h->u.imit.unused < blocksize) return GPG_ERR_NO_ERROR; h->u.imit.count ++; burn = gost_imit_block (&h->u.imit.ctx, &h->u.imit.n1, &h->u.imit.n2, h->u.imit.lastiv); h->u.imit.unused = 0; } while (buflen >= blocksize) { h->u.imit.count ++; burn = gost_imit_block (&h->u.imit.ctx, &h->u.imit.n1, &h->u.imit.n2, buf); buf += blocksize; buflen -= blocksize; } for (; buflen; buflen--) h->u.imit.lastiv[h->u.imit.unused++] = *buf++; _gcry_burn_stack (burn); return GPG_ERR_NO_ERROR; } static void gost_imit_finish (gcry_mac_hd_t h) { static const unsigned char zero[8] = {0}; /* Fill till full block */ if (h->u.imit.unused) gost_imit_write(h, zero, 8 - h->u.imit.unused); if (h->u.imit.count == 1) gost_imit_write(h, zero, 8); } static gcry_err_code_t gost_imit_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { unsigned int dlen = 8; unsigned char digest[8]; gost_imit_finish (h); buf_put_le32 (digest+0, h->u.imit.n1); buf_put_le32 (digest+4, h->u.imit.n2); if (*outlen <= dlen) buf_cpy (outbuf, digest, *outlen); else { buf_cpy (outbuf, digest, dlen); *outlen = dlen; } return 0; } static gcry_err_code_t gost_imit_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { unsigned char tbuf[8]; gost_imit_finish (h); buf_put_le32 (tbuf+0, h->u.imit.n1); buf_put_le32 (tbuf+4, h->u.imit.n2); return buf_eq_const(tbuf, buf, buflen) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } static unsigned int gost_imit_get_maclen (int algo) { (void) algo; return 4; /* or 8 */ } static unsigned int gost_imit_get_keylen (int algo) { (void) algo; return 256 / 8; } static gpg_err_code_t gost_imit_set_extra_info (gcry_mac_hd_t hd, int what, const void *buffer, size_t buflen) { gpg_err_code_t ec = 0; (void)buffer; (void)buflen; switch (what) { case GCRYCTL_SET_SBOX: ec = gost_set_sbox (&hd->u.imit.ctx, buffer); break; default: ec = GPG_ERR_INV_OP; break; } return ec; } static gcry_mac_spec_ops_t gost_imit_ops = { gost_imit_open, gost_imit_close, gost_imit_setkey, gost_imit_setiv, gost_imit_reset, gost_imit_write, gost_imit_read, gost_imit_verify, gost_imit_get_maclen, gost_imit_get_keylen, gost_imit_set_extra_info, NULL }; -gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit = +const gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit = { GCRY_MAC_GOST28147_IMIT, {0, 0}, "GOST28147_IMIT", &gost_imit_ops }; diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c index 588d5dc1..93de83b4 100644 --- a/cipher/gostr3411-94.c +++ b/cipher/gostr3411-94.c @@ -1,383 +1,383 @@ /* gostr3411-94.c - GOST R 34.11-94 hash function * Copyright (C) 2012 Free Software Foundation, Inc. * * 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 . */ #include #include #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" #include "gost.h" #define max(a, b) (((a) > (b)) ? (a) : (b)) typedef struct { gcry_md_block_ctx_t bctx; union { u32 h[8]; byte result[32]; }; u32 sigma[8]; u32 len; int cryptopro; } GOSTR3411_CONTEXT; static unsigned int transform (void *c, const unsigned char *data, size_t nblks); static void gost3411_init (void *context, unsigned int flags) { GOSTR3411_CONTEXT *hd = context; (void)flags; memset (hd->h, 0, 32); memset (hd->sigma, 0, 32); hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize_shift = _gcry_ctz(32); hd->bctx.bwrite = transform; hd->cryptopro = 0; } static void gost3411_cp_init (void *context, unsigned int flags) { GOSTR3411_CONTEXT *hd = context; gost3411_init (context, flags); hd->cryptopro = 1; } static void do_p (u32 *p, u32 *u, u32 *v) { int k; u32 t[8]; for (k = 0; k < 8; k++) t[k] = u[k] ^ v[k]; k = 0; p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 | ((t[2] >> (8*k)) & 0xff) << 8 | ((t[4] >> (8*k)) & 0xff) << 16 | ((t[6] >> (8*k)) & 0xff) << 24; p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 | ((t[3] >> (8*k)) & 0xff) << 8 | ((t[5] >> (8*k)) & 0xff) << 16 | ((t[7] >> (8*k)) & 0xff) << 24; k = 1; p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 | ((t[2] >> (8*k)) & 0xff) << 8 | ((t[4] >> (8*k)) & 0xff) << 16 | ((t[6] >> (8*k)) & 0xff) << 24; p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 | ((t[3] >> (8*k)) & 0xff) << 8 | ((t[5] >> (8*k)) & 0xff) << 16 | ((t[7] >> (8*k)) & 0xff) << 24; k = 2; p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 | ((t[2] >> (8*k)) & 0xff) << 8 | ((t[4] >> (8*k)) & 0xff) << 16 | ((t[6] >> (8*k)) & 0xff) << 24; p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 | ((t[3] >> (8*k)) & 0xff) << 8 | ((t[5] >> (8*k)) & 0xff) << 16 | ((t[7] >> (8*k)) & 0xff) << 24; k = 3; p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 | ((t[2] >> (8*k)) & 0xff) << 8 | ((t[4] >> (8*k)) & 0xff) << 16 | ((t[6] >> (8*k)) & 0xff) << 24; p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 | ((t[3] >> (8*k)) & 0xff) << 8 | ((t[5] >> (8*k)) & 0xff) << 16 | ((t[7] >> (8*k)) & 0xff) << 24; } static void do_a (u32 *u) { u32 t[2]; int i; memcpy(t, u, 2*4); for (i = 0; i < 6; i++) u[i] = u[i+2]; u[6] = u[0] ^ t[0]; u[7] = u[1] ^ t[1]; } /* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */ static void do_a2 (u32 *u) { u32 t[4]; int i; memcpy (t, u, 16); memcpy (u, u + 4, 16); for (i = 0; i < 2; i++) { u[4+i] = t[i] ^ t[i + 2]; u[6+i] = u[i] ^ t[i + 2]; } } static void do_apply_c2 (u32 *u) { u[ 0] ^= 0xff00ff00; u[ 1] ^= 0xff00ff00; u[ 2] ^= 0x00ff00ff; u[ 3] ^= 0x00ff00ff; u[ 4] ^= 0x00ffff00; u[ 5] ^= 0xff0000ff; u[ 6] ^= 0x000000ff; u[ 7] ^= 0xff00ffff; } #define do_chi_step12(e) \ e[6] ^= ((e[6] >> 16) ^ e[7] ^ (e[7] >> 16) ^ e[4] ^ (e[5] >>16)) & 0xffff; #define do_chi_step13(e) \ e[6] ^= ((e[7] ^ (e[7] >> 16) ^ e[0] ^ (e[4] >> 16) ^ e[6]) & 0xffff) << 16; #define do_chi_doublestep(e, i) \ e[i] ^= (e[i] >> 16) ^ (e[(i+1)%8] << 16) ^ e[(i+1)%8] ^ (e[(i+1)%8] >> 16) ^ (e[(i+2)%8] << 16) ^ e[(i+6)%8] ^ (e[(i+7)%8] >> 16); \ e[i] ^= (e[i] << 16); static void do_chi_submix12 (u32 *e, u32 *x) { e[6] ^= x[0]; e[7] ^= x[1]; e[0] ^= x[2]; e[1] ^= x[3]; e[2] ^= x[4]; e[3] ^= x[5]; e[4] ^= x[6]; e[5] ^= x[7]; } static void do_chi_submix13 (u32 *e, u32 *x) { e[6] ^= (x[0] << 16) | (x[7] >> 16); e[7] ^= (x[1] << 16) | (x[0] >> 16); e[0] ^= (x[2] << 16) | (x[1] >> 16); e[1] ^= (x[3] << 16) | (x[2] >> 16); e[2] ^= (x[4] << 16) | (x[3] >> 16); e[3] ^= (x[5] << 16) | (x[4] >> 16); e[4] ^= (x[6] << 16) | (x[5] >> 16); e[5] ^= (x[7] << 16) | (x[6] >> 16); } static void do_add (u32 *s, u32 *a) { u32 carry = 0; int i; for (i = 0; i < 8; i++) { u32 op = carry + a[i]; s[i] += op; carry = (a[i] > op) || (op > s[i]); } } static unsigned int do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m) { u32 u[8], v[8]; u32 s[8]; u32 k[8]; unsigned int burn; int i; memcpy (u, h, 32); memcpy (v, m, 32); for (i = 0; i < 4; i++) { do_p (k, u, v); burn = _gcry_gost_enc_data (k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro); do_a (u); if (i == 1) do_apply_c2 (u); do_a2 (v); } for (i = 0; i < 5; i++) { do_chi_doublestep (s, 0); do_chi_doublestep (s, 1); do_chi_doublestep (s, 2); do_chi_doublestep (s, 3); do_chi_doublestep (s, 4); /* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */ if (i == 4) break; do_chi_doublestep (s, 5); if (i == 0) do_chi_submix12(s, m); do_chi_step12 (s); if (i == 0) do_chi_submix13(s, h); do_chi_step13 (s); do_chi_doublestep (s, 7); } memcpy (h, s+5, 12); memcpy (h+3, s, 20); return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ + 4 * 32 + 2 * sizeof(int) /* stack */ + max(burn /* _gcry_gost_enc_one */, sizeof(void*) * 2 /* do_a2 call */ + 16 + sizeof(int) /* do_a2 stack */ ); } static unsigned int transform_blk (void *ctx, const unsigned char *data) { GOSTR3411_CONTEXT *hd = ctx; u32 m[8]; unsigned int burn; int i; for (i = 0; i < 8; i++) m[i] = buf_get_le32(data + i*4); burn = do_hash_step (hd, hd->h, m); do_add (hd->sigma, m); return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*); } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 32; } while (--nblks); return burn; } /* The routine finally terminates the computation and returns the digest. The handle is prepared for a new cycle, but adding bytes to the handle will the destroy the returned buffer. Returns: 32 bytes with the message the digest. */ static void gost3411_final (void *context) { GOSTR3411_CONTEXT *hd = context; size_t padlen = 0; u32 l[8]; int i; MD_NBLOCKS_TYPE nblocks; if (hd->bctx.count > 0) { padlen = 32 - hd->bctx.count; memset (hd->bctx.buf + hd->bctx.count, 0, padlen); hd->bctx.count += padlen; _gcry_md_block_write (hd, NULL, 0); /* flush */; } if (hd->bctx.count != 0) return; /* Something went wrong */ memset (l, 0, 32); nblocks = hd->bctx.nblocks; if (padlen) { nblocks --; l[0] = 256 - padlen * 8; } l[0] |= nblocks << 8; nblocks >>= 24; for (i = 1; i < 8 && nblocks != 0; i++) { l[i] = nblocks; nblocks >>= 24; } do_hash_step (hd, hd->h, l); do_hash_step (hd, hd->h, hd->sigma); for (i = 0; i < 8; i++) hd->h[i] = le_bswap32(hd->h[i]); } static byte * gost3411_read (void *context) { GOSTR3411_CONTEXT *hd = context; return hd->result; } -static unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */ +static const unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */ { 0x2a, 0x85, 0x03, 0x02, 0x02, 0x03 }; -static gcry_md_oid_spec_t oid_spec_gostr3411[] = +static const gcry_md_oid_spec_t oid_spec_gostr3411[] = { /* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */ { "1.2.643.2.2.3" }, /* iso.member-body.ru.rans.cryptopro.9 (gostR3411-94) */ { "1.2.643.2.2.9" }, {NULL}, }; -gcry_md_spec_t _gcry_digest_spec_gost3411_94 = +const gcry_md_spec_t _gcry_digest_spec_gost3411_94 = { GCRY_MD_GOSTR3411_94, {0, 0}, "GOSTR3411_94", NULL, 0, NULL, 32, gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL, NULL, sizeof (GOSTR3411_CONTEXT) }; -gcry_md_spec_t _gcry_digest_spec_gost3411_cp = +const gcry_md_spec_t _gcry_digest_spec_gost3411_cp = { GCRY_MD_GOSTR3411_CP, {0, 0}, "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32, gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL, NULL, sizeof (GOSTR3411_CONTEXT) }; diff --git a/cipher/keccak.c b/cipher/keccak.c index c03a1fac..f3502022 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -1,1561 +1,1561 @@ /* keccak.c - SHA3 hash functions * Copyright (C) 2015 g10 Code GmbH * * 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 . */ #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* USE_64BIT indicates whether to use 64-bit generic implementation. * USE_32BIT indicates whether to use 32-bit generic implementation. */ #undef USE_64BIT #if defined(__x86_64__) || SIZEOF_UNSIGNED_LONG == 8 # define USE_64BIT 1 #else # define USE_32BIT 1 #endif /* USE_64BIT_BMI2 indicates whether to compile with 64-bit Intel BMI2 code. */ #undef USE_64BIT_BMI2 #if defined(USE_64BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \ defined(HAVE_CPU_ARCH_X86) # define USE_64BIT_BMI2 1 #endif /* USE_64BIT_SHLD indicates whether to compile with 64-bit Intel SHLD code. */ #undef USE_64BIT_SHLD #if defined(USE_64BIT) && defined (__GNUC__) && defined(__x86_64__) && \ defined(HAVE_CPU_ARCH_X86) # define USE_64BIT_SHLD 1 #endif /* USE_32BIT_BMI2 indicates whether to compile with 32-bit Intel BMI2 code. */ #undef USE_32BIT_BMI2 #if defined(USE_32BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \ defined(HAVE_CPU_ARCH_X86) # define USE_32BIT_BMI2 1 #endif /* USE_64BIT_ARM_NEON indicates whether to enable 64-bit ARM/NEON assembly * code. */ #undef USE_64BIT_ARM_NEON #ifdef ENABLE_NEON_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_NEON) # define USE_64BIT_ARM_NEON 1 # endif #endif /*ENABLE_NEON_SUPPORT*/ /* USE_S390X_CRYPTO indicates whether to enable zSeries code. */ #undef USE_S390X_CRYPTO #if defined(HAVE_GCC_INLINE_ASM_S390X) # define USE_S390X_CRYPTO 1 #endif /* USE_S390X_CRYPTO */ #if defined(USE_64BIT) || defined(USE_64BIT_ARM_NEON) # define NEED_COMMON64 1 #endif #ifdef USE_32BIT # define NEED_COMMON32BI 1 #endif #define SHA3_DELIMITED_SUFFIX 0x06 #define SHAKE_DELIMITED_SUFFIX 0x1F typedef struct { union { #ifdef NEED_COMMON64 u64 state64[25]; #endif #ifdef NEED_COMMON32BI u32 state32bi[50]; #endif } u; } KECCAK_STATE; typedef struct { unsigned int (*permute)(KECCAK_STATE *hd); unsigned int (*absorb)(KECCAK_STATE *hd, int pos, const byte *lanes, unsigned int nlanes, int blocklanes); unsigned int (*extract) (KECCAK_STATE *hd, unsigned int pos, byte *outbuf, unsigned int outlen); } keccak_ops_t; typedef struct KECCAK_CONTEXT_S { KECCAK_STATE state; unsigned int outlen; unsigned int blocksize; unsigned int count; unsigned int suffix; const keccak_ops_t *ops; #ifdef USE_S390X_CRYPTO unsigned int kimd_func; unsigned int buf_pos; byte buf[1344 / 8]; /* SHAKE128 requires biggest buffer, 1344 bits. */ #endif } KECCAK_CONTEXT; #ifdef NEED_COMMON64 const u64 _gcry_keccak_round_consts_64bit[24 + 1] = { U64_C(0x0000000000000001), U64_C(0x0000000000008082), U64_C(0x800000000000808A), U64_C(0x8000000080008000), U64_C(0x000000000000808B), U64_C(0x0000000080000001), U64_C(0x8000000080008081), U64_C(0x8000000000008009), U64_C(0x000000000000008A), U64_C(0x0000000000000088), U64_C(0x0000000080008009), U64_C(0x000000008000000A), U64_C(0x000000008000808B), U64_C(0x800000000000008B), U64_C(0x8000000000008089), U64_C(0x8000000000008003), U64_C(0x8000000000008002), U64_C(0x8000000000000080), U64_C(0x000000000000800A), U64_C(0x800000008000000A), U64_C(0x8000000080008081), U64_C(0x8000000000008080), U64_C(0x0000000080000001), U64_C(0x8000000080008008), U64_C(0xFFFFFFFFFFFFFFFF) }; static unsigned int keccak_extract64(KECCAK_STATE *hd, unsigned int pos, byte *outbuf, unsigned int outlen) { unsigned int i; /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */ for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++) { u64 tmp = hd->u.state64[i]; buf_put_le64(outbuf, tmp); outbuf += 8; } return 0; } #endif /* NEED_COMMON64 */ #ifdef NEED_COMMON32BI static const u32 round_consts_32bit[2 * 24] = { 0x00000001UL, 0x00000000UL, 0x00000000UL, 0x00000089UL, 0x00000000UL, 0x8000008bUL, 0x00000000UL, 0x80008080UL, 0x00000001UL, 0x0000008bUL, 0x00000001UL, 0x00008000UL, 0x00000001UL, 0x80008088UL, 0x00000001UL, 0x80000082UL, 0x00000000UL, 0x0000000bUL, 0x00000000UL, 0x0000000aUL, 0x00000001UL, 0x00008082UL, 0x00000000UL, 0x00008003UL, 0x00000001UL, 0x0000808bUL, 0x00000001UL, 0x8000000bUL, 0x00000001UL, 0x8000008aUL, 0x00000001UL, 0x80000081UL, 0x00000000UL, 0x80000081UL, 0x00000000UL, 0x80000008UL, 0x00000000UL, 0x00000083UL, 0x00000000UL, 0x80008003UL, 0x00000001UL, 0x80008088UL, 0x00000000UL, 0x80000088UL, 0x00000001UL, 0x00008000UL, 0x00000000UL, 0x80008082UL }; static unsigned int keccak_extract32bi(KECCAK_STATE *hd, unsigned int pos, byte *outbuf, unsigned int outlen) { unsigned int i; u32 x0; u32 x1; u32 t; /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */ for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++) { x0 = hd->u.state32bi[i * 2 + 0]; x1 = hd->u.state32bi[i * 2 + 1]; t = (x0 & 0x0000FFFFUL) + (x1 << 16); x1 = (x0 >> 16) + (x1 & 0xFFFF0000UL); x0 = t; t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); buf_put_le32(&outbuf[0], x0); buf_put_le32(&outbuf[4], x1); outbuf += 8; } return 0; } static inline void keccak_absorb_lane32bi(u32 *lane, u32 x0, u32 x1) { u32 t; t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); lane[0] ^= (x0 & 0x0000FFFFUL) + (x1 << 16); lane[1] ^= (x0 >> 16) + (x1 & 0xFFFF0000UL); } #endif /* NEED_COMMON32BI */ /* Construct generic 64-bit implementation. */ #ifdef USE_64BIT #if __GNUC__ >= 4 && defined(__x86_64__) static inline void absorb_lanes64_8(u64 *dst, const byte *in) { asm ("movdqu 0*16(%[dst]), %%xmm0\n\t" "movdqu 0*16(%[in]), %%xmm4\n\t" "movdqu 1*16(%[dst]), %%xmm1\n\t" "movdqu 1*16(%[in]), %%xmm5\n\t" "movdqu 2*16(%[dst]), %%xmm2\n\t" "movdqu 3*16(%[dst]), %%xmm3\n\t" "pxor %%xmm4, %%xmm0\n\t" "pxor %%xmm5, %%xmm1\n\t" "movdqu 2*16(%[in]), %%xmm4\n\t" "movdqu 3*16(%[in]), %%xmm5\n\t" "movdqu %%xmm0, 0*16(%[dst])\n\t" "pxor %%xmm4, %%xmm2\n\t" "movdqu %%xmm1, 1*16(%[dst])\n\t" "pxor %%xmm5, %%xmm3\n\t" "movdqu %%xmm2, 2*16(%[dst])\n\t" "movdqu %%xmm3, 3*16(%[dst])\n\t" : : [dst] "r" (dst), [in] "r" (in) : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "memory"); } static inline void absorb_lanes64_4(u64 *dst, const byte *in) { asm ("movdqu 0*16(%[dst]), %%xmm0\n\t" "movdqu 0*16(%[in]), %%xmm4\n\t" "movdqu 1*16(%[dst]), %%xmm1\n\t" "movdqu 1*16(%[in]), %%xmm5\n\t" "pxor %%xmm4, %%xmm0\n\t" "pxor %%xmm5, %%xmm1\n\t" "movdqu %%xmm0, 0*16(%[dst])\n\t" "movdqu %%xmm1, 1*16(%[dst])\n\t" : : [dst] "r" (dst), [in] "r" (in) : "xmm0", "xmm1", "xmm4", "xmm5", "memory"); } static inline void absorb_lanes64_2(u64 *dst, const byte *in) { asm ("movdqu 0*16(%[dst]), %%xmm0\n\t" "movdqu 0*16(%[in]), %%xmm4\n\t" "pxor %%xmm4, %%xmm0\n\t" "movdqu %%xmm0, 0*16(%[dst])\n\t" : : [dst] "r" (dst), [in] "r" (in) : "xmm0", "xmm4", "memory"); } #else /* __x86_64__ */ static inline void absorb_lanes64_8(u64 *dst, const byte *in) { dst[0] ^= buf_get_le64(in + 8 * 0); dst[1] ^= buf_get_le64(in + 8 * 1); dst[2] ^= buf_get_le64(in + 8 * 2); dst[3] ^= buf_get_le64(in + 8 * 3); dst[4] ^= buf_get_le64(in + 8 * 4); dst[5] ^= buf_get_le64(in + 8 * 5); dst[6] ^= buf_get_le64(in + 8 * 6); dst[7] ^= buf_get_le64(in + 8 * 7); } static inline void absorb_lanes64_4(u64 *dst, const byte *in) { dst[0] ^= buf_get_le64(in + 8 * 0); dst[1] ^= buf_get_le64(in + 8 * 1); dst[2] ^= buf_get_le64(in + 8 * 2); dst[3] ^= buf_get_le64(in + 8 * 3); } static inline void absorb_lanes64_2(u64 *dst, const byte *in) { dst[0] ^= buf_get_le64(in + 8 * 0); dst[1] ^= buf_get_le64(in + 8 * 1); } #endif /* !__x86_64__ */ static inline void absorb_lanes64_1(u64 *dst, const byte *in) { dst[0] ^= buf_get_le64(in + 8 * 0); } # define ANDN64(x, y) (~(x) & (y)) # define ROL64(x, n) (((x) << ((unsigned int)n & 63)) | \ ((x) >> ((64 - (unsigned int)(n)) & 63))) # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64 # define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64 # include "keccak_permute_64.h" # undef ANDN64 # undef ROL64 # undef KECCAK_F1600_PERMUTE_FUNC_NAME # undef KECCAK_F1600_ABSORB_FUNC_NAME static const keccak_ops_t keccak_generic64_ops = { .permute = keccak_f1600_state_permute64, .absorb = keccak_absorb_lanes64, .extract = keccak_extract64, }; #endif /* USE_64BIT */ /* Construct 64-bit Intel SHLD implementation. */ #ifdef USE_64BIT_SHLD # define ANDN64(x, y) (~(x) & (y)) # define ROL64(x, n) ({ \ u64 tmp = (x); \ asm ("shldq %1, %0, %0" \ : "+r" (tmp) \ : "J" ((n) & 63) \ : "cc"); \ tmp; }) # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_shld # define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_shld # include "keccak_permute_64.h" # undef ANDN64 # undef ROL64 # undef KECCAK_F1600_PERMUTE_FUNC_NAME # undef KECCAK_F1600_ABSORB_FUNC_NAME static const keccak_ops_t keccak_shld_64_ops = { .permute = keccak_f1600_state_permute64_shld, .absorb = keccak_absorb_lanes64_shld, .extract = keccak_extract64, }; #endif /* USE_64BIT_SHLD */ /* Construct 64-bit Intel BMI2 implementation. */ #ifdef USE_64BIT_BMI2 # define ANDN64(x, y) ({ \ u64 tmp; \ asm ("andnq %2, %1, %0" \ : "=r" (tmp) \ : "r0" (x), "rm" (y)); \ tmp; }) # define ROL64(x, n) ({ \ u64 tmp; \ asm ("rorxq %2, %1, %0" \ : "=r" (tmp) \ : "rm0" (x), "J" (64 - ((n) & 63))); \ tmp; }) # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_bmi2 # define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_bmi2 # include "keccak_permute_64.h" # undef ANDN64 # undef ROL64 # undef KECCAK_F1600_PERMUTE_FUNC_NAME # undef KECCAK_F1600_ABSORB_FUNC_NAME static const keccak_ops_t keccak_bmi2_64_ops = { .permute = keccak_f1600_state_permute64_bmi2, .absorb = keccak_absorb_lanes64_bmi2, .extract = keccak_extract64, }; #endif /* USE_64BIT_BMI2 */ /* 64-bit ARMv7/NEON implementation. */ #ifdef USE_64BIT_ARM_NEON unsigned int _gcry_keccak_permute_armv7_neon(u64 *state); unsigned int _gcry_keccak_absorb_lanes64_armv7_neon(u64 *state, int pos, const byte *lanes, unsigned int nlanes, int blocklanes); static unsigned int keccak_permute64_armv7_neon(KECCAK_STATE *hd) { return _gcry_keccak_permute_armv7_neon(hd->u.state64); } static unsigned int keccak_absorb_lanes64_armv7_neon(KECCAK_STATE *hd, int pos, const byte *lanes, unsigned int nlanes, int blocklanes) { if (blocklanes < 0) { /* blocklanes == -1, permutationless absorb from keccak_final. */ while (nlanes) { hd->u.state64[pos] ^= buf_get_le64(lanes); lanes += 8; nlanes--; } return 0; } else { return _gcry_keccak_absorb_lanes64_armv7_neon(hd->u.state64, pos, lanes, nlanes, blocklanes); } } static const keccak_ops_t keccak_armv7_neon_64_ops = { .permute = keccak_permute64_armv7_neon, .absorb = keccak_absorb_lanes64_armv7_neon, .extract = keccak_extract64, }; #endif /* USE_64BIT_ARM_NEON */ /* Construct generic 32-bit implementation. */ #ifdef USE_32BIT # define ANDN32(x, y) (~(x) & (y)) # define ROL32(x, n) (((x) << ((unsigned int)n & 31)) | \ ((x) >> ((32 - (unsigned int)(n)) & 31))) # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute32bi # include "keccak_permute_32.h" # undef ANDN32 # undef ROL32 # undef KECCAK_F1600_PERMUTE_FUNC_NAME static unsigned int keccak_absorb_lanes32bi(KECCAK_STATE *hd, int pos, const byte *lanes, unsigned int nlanes, int blocklanes) { unsigned int burn = 0; while (nlanes) { keccak_absorb_lane32bi(&hd->u.state32bi[pos * 2], buf_get_le32(lanes + 0), buf_get_le32(lanes + 4)); lanes += 8; nlanes--; if (++pos == blocklanes) { burn = keccak_f1600_state_permute32bi(hd); pos = 0; } } return burn; } static const keccak_ops_t keccak_generic32bi_ops = { .permute = keccak_f1600_state_permute32bi, .absorb = keccak_absorb_lanes32bi, .extract = keccak_extract32bi, }; #endif /* USE_32BIT */ /* Construct 32-bit Intel BMI2 implementation. */ #ifdef USE_32BIT_BMI2 # define ANDN32(x, y) ({ \ u32 tmp; \ asm ("andnl %2, %1, %0" \ : "=r" (tmp) \ : "r0" (x), "rm" (y)); \ tmp; }) # define ROL32(x, n) ({ \ u32 tmp; \ asm ("rorxl %2, %1, %0" \ : "=r" (tmp) \ : "rm0" (x), "J" (32 - ((n) & 31))); \ tmp; }) # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute32bi_bmi2 # include "keccak_permute_32.h" # undef ANDN32 # undef ROL32 # undef KECCAK_F1600_PERMUTE_FUNC_NAME static inline u32 pext(u32 x, u32 mask) { u32 tmp; asm ("pextl %2, %1, %0" : "=r" (tmp) : "r0" (x), "rm" (mask)); return tmp; } static inline u32 pdep(u32 x, u32 mask) { u32 tmp; asm ("pdepl %2, %1, %0" : "=r" (tmp) : "r0" (x), "rm" (mask)); return tmp; } static inline void keccak_absorb_lane32bi_bmi2(u32 *lane, u32 x0, u32 x1) { x0 = pdep(pext(x0, 0x55555555), 0x0000ffff) | (pext(x0, 0xaaaaaaaa) << 16); x1 = pdep(pext(x1, 0x55555555), 0x0000ffff) | (pext(x1, 0xaaaaaaaa) << 16); lane[0] ^= (x0 & 0x0000FFFFUL) + (x1 << 16); lane[1] ^= (x0 >> 16) + (x1 & 0xFFFF0000UL); } static unsigned int keccak_absorb_lanes32bi_bmi2(KECCAK_STATE *hd, int pos, const byte *lanes, unsigned int nlanes, int blocklanes) { unsigned int burn = 0; while (nlanes) { keccak_absorb_lane32bi_bmi2(&hd->u.state32bi[pos * 2], buf_get_le32(lanes + 0), buf_get_le32(lanes + 4)); lanes += 8; nlanes--; if (++pos == blocklanes) { burn = keccak_f1600_state_permute32bi_bmi2(hd); pos = 0; } } return burn; } static unsigned int keccak_extract32bi_bmi2(KECCAK_STATE *hd, unsigned int pos, byte *outbuf, unsigned int outlen) { unsigned int i; u32 x0; u32 x1; u32 t; /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */ for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++) { x0 = hd->u.state32bi[i * 2 + 0]; x1 = hd->u.state32bi[i * 2 + 1]; t = (x0 & 0x0000FFFFUL) + (x1 << 16); x1 = (x0 >> 16) + (x1 & 0xFFFF0000UL); x0 = t; x0 = pdep(pext(x0, 0xffff0001), 0xaaaaaaab) | pdep(x0 >> 1, 0x55555554); x1 = pdep(pext(x1, 0xffff0001), 0xaaaaaaab) | pdep(x1 >> 1, 0x55555554); buf_put_le32(&outbuf[0], x0); buf_put_le32(&outbuf[4], x1); outbuf += 8; } return 0; } static const keccak_ops_t keccak_bmi2_32bi_ops = { .permute = keccak_f1600_state_permute32bi_bmi2, .absorb = keccak_absorb_lanes32bi_bmi2, .extract = keccak_extract32bi_bmi2, }; #endif /* USE_32BIT_BMI2 */ #ifdef USE_S390X_CRYPTO #include "asm-inline-s390x.h" static inline void keccak_bwrite_s390x (void *context, const byte *in, size_t inlen) { KECCAK_CONTEXT *ctx = context; /* Write full-blocks. */ kimd_execute (ctx->kimd_func, &ctx->state, in, inlen); return; } static inline void keccak_final_s390x (void *context) { KECCAK_CONTEXT *ctx = context; if (ctx->suffix == SHA3_DELIMITED_SUFFIX) { klmd_execute (ctx->kimd_func, &ctx->state, ctx->buf, ctx->count); } else { klmd_shake_execute (ctx->kimd_func, &ctx->state, NULL, 0, ctx->buf, ctx->count); ctx->count = 0; ctx->buf_pos = 0; } return; } static inline void keccak_bextract_s390x (void *context, byte *out, size_t outlen) { KECCAK_CONTEXT *ctx = context; /* Extract full-blocks. */ klmd_shake_execute (ctx->kimd_func | KLMD_PADDING_STATE, &ctx->state, out, outlen, NULL, 0); return; } static void keccak_write_s390x (void *context, const byte *inbuf, size_t inlen) { KECCAK_CONTEXT *hd = context; const size_t blocksize = hd->blocksize; size_t inblocks; size_t copylen; while (hd->count) { if (hd->count == blocksize) /* Flush the buffer. */ { keccak_bwrite_s390x (hd, hd->buf, blocksize); hd->count = 0; } else { copylen = inlen; if (copylen > blocksize - hd->count) copylen = blocksize - hd->count; if (copylen == 0) break; buf_cpy (&hd->buf[hd->count], inbuf, copylen); hd->count += copylen; inbuf += copylen; inlen -= copylen; } } if (inlen == 0) return; if (inlen >= blocksize) { inblocks = inlen / blocksize; keccak_bwrite_s390x (hd, inbuf, inblocks * blocksize); hd->count = 0; inlen -= inblocks * blocksize; inbuf += inblocks * blocksize; } if (inlen) { buf_cpy (hd->buf, inbuf, inlen); hd->count = inlen; } } static void keccak_extract_s390x (void *context, void *outbuf_arg, size_t outlen) { KECCAK_CONTEXT *hd = context; const size_t blocksize = hd->blocksize; byte *outbuf = outbuf_arg; while (outlen) { gcry_assert(hd->count == 0 || hd->buf_pos < hd->count); if (hd->buf_pos < hd->count && outlen) { size_t copylen = hd->count - hd->buf_pos; if (copylen > outlen) copylen = outlen; buf_cpy (outbuf, &hd->buf[hd->buf_pos], copylen); outbuf += copylen; outlen -= copylen; hd->buf_pos += copylen; } if (hd->buf_pos == hd->count) { hd->buf_pos = 0; hd->count = 0; } if (outlen == 0) return; if (outlen >= blocksize) { size_t outblocks = outlen / blocksize; keccak_bextract_s390x (context, outbuf, outblocks * blocksize); outlen -= outblocks * blocksize; outbuf += outblocks * blocksize; if (outlen == 0) return; } keccak_bextract_s390x (context, hd->buf, blocksize); hd->count = blocksize; } } #endif /* USE_S390X_CRYPTO */ static void keccak_write (void *context, const void *inbuf_arg, size_t inlen) { KECCAK_CONTEXT *ctx = context; const size_t bsize = ctx->blocksize; const size_t blocklanes = bsize / 8; const byte *inbuf = inbuf_arg; unsigned int nburn, burn = 0; unsigned int count, i; unsigned int pos, nlanes; #ifdef USE_S390X_CRYPTO if (ctx->kimd_func) { keccak_write_s390x (context, inbuf, inlen); return; } #endif count = ctx->count; if (inlen && (count % 8)) { byte lane[8] = { 0, }; /* Complete absorbing partial input lane. */ pos = count / 8; for (i = count % 8; inlen && i < 8; i++) { lane[i] = *inbuf++; inlen--; count++; } if (count == bsize) count = 0; nburn = ctx->ops->absorb(&ctx->state, pos, lane, 1, (count % 8) ? -1 : blocklanes); burn = nburn > burn ? nburn : burn; } /* Absorb full input lanes. */ pos = count / 8; nlanes = inlen / 8; if (nlanes > 0) { nburn = ctx->ops->absorb(&ctx->state, pos, inbuf, nlanes, blocklanes); burn = nburn > burn ? nburn : burn; inlen -= nlanes * 8; inbuf += nlanes * 8; count += nlanes * 8; count = count % bsize; } if (inlen) { byte lane[8] = { 0, }; /* Absorb remaining partial input lane. */ pos = count / 8; for (i = count % 8; inlen && i < 8; i++) { lane[i] = *inbuf++; inlen--; count++; } nburn = ctx->ops->absorb(&ctx->state, pos, lane, 1, -1); burn = nburn > burn ? nburn : burn; gcry_assert(count < bsize); } ctx->count = count; if (burn) _gcry_burn_stack (burn); } static void keccak_init (int algo, void *context, unsigned int flags) { KECCAK_CONTEXT *ctx = context; KECCAK_STATE *hd = &ctx->state; unsigned int features = _gcry_get_hw_features (); (void)flags; (void)features; memset (hd, 0, sizeof *hd); ctx->count = 0; /* Select generic implementation. */ #ifdef USE_64BIT ctx->ops = &keccak_generic64_ops; #elif defined USE_32BIT ctx->ops = &keccak_generic32bi_ops; #endif /* Select optimized implementation based in hw features. */ if (0) {} #ifdef USE_64BIT_ARM_NEON else if (features & HWF_ARM_NEON) ctx->ops = &keccak_armv7_neon_64_ops; #endif #ifdef USE_64BIT_BMI2 else if (features & HWF_INTEL_BMI2) ctx->ops = &keccak_bmi2_64_ops; #endif #ifdef USE_32BIT_BMI2 else if (features & HWF_INTEL_BMI2) ctx->ops = &keccak_bmi2_32bi_ops; #endif #ifdef USE_64BIT_SHLD else if (features & HWF_INTEL_FAST_SHLD) ctx->ops = &keccak_shld_64_ops; #endif /* Set input block size, in Keccak terms this is called 'rate'. */ switch (algo) { case GCRY_MD_SHA3_224: ctx->suffix = SHA3_DELIMITED_SUFFIX; ctx->blocksize = 1152 / 8; ctx->outlen = 224 / 8; break; case GCRY_MD_SHA3_256: ctx->suffix = SHA3_DELIMITED_SUFFIX; ctx->blocksize = 1088 / 8; ctx->outlen = 256 / 8; break; case GCRY_MD_SHA3_384: ctx->suffix = SHA3_DELIMITED_SUFFIX; ctx->blocksize = 832 / 8; ctx->outlen = 384 / 8; break; case GCRY_MD_SHA3_512: ctx->suffix = SHA3_DELIMITED_SUFFIX; ctx->blocksize = 576 / 8; ctx->outlen = 512 / 8; break; case GCRY_MD_SHAKE128: ctx->suffix = SHAKE_DELIMITED_SUFFIX; ctx->blocksize = 1344 / 8; ctx->outlen = 0; break; case GCRY_MD_SHAKE256: ctx->suffix = SHAKE_DELIMITED_SUFFIX; ctx->blocksize = 1088 / 8; ctx->outlen = 0; break; default: BUG(); } #ifdef USE_S390X_CRYPTO ctx->kimd_func = 0; if ((features & HWF_S390X_MSA) != 0) { unsigned int kimd_func = 0; switch (algo) { case GCRY_MD_SHA3_224: kimd_func = KMID_FUNCTION_SHA3_224; break; case GCRY_MD_SHA3_256: kimd_func = KMID_FUNCTION_SHA3_256; break; case GCRY_MD_SHA3_384: kimd_func = KMID_FUNCTION_SHA3_384; break; case GCRY_MD_SHA3_512: kimd_func = KMID_FUNCTION_SHA3_512; break; case GCRY_MD_SHAKE128: kimd_func = KMID_FUNCTION_SHAKE128; break; case GCRY_MD_SHAKE256: kimd_func = KMID_FUNCTION_SHAKE256; break; } if ((kimd_query () & km_function_to_mask (kimd_func)) && (klmd_query () & km_function_to_mask (kimd_func))) { ctx->kimd_func = kimd_func; } } #endif } static void sha3_224_init (void *context, unsigned int flags) { keccak_init (GCRY_MD_SHA3_224, context, flags); } static void sha3_256_init (void *context, unsigned int flags) { keccak_init (GCRY_MD_SHA3_256, context, flags); } static void sha3_384_init (void *context, unsigned int flags) { keccak_init (GCRY_MD_SHA3_384, context, flags); } static void sha3_512_init (void *context, unsigned int flags) { keccak_init (GCRY_MD_SHA3_512, context, flags); } static void shake128_init (void *context, unsigned int flags) { keccak_init (GCRY_MD_SHAKE128, context, flags); } static void shake256_init (void *context, unsigned int flags) { keccak_init (GCRY_MD_SHAKE256, context, flags); } /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the * handle will the destroy the returned buffer. * Returns: 64 bytes representing the digest. When used for sha384, * we take the leftmost 48 of those bytes. */ static void keccak_final (void *context) { KECCAK_CONTEXT *ctx = context; KECCAK_STATE *hd = &ctx->state; const size_t bsize = ctx->blocksize; const byte suffix = ctx->suffix; unsigned int nburn, burn = 0; unsigned int lastbytes; byte lane[8]; #ifdef USE_S390X_CRYPTO if (ctx->kimd_func) { keccak_final_s390x (context); return; } #endif lastbytes = ctx->count; /* Do the padding and switch to the squeezing phase */ /* Absorb the last few bits and add the first bit of padding (which coincides with the delimiter in delimited suffix) */ buf_put_le64(lane, (u64)suffix << ((lastbytes % 8) * 8)); nburn = ctx->ops->absorb(&ctx->state, lastbytes / 8, lane, 1, -1); burn = nburn > burn ? nburn : burn; /* Add the second bit of padding. */ buf_put_le64(lane, (u64)0x80 << (((bsize - 1) % 8) * 8)); nburn = ctx->ops->absorb(&ctx->state, (bsize - 1) / 8, lane, 1, -1); burn = nburn > burn ? nburn : burn; if (suffix == SHA3_DELIMITED_SUFFIX) { /* Switch to the squeezing phase. */ nburn = ctx->ops->permute(hd); burn = nburn > burn ? nburn : burn; /* Squeeze out the SHA3 digest. */ nburn = ctx->ops->extract(hd, 0, (void *)hd, ctx->outlen); burn = nburn > burn ? nburn : burn; } else { /* Output for SHAKE can now be read with md_extract(). */ ctx->count = 0; } wipememory(lane, sizeof(lane)); if (burn) _gcry_burn_stack (burn); } static byte * keccak_read (void *context) { KECCAK_CONTEXT *ctx = (KECCAK_CONTEXT *) context; KECCAK_STATE *hd = &ctx->state; return (byte *)&hd->u; } static void keccak_extract (void *context, void *out, size_t outlen) { KECCAK_CONTEXT *ctx = context; KECCAK_STATE *hd = &ctx->state; const size_t bsize = ctx->blocksize; unsigned int nburn, burn = 0; byte *outbuf = out; unsigned int nlanes; unsigned int nleft; unsigned int count; unsigned int i; byte lane[8]; #ifdef USE_S390X_CRYPTO if (ctx->kimd_func) { keccak_extract_s390x (context, out, outlen); return; } #endif count = ctx->count; while (count && outlen && (outlen < 8 || count % 8)) { /* Extract partial lane. */ nburn = ctx->ops->extract(hd, count / 8, lane, 8); burn = nburn > burn ? nburn : burn; for (i = count % 8; outlen && i < 8; i++) { *outbuf++ = lane[i]; outlen--; count++; } gcry_assert(count <= bsize); if (count == bsize) count = 0; } if (outlen >= 8 && count) { /* Extract tail of partial block. */ nlanes = outlen / 8; nleft = (bsize - count) / 8; nlanes = nlanes < nleft ? nlanes : nleft; nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8); burn = nburn > burn ? nburn : burn; outlen -= nlanes * 8; outbuf += nlanes * 8; count += nlanes * 8; gcry_assert(count <= bsize); if (count == bsize) count = 0; } while (outlen >= bsize) { gcry_assert(count == 0); /* Squeeze more. */ nburn = ctx->ops->permute(hd); burn = nburn > burn ? nburn : burn; /* Extract full block. */ nburn = ctx->ops->extract(hd, 0, outbuf, bsize); burn = nburn > burn ? nburn : burn; outlen -= bsize; outbuf += bsize; } if (outlen) { gcry_assert(outlen < bsize); if (count == 0) { /* Squeeze more. */ nburn = ctx->ops->permute(hd); burn = nburn > burn ? nburn : burn; } if (outlen >= 8) { /* Extract head of partial block. */ nlanes = outlen / 8; nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8); burn = nburn > burn ? nburn : burn; outlen -= nlanes * 8; outbuf += nlanes * 8; count += nlanes * 8; gcry_assert(count < bsize); } if (outlen) { /* Extract head of partial lane. */ nburn = ctx->ops->extract(hd, count / 8, lane, 8); burn = nburn > burn ? nburn : burn; for (i = count % 8; outlen && i < 8; i++) { *outbuf++ = lane[i]; outlen--; count++; } gcry_assert(count < bsize); } } ctx->count = count; if (burn) _gcry_burn_stack (burn); } /* Variant of the above shortcut function using multiple buffers. */ static void _gcry_sha3_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt, const gcry_md_spec_t *spec) { KECCAK_CONTEXT hd; spec->init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) keccak_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); keccak_final (&hd); if (spec->mdlen > 0) memcpy (outbuf, keccak_read (&hd), spec->mdlen); else keccak_extract (&hd, outbuf, nbytes); } static void _gcry_sha3_224_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, &_gcry_digest_spec_sha3_224); } static void _gcry_sha3_256_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, &_gcry_digest_spec_sha3_256); } static void _gcry_sha3_384_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, &_gcry_digest_spec_sha3_384); } static void _gcry_sha3_512_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, &_gcry_digest_spec_sha3_512); } static void _gcry_shake128_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, &_gcry_digest_spec_shake128); } static void _gcry_shake256_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, &_gcry_digest_spec_shake256); } /* Self-test section. */ static gpg_err_code_t selftests_keccak (int algo, int extended, selftest_report_func_t report) { const char *what; const char *errtxt; const char *short_hash; const char *long_hash; const char *one_million_a_hash; int hash_len; switch (algo) { default: BUG(); case GCRY_MD_SHA3_224: short_hash = "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f" "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf"; long_hash = "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5" "\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc"; one_million_a_hash = "\xd6\x93\x35\xb9\x33\x25\x19\x2e\x51\x6a\x91\x2e\x6d\x19\xa1\x5c" "\xb5\x1c\x6e\xd5\xc1\x52\x43\xe7\xa7\xfd\x65\x3c"; hash_len = 28; break; case GCRY_MD_SHA3_256: short_hash = "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd" "\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32"; long_hash = "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb" "\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18"; one_million_a_hash = "\x5c\x88\x75\xae\x47\x4a\x36\x34\xba\x4f\xd5\x5e\xc8\x5b\xff\xd6" "\x61\xf3\x2a\xca\x75\xc6\xd6\x99\xd0\xcd\xcb\x6c\x11\x58\x91\xc1"; hash_len = 32; break; case GCRY_MD_SHA3_384: short_hash = "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d" "\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2" "\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25"; long_hash = "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91" "\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc" "\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7"; one_million_a_hash = "\xee\xe9\xe2\x4d\x78\xc1\x85\x53\x37\x98\x34\x51\xdf\x97\xc8\xad" "\x9e\xed\xf2\x56\xc6\x33\x4f\x8e\x94\x8d\x25\x2d\x5e\x0e\x76\x84" "\x7a\xa0\x77\x4d\xdb\x90\xa8\x42\x19\x0d\x2c\x55\x8b\x4b\x83\x40"; hash_len = 48; break; case GCRY_MD_SHA3_512: short_hash = "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e" "\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e" "\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40" "\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0"; long_hash = "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9" "\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa" "\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89" "\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85"; one_million_a_hash = "\x3c\x3a\x87\x6d\xa1\x40\x34\xab\x60\x62\x7c\x07\x7b\xb9\x8f\x7e" "\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59" "\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66" "\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87"; hash_len = 64; break; case GCRY_MD_SHAKE128: short_hash = "\x58\x81\x09\x2d\xd8\x18\xbf\x5c\xf8\xa3\xdd\xb7\x93\xfb\xcb\xa7" "\x40\x97\xd5\xc5\x26\xa6\xd3\x5f\x97\xb8\x33\x51\x94\x0f\x2c\xc8"; long_hash = "\x7b\x6d\xf6\xff\x18\x11\x73\xb6\xd7\x89\x8d\x7f\xf6\x3f\xb0\x7b" "\x7c\x23\x7d\xaf\x47\x1a\x5a\xe5\x60\x2a\xdb\xcc\xef\x9c\xcf\x4b"; one_million_a_hash = "\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11" "\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58"; hash_len = 32; break; case GCRY_MD_SHAKE256: short_hash = "\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11\x4d" "\x8d\xb4\x45\x30\xf8\xf1\xe1\xee\x4f\x94\xea\x37\xe7\x8b\x57\x39"; long_hash = "\x98\xbe\x04\x51\x6c\x04\xcc\x73\x59\x3f\xef\x3e\xd0\x35\x2e\xa9" "\xf6\x44\x39\x42\xd6\x95\x0e\x29\xa3\x72\xa6\x81\xc3\xde\xaf\x45"; one_million_a_hash = "\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb" "\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a"; hash_len = 32; break; } what = "short string"; errtxt = _gcry_hash_selftest_check_one (algo, 0, "abc", 3, short_hash, hash_len); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (algo, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, long_hash, hash_len); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (algo, 1, NULL, 0, one_million_a_hash, hash_len); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", algo, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA3_224: case GCRY_MD_SHA3_256: case GCRY_MD_SHA3_384: case GCRY_MD_SHA3_512: case GCRY_MD_SHAKE128: case GCRY_MD_SHAKE256: ec = selftests_keccak (algo, extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } -static byte sha3_224_asn[] = { 0x30 }; -static gcry_md_oid_spec_t oid_spec_sha3_224[] = +static const byte sha3_224_asn[] = { 0x30 }; +static const gcry_md_oid_spec_t oid_spec_sha3_224[] = { { "2.16.840.1.101.3.4.2.7" }, /* PKCS#1 sha3_224WithRSAEncryption */ { "?" }, { NULL } }; -static byte sha3_256_asn[] = { 0x30 }; -static gcry_md_oid_spec_t oid_spec_sha3_256[] = +static const byte sha3_256_asn[] = { 0x30 }; +static const gcry_md_oid_spec_t oid_spec_sha3_256[] = { { "2.16.840.1.101.3.4.2.8" }, /* PKCS#1 sha3_256WithRSAEncryption */ { "?" }, { NULL } }; -static byte sha3_384_asn[] = { 0x30 }; -static gcry_md_oid_spec_t oid_spec_sha3_384[] = +static const byte sha3_384_asn[] = { 0x30 }; +static const gcry_md_oid_spec_t oid_spec_sha3_384[] = { { "2.16.840.1.101.3.4.2.9" }, /* PKCS#1 sha3_384WithRSAEncryption */ { "?" }, { NULL } }; -static byte sha3_512_asn[] = { 0x30 }; -static gcry_md_oid_spec_t oid_spec_sha3_512[] = +static const byte sha3_512_asn[] = { 0x30 }; +static const gcry_md_oid_spec_t oid_spec_sha3_512[] = { { "2.16.840.1.101.3.4.2.10" }, /* PKCS#1 sha3_512WithRSAEncryption */ { "?" }, { NULL } }; -static byte shake128_asn[] = { 0x30 }; -static gcry_md_oid_spec_t oid_spec_shake128[] = +static const byte shake128_asn[] = { 0x30 }; +static const gcry_md_oid_spec_t oid_spec_shake128[] = { { "2.16.840.1.101.3.4.2.11" }, /* PKCS#1 shake128WithRSAEncryption */ { "?" }, { NULL } }; -static byte shake256_asn[] = { 0x30 }; -static gcry_md_oid_spec_t oid_spec_shake256[] = +static const byte shake256_asn[] = { 0x30 }; +static const gcry_md_oid_spec_t oid_spec_shake256[] = { { "2.16.840.1.101.3.4.2.12" }, /* PKCS#1 shake256WithRSAEncryption */ { "?" }, { NULL } }; -gcry_md_spec_t _gcry_digest_spec_sha3_224 = +const gcry_md_spec_t _gcry_digest_spec_sha3_224 = { GCRY_MD_SHA3_224, {0, 1}, "SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 28, sha3_224_init, keccak_write, keccak_final, keccak_read, NULL, _gcry_sha3_224_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; -gcry_md_spec_t _gcry_digest_spec_sha3_256 = +const gcry_md_spec_t _gcry_digest_spec_sha3_256 = { GCRY_MD_SHA3_256, {0, 1}, "SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 32, sha3_256_init, keccak_write, keccak_final, keccak_read, NULL, _gcry_sha3_256_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; -gcry_md_spec_t _gcry_digest_spec_sha3_384 = +const gcry_md_spec_t _gcry_digest_spec_sha3_384 = { GCRY_MD_SHA3_384, {0, 1}, "SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 48, sha3_384_init, keccak_write, keccak_final, keccak_read, NULL, _gcry_sha3_384_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; -gcry_md_spec_t _gcry_digest_spec_sha3_512 = +const gcry_md_spec_t _gcry_digest_spec_sha3_512 = { GCRY_MD_SHA3_512, {0, 1}, "SHA3-512", sha3_512_asn, DIM (sha3_512_asn), oid_spec_sha3_512, 64, sha3_512_init, keccak_write, keccak_final, keccak_read, NULL, _gcry_sha3_512_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; -gcry_md_spec_t _gcry_digest_spec_shake128 = +const gcry_md_spec_t _gcry_digest_spec_shake128 = { GCRY_MD_SHAKE128, {0, 1}, "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 0, shake128_init, keccak_write, keccak_final, NULL, keccak_extract, _gcry_shake128_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; -gcry_md_spec_t _gcry_digest_spec_shake256 = +const gcry_md_spec_t _gcry_digest_spec_shake256 = { GCRY_MD_SHAKE256, {0, 1}, "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 0, shake256_init, keccak_write, keccak_final, NULL, keccak_extract, _gcry_shake256_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c index 0538de37..b80c3406 100644 --- a/cipher/mac-cmac.c +++ b/cipher/mac-cmac.c @@ -1,524 +1,524 @@ /* mac-cmac.c - CMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * Copyright (C) 2008 Free Software Foundation, Inc. * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "./mac-internal.h" static int map_mac_algo_to_cipher (int mac_algo) { switch (mac_algo) { default: return GCRY_CIPHER_NONE; case GCRY_MAC_CMAC_AES: return GCRY_CIPHER_AES; case GCRY_MAC_CMAC_3DES: return GCRY_CIPHER_3DES; case GCRY_MAC_CMAC_CAMELLIA: return GCRY_CIPHER_CAMELLIA128; case GCRY_MAC_CMAC_IDEA: return GCRY_CIPHER_IDEA; case GCRY_MAC_CMAC_CAST5: return GCRY_CIPHER_CAST5; case GCRY_MAC_CMAC_BLOWFISH: return GCRY_CIPHER_BLOWFISH; case GCRY_MAC_CMAC_TWOFISH: return GCRY_CIPHER_TWOFISH; case GCRY_MAC_CMAC_SERPENT: return GCRY_CIPHER_SERPENT128; case GCRY_MAC_CMAC_SEED: return GCRY_CIPHER_SEED; case GCRY_MAC_CMAC_RFC2268: return GCRY_CIPHER_RFC2268_128; case GCRY_MAC_CMAC_GOST28147: return GCRY_CIPHER_GOST28147; case GCRY_MAC_CMAC_SM4: return GCRY_CIPHER_SM4; } } static gcry_err_code_t cmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_cipher_hd_t hd; int secure = (h->magic == CTX_MAC_MAGIC_SECURE); int cipher_algo; unsigned int flags; cipher_algo = map_mac_algo_to_cipher (h->spec->algo); flags = (secure ? GCRY_CIPHER_SECURE : 0); err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CMAC, flags); if (err) return err; h->u.cmac.cipher_algo = cipher_algo; h->u.cmac.ctx = hd; h->u.cmac.blklen = _gcry_cipher_get_algo_blklen (cipher_algo); return 0; } static void cmac_close (gcry_mac_hd_t h) { _gcry_cipher_close (h->u.cmac.ctx); h->u.cmac.ctx = NULL; } static gcry_err_code_t cmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_cipher_setkey (h->u.cmac.ctx, key, keylen); } static gcry_err_code_t cmac_reset (gcry_mac_hd_t h) { return _gcry_cipher_reset (h->u.cmac.ctx); } static gcry_err_code_t cmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_cmac_authenticate (h->u.cmac.ctx, buf, buflen); } static gcry_err_code_t cmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { if (*outlen > h->u.cmac.blklen) *outlen = h->u.cmac.blklen; return _gcry_cipher_cmac_get_tag (h->u.cmac.ctx, outbuf, *outlen); } static gcry_err_code_t cmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_cmac_check_tag (h->u.cmac.ctx, buf, buflen); } static unsigned int cmac_get_maclen (int algo) { return _gcry_cipher_get_algo_blklen (map_mac_algo_to_cipher (algo)); } static unsigned int cmac_get_keylen (int algo) { return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); } /* Check one CMAC with MAC ALGO using the regular MAC * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key * and (EXPECT,EXPECTLEN) the expected result. Returns NULL on * success or a string describing the failure. */ static const char * check_one (int algo, const char *data, size_t datalen, const char *key, size_t keylen, const char *expect, size_t expectlen) { gcry_mac_hd_t hd; unsigned char mac[512]; /* hardcoded to avoid allocation */ unsigned int maclen; size_t macoutlen; int i; gcry_error_t err = 0; err = _gcry_mac_open (&hd, algo, 0, NULL); if (err) return "gcry_mac_open failed"; i = _gcry_mac_get_algo (hd); if (i != algo) return "gcry_mac_get_algo failed"; maclen = _gcry_mac_get_algo_maclen (algo); if (maclen < 1 || maclen > 500) return "gcry_mac_get_algo_maclen failed"; if (maclen != expectlen) return "invalid tests data"; err = _gcry_mac_setkey (hd, key, keylen); if (err) { _gcry_mac_close (hd); return "gcry_mac_setkey failed"; } err = _gcry_mac_write (hd, data, datalen); if (err) { _gcry_mac_close (hd); return "gcry_mac_write failed"; } err = _gcry_mac_verify (hd, expect, maclen); if (err) { _gcry_mac_close (hd); return "gcry_mac_verify failed"; } macoutlen = maclen; err = _gcry_mac_read (hd, mac, &macoutlen); _gcry_mac_close (hd); if (err) return "gcry_mac_read failed"; if (memcmp (mac, expect, maclen)) return "does not match"; return NULL; } /* * CMAC AES and DES test vectors are from * http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica \ * tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ static gpg_err_code_t selftests_cmac_3des (int extended, selftest_report_func_t report) { static const struct { const char *desc; const char *data; const char *key; const char *expect; } tv[] = { { "Basic 3DES", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\x74\x3d\xdb\xe0\xce\x2d\xc2\xed" }, { "Extended 3DES #1", "", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\xb7\xa6\x88\xe1\x22\xff\xaf\x95" }, { "Extended 3DES #2", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\x8e\x8f\x29\x31\x36\x28\x37\x97" }, { "Extended 3DES #3", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\x33\xe6\xb1\x09\x24\x00\xea\xe5" }, { "Extended 3DES #4", "", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\xbd\x2e\xbf\x9a\x3b\xa0\x03\x61" }, { "Extended 3DES #5", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\x4f\xf2\xab\x81\x3c\x53\xce\x83" }, { "Extended 3DES #6", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\x62\xdd\x1b\x47\x19\x02\xbd\x4e" }, { "Extended 3DES #7", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\x31\xb1\xe4\x31\xda\xbc\x4e\xb8" }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MAC_CMAC_3DES, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, 8); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("cmac", GCRY_MAC_CMAC_3DES, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_cmac_aes (int extended, selftest_report_func_t report) { static const struct { const char *desc; const char *data; const char *key; const char *expect; } tv[] = { { "Basic AES128", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61\x14\x97\xc8\x27" }, { "Basic AES192", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\x8a\x1d\xe5\xbe\x2e\xb3\x1a\xad\x08\x9a\x82\xe6\xee\x90\x8b\x0e" }, { "Basic AES256", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\xaa\xf3\xd8\xf1\xde\x56\x40\xc2\x32\xf5\xb1\x69\xb9\xc9\x11\xe6" }, { "Extended AES #1", "", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12\x9b\x75\x67\x46" }, { "Extended AES #2", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\x9e\x99\xa7\xbf\x31\xe7\x10\x90\x06\x62\xf6\x5e\x61\x7c\x51\x84" }, { "Extended AES #3", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\xe1\x99\x21\x90\x54\x9f\x6e\xd5\x69\x6a\x2c\x05\x6c\x31\x54\x10" }, { "Extended AES #4", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c" }, { "Extended AES #5", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17\x79\x36\x3c\xfe" }, { "Extended AES #6", "", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\xd1\x7d\xdf\x46\xad\xaa\xcd\xe5\x31\xca\xc4\x83\xde\x7a\x93\x67" }, { "Extended AES #7", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\xa1\xd5\xdf\x0e\xed\x79\x0f\x79\x4d\x77\x58\x96\x59\xf3\x9a\x11" }, { "Extended AES #8", "", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\x02\x89\x62\xf6\x1b\x7b\xf8\x9e\xfc\x6b\x55\x1f\x46\x67\xd9\x83" }, { "Extended AES #9", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\x28\xa7\x02\x3f\x45\x2e\x8f\x82\xbd\x4b\xf2\x8d\x8c\x37\xc3\x5c" }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MAC_CMAC_AES, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, strlen (tv[tvidx].expect)); if (errtxt) goto failed; if (tvidx >= 2 && !extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("cmac", GCRY_MAC_CMAC_AES, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t cmac_selftest (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MAC_CMAC_3DES: ec = selftests_cmac_3des (extended, report); break; case GCRY_MAC_CMAC_AES: ec = selftests_cmac_aes (extended, report); break; default: ec = GPG_ERR_MAC_ALGO; break; } return ec; } static gcry_mac_spec_ops_t cmac_ops = { cmac_open, cmac_close, cmac_setkey, NULL, cmac_reset, cmac_write, cmac_read, cmac_verify, cmac_get_maclen, cmac_get_keylen, NULL, cmac_selftest }; #if USE_BLOWFISH -gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish = { GCRY_MAC_CMAC_BLOWFISH, {0, 0}, "CMAC_BLOWFISH", &cmac_ops }; #endif #if USE_DES -gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes = { GCRY_MAC_CMAC_3DES, {0, 0}, "CMAC_3DES", &cmac_ops }; #endif #if USE_CAST5 -gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5 = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5 = { GCRY_MAC_CMAC_CAST5, {0, 0}, "CMAC_CAST5", &cmac_ops }; #endif #if USE_AES -gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes = { GCRY_MAC_CMAC_AES, {0, 1}, "CMAC_AES", &cmac_ops }; #endif #if USE_TWOFISH -gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish = { GCRY_MAC_CMAC_TWOFISH, {0, 0}, "CMAC_TWOFISH", &cmac_ops }; #endif #if USE_SERPENT -gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent = { GCRY_MAC_CMAC_SERPENT, {0, 0}, "CMAC_SERPENT", &cmac_ops }; #endif #if USE_RFC2268 -gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268 = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268 = { GCRY_MAC_CMAC_RFC2268, {0, 0}, "CMAC_RFC2268", &cmac_ops }; #endif #if USE_SEED -gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed = { GCRY_MAC_CMAC_SEED, {0, 0}, "CMAC_SEED", &cmac_ops }; #endif #if USE_CAMELLIA -gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia = { GCRY_MAC_CMAC_CAMELLIA, {0, 0}, "CMAC_CAMELLIA", &cmac_ops }; #endif #if USE_IDEA -gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea = { GCRY_MAC_CMAC_IDEA, {0, 0}, "CMAC_IDEA", &cmac_ops }; #endif #if USE_GOST28147 -gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147 = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147 = { GCRY_MAC_CMAC_GOST28147, {0, 0}, "CMAC_GOST28147", &cmac_ops }; #endif #if USE_SM4 -gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4 = { +const gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4 = { GCRY_MAC_CMAC_SM4, {0, 0}, "CMAC_SM4", &cmac_ops }; #endif diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c index 1d59d085..12f515eb 100644 --- a/cipher/mac-gmac.c +++ b/cipher/mac-gmac.c @@ -1,187 +1,187 @@ /* mac-gmac.c - GMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "./mac-internal.h" static int map_mac_algo_to_cipher (int mac_algo) { switch (mac_algo) { default: return GCRY_CIPHER_NONE; case GCRY_MAC_GMAC_AES: return GCRY_CIPHER_AES; case GCRY_MAC_GMAC_CAMELLIA: return GCRY_CIPHER_CAMELLIA128; case GCRY_MAC_GMAC_TWOFISH: return GCRY_CIPHER_TWOFISH; case GCRY_MAC_GMAC_SERPENT: return GCRY_CIPHER_SERPENT128; case GCRY_MAC_GMAC_SEED: return GCRY_CIPHER_SEED; } } static gcry_err_code_t gmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_cipher_hd_t hd; int secure = (h->magic == CTX_MAC_MAGIC_SECURE); int cipher_algo; unsigned int flags; cipher_algo = map_mac_algo_to_cipher (h->spec->algo); flags = (secure ? GCRY_CIPHER_SECURE : 0); err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_GCM, flags); if (err) return err; h->u.gmac.cipher_algo = cipher_algo; h->u.gmac.ctx = hd; return 0; } static void gmac_close (gcry_mac_hd_t h) { _gcry_cipher_close (h->u.gmac.ctx); h->u.gmac.ctx = NULL; } static gcry_err_code_t gmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_cipher_setkey (h->u.gmac.ctx, key, keylen); } static gcry_err_code_t gmac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { return _gcry_cipher_setiv (h->u.gmac.ctx, iv, ivlen); } static gcry_err_code_t gmac_reset (gcry_mac_hd_t h) { return _gcry_cipher_reset (h->u.gmac.ctx); } static gcry_err_code_t gmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_authenticate (h->u.gmac.ctx, buf, buflen); } static gcry_err_code_t gmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { if (*outlen > GCRY_GCM_BLOCK_LEN) *outlen = GCRY_GCM_BLOCK_LEN; return _gcry_cipher_gettag (h->u.gmac.ctx, outbuf, *outlen); } static gcry_err_code_t gmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_checktag (h->u.gmac.ctx, buf, buflen); } static unsigned int gmac_get_maclen (int algo) { (void)algo; return GCRY_GCM_BLOCK_LEN; } static unsigned int gmac_get_keylen (int algo) { return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); } static gcry_mac_spec_ops_t gmac_ops = { gmac_open, gmac_close, gmac_setkey, gmac_setiv, gmac_reset, gmac_write, gmac_read, gmac_verify, gmac_get_maclen, gmac_get_keylen, NULL, NULL }; #if USE_AES -gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = { +const gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = { GCRY_MAC_GMAC_AES, {0, 0}, "GMAC_AES", &gmac_ops }; #endif #if USE_TWOFISH -gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish = { +const gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish = { GCRY_MAC_GMAC_TWOFISH, {0, 0}, "GMAC_TWOFISH", &gmac_ops }; #endif #if USE_SERPENT -gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent = { +const gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent = { GCRY_MAC_GMAC_SERPENT, {0, 0}, "GMAC_SERPENT", &gmac_ops }; #endif #if USE_SEED -gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed = { +const gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed = { GCRY_MAC_GMAC_SEED, {0, 0}, "GMAC_SEED", &gmac_ops }; #endif #if USE_CAMELLIA -gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia = { +const gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia = { GCRY_MAC_GMAC_CAMELLIA, {0, 0}, "GMAC_CAMELLIA", &gmac_ops }; #endif diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c index 38746241..108a4408 100644 --- a/cipher/mac-hmac.c +++ b/cipher/mac-hmac.c @@ -1,1466 +1,1466 @@ /* mac-hmac.c - HMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * Copyright (C) 2008 Free Software Foundation, Inc. * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "./mac-internal.h" #include "bufhelp.h" #include "cipher.h" static int map_mac_algo_to_md (int mac_algo) { switch (mac_algo) { default: return GCRY_MD_NONE; case GCRY_MAC_HMAC_MD2: return GCRY_MD_MD2; case GCRY_MAC_HMAC_MD4: return GCRY_MD_MD4; case GCRY_MAC_HMAC_MD5: return GCRY_MD_MD5; case GCRY_MAC_HMAC_SHA1: return GCRY_MD_SHA1; case GCRY_MAC_HMAC_SHA224: return GCRY_MD_SHA224; case GCRY_MAC_HMAC_SHA256: return GCRY_MD_SHA256; case GCRY_MAC_HMAC_SHA384: return GCRY_MD_SHA384; case GCRY_MAC_HMAC_SHA512: return GCRY_MD_SHA512; case GCRY_MAC_HMAC_SHA512_256: return GCRY_MD_SHA512_256; case GCRY_MAC_HMAC_SHA512_224: return GCRY_MD_SHA512_224; case GCRY_MAC_HMAC_SHA3_224: return GCRY_MD_SHA3_224; case GCRY_MAC_HMAC_SHA3_256: return GCRY_MD_SHA3_256; case GCRY_MAC_HMAC_SHA3_384: return GCRY_MD_SHA3_384; case GCRY_MAC_HMAC_SHA3_512: return GCRY_MD_SHA3_512; case GCRY_MAC_HMAC_RMD160: return GCRY_MD_RMD160; case GCRY_MAC_HMAC_TIGER1: return GCRY_MD_TIGER1; case GCRY_MAC_HMAC_WHIRLPOOL: return GCRY_MD_WHIRLPOOL; case GCRY_MAC_HMAC_GOSTR3411_94: return GCRY_MD_GOSTR3411_94; case GCRY_MAC_HMAC_GOSTR3411_CP: return GCRY_MD_GOSTR3411_CP; case GCRY_MAC_HMAC_STRIBOG256: return GCRY_MD_STRIBOG256; case GCRY_MAC_HMAC_STRIBOG512: return GCRY_MD_STRIBOG512; case GCRY_MAC_HMAC_BLAKE2B_512: return GCRY_MD_BLAKE2B_512; case GCRY_MAC_HMAC_BLAKE2B_384: return GCRY_MD_BLAKE2B_384; case GCRY_MAC_HMAC_BLAKE2B_256: return GCRY_MD_BLAKE2B_256; case GCRY_MAC_HMAC_BLAKE2B_160: return GCRY_MD_BLAKE2B_160; case GCRY_MAC_HMAC_BLAKE2S_256: return GCRY_MD_BLAKE2S_256; case GCRY_MAC_HMAC_BLAKE2S_224: return GCRY_MD_BLAKE2S_224; case GCRY_MAC_HMAC_BLAKE2S_160: return GCRY_MD_BLAKE2S_160; case GCRY_MAC_HMAC_BLAKE2S_128: return GCRY_MD_BLAKE2S_128; case GCRY_MAC_HMAC_SM3: return GCRY_MD_SM3; } } static gcry_err_code_t hmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_md_hd_t hd; int secure = (h->magic == CTX_MAC_MAGIC_SECURE); unsigned int flags; int md_algo; md_algo = map_mac_algo_to_md (h->spec->algo); flags = GCRY_MD_FLAG_HMAC; flags |= (secure ? GCRY_MD_FLAG_SECURE : 0); err = _gcry_md_open (&hd, md_algo, flags); if (err) return err; h->u.hmac.md_algo = md_algo; h->u.hmac.md_ctx = hd; return 0; } static void hmac_close (gcry_mac_hd_t h) { _gcry_md_close (h->u.hmac.md_ctx); h->u.hmac.md_ctx = NULL; } static gcry_err_code_t hmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_md_setkey (h->u.hmac.md_ctx, key, keylen); } static gcry_err_code_t hmac_reset (gcry_mac_hd_t h) { _gcry_md_reset (h->u.hmac.md_ctx); return 0; } static gcry_err_code_t hmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { _gcry_md_write (h->u.hmac.md_ctx, buf, buflen); return 0; } static gcry_err_code_t hmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { unsigned int dlen; const unsigned char *digest; dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo); digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); if (*outlen <= dlen) buf_cpy (outbuf, digest, *outlen); else { buf_cpy (outbuf, digest, dlen); *outlen = dlen; } return 0; } static gcry_err_code_t hmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { unsigned int dlen; const unsigned char *digest; dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo); digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); if (buflen > dlen) return GPG_ERR_INV_LENGTH; return buf_eq_const (buf, digest, buflen) ? 0 : GPG_ERR_CHECKSUM; } static unsigned int hmac_get_maclen (int algo) { return _gcry_md_get_algo_dlen (map_mac_algo_to_md (algo)); } static unsigned int hmac_get_keylen (int algo) { /* Return blocksize for default key length. */ switch (algo) { case GCRY_MD_SHA3_224: return 1152 / 8; case GCRY_MD_SHA3_256: return 1088 / 8; case GCRY_MD_SHA3_384: return 832 / 8; case GCRY_MD_SHA3_512: return 576 / 8; case GCRY_MAC_HMAC_SHA384: case GCRY_MAC_HMAC_SHA512: return 128; case GCRY_MAC_HMAC_GOSTR3411_94: return 32; default: return 64; } } /* Check one HMAC with digest ALGO using the regualr HAMC * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key * and (EXPECT,EXPECTLEN) the expected result. If TRUNC is set, the * EXPECTLEN may be less than the digest length. Returns NULL on * success or a string describing the failure. */ static const char * check_one (int algo, const void *data, size_t datalen, const void *key, size_t keylen, const void *expect, size_t expectlen, int trunc) { gcry_md_hd_t hd; const unsigned char *digest; /* printf ("HMAC algo %d\n", algo); */ if (trunc) { if (_gcry_md_get_algo_dlen (algo) < expectlen) return "invalid tests data"; } else { if (_gcry_md_get_algo_dlen (algo) != expectlen) return "invalid tests data"; } if (_gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC)) return "gcry_md_open failed"; if (_gcry_md_setkey (hd, key, keylen)) { _gcry_md_close (hd); return "gcry_md_setkey failed"; } _gcry_md_write (hd, data, datalen); digest = _gcry_md_read (hd, algo); if (!digest) { _gcry_md_close (hd); return "gcry_md_read failed"; } if (memcmp (digest, expect, expectlen)) { /* int i; */ /* fputs (" {", stdout); */ /* for (i=0; i < expectlen-1; i++) */ /* { */ /* if (i && !(i % 8)) */ /* fputs ("\n ", stdout); */ /* printf (" 0x%02x,", digest[i]); */ /* } */ /* printf (" 0x%02x } },\n", digest[i]); */ _gcry_md_close (hd); return "does not match"; } _gcry_md_close (hd); return NULL; } static gpg_err_code_t selftests_sha1 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; unsigned char key[128]; int i, j; what = "FIPS-198a, A.1"; for (i=0; i < 64; i++) key[i] = i; errtxt = check_one (GCRY_MD_SHA1, "Sample #1", 9, key, 64, "\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12" "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a", 20, 0); if (errtxt) goto failed; if (extended) { what = "FIPS-198a, A.2"; for (i=0, j=0x30; i < 20; i++) key[i] = j++; errtxt = check_one (GCRY_MD_SHA1, "Sample #2", 9, key, 20, "\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82" "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20, 0); if (errtxt) goto failed; what = "FIPS-198a, A.3"; for (i=0, j=0x50; i < 100; i++) key[i] = j++; errtxt = check_one (GCRY_MD_SHA1, "Sample #3", 9, key, 100, "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0" "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20, 0); if (errtxt) goto failed; what = "FIPS-198a, A.4"; for (i=0, j=0x70; i < 49; i++) key[i] = j++; errtxt = check_one (GCRY_MD_SHA1, "Sample #4", 9, key, 49, "\x9e\xa8\x86\xef\xe2\x68\xdb\xec\xce\x42" "\x0c\x75\x24\xdf\x32\xe0\x75\x1a\x2a\x26", 20, 0); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA1, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha224 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[28]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, 0xe7, 0xaf, 0xec, 0x5a } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, 0xf6, 0xf5, 0x65, 0xd1 } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA224, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA224, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha256 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[32]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA256, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA256, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha384 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[48]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27 } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA384, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA384, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha512 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[64]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA512, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA512, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Test for the SHA3 algorithms. Vectors taken on 2017-07-18 from * http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html */ static gpg_err_code_t selftests_sha3 (int hashalgo, int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect_224[28]; const char expect_256[32]; const char expect_384[48]; const char expect_512[64]; unsigned char trunc; } tv[] = { { "data-9 key-20", /* Test 1 */ "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0x3b, 0x16, 0x54, 0x6b, 0xbc, 0x7b, 0xe2, 0x70, 0x6a, 0x03, 0x1d, 0xca, 0xfd, 0x56, 0x37, 0x3d, 0x98, 0x84, 0x36, 0x76, 0x41, 0xd8, 0xc5, 0x9a, 0xf3, 0xc8, 0x60, 0xf7 }, { 0xba, 0x85, 0x19, 0x23, 0x10, 0xdf, 0xfa, 0x96, 0xe2, 0xa3, 0xa4, 0x0e, 0x69, 0x77, 0x43, 0x51, 0x14, 0x0b, 0xb7, 0x18, 0x5e, 0x12, 0x02, 0xcd, 0xcc, 0x91, 0x75, 0x89, 0xf9, 0x5e, 0x16, 0xbb }, { 0x68, 0xd2, 0xdc, 0xf7, 0xfd, 0x4d, 0xdd, 0x0a, 0x22, 0x40, 0xc8, 0xa4, 0x37, 0x30, 0x5f, 0x61, 0xfb, 0x73, 0x34, 0xcf, 0xb5, 0xd0, 0x22, 0x6e, 0x1b, 0xc2, 0x7d, 0xc1, 0x0a, 0x2e, 0x72, 0x3a, 0x20, 0xd3, 0x70, 0xb4, 0x77, 0x43, 0x13, 0x0e, 0x26, 0xac, 0x7e, 0x3d, 0x53, 0x28, 0x86, 0xbd }, { 0xeb, 0x3f, 0xbd, 0x4b, 0x2e, 0xaa, 0xb8, 0xf5, 0xc5, 0x04, 0xbd, 0x3a, 0x41, 0x46, 0x5a, 0xac, 0xec, 0x15, 0x77, 0x0a, 0x7c, 0xab, 0xac, 0x53, 0x1e, 0x48, 0x2f, 0x86, 0x0b, 0x5e, 0xc7, 0xba, 0x47, 0xcc, 0xb2, 0xc6, 0xf2, 0xaf, 0xce, 0x8f, 0x88, 0xd2, 0x2b, 0x6d, 0xc6, 0x13, 0x80, 0xf2, 0x3a, 0x66, 0x8f, 0xd3, 0x88, 0x8b, 0xb8, 0x05, 0x37, 0xc0, 0xa0, 0xb8, 0x64, 0x07, 0x68, 0x9e } }, { "data-28 key-4", /* Test 2 */ /* Test with a key shorter than the length of the HMAC output. */ "what do ya want for nothing?", "Jefe", { 0x7f, 0xdb, 0x8d, 0xd8, 0x8b, 0xd2, 0xf6, 0x0d, 0x1b, 0x79, 0x86, 0x34, 0xad, 0x38, 0x68, 0x11, 0xc2, 0xcf, 0xc8, 0x5b, 0xfa, 0xf5, 0xd5, 0x2b, 0xba, 0xce, 0x5e, 0x66 }, { 0xc7, 0xd4, 0x07, 0x2e, 0x78, 0x88, 0x77, 0xae, 0x35, 0x96, 0xbb, 0xb0, 0xda, 0x73, 0xb8, 0x87, 0xc9, 0x17, 0x1f, 0x93, 0x09, 0x5b, 0x29, 0x4a, 0xe8, 0x57, 0xfb, 0xe2, 0x64, 0x5e, 0x1b, 0xa5 }, { 0xf1, 0x10, 0x1f, 0x8c, 0xbf, 0x97, 0x66, 0xfd, 0x67, 0x64, 0xd2, 0xed, 0x61, 0x90, 0x3f, 0x21, 0xca, 0x9b, 0x18, 0xf5, 0x7c, 0xf3, 0xe1, 0xa2, 0x3c, 0xa1, 0x35, 0x08, 0xa9, 0x32, 0x43, 0xce, 0x48, 0xc0, 0x45, 0xdc, 0x00, 0x7f, 0x26, 0xa2, 0x1b, 0x3f, 0x5e, 0x0e, 0x9d, 0xf4, 0xc2, 0x0a }, { 0x5a, 0x4b, 0xfe, 0xab, 0x61, 0x66, 0x42, 0x7c, 0x7a, 0x36, 0x47, 0xb7, 0x47, 0x29, 0x2b, 0x83, 0x84, 0x53, 0x7c, 0xdb, 0x89, 0xaf, 0xb3, 0xbf, 0x56, 0x65, 0xe4, 0xc5, 0xe7, 0x09, 0x35, 0x0b, 0x28, 0x7b, 0xae, 0xc9, 0x21, 0xfd, 0x7c, 0xa0, 0xee, 0x7a, 0x0c, 0x31, 0xd0, 0x22, 0xa9, 0x5e, 0x1f, 0xc9, 0x2b, 0xa9, 0xd7, 0x7d, 0xf8, 0x83, 0x96, 0x02, 0x75, 0xbe, 0xb4, 0xe6, 0x20, 0x24 } }, { "data-50 key-20", /* Test 3 */ /* Test with a combined length of key and data that is larger * than 64 bytes (= block-size of SHA-224 and SHA-256). */ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x67, 0x6c, 0xfc, 0x7d, 0x16, 0x15, 0x36, 0x38, 0x78, 0x03, 0x90, 0x69, 0x2b, 0xe1, 0x42, 0xd2, 0xdf, 0x7c, 0xe9, 0x24, 0xb9, 0x09, 0xc0, 0xc0, 0x8d, 0xbf, 0xdc, 0x1a }, { 0x84, 0xec, 0x79, 0x12, 0x4a, 0x27, 0x10, 0x78, 0x65, 0xce, 0xdd, 0x8b, 0xd8, 0x2d, 0xa9, 0x96, 0x5e, 0x5e, 0xd8, 0xc3, 0x7b, 0x0a, 0xc9, 0x80, 0x05, 0xa7, 0xf3, 0x9e, 0xd5, 0x8a, 0x42, 0x07 }, { 0x27, 0x5c, 0xd0, 0xe6, 0x61, 0xbb, 0x8b, 0x15, 0x1c, 0x64, 0xd2, 0x88, 0xf1, 0xf7, 0x82, 0xfb, 0x91, 0xa8, 0xab, 0xd5, 0x68, 0x58, 0xd7, 0x2b, 0xab, 0xb2, 0xd4, 0x76, 0xf0, 0x45, 0x83, 0x73, 0xb4, 0x1b, 0x6a, 0xb5, 0xbf, 0x17, 0x4b, 0xec, 0x42, 0x2e, 0x53, 0xfc, 0x31, 0x35, 0xac, 0x6e }, { 0x30, 0x9e, 0x99, 0xf9, 0xec, 0x07, 0x5e, 0xc6, 0xc6, 0xd4, 0x75, 0xed, 0xa1, 0x18, 0x06, 0x87, 0xfc, 0xf1, 0x53, 0x11, 0x95, 0x80, 0x2a, 0x99, 0xb5, 0x67, 0x74, 0x49, 0xa8, 0x62, 0x51, 0x82, 0x85, 0x1c, 0xb3, 0x32, 0xaf, 0xb6, 0xa8, 0x9c, 0x41, 0x13, 0x25, 0xfb, 0xcb, 0xcd, 0x42, 0xaf, 0xcb, 0x7b, 0x6e, 0x5a, 0xab, 0x7e, 0xa4, 0x2c, 0x66, 0x0f, 0x97, 0xfd, 0x85, 0x84, 0xbf, 0x03 } }, { "data-50 key-25", /* Test 4 */ /* Test with a combined length of key and data that is larger * than 64 bytes (= block-size of SHA-224 and SHA-256). */ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0xa9, 0xd7, 0x68, 0x5a, 0x19, 0xc4, 0xe0, 0xdb, 0xd9, 0xdf, 0x25, 0x56, 0xcc, 0x8a, 0x7d, 0x2a, 0x77, 0x33, 0xb6, 0x76, 0x25, 0xce, 0x59, 0x4c, 0x78, 0x27, 0x0e, 0xeb }, { 0x57, 0x36, 0x6a, 0x45, 0xe2, 0x30, 0x53, 0x21, 0xa4, 0xbc, 0x5a, 0xa5, 0xfe, 0x2e, 0xf8, 0xa9, 0x21, 0xf6, 0xaf, 0x82, 0x73, 0xd7, 0xfe, 0x7b, 0xe6, 0xcf, 0xed, 0xb3, 0xf0, 0xae, 0xa6, 0xd7 }, { 0x3a, 0x5d, 0x7a, 0x87, 0x97, 0x02, 0xc0, 0x86, 0xbc, 0x96, 0xd1, 0xdd, 0x8a, 0xa1, 0x5d, 0x9c, 0x46, 0x44, 0x6b, 0x95, 0x52, 0x13, 0x11, 0xc6, 0x06, 0xfd, 0xc4, 0xe3, 0x08, 0xf4, 0xb9, 0x84, 0xda, 0x2d, 0x0f, 0x94, 0x49, 0xb3, 0xba, 0x84, 0x25, 0xec, 0x7f, 0xb8, 0xc3, 0x1b, 0xc1, 0x36 }, { 0xb2, 0x7e, 0xab, 0x1d, 0x6e, 0x8d, 0x87, 0x46, 0x1c, 0x29, 0xf7, 0xf5, 0x73, 0x9d, 0xd5, 0x8e, 0x98, 0xaa, 0x35, 0xf8, 0xe8, 0x23, 0xad, 0x38, 0xc5, 0x49, 0x2a, 0x20, 0x88, 0xfa, 0x02, 0x81, 0x99, 0x3b, 0xbf, 0xff, 0x9a, 0x0e, 0x9c, 0x6b, 0xf1, 0x21, 0xae, 0x9e, 0xc9, 0xbb, 0x09, 0xd8, 0x4a, 0x5e, 0xba, 0xc8, 0x17, 0x18, 0x2e, 0xa9, 0x74, 0x67, 0x3f, 0xb1, 0x33, 0xca, 0x0d, 0x1d } }, { "data-20 key-20 trunc", /* Test 5 */ /* Test with a truncation of output to 128 bits. */ "Test With Truncation", "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c", { 0x49, 0xfd, 0xd3, 0xab, 0xd0, 0x05, 0xeb, 0xb8, 0xae, 0x63, 0xfe, 0xa9, 0x46, 0xd1, 0x88, 0x3c }, { 0x6e, 0x02, 0xc6, 0x45, 0x37, 0xfb, 0x11, 0x80, 0x57, 0xab, 0xb7, 0xfb, 0x66, 0xa2, 0x3b, 0x3c }, { 0x47, 0xc5, 0x1a, 0xce, 0x1f, 0xfa, 0xcf, 0xfd, 0x74, 0x94, 0x72, 0x46, 0x82, 0x61, 0x57, 0x83 }, { 0x0f, 0xa7, 0x47, 0x59, 0x48, 0xf4, 0x3f, 0x48, 0xca, 0x05, 0x16, 0x67, 0x1e, 0x18, 0x97, 0x8c }, 16 }, { "data-54 key-131", /* Test 6 */ /* Test with a key larger than 128 bytes (= block-size of * SHA-384 and SHA-512). */ "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xb4, 0xa1, 0xf0, 0x4c, 0x00, 0x28, 0x7a, 0x9b, 0x7f, 0x60, 0x75, 0xb3, 0x13, 0xd2, 0x79, 0xb8, 0x33, 0xbc, 0x8f, 0x75, 0x12, 0x43, 0x52, 0xd0, 0x5f, 0xb9, 0x99, 0x5f }, { 0xed, 0x73, 0xa3, 0x74, 0xb9, 0x6c, 0x00, 0x52, 0x35, 0xf9, 0x48, 0x03, 0x2f, 0x09, 0x67, 0x4a, 0x58, 0xc0, 0xce, 0x55, 0x5c, 0xfc, 0x1f, 0x22, 0x3b, 0x02, 0x35, 0x65, 0x60, 0x31, 0x2c, 0x3b }, { 0x0f, 0xc1, 0x95, 0x13, 0xbf, 0x6b, 0xd8, 0x78, 0x03, 0x70, 0x16, 0x70, 0x6a, 0x0e, 0x57, 0xbc, 0x52, 0x81, 0x39, 0x83, 0x6b, 0x9a, 0x42, 0xc3, 0xd4, 0x19, 0xe4, 0x98, 0xe0, 0xe1, 0xfb, 0x96, 0x16, 0xfd, 0x66, 0x91, 0x38, 0xd3, 0x3a, 0x11, 0x05, 0xe0, 0x7c, 0x72, 0xb6, 0x95, 0x3b, 0xcc }, { 0x00, 0xf7, 0x51, 0xa9, 0xe5, 0x06, 0x95, 0xb0, 0x90, 0xed, 0x69, 0x11, 0xa4, 0xb6, 0x55, 0x24, 0x95, 0x1c, 0xdc, 0x15, 0xa7, 0x3a, 0x5d, 0x58, 0xbb, 0x55, 0x21, 0x5e, 0xa2, 0xcd, 0x83, 0x9a, 0xc7, 0x9d, 0x2b, 0x44, 0xa3, 0x9b, 0xaf, 0xab, 0x27, 0xe8, 0x3f, 0xde, 0x9e, 0x11, 0xf6, 0x34, 0x0b, 0x11, 0xd9, 0x91, 0xb1, 0xb9, 0x1b, 0xf2, 0xee, 0xe7, 0xfc, 0x87, 0x24, 0x26, 0xc3, 0xa4 } }, { "data-54 key-147", /* Test 6a */ /* Test with a key larger than 144 bytes (= block-size of * SHA3-224). */ "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xb9, 0x6d, 0x73, 0x0c, 0x14, 0x8c, 0x2d, 0xaa, 0xd8, 0x64, 0x9d, 0x83, 0xde, 0xfa, 0xa3, 0x71, 0x97, 0x38, 0xd3, 0x47, 0x75, 0x39, 0x7b, 0x75, 0x71, 0xc3, 0x85, 0x15 }, { 0xa6, 0x07, 0x2f, 0x86, 0xde, 0x52, 0xb3, 0x8b, 0xb3, 0x49, 0xfe, 0x84, 0xcd, 0x6d, 0x97, 0xfb, 0x6a, 0x37, 0xc4, 0xc0, 0xf6, 0x2a, 0xae, 0x93, 0x98, 0x11, 0x93, 0xa7, 0x22, 0x9d, 0x34, 0x67 }, { 0x71, 0x3d, 0xff, 0x03, 0x02, 0xc8, 0x50, 0x86, 0xec, 0x5a, 0xd0, 0x76, 0x8d, 0xd6, 0x5a, 0x13, 0xdd, 0xd7, 0x90, 0x68, 0xd8, 0xd4, 0xc6, 0x21, 0x2b, 0x71, 0x2e, 0x41, 0x64, 0x94, 0x49, 0x11, 0x14, 0x80, 0x23, 0x00, 0x44, 0x18, 0x5a, 0x99, 0x10, 0x3e, 0xd8, 0x20, 0x04, 0xdd, 0xbf, 0xcc }, { 0xb1, 0x48, 0x35, 0xc8, 0x19, 0xa2, 0x90, 0xef, 0xb0, 0x10, 0xac, 0xe6, 0xd8, 0x56, 0x8d, 0xc6, 0xb8, 0x4d, 0xe6, 0x0b, 0xc4, 0x9b, 0x00, 0x4c, 0x3b, 0x13, 0xed, 0xa7, 0x63, 0x58, 0x94, 0x51, 0xe5, 0xdd, 0x74, 0x29, 0x28, 0x84, 0xd1, 0xbd, 0xce, 0x64, 0xe6, 0xb9, 0x19, 0xdd, 0x61, 0xdc, 0x9c, 0x56, 0xa2, 0x82, 0xa8, 0x1c, 0x0b, 0xd1, 0x4f, 0x1f, 0x36, 0x5b, 0x49, 0xb8, 0x3a, 0x5b } }, { "data-152 key-131", /* Test 7 */ /* Test with a key and data that is larger than 128 bytes (= * block-size of SHA-384 and SHA-512). */ "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x05, 0xd8, 0xcd, 0x6d, 0x00, 0xfa, 0xea, 0x8d, 0x1e, 0xb6, 0x8a, 0xde, 0x28, 0x73, 0x0b, 0xbd, 0x3c, 0xba, 0xb6, 0x92, 0x9f, 0x0a, 0x08, 0x6b, 0x29, 0xcd, 0x62, 0xa0 }, { 0x65, 0xc5, 0xb0, 0x6d, 0x4c, 0x3d, 0xe3, 0x2a, 0x7a, 0xef, 0x87, 0x63, 0x26, 0x1e, 0x49, 0xad, 0xb6, 0xe2, 0x29, 0x3e, 0xc8, 0xe7, 0xc6, 0x1e, 0x8d, 0xe6, 0x17, 0x01, 0xfc, 0x63, 0xe1, 0x23 }, { 0x02, 0x6f, 0xdf, 0x6b, 0x50, 0x74, 0x1e, 0x37, 0x38, 0x99, 0xc9, 0xf7, 0xd5, 0x40, 0x6d, 0x4e, 0xb0, 0x9f, 0xc6, 0x66, 0x56, 0x36, 0xfc, 0x1a, 0x53, 0x00, 0x29, 0xdd, 0xf5, 0xcf, 0x3c, 0xa5, 0xa9, 0x00, 0xed, 0xce, 0x01, 0xf5, 0xf6, 0x1e, 0x2f, 0x40, 0x8c, 0xdf, 0x2f, 0xd3, 0xe7, 0xe8 }, { 0x38, 0xa4, 0x56, 0xa0, 0x04, 0xbd, 0x10, 0xd3, 0x2c, 0x9a, 0xb8, 0x33, 0x66, 0x84, 0x11, 0x28, 0x62, 0xc3, 0xdb, 0x61, 0xad, 0xcc, 0xa3, 0x18, 0x29, 0x35, 0x5e, 0xaf, 0x46, 0xfd, 0x5c, 0x73, 0xd0, 0x6a, 0x1f, 0x0d, 0x13, 0xfe, 0xc9, 0xa6, 0x52, 0xfb, 0x38, 0x11, 0xb5, 0x77, 0xb1, 0xb1, 0xd1, 0xb9, 0x78, 0x9f, 0x97, 0xae, 0x5b, 0x83, 0xc6, 0xf4, 0x4d, 0xfc, 0xf1, 0xd6, 0x7e, 0xba } }, { "data-152 key-147", /* Test 7a */ /* Test with a key larger than 144 bytes (= block-size of * SHA3-224). */ "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xc7, 0x9c, 0x9b, 0x09, 0x34, 0x24, 0xe5, 0x88, 0xa9, 0x87, 0x8b, 0xbc, 0xb0, 0x89, 0xe0, 0x18, 0x27, 0x00, 0x96, 0xe9, 0xb4, 0xb1, 0xa9, 0xe8, 0x22, 0x0c, 0x86, 0x6a }, { 0xe6, 0xa3, 0x6d, 0x9b, 0x91, 0x5f, 0x86, 0xa0, 0x93, 0xca, 0xc7, 0xd1, 0x10, 0xe9, 0xe0, 0x4c, 0xf1, 0xd6, 0x10, 0x0d, 0x30, 0x47, 0x55, 0x09, 0xc2, 0x47, 0x5f, 0x57, 0x1b, 0x75, 0x8b, 0x5a }, { 0xca, 0xd1, 0x8a, 0x8f, 0xf6, 0xc4, 0xcc, 0x3a, 0xd4, 0x87, 0xb9, 0x5f, 0x97, 0x69, 0xe9, 0xb6, 0x1c, 0x06, 0x2a, 0xef, 0xd6, 0x95, 0x25, 0x69, 0xe6, 0xe6, 0x42, 0x18, 0x97, 0x05, 0x4c, 0xfc, 0x70, 0xb5, 0xfd, 0xc6, 0x60, 0x5c, 0x18, 0x45, 0x71, 0x12, 0xfc, 0x6a, 0xaa, 0xd4, 0x55, 0x85 }, { 0xdc, 0x03, 0x0e, 0xe7, 0x88, 0x70, 0x34, 0xf3, 0x2c, 0xf4, 0x02, 0xdf, 0x34, 0x62, 0x2f, 0x31, 0x1f, 0x3e, 0x6c, 0xf0, 0x48, 0x60, 0xc6, 0xbb, 0xd7, 0xfa, 0x48, 0x86, 0x74, 0x78, 0x2b, 0x46, 0x59, 0xfd, 0xbd, 0xf3, 0xfd, 0x87, 0x78, 0x52, 0x88, 0x5c, 0xfe, 0x6e, 0x22, 0x18, 0x5f, 0xe7, 0xb2, 0xee, 0x95, 0x20, 0x43, 0x62, 0x9b, 0xc9, 0xd5, 0xf3, 0x29, 0x8a, 0x41, 0xd0, 0x2c, 0x66 } }/*,*/ /* Our API does not allow to specify a bit count and thus we * can't use the following test. */ /* { "data-5bit key-4", /\* Test 8 *\/ */ /* /\* Test with data bit size no multiple of 8, the data bits are */ /* * '11001' from the NIST example using SHA-3 order (= 5 bits */ /* * from LSB hex byte 13 or 5 bits from MSB hex byte c8). *\/ */ /* "\xc8", */ /* "Jefe", */ /* { 0x5f, 0x8c, 0x0e, 0xa7, 0xfa, 0xfe, 0xcd, 0x0c, */ /* 0x34, 0x63, 0xaa, 0xd0, 0x97, 0x42, 0xce, 0xce, */ /* 0xb1, 0x42, 0xfe, 0x0a, 0xb6, 0xf4, 0x53, 0x94, */ /* 0x38, 0xc5, 0x9d, 0xe8 }, */ /* { 0xec, 0x82, 0x22, 0x77, 0x3f, 0xac, 0x68, 0xb3, */ /* 0xd3, 0xdc, 0xb1, 0x82, 0xae, 0xc8, 0xb0, 0x50, */ /* 0x7a, 0xce, 0x44, 0x48, 0xd2, 0x0a, 0x11, 0x47, */ /* 0xe6, 0x82, 0x11, 0x8d, 0xa4, 0xe3, 0xf4, 0x4c }, */ /* { 0x21, 0xfb, 0xd3, 0xbf, 0x3e, 0xbb, 0xa3, 0xcf, */ /* 0xc9, 0xef, 0x64, 0xc0, 0x59, 0x1c, 0x92, 0xc5, */ /* 0xac, 0xb2, 0x65, 0xe9, 0x2d, 0x87, 0x61, 0xd1, */ /* 0xf9, 0x1a, 0x52, 0xa1, 0x03, 0xa6, 0xc7, 0x96, */ /* 0x94, 0xcf, 0xd6, 0x7a, 0x9a, 0x2a, 0xc1, 0x32, */ /* 0x4f, 0x02, 0xfe, 0xa6, 0x3b, 0x81, 0xef, 0xfc }, */ /* { 0x27, 0xf9, 0x38, 0x8c, 0x15, 0x67, 0xef, 0x4e, */ /* 0xf2, 0x00, 0x60, 0x2a, 0x6c, 0xf8, 0x71, 0xd6, */ /* 0x8a, 0x6f, 0xb0, 0x48, 0xd4, 0x73, 0x7a, 0xc4, */ /* 0x41, 0x8a, 0x2f, 0x02, 0x12, 0x89, 0xd1, 0x3d, */ /* 0x1f, 0xd1, 0x12, 0x0f, 0xec, 0xb9, 0xcf, 0x96, */ /* 0x4c, 0x5b, 0x11, 0x7a, 0xb5, 0xb1, 0x1c, 0x61, */ /* 0x4b, 0x2d, 0xa3, 0x9d, 0xad, 0xd5, 0x1f, 0x2f, */ /* 0x5e, 0x22, 0xaa, 0xcc, 0xec, 0x7d, 0x57, 0x6e } */ /* } */ }; const char *what; const char *errtxt; int tvidx; const char *expect; int nexpect; for (tvidx=0; tvidx < DIM(tv); tvidx++) { what = tv[tvidx].desc; if (hashalgo == GCRY_MD_SHA3_224) { expect = tv[tvidx].expect_224; nexpect = DIM (tv[tvidx].expect_224); } else if (hashalgo == GCRY_MD_SHA3_256) { expect = tv[tvidx].expect_256; nexpect = DIM (tv[tvidx].expect_256); } else if (hashalgo == GCRY_MD_SHA3_384) { expect = tv[tvidx].expect_384; nexpect = DIM (tv[tvidx].expect_384); } else if (hashalgo == GCRY_MD_SHA3_512) { expect = tv[tvidx].expect_512; nexpect = DIM (tv[tvidx].expect_512); } else BUG(); if (tv[tvidx].trunc && tv[tvidx].trunc < nexpect) nexpect = tv[tvidx].trunc; errtxt = check_one (hashalgo, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), expect, nexpect, !!tv[tvidx].trunc); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", hashalgo, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t hmac_selftest (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MAC_HMAC_SHA1: ec = selftests_sha1 (extended, report); break; case GCRY_MAC_HMAC_SHA224: ec = selftests_sha224 (extended, report); break; case GCRY_MAC_HMAC_SHA256: ec = selftests_sha256 (extended, report); break; case GCRY_MAC_HMAC_SHA384: ec = selftests_sha384 (extended, report); break; case GCRY_MAC_HMAC_SHA512: ec = selftests_sha512 (extended, report); break; case GCRY_MAC_HMAC_SHA3_224: case GCRY_MAC_HMAC_SHA3_256: case GCRY_MAC_HMAC_SHA3_384: case GCRY_MAC_HMAC_SHA3_512: { int md_algo = map_mac_algo_to_md (algo); ec = selftests_sha3 (md_algo, extended, report); } break; default: ec = GPG_ERR_MAC_ALGO; break; } return ec; } static const gcry_mac_spec_ops_t hmac_ops = { hmac_open, hmac_close, hmac_setkey, NULL, hmac_reset, hmac_write, hmac_read, hmac_verify, hmac_get_maclen, hmac_get_keylen, NULL, hmac_selftest }; #if USE_SHA1 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1 = { GCRY_MAC_HMAC_SHA1, {0, 1}, "HMAC_SHA1", &hmac_ops }; #endif #if USE_SHA256 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256 = { GCRY_MAC_HMAC_SHA256, {0, 1}, "HMAC_SHA256", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224 = { GCRY_MAC_HMAC_SHA224, {0, 1}, "HMAC_SHA224", &hmac_ops }; #endif #if USE_SHA512 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512 = { GCRY_MAC_HMAC_SHA512, {0, 1}, "HMAC_SHA512", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = { GCRY_MAC_HMAC_SHA384, {0, 1}, "HMAC_SHA384", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256 = { GCRY_MAC_HMAC_SHA512_256, {0, 1}, "HMAC_SHA512_256", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224 = { GCRY_MAC_HMAC_SHA512_224, {0, 1}, "HMAC_SHA512_224", &hmac_ops }; #endif #if USE_SHA3 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224 = { GCRY_MAC_HMAC_SHA3_224, {0, 1}, "HMAC_SHA3_224", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256 = { GCRY_MAC_HMAC_SHA3_256, {0, 1}, "HMAC_SHA3_256", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384 = { GCRY_MAC_HMAC_SHA3_384, {0, 1}, "HMAC_SHA3_384", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512 = { GCRY_MAC_HMAC_SHA3_512, {0, 1}, "HMAC_SHA3_512", &hmac_ops }; #endif #if USE_GOST_R_3411_94 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94 = { GCRY_MAC_HMAC_GOSTR3411_94, {0, 0}, "HMAC_GOSTR3411_94", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp = { GCRY_MAC_HMAC_GOSTR3411_CP, {0, 0}, "HMAC_GOSTR3411_CP", &hmac_ops }; #endif #if USE_GOST_R_3411_12 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256 = { GCRY_MAC_HMAC_STRIBOG256, {0, 0}, "HMAC_STRIBOG256", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512 = { GCRY_MAC_HMAC_STRIBOG512, {0, 0}, "HMAC_STRIBOG512", &hmac_ops }; #endif #if USE_WHIRLPOOL -gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool = { GCRY_MAC_HMAC_WHIRLPOOL, {0, 0}, "HMAC_WHIRLPOOL", &hmac_ops }; #endif #if USE_RMD160 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160 = { GCRY_MAC_HMAC_RMD160, {0, 0}, "HMAC_RIPEMD160", &hmac_ops }; #endif #if USE_TIGER -gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1 = { GCRY_MAC_HMAC_TIGER1, {0, 0}, "HMAC_TIGER", &hmac_ops }; #endif #if USE_MD5 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = { GCRY_MAC_HMAC_MD5, {0, 0}, "HMAC_MD5", &hmac_ops }; #endif #if USE_MD4 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4 = { GCRY_MAC_HMAC_MD4, {0, 0}, "HMAC_MD4", &hmac_ops }; #endif #if USE_MD2 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = { GCRY_MAC_HMAC_MD2, {0, 0}, "HMAC_MD2", &hmac_ops }; #endif #if USE_BLAKE2 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512 = { GCRY_MAC_HMAC_BLAKE2B_512, {0, 0}, "HMAC_BLAKE2B_512", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384 = { GCRY_MAC_HMAC_BLAKE2B_384, {0, 0}, "HMAC_BLAKE2B_384", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256 = { GCRY_MAC_HMAC_BLAKE2B_256, {0, 0}, "HMAC_BLAKE2B_256", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160 = { GCRY_MAC_HMAC_BLAKE2B_160, {0, 0}, "HMAC_BLAKE2B_160", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256 = { GCRY_MAC_HMAC_BLAKE2S_256, {0, 0}, "HMAC_BLAKE2S_256", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224 = { GCRY_MAC_HMAC_BLAKE2S_224, {0, 0}, "HMAC_BLAKE2S_224", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160 = { GCRY_MAC_HMAC_BLAKE2S_160, {0, 0}, "HMAC_BLAKE2S_160", &hmac_ops }; -gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128 = { GCRY_MAC_HMAC_BLAKE2S_128, {0, 0}, "HMAC_BLAKE2S_128", &hmac_ops }; #endif #if USE_SM3 -gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3 = { +const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3 = { GCRY_MAC_HMAC_SM3, {0, 0}, "HMAC_SM3", &hmac_ops }; #endif diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index bb5c8b74..01998152 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -1,275 +1,275 @@ /* mac-internal.h - Internal defs for mac.c * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include "g10lib.h" #include "cipher-proto.h" #include "gost.h" /* The data object used to hold a handle to an encryption object. */ struct gcry_mac_handle; /* The data object used to hold poly1305-mac context. */ struct poly1305mac_context_s; /* * * Message authentication code related definitions. * */ /* Magic values for the context structure. */ #define CTX_MAC_MAGIC_NORMAL 0x59d9b8af #define CTX_MAC_MAGIC_SECURE 0x12c27cd0 /* MAC module functions. */ typedef gcry_err_code_t (*gcry_mac_open_func_t)(gcry_mac_hd_t h); typedef void (*gcry_mac_close_func_t)(gcry_mac_hd_t h); typedef gcry_err_code_t (*gcry_mac_setkey_func_t)(gcry_mac_hd_t h, const unsigned char *key, size_t keylen); typedef gcry_err_code_t (*gcry_mac_setiv_func_t)(gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen); typedef gcry_err_code_t (*gcry_mac_reset_func_t)(gcry_mac_hd_t h); typedef gcry_err_code_t (*gcry_mac_write_func_t)(gcry_mac_hd_t h, const unsigned char *inbuf, size_t inlen); typedef gcry_err_code_t (*gcry_mac_read_func_t)(gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen); typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h, const unsigned char *inbuf, size_t inlen); typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo); typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo); /* The type used to convey additional information to a MAC. */ typedef gpg_err_code_t (*gcry_mac_set_extra_info_t) (gcry_mac_hd_t h, int what, const void *buffer, size_t buflen); typedef struct gcry_mac_spec_ops { gcry_mac_open_func_t open; gcry_mac_close_func_t close; gcry_mac_setkey_func_t setkey; gcry_mac_setiv_func_t setiv; gcry_mac_reset_func_t reset; gcry_mac_write_func_t write; gcry_mac_read_func_t read; gcry_mac_verify_func_t verify; gcry_mac_get_maclen_func_t get_maclen; gcry_mac_get_keylen_func_t get_keylen; gcry_mac_set_extra_info_t set_extra_info; selftest_func_t selftest; } gcry_mac_spec_ops_t; /* Module specification structure for message authentication codes. */ typedef struct gcry_mac_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; const gcry_mac_spec_ops_t *ops; } gcry_mac_spec_t; /* The handle structure. */ struct gcry_mac_handle { int magic; int algo; const gcry_mac_spec_t *spec; gcry_ctx_t gcry_ctx; union { struct { gcry_md_hd_t md_ctx; int md_algo; } hmac; struct { gcry_cipher_hd_t ctx; int cipher_algo; unsigned int blklen; } cmac; struct { gcry_cipher_hd_t ctx; int cipher_algo; } gmac; struct { struct poly1305mac_context_s *ctx; } poly1305mac; struct { GOST28147_context ctx; u32 n1, n2; unsigned int unused; unsigned int count; unsigned char lastiv[8]; /* IMIT blocksize */ } imit; } u; }; /* * The HMAC algorithm specifications (mac-hmac.c). */ #if USE_SHA1 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1; #endif #if USE_SHA256 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224; #endif #if USE_SHA512 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256; #endif #if USE_SHA3 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512; #endif #if USE_GOST_R_3411_94 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp; #endif #if USE_GOST_R_3411_12 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512; #endif #if USE_WHIRLPOOL -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool; #endif #if USE_RMD160 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160; #endif #if USE_TIGER -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1; #endif #if USE_MD5 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5; #endif #if USE_MD4 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4; #endif #if USE_BLAKE2 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160; -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128; #endif #if USE_SM3 -extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3; +extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3; #endif /* * The CMAC algorithm specifications (mac-cmac.c). */ #if USE_BLOWFISH -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish; #endif #if USE_DES -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes; #endif #if USE_CAST5 -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5; #endif #if USE_AES -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes; #endif #if USE_TWOFISH -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish; #endif #if USE_SERPENT -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent; #endif #if USE_RFC2268 -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268; #endif #if USE_SEED -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed; #endif #if USE_CAMELLIA -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia; #endif #if USE_IDEA -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea; #endif #if USE_GOST28147 -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147; #endif #if USE_GOST28147 -extern gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit; +extern const gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit; #endif #if USE_SM4 -extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4; +extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4; #endif /* * The GMAC algorithm specifications (mac-gmac.c). */ #if USE_AES -extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes; +extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes; #endif #if USE_TWOFISH -extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish; +extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish; #endif #if USE_SERPENT -extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent; +extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent; #endif #if USE_SEED -extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed; +extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed; #endif #if USE_CAMELLIA -extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia; +extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia; #endif /* * The Poly1305 MAC algorithm specifications (mac-poly1305.c). */ -extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac; +extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac; #if USE_AES -extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes; +extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes; #endif #if USE_CAMELLIA -extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia; +extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia; #endif #if USE_TWOFISH -extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish; +extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish; #endif #if USE_SERPENT -extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent; +extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent; #endif #if USE_SEED -extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed; +extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed; #endif diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c index 46ea735f..3abc7774 100644 --- a/cipher/mac-poly1305.c +++ b/cipher/mac-poly1305.c @@ -1,364 +1,364 @@ /* mac-poly1305.c - Poly1305 based MACs * Copyright (C) 2014 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "mac-internal.h" #include "poly1305-internal.h" struct poly1305mac_context_s { poly1305_context_t ctx; gcry_cipher_hd_t hd; struct { unsigned int key_set:1; unsigned int nonce_set:1; unsigned int tag:1; } marks; byte tag[POLY1305_TAGLEN]; byte key[POLY1305_KEYLEN]; }; static gcry_err_code_t poly1305mac_open (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx; int secure = (h->magic == CTX_MAC_MAGIC_SECURE); unsigned int flags = (secure ? GCRY_CIPHER_SECURE : 0); gcry_err_code_t err; int cipher_algo; if (secure) mac_ctx = xtrycalloc_secure (1, sizeof(*mac_ctx)); else mac_ctx = xtrycalloc (1, sizeof(*mac_ctx)); if (!mac_ctx) return gpg_err_code_from_syserror (); h->u.poly1305mac.ctx = mac_ctx; switch (h->spec->algo) { default: /* already checked. */ case GCRY_MAC_POLY1305: /* plain Poly1305. */ cipher_algo = -1; return 0; case GCRY_MAC_POLY1305_AES: cipher_algo = GCRY_CIPHER_AES; break; case GCRY_MAC_POLY1305_CAMELLIA: cipher_algo = GCRY_CIPHER_CAMELLIA128; break; case GCRY_MAC_POLY1305_TWOFISH: cipher_algo = GCRY_CIPHER_TWOFISH; break; case GCRY_MAC_POLY1305_SERPENT: cipher_algo = GCRY_CIPHER_SERPENT128; break; case GCRY_MAC_POLY1305_SEED: cipher_algo = GCRY_CIPHER_SEED; break; } err = _gcry_cipher_open_internal (&mac_ctx->hd, cipher_algo, GCRY_CIPHER_MODE_ECB, flags); if (err) goto err_free; return 0; err_free: xfree(h->u.poly1305mac.ctx); return err; } static void poly1305mac_close (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (h->spec->algo != GCRY_MAC_POLY1305) _gcry_cipher_close (mac_ctx->hd); xfree(mac_ctx); } static gcry_err_code_t poly1305mac_prepare_key (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; size_t block_keylen = keylen - 16; /* Need at least 16 + 1 byte key. */ if (keylen <= 16) return GPG_ERR_INV_KEYLEN; /* For Poly1305-AES, first part of key is passed to Poly1305 as is. */ memcpy (mac_ctx->key, key + block_keylen, 16); /* Remaining part is used as key for the block cipher. */ return _gcry_cipher_setkey (mac_ctx->hd, key, block_keylen); } static gcry_err_code_t poly1305mac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); mac_ctx->marks.key_set = 0; mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; if (h->spec->algo != GCRY_MAC_POLY1305) { err = poly1305mac_prepare_key (h, key, keylen); if (err) return err; /* Poly1305-AES/etc also need nonce. */ mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 0; } else { /* For plain Poly1305, key is the nonce and setup is complete now. */ if (keylen != POLY1305_KEYLEN) return GPG_ERR_INV_KEYLEN; memcpy (mac_ctx->key, key, keylen); err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); if (err) { memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); return err; } mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 1; } return 0; } static gcry_err_code_t poly1305mac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; if (h->spec->algo == GCRY_MAC_POLY1305) return GPG_ERR_INV_ARG; if (ivlen != 16) return GPG_ERR_INV_ARG; if (!mac_ctx->marks.key_set) return 0; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; /* Prepare second part of the poly1305 key. */ err = _gcry_cipher_encrypt (mac_ctx->hd, mac_ctx->key + 16, 16, iv, 16); if (err) return err; err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); if (err) return err; mac_ctx->marks.nonce_set = 1; return 0; } static gcry_err_code_t poly1305mac_reset (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 1; mac_ctx->marks.tag = 0; return _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); } static gcry_err_code_t poly1305mac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set || mac_ctx->marks.tag) return GPG_ERR_INV_STATE; _gcry_poly1305_update (&mac_ctx->ctx, buf, buflen); return 0; } static gcry_err_code_t poly1305mac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; if (!mac_ctx->marks.tag) { _gcry_poly1305_finish(&mac_ctx->ctx, mac_ctx->tag); memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); mac_ctx->marks.tag = 1; } if (*outlen == 0) return 0; if (*outlen <= POLY1305_TAGLEN) buf_cpy (outbuf, mac_ctx->tag, *outlen); else { buf_cpy (outbuf, mac_ctx->tag, POLY1305_TAGLEN); *outlen = POLY1305_TAGLEN; } return 0; } static gcry_err_code_t poly1305mac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; size_t outlen = 0; /* Check and finalize tag. */ err = poly1305mac_read(h, NULL, &outlen); if (err) return err; if (buflen > POLY1305_TAGLEN) return GPG_ERR_INV_LENGTH; return buf_eq_const (buf, mac_ctx->tag, buflen) ? 0 : GPG_ERR_CHECKSUM; } static unsigned int poly1305mac_get_maclen (int algo) { (void)algo; return POLY1305_TAGLEN; } static unsigned int poly1305mac_get_keylen (int algo) { (void)algo; return POLY1305_KEYLEN; } static gcry_mac_spec_ops_t poly1305mac_ops = { poly1305mac_open, poly1305mac_close, poly1305mac_setkey, poly1305mac_setiv, poly1305mac_reset, poly1305mac_write, poly1305mac_read, poly1305mac_verify, poly1305mac_get_maclen, poly1305mac_get_keylen, NULL, NULL, }; -gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = { +const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = { GCRY_MAC_POLY1305, {0, 0}, "POLY1305", &poly1305mac_ops }; #if USE_AES -gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = { +const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = { GCRY_MAC_POLY1305_AES, {0, 0}, "POLY1305_AES", &poly1305mac_ops }; #endif #if USE_CAMELLIA -gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = { +const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = { GCRY_MAC_POLY1305_CAMELLIA, {0, 0}, "POLY1305_CAMELLIA", &poly1305mac_ops }; #endif #if USE_TWOFISH -gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = { +const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = { GCRY_MAC_POLY1305_TWOFISH, {0, 0}, "POLY1305_TWOFISH", &poly1305mac_ops }; #endif #if USE_SERPENT -gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = { +const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = { GCRY_MAC_POLY1305_SERPENT, {0, 0}, "POLY1305_SERPENT", &poly1305mac_ops }; #endif #if USE_SEED -gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = { +const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = { GCRY_MAC_POLY1305_SEED, {0, 0}, "POLY1305_SEED", &poly1305mac_ops }; #endif diff --git a/cipher/mac.c b/cipher/mac.c index 9851b81c..ba1eb300 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -1,802 +1,802 @@ /* mac.c - message authentication code dispatcher * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "mac-internal.h" /* This is the list of the digest implementations included in libgcrypt. */ -static gcry_mac_spec_t * const mac_list[] = { +static const gcry_mac_spec_t * const 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, &_gcry_mac_type_spec_hmac_sha512_256, &_gcry_mac_type_spec_hmac_sha512_224, #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 #if USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_94, &_gcry_mac_type_spec_hmac_gost3411_cp, #endif #if 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_BLAKE2 &_gcry_mac_type_spec_hmac_blake2b_512, &_gcry_mac_type_spec_hmac_blake2b_384, &_gcry_mac_type_spec_hmac_blake2b_256, &_gcry_mac_type_spec_hmac_blake2b_160, &_gcry_mac_type_spec_hmac_blake2s_256, &_gcry_mac_type_spec_hmac_blake2s_224, &_gcry_mac_type_spec_hmac_blake2s_160, &_gcry_mac_type_spec_hmac_blake2s_128, #endif #if USE_SM3 &_gcry_mac_type_spec_hmac_sm3, #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 #if USE_IDEA &_gcry_mac_type_spec_cmac_idea, #endif #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147, &_gcry_mac_type_spec_gost28147_imit, #endif &_gcry_mac_type_spec_poly1305mac, #if USE_SM4 &_gcry_mac_type_spec_cmac_sm4, #endif NULL, }; /* HMAC implementations start with index 101 (enum gcry_mac_algos) */ -static gcry_mac_spec_t * const mac_list_algo101[] = +static const gcry_mac_spec_t * const mac_list_algo101[] = { #if USE_SHA256 &_gcry_mac_type_spec_hmac_sha256, &_gcry_mac_type_spec_hmac_sha224, #else NULL, NULL, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512, &_gcry_mac_type_spec_hmac_sha384, #else NULL, NULL, #endif #if USE_SHA1 &_gcry_mac_type_spec_hmac_sha1, #else NULL, #endif #if USE_MD5 &_gcry_mac_type_spec_hmac_md5, #else NULL, #endif #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #else NULL, #endif #if USE_RMD160 &_gcry_mac_type_spec_hmac_rmd160, #else NULL, #endif #if USE_TIGER &_gcry_mac_type_spec_hmac_tiger1, #else NULL, #endif #if USE_WHIRLPOOL &_gcry_mac_type_spec_hmac_whirlpool, #else NULL, #endif #if USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_94, #else NULL, #endif #if USE_GOST_R_3411_12 &_gcry_mac_type_spec_hmac_stribog256, &_gcry_mac_type_spec_hmac_stribog512, #else NULL, NULL, #endif #if USE_MD2 &_gcry_mac_type_spec_hmac_md2, #else NULL, #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, #else NULL, NULL, NULL, NULL, #endif #if USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_cp, #else NULL, #endif #if USE_BLAKE2 &_gcry_mac_type_spec_hmac_blake2b_512, &_gcry_mac_type_spec_hmac_blake2b_384, &_gcry_mac_type_spec_hmac_blake2b_256, &_gcry_mac_type_spec_hmac_blake2b_160, &_gcry_mac_type_spec_hmac_blake2s_256, &_gcry_mac_type_spec_hmac_blake2s_224, &_gcry_mac_type_spec_hmac_blake2s_160, &_gcry_mac_type_spec_hmac_blake2s_128, #else NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #endif #if USE_SM3 &_gcry_mac_type_spec_hmac_sm3, #else NULL, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512_256, &_gcry_mac_type_spec_hmac_sha512_224, #else NULL, NULL, #endif }; /* CMAC implementations start with index 201 (enum gcry_mac_algos) */ -static gcry_mac_spec_t * const mac_list_algo201[] = +static const gcry_mac_spec_t * const mac_list_algo201[] = { #if USE_AES &_gcry_mac_type_spec_cmac_aes, #else NULL, #endif #if USE_DES &_gcry_mac_type_spec_cmac_tripledes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, #else NULL, #endif #if USE_CAST5 &_gcry_mac_type_spec_cmac_cast5, #else NULL, #endif #if USE_BLOWFISH &_gcry_mac_type_spec_cmac_blowfish, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_cmac_seed, #else NULL, #endif #if USE_RFC2268 &_gcry_mac_type_spec_cmac_rfc2268, #else NULL, #endif #if USE_IDEA &_gcry_mac_type_spec_cmac_idea, #else NULL, #endif #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147, #else NULL, #endif #if USE_SM4 &_gcry_mac_type_spec_cmac_sm4 #else NULL #endif }; /* GMAC implementations start with index 401 (enum gcry_mac_algos) */ -static gcry_mac_spec_t * const mac_list_algo401[] = +static const gcry_mac_spec_t * const mac_list_algo401[] = { #if USE_AES &_gcry_mac_type_spec_gmac_aes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_gmac_camellia, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_gmac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_gmac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_gmac_seed #else NULL #endif }; /* Poly1305-MAC implementations start with index 501 (enum gcry_mac_algos) */ -static gcry_mac_spec_t * const mac_list_algo501[] = +static const gcry_mac_spec_t * const mac_list_algo501[] = { &_gcry_mac_type_spec_poly1305mac, #if USE_AES &_gcry_mac_type_spec_poly1305mac_aes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_poly1305mac_camellia, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_poly1305mac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_poly1305mac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_poly1305mac_seed #else NULL #endif }; /* Explicitly initialize this module. */ gcry_err_code_t _gcry_mac_init (void) { return 0; } /* Return the spec structure for the MAC algorithm ALGO. For an unknown algorithm NULL is returned. */ static const gcry_mac_spec_t * spec_from_algo (int algo) { const gcry_mac_spec_t *spec = NULL; if (algo >= 101 && algo < 101 + DIM(mac_list_algo101)) spec = mac_list_algo101[algo - 101]; else if (algo >= 201 && algo < 201 + DIM(mac_list_algo201)) spec = mac_list_algo201[algo - 201]; else if (algo >= 401 && algo < 401 + DIM(mac_list_algo401)) spec = mac_list_algo401[algo - 401]; else if (algo >= 501 && algo < 501 + DIM(mac_list_algo501)) spec = mac_list_algo501[algo - 501]; #if USE_GOST28147 else if (algo == GCRY_MAC_GOST28147_IMIT) spec = &_gcry_mac_type_spec_gost28147_imit; #endif if (spec) gcry_assert (spec->algo == algo); return spec; } /* Lookup a mac's spec by its name. */ -static gcry_mac_spec_t * +static const gcry_mac_spec_t * spec_from_name (const char *name) { - gcry_mac_spec_t *spec; + const 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; + const 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; + const gcry_mac_spec_t *spec; spec = spec_from_algo (algorithm); return spec ? spec->name : "?"; } static gcry_err_code_t check_mac_algo (int algorithm) { const gcry_mac_spec_t *spec; spec = spec_from_algo (algorithm); if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())) 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; + const 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->flags.fips && fips_mode ()) 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_MAC_MAGIC_SECURE : CTX_MAC_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; + const 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; + const 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; case GCRYCTL_SET_SBOX: if (hd->spec->ops->set_extra_info) rc = hd->spec->ops->set_extra_info (hd, GCRYCTL_SET_SBOX, buffer, buflen); else rc = GPG_ERR_NOT_SUPPORTED; 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; } /* Run the self-tests for the MAC. */ gpg_error_t _gcry_mac_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec; const gcry_mac_spec_t *spec; spec = spec_from_algo (algo); if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()) && spec->ops && spec->ops->selftest) ec = spec->ops->selftest (algo, extended, report); else { ec = GPG_ERR_MAC_ALGO; if (report) report ("mac", algo, "module", spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())? "no selftest available" : spec? "algorithm disabled" : "algorithm not found"); } return gpg_error (ec); } diff --git a/cipher/md.c b/cipher/md.c index 68f5ffdf..34336b5c 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1,1636 +1,1636 @@ /* md.c - message digest dispatcher * Copyright (C) 1998, 1999, 2002, 2003, 2006, * 2008 Free Software Foundation, Inc. * Copyright (C) 2013, 2014 g10 Code GmbH * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" /* This is the list of the digest implementations included in libgcrypt. */ -static gcry_md_spec_t * const digest_list[] = +static const gcry_md_spec_t * const digest_list[] = { #if USE_CRC &_gcry_digest_spec_crc32, &_gcry_digest_spec_crc32_rfc1510, &_gcry_digest_spec_crc24_rfc2440, #endif #if USE_SHA1 &_gcry_digest_spec_sha1, #endif #if USE_SHA256 &_gcry_digest_spec_sha256, &_gcry_digest_spec_sha224, #endif #if USE_SHA512 &_gcry_digest_spec_sha512, &_gcry_digest_spec_sha384, &_gcry_digest_spec_sha512_256, &_gcry_digest_spec_sha512_224, #endif #if USE_SHA3 &_gcry_digest_spec_sha3_224, &_gcry_digest_spec_sha3_256, &_gcry_digest_spec_sha3_384, &_gcry_digest_spec_sha3_512, &_gcry_digest_spec_shake128, &_gcry_digest_spec_shake256, #endif #if USE_GOST_R_3411_94 &_gcry_digest_spec_gost3411_94, &_gcry_digest_spec_gost3411_cp, #endif #if USE_GOST_R_3411_12 &_gcry_digest_spec_stribog_256, &_gcry_digest_spec_stribog_512, #endif #if USE_WHIRLPOOL &_gcry_digest_spec_whirlpool, #endif #if USE_RMD160 &_gcry_digest_spec_rmd160, #endif #if USE_TIGER &_gcry_digest_spec_tiger, &_gcry_digest_spec_tiger1, &_gcry_digest_spec_tiger2, #endif #if USE_MD5 &_gcry_digest_spec_md5, #endif #if USE_MD4 &_gcry_digest_spec_md4, #endif #if USE_MD2 &_gcry_digest_spec_md2, #endif #if USE_BLAKE2 &_gcry_digest_spec_blake2b_512, &_gcry_digest_spec_blake2b_384, &_gcry_digest_spec_blake2b_256, &_gcry_digest_spec_blake2b_160, &_gcry_digest_spec_blake2s_256, &_gcry_digest_spec_blake2s_224, &_gcry_digest_spec_blake2s_160, &_gcry_digest_spec_blake2s_128, #endif #if USE_SM3 &_gcry_digest_spec_sm3, #endif NULL }; /* Digest implementations starting with index 0 (enum gcry_md_algos) */ -static gcry_md_spec_t * const digest_list_algo0[] = +static const gcry_md_spec_t * const digest_list_algo0[] = { NULL, /* GCRY_MD_NONE */ #if USE_MD5 &_gcry_digest_spec_md5, #else NULL, #endif #if USE_SHA1 &_gcry_digest_spec_sha1, #else NULL, #endif #if USE_RMD160 &_gcry_digest_spec_rmd160, #else NULL, #endif NULL, /* Unused index 4 */ #if USE_MD2 &_gcry_digest_spec_md2, #else NULL, #endif #if USE_TIGER &_gcry_digest_spec_tiger, #else NULL, #endif NULL, /* GCRY_MD_HAVAL */ #if USE_SHA256 &_gcry_digest_spec_sha256, #else NULL, #endif #if USE_SHA512 &_gcry_digest_spec_sha384, &_gcry_digest_spec_sha512, #else NULL, NULL, #endif #if USE_SHA256 &_gcry_digest_spec_sha224 #else NULL #endif }; /* Digest implementations starting with index 301 (enum gcry_md_algos) */ -static gcry_md_spec_t * const digest_list_algo301[] = +static const gcry_md_spec_t * const digest_list_algo301[] = { #if USE_MD4 &_gcry_digest_spec_md4, #else NULL, #endif #if USE_CRC &_gcry_digest_spec_crc32, &_gcry_digest_spec_crc32_rfc1510, &_gcry_digest_spec_crc24_rfc2440, #else NULL, NULL, NULL, #endif #if USE_WHIRLPOOL &_gcry_digest_spec_whirlpool, #else NULL, #endif #if USE_TIGER &_gcry_digest_spec_tiger1, &_gcry_digest_spec_tiger2, #else NULL, NULL, #endif #if USE_GOST_R_3411_94 &_gcry_digest_spec_gost3411_94, #else NULL, #endif #if USE_GOST_R_3411_12 &_gcry_digest_spec_stribog_256, &_gcry_digest_spec_stribog_512, #else NULL, NULL, #endif #if USE_GOST_R_3411_94 &_gcry_digest_spec_gost3411_cp, #else NULL, #endif #if USE_SHA3 &_gcry_digest_spec_sha3_224, &_gcry_digest_spec_sha3_256, &_gcry_digest_spec_sha3_384, &_gcry_digest_spec_sha3_512, &_gcry_digest_spec_shake128, &_gcry_digest_spec_shake256, #else NULL, NULL, NULL, NULL, NULL, NULL, #endif #if USE_BLAKE2 &_gcry_digest_spec_blake2b_512, &_gcry_digest_spec_blake2b_384, &_gcry_digest_spec_blake2b_256, &_gcry_digest_spec_blake2b_160, &_gcry_digest_spec_blake2s_256, &_gcry_digest_spec_blake2s_224, &_gcry_digest_spec_blake2s_160, &_gcry_digest_spec_blake2s_128, #else NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #endif #if USE_SM3 &_gcry_digest_spec_sm3, #else NULL, #endif #if USE_SHA512 &_gcry_digest_spec_sha512_256, &_gcry_digest_spec_sha512_224, #else NULL, NULL, #endif }; typedef struct gcry_md_list { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; struct gcry_md_list *next; size_t actual_struct_size; /* Allocated size of this structure. */ PROPERLY_ALIGNED_TYPE context[1]; } GcryDigestEntry; /* This structure is put right after the gcry_md_hd_t buffer, so that * only one memory block is needed. */ struct gcry_md_context { int magic; struct { unsigned int secure:1; unsigned int finalized:1; unsigned int bugemu1:1; unsigned int hmac:1; } flags; size_t actual_handle_size; /* Allocated size of this handle. */ FILE *debug; GcryDigestEntry *list; }; #define CTX_MAGIC_NORMAL 0x11071961 #define CTX_MAGIC_SECURE 0x16917011 static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo); static void md_close (gcry_md_hd_t a); static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen); static byte *md_read( gcry_md_hd_t a, int algo ); static int md_get_algo( gcry_md_hd_t a ); static int md_digest_length( int algo ); static void md_start_debug ( gcry_md_hd_t a, const char *suffix ); static void md_stop_debug ( gcry_md_hd_t a ); static int map_algo (int algo) { return algo; } /* Return the spec structure for the hash algorithm ALGO. For an unknown algorithm NULL is returned. */ -static gcry_md_spec_t * +static const gcry_md_spec_t * spec_from_algo (int algo) { - gcry_md_spec_t *spec = NULL; + const gcry_md_spec_t *spec = NULL; algo = map_algo (algo); if (algo >= 0 && algo < DIM(digest_list_algo0)) spec = digest_list_algo0[algo]; else if (algo >= 301 && algo < 301 + DIM(digest_list_algo301)) spec = digest_list_algo301[algo - 301]; if (spec) gcry_assert (spec->algo == algo); return spec; } /* Lookup a hash's spec by its name. */ -static gcry_md_spec_t * +static const gcry_md_spec_t * spec_from_name (const char *name) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; int idx; for (idx=0; (spec = digest_list[idx]); idx++) { if (!stricmp (name, spec->name)) return spec; } return NULL; } /* Lookup a hash's spec by its OID. */ -static gcry_md_spec_t * +static const gcry_md_spec_t * spec_from_oid (const char *oid) { - gcry_md_spec_t *spec; - gcry_md_oid_spec_t *oid_specs; + const gcry_md_spec_t *spec; + const gcry_md_oid_spec_t *oid_specs; int idx, j; for (idx=0; (spec = digest_list[idx]); idx++) { oid_specs = spec->oids; if (oid_specs) { for (j = 0; oid_specs[j].oidstring; j++) if (!stricmp (oid, oid_specs[j].oidstring)) return spec; } } return NULL; } -static gcry_md_spec_t * +static const gcry_md_spec_t * search_oid (const char *oid, gcry_md_oid_spec_t *oid_spec) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; int i; if (!oid) return NULL; if (!strncmp (oid, "oid.", 4) || !strncmp (oid, "OID.", 4)) oid += 4; spec = spec_from_oid (oid); if (spec && spec->oids) { for (i = 0; spec->oids[i].oidstring; i++) if (!stricmp (oid, spec->oids[i].oidstring)) { if (oid_spec) *oid_spec = spec->oids[i]; return spec; } } return NULL; } /**************** * Map a string to the digest algo */ int _gcry_md_map_name (const char *string) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; if (!string) return 0; /* If the string starts with a digit (optionally prefixed with either "OID." or "oid."), we first look into our table of ASN.1 object identifiers to figure out the algorithm */ spec = search_oid (string, NULL); if (spec) return spec->algo; /* Not found, search a matching digest 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_md_test_algo() to check whether the algorithm * is valid. */ const char * _gcry_md_algo_name (int algorithm) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; spec = spec_from_algo (algorithm); return spec ? spec->name : "?"; } static gcry_err_code_t check_digest_algo (int algorithm) { const gcry_md_spec_t *spec; spec = spec_from_algo (algorithm); if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())) return 0; return GPG_ERR_DIGEST_ALGO; } /**************** * Open a message digest handle for use with algorithm ALGO. * More algorithms may be added by md_enable(). The initial algorithm * may be 0. */ static gcry_err_code_t md_open (gcry_md_hd_t *h, int algo, unsigned int flags) { gcry_err_code_t err = 0; int secure = !!(flags & GCRY_MD_FLAG_SECURE); int hmac = !!(flags & GCRY_MD_FLAG_HMAC); int bufsize = secure ? 512 : 1024; gcry_md_hd_t hd; size_t n; /* Allocate a memory area to hold the caller visible buffer with it's * control information and the data required by this module. Set the * context pointer at the beginning to this area. * We have to use this strange scheme because we want to hide the * internal data but have a variable sized buffer. * * +---+------+---........------+-------------+ * !ctx! bctl ! buffer ! private ! * +---+------+---........------+-------------+ * ! ^ * !---------------------------! * * We have to make sure that private is well aligned. */ n = offsetof (struct gcry_md_handle, buf) + bufsize; n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1) / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE); /* Allocate and set the Context pointer to the private data */ if (secure) hd = xtrymalloc_secure (n + sizeof (struct gcry_md_context)); else hd = xtrymalloc (n + sizeof (struct gcry_md_context)); if (! hd) err = gpg_err_code_from_errno (errno); if (! err) { struct gcry_md_context *ctx; ctx = (void *) (hd->buf - offsetof (struct gcry_md_handle, buf) + n); /* Setup the globally visible data (bctl in the diagram).*/ hd->ctx = ctx; hd->bufsize = n - offsetof (struct gcry_md_handle, buf); hd->bufpos = 0; /* Initialize the private data. */ wipememory2 (ctx, 0, sizeof *ctx); ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; ctx->actual_handle_size = n + sizeof (struct gcry_md_context); ctx->flags.secure = secure; ctx->flags.hmac = hmac; ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1); } if (! err) { /* Hmmm, should we really do that? - yes [-wk] */ _gcry_fast_random_poll (); if (algo) { err = md_enable (hd, algo); if (err) md_close (hd); } } if (! err) *h = hd; return err; } /* Create a message digest object for algorithm ALGO. FLAGS may be given as an bitwise OR of the gcry_md_flags values. ALGO may be given as 0 if the algorithms to be used are later set using gcry_md_enable. H is guaranteed to be a valid handle or NULL on error. */ gcry_err_code_t _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) { gcry_err_code_t rc; gcry_md_hd_t hd; if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_BUGEMU1))) rc = GPG_ERR_INV_ARG; else rc = md_open (&hd, algo, flags); *h = rc? NULL : hd; return rc; } static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algorithm) { struct gcry_md_context *h = hd->ctx; - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; GcryDigestEntry *entry; gcry_err_code_t err = 0; for (entry = h->list; entry; entry = entry->next) if (entry->spec->algo == algorithm) return 0; /* Already enabled */ spec = spec_from_algo (algorithm); if (!spec) { log_debug ("md_enable: algorithm %d not available\n", algorithm); err = GPG_ERR_DIGEST_ALGO; } if (!err && spec->flags.disabled) err = GPG_ERR_DIGEST_ALGO; /* Any non-FIPS algorithm should go this way */ if (!err && !spec->flags.fips && fips_mode ()) err = GPG_ERR_DIGEST_ALGO; if (!err && h->flags.hmac && spec->read == NULL) { /* Expandable output function cannot act as part of HMAC. */ err = GPG_ERR_DIGEST_ALGO; } if (!err) { size_t size = (sizeof (*entry) + spec->contextsize * (h->flags.hmac? 3 : 1) - sizeof (entry->context)); /* And allocate a new list entry. */ if (h->flags.secure) entry = xtrymalloc_secure (size); else entry = xtrymalloc (size); if (! entry) err = gpg_err_code_from_errno (errno); else { entry->spec = spec; entry->next = h->list; entry->actual_struct_size = size; h->list = entry; /* And init this instance. */ entry->spec->init (entry->context, h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0); } } return err; } gcry_err_code_t _gcry_md_enable (gcry_md_hd_t hd, int algorithm) { return md_enable (hd, algorithm); } static gcry_err_code_t md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) { gcry_err_code_t err = 0; struct gcry_md_context *a = ahd->ctx; struct gcry_md_context *b; GcryDigestEntry *ar, *br; gcry_md_hd_t bhd; size_t n; if (ahd->bufpos) md_write (ahd, NULL, 0); n = (char *) ahd->ctx - (char *) ahd; if (a->flags.secure) bhd = xtrymalloc_secure (n + sizeof (struct gcry_md_context)); else bhd = xtrymalloc (n + sizeof (struct gcry_md_context)); if (!bhd) { err = gpg_err_code_from_syserror (); goto leave; } bhd->ctx = b = (void *) ((char *) bhd + n); /* No need to copy the buffer due to the write above. */ gcry_assert (ahd->bufsize == (n - offsetof (struct gcry_md_handle, buf))); bhd->bufsize = ahd->bufsize; bhd->bufpos = 0; gcry_assert (! ahd->bufpos); memcpy (b, a, sizeof *a); b->list = NULL; b->debug = NULL; /* Copy the complete list of algorithms. The copied list is reversed, but that doesn't matter. */ for (ar = a->list; ar; ar = ar->next) { if (a->flags.secure) br = xtrymalloc_secure (ar->actual_struct_size); else br = xtrymalloc (ar->actual_struct_size); if (!br) { err = gpg_err_code_from_syserror (); md_close (bhd); goto leave; } memcpy (br, ar, ar->actual_struct_size); br->next = b->list; b->list = br; } if (a->debug) md_start_debug (bhd, "unknown"); *b_hd = bhd; leave: return err; } gcry_err_code_t _gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd) { gcry_err_code_t rc; rc = md_copy (hd, handle); if (rc) *handle = NULL; return rc; } /* * Reset all contexts and discard any buffered stuff. This may be used * instead of a md_close(); md_open(). */ void _gcry_md_reset (gcry_md_hd_t a) { GcryDigestEntry *r; /* Note: We allow this even in fips non operational mode. */ a->bufpos = a->ctx->flags.finalized = 0; if (a->ctx->flags.hmac) for (r = a->ctx->list; r; r = r->next) { memcpy (r->context, (char *)r->context + r->spec->contextsize, r->spec->contextsize); } else for (r = a->ctx->list; r; r = r->next) { memset (r->context, 0, r->spec->contextsize); (*r->spec->init) (r->context, a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0); } } static void md_close (gcry_md_hd_t a) { GcryDigestEntry *r, *r2; if (! a) return; if (a->ctx->debug) md_stop_debug (a); for (r = a->ctx->list; r; r = r2) { r2 = r->next; wipememory (r, r->actual_struct_size); xfree (r); } wipememory (a, a->ctx->actual_handle_size); xfree(a); } void _gcry_md_close (gcry_md_hd_t hd) { /* Note: We allow this even in fips non operational mode. */ md_close (hd); } static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen) { GcryDigestEntry *r; if (a->ctx->debug) { if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1) BUG(); if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1) BUG(); } for (r = a->ctx->list; r; r = r->next) { if (a->bufpos) (*r->spec->write) (r->context, a->buf, a->bufpos); (*r->spec->write) (r->context, inbuf, inlen); } a->bufpos = 0; } /* Note that this function may be used after finalize and read to keep on writing to the transform function so to mitigate timing attacks. */ void _gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen) { md_write (hd, inbuf, inlen); } static void md_final (gcry_md_hd_t a) { GcryDigestEntry *r; if (a->ctx->flags.finalized) return; if (a->bufpos) md_write (a, NULL, 0); for (r = a->ctx->list; r; r = r->next) (*r->spec->final) (r->context); a->ctx->flags.finalized = 1; if (!a->ctx->flags.hmac) return; for (r = a->ctx->list; r; r = r->next) { byte *p; size_t dlen = r->spec->mdlen; byte *hash; gcry_err_code_t err; if (r->spec->read == NULL) continue; p = r->spec->read (r->context); if (a->ctx->flags.secure) hash = xtrymalloc_secure (dlen); else hash = xtrymalloc (dlen); if (!hash) { err = gpg_err_code_from_errno (errno); _gcry_fatal_error (err, NULL); } memcpy (hash, p, dlen); memcpy (r->context, (char *)r->context + r->spec->contextsize * 2, r->spec->contextsize); (*r->spec->write) (r->context, hash, dlen); (*r->spec->final) (r->context); xfree (hash); } } static gcry_err_code_t md_setkey (gcry_md_hd_t h, const unsigned char *key, size_t keylen) { gcry_err_code_t rc = 0; GcryDigestEntry *r; int algo_had_setkey = 0; if (!h->ctx->list) return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */ if (h->ctx->flags.hmac) return GPG_ERR_DIGEST_ALGO; /* Tried md_setkey for HMAC md. */ for (r = h->ctx->list; r; r = r->next) { switch (r->spec->algo) { #if USE_BLAKE2 /* TODO? add spec->init_with_key? */ case GCRY_MD_BLAKE2B_512: case GCRY_MD_BLAKE2B_384: case GCRY_MD_BLAKE2B_256: case GCRY_MD_BLAKE2B_160: case GCRY_MD_BLAKE2S_256: case GCRY_MD_BLAKE2S_224: case GCRY_MD_BLAKE2S_160: case GCRY_MD_BLAKE2S_128: algo_had_setkey = 1; memset (r->context, 0, r->spec->contextsize); rc = _gcry_blake2_init_with_key (r->context, h->ctx->flags.bugemu1 ? GCRY_MD_FLAG_BUGEMU1:0, key, keylen, r->spec->algo); break; #endif default: rc = GPG_ERR_DIGEST_ALGO; break; } if (rc) break; } if (rc && !algo_had_setkey) { /* None of algorithms had setkey implementation, so contexts were not * modified. Just return error. */ return rc; } else if (rc && algo_had_setkey) { /* Some of the contexts have been modified, but got error. Reset * all contexts. */ _gcry_md_reset (h); return rc; } /* Successful md_setkey implies reset. */ h->bufpos = h->ctx->flags.finalized = 0; return 0; } static gcry_err_code_t prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen) { GcryDigestEntry *r; if (!a->ctx->list) return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */ if (!a->ctx->flags.hmac) return GPG_ERR_DIGEST_ALGO; /* Tried prepare_macpads for non-HMAC md. */ for (r = a->ctx->list; r; r = r->next) { const unsigned char *k; size_t k_len; unsigned char *key_allocated = NULL; int macpad_Bsize; int i; switch (r->spec->algo) { /* TODO: add spec->blocksize */ case GCRY_MD_SHA3_224: macpad_Bsize = 1152 / 8; break; case GCRY_MD_SHA3_256: macpad_Bsize = 1088 / 8; break; case GCRY_MD_SHA3_384: macpad_Bsize = 832 / 8; break; case GCRY_MD_SHA3_512: macpad_Bsize = 576 / 8; break; case GCRY_MD_SHA384: case GCRY_MD_SHA512: case GCRY_MD_SHA512_256: case GCRY_MD_SHA512_224: case GCRY_MD_BLAKE2B_512: case GCRY_MD_BLAKE2B_384: case GCRY_MD_BLAKE2B_256: case GCRY_MD_BLAKE2B_160: macpad_Bsize = 128; break; case GCRY_MD_GOSTR3411_94: case GCRY_MD_GOSTR3411_CP: macpad_Bsize = 32; break; default: macpad_Bsize = 64; break; } if ( keylen > macpad_Bsize ) { k = key_allocated = xtrymalloc_secure (r->spec->mdlen); if (!k) return gpg_err_code_from_errno (errno); _gcry_md_hash_buffer (r->spec->algo, key_allocated, key, keylen); k_len = r->spec->mdlen; gcry_assert ( k_len <= macpad_Bsize ); } else { k = key; k_len = keylen; } (*r->spec->init) (r->context, a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0); a->bufpos = 0; for (i=0; i < k_len; i++ ) _gcry_md_putc (a, k[i] ^ 0x36); for (; i < macpad_Bsize; i++ ) _gcry_md_putc (a, 0x36); (*r->spec->write) (r->context, a->buf, a->bufpos); memcpy ((char *)r->context + r->spec->contextsize, r->context, r->spec->contextsize); (*r->spec->init) (r->context, a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0); a->bufpos = 0; for (i=0; i < k_len; i++ ) _gcry_md_putc (a, k[i] ^ 0x5c); for (; i < macpad_Bsize; i++ ) _gcry_md_putc (a, 0x5c); (*r->spec->write) (r->context, a->buf, a->bufpos); memcpy ((char *)r->context + r->spec->contextsize*2, r->context, r->spec->contextsize); xfree (key_allocated); } a->bufpos = 0; return 0; } gcry_err_code_t _gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc = 0; (void)buflen; /* Currently not used. */ switch (cmd) { case GCRYCTL_FINALIZE: md_final (hd); break; case GCRYCTL_START_DUMP: md_start_debug (hd, buffer); break; case GCRYCTL_STOP_DUMP: md_stop_debug ( hd ); break; default: rc = GPG_ERR_INV_OP; } return rc; } gcry_err_code_t _gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen) { gcry_err_code_t rc; if (hd->ctx->flags.hmac) { rc = prepare_macpads (hd, key, keylen); if (!rc) _gcry_md_reset (hd); } else { rc = md_setkey (hd, key, keylen); } return rc; } /* The new debug interface. If SUFFIX is a string it creates an debug file for the context HD. IF suffix is NULL, the file is closed and debugging is stopped. */ void _gcry_md_debug (gcry_md_hd_t hd, const char *suffix) { if (suffix) md_start_debug (hd, suffix); else md_stop_debug (hd); } /**************** * If ALGO is null get the digest for the used algo (which should be * only one) */ static byte * md_read( gcry_md_hd_t a, int algo ) { GcryDigestEntry *r = a->ctx->list; if (! algo) { /* Return the first algorithm */ if (r) { if (r->next) log_debug ("more than one algorithm in md_read(0)\n"); if (r->spec->read) return r->spec->read (r->context); } } else { for (r = a->ctx->list; r; r = r->next) if (r->spec->algo == algo) { if (r->spec->read) return r->spec->read (r->context); break; } } if (r && !r->spec->read) _gcry_fatal_error (GPG_ERR_DIGEST_ALGO, "requested algo has no fixed digest length"); else _gcry_fatal_error (GPG_ERR_DIGEST_ALGO, "requested algo not in md context"); return NULL; } /* * Read out the complete digest, this function implictly finalizes * the hash. */ byte * _gcry_md_read (gcry_md_hd_t hd, int algo) { /* This function is expected to always return a digest, thus we can't return an error which we actually should do in non-operational state. */ _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0); return md_read (hd, algo); } /**************** * If ALGO is null get the digest for the used algo (which should be * only one) */ static gcry_err_code_t md_extract(gcry_md_hd_t a, int algo, void *out, size_t outlen) { GcryDigestEntry *r = a->ctx->list; if (!algo) { /* Return the first algorithm */ if (r && r->spec->extract) { if (r->next) log_debug ("more than one algorithm in md_extract(0)\n"); r->spec->extract (r->context, out, outlen); return 0; } } else { for (r = a->ctx->list; r; r = r->next) if (r->spec->algo == algo && r->spec->extract) { r->spec->extract (r->context, out, outlen); return 0; } } return GPG_ERR_DIGEST_ALGO; } /* * Expand the output from XOF class digest, this function implictly finalizes * the hash. */ gcry_err_code_t _gcry_md_extract (gcry_md_hd_t hd, int algo, void *out, size_t outlen) { _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0); return md_extract (hd, algo, out, outlen); } /* * Read out an intermediate digest. Not yet functional. */ gcry_err_code_t _gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen) { (void)hd; (void)algo; (void)buffer; (void)buflen; /*md_digest ... */ fips_signal_error ("unimplemented function called"); return GPG_ERR_INTERNAL; } /* * Shortcut function to hash a buffer with a given algo. The only * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The * supplied digest buffer must be large enough to store the resulting * hash. No error is returned, the function will abort on an invalid * algo. DISABLED_ALGOS are ignored here. */ void _gcry_md_hash_buffer (int algo, void *digest, const void *buffer, size_t length) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; spec = spec_from_algo (algo); if (!spec) { log_debug ("md_hash_buffer: algorithm %d not available\n", algo); return; } if (spec->hash_buffers != NULL) { gcry_buffer_t iov; iov.size = 0; iov.data = (void *)buffer; iov.off = 0; iov.len = length; if (spec->flags.disabled || (!spec->flags.fips && fips_mode ())) log_bug ("gcry_md_hash_buffer failed for algo %d: %s", algo, gpg_strerror (gcry_error (GPG_ERR_DIGEST_ALGO))); spec->hash_buffers (digest, spec->mdlen, &iov, 1); } else { /* For the others we do not have a fast function, so we use the normal functions. */ gcry_md_hd_t h; gpg_err_code_t err; err = md_open (&h, algo, 0); if (err) log_bug ("gcry_md_open failed for algo %d: %s", algo, gpg_strerror (gcry_error(err))); md_write (h, (byte *) buffer, length); md_final (h); memcpy (digest, md_read (h, algo), md_digest_length (algo)); md_close (h); } } /* Shortcut function to hash multiple buffers with a given algo. In contrast to gcry_md_hash_buffer, this function returns an error on invalid arguments or on other problems; disabled algorithms are _not_ ignored but flagged as an error. The data to sign is taken from the array IOV which has IOVCNT items. The only supported flag in FLAGS is GCRY_MD_FLAG_HMAC which turns this function into a HMAC function; the first item in IOV is then used as the key. On success 0 is returned and resulting hash or HMAC is stored at DIGEST. DIGESTLEN may be given as -1, in which case DIGEST must have been provided by the caller with an appropriate length. DIGESTLEN may also be the appropriate length or, in case of XOF algorithms, DIGESTLEN indicates number bytes to extract from XOF to DIGEST. */ gpg_err_code_t _gcry_md_hash_buffers_extract (int algo, unsigned int flags, void *digest, int digestlen, const gcry_buffer_t *iov, int iovcnt) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; int hmac; if (!iov || iovcnt < 0) return GPG_ERR_INV_ARG; if (flags & ~(GCRY_MD_FLAG_HMAC)) return GPG_ERR_INV_ARG; hmac = !!(flags & GCRY_MD_FLAG_HMAC); if (hmac && iovcnt < 1) return GPG_ERR_INV_ARG; spec = spec_from_algo (algo); if (!spec) { log_debug ("md_hash_buffers: algorithm %d not available\n", algo); return GPG_ERR_DIGEST_ALGO; } if (spec->mdlen > 0 && digestlen != -1 && digestlen != spec->mdlen) return GPG_ERR_DIGEST_ALGO; if (spec->mdlen == 0 && digestlen == -1) return GPG_ERR_DIGEST_ALGO; if (!hmac && spec->hash_buffers) { if (spec->flags.disabled || (!spec->flags.fips && fips_mode ())) return GPG_ERR_DIGEST_ALGO; spec->hash_buffers (digest, digestlen, iov, iovcnt); } else { /* For the others we do not have a fast function, so we use the normal functions. */ gcry_md_hd_t h; gpg_err_code_t rc; rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0)); if (rc) return rc; if (hmac) { rc = _gcry_md_setkey (h, (const char*)iov[0].data + iov[0].off, iov[0].len); if (rc) { md_close (h); return rc; } iov++; iovcnt--; } for (;iovcnt; iov++, iovcnt--) md_write (h, (const char*)iov[0].data + iov[0].off, iov[0].len); md_final (h); if (spec->mdlen > 0) memcpy (digest, md_read (h, algo), spec->mdlen); else if (digestlen > 0) md_extract (h, algo, digest, digestlen); md_close (h); } return 0; } /* Shortcut function to hash multiple buffers with a given algo. In contrast to gcry_md_hash_buffer, this function returns an error on invalid arguments or on other problems; disabled algorithms are _not_ ignored but flagged as an error. The data to sign is taken from the array IOV which has IOVCNT items. The only supported flag in FLAGS is GCRY_MD_FLAG_HMAC which turns this function into a HMAC function; the first item in IOV is then used as the key. On success 0 is returned and resulting hash or HMAC is stored at DIGEST which must have been provided by the caller with an appropriate length. */ gpg_err_code_t _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, const gcry_buffer_t *iov, int iovcnt) { return _gcry_md_hash_buffers_extract(algo, flags, digest, -1, iov, iovcnt); } static int md_get_algo (gcry_md_hd_t a) { GcryDigestEntry *r = a->ctx->list; if (r && r->next) { fips_signal_error ("possible usage error"); log_error ("WARNING: more than one algorithm in md_get_algo()\n"); } return r ? r->spec->algo : 0; } int _gcry_md_get_algo (gcry_md_hd_t hd) { return md_get_algo (hd); } /**************** * Return the length of the digest */ static int md_digest_length (int algorithm) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; spec = spec_from_algo (algorithm); return spec? spec->mdlen : 0; } /**************** * Return the length of the digest in bytes. * This function will return 0 in case of errors. */ unsigned int _gcry_md_get_algo_dlen (int algorithm) { return md_digest_length (algorithm); } /* Hmmm: add a mode to enumerate the OIDs * to make g10/sig-check.c more portable */ static const byte * md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) { - gcry_md_spec_t *spec; + const gcry_md_spec_t *spec; const byte *asnoid = NULL; spec = spec_from_algo (algorithm); if (spec) { if (asnlen) *asnlen = spec->asnlen; if (mdlen) *mdlen = spec->mdlen; asnoid = spec->asnoid; } else log_bug ("no ASN.1 OID for md algo %d\n", algorithm); return asnoid; } /**************** * Return information about the given cipher algorithm * WHAT select the kind of information returned: * GCRYCTL_TEST_ALGO: * Returns 0 when the specified algorithm is available for use. * buffer and nbytes must be zero. * GCRYCTL_GET_ASNOID: * Return the ASNOID of the algorithm in buffer. if buffer is NULL, only * the required length is returned. * GCRYCTL_SELFTEST * Helper for the regression tests - shall not be used by applications. * * 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_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) { gcry_err_code_t rc; switch (what) { case GCRYCTL_TEST_ALGO: if (buffer || nbytes) rc = GPG_ERR_INV_ARG; else rc = check_digest_algo (algo); break; case GCRYCTL_GET_ASNOID: /* We need to check that the algo is available because md_asn_oid would otherwise raise an assertion. */ rc = check_digest_algo (algo); if (!rc) { const char unsigned *asn; size_t asnlen; asn = md_asn_oid (algo, &asnlen, NULL); if (buffer && (*nbytes >= asnlen)) { memcpy (buffer, asn, asnlen); *nbytes = asnlen; } else if (!buffer && nbytes) *nbytes = asnlen; else { if (buffer) rc = GPG_ERR_TOO_SHORT; else rc = GPG_ERR_INV_ARG; } } break; case GCRYCTL_SELFTEST: /* Helper function for the regression tests. */ rc = gpg_err_code (_gcry_md_selftest (algo, nbytes? (int)*nbytes : 0, NULL)); break; default: rc = GPG_ERR_INV_OP; break; } return rc; } static void md_start_debug ( gcry_md_hd_t md, const char *suffix ) { static int idx=0; char buf[50]; if (fips_mode ()) return; if ( md->ctx->debug ) { log_debug("Oops: md debug already started\n"); return; } idx++; snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix ); md->ctx->debug = fopen(buf, "w"); if ( !md->ctx->debug ) log_debug("md debug: can't open %s\n", buf ); } static void md_stop_debug( gcry_md_hd_t md ) { if ( md->ctx->debug ) { if ( md->bufpos ) md_write ( md, NULL, 0 ); fclose (md->ctx->debug); md->ctx->debug = NULL; } { /* a kludge to pull in the __muldi3 for Solaris */ volatile u32 a = (u32)(uintptr_t)md; volatile u64 b = 42; volatile u64 c; c = a * b; (void)c; } } /* * Return information about the digest handle. * GCRYCTL_IS_SECURE: * Returns 1 when the handle works on secured memory * otherwise 0 is returned. There is no error return. * GCRYCTL_IS_ALGO_ENABLED: * Returns 1 if the algo is enabled for that handle. * The algo must be passed as the address of an int. */ gcry_err_code_t _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes) { gcry_err_code_t rc = 0; switch (cmd) { case GCRYCTL_IS_SECURE: *nbytes = h->ctx->flags.secure; break; case GCRYCTL_IS_ALGO_ENABLED: { GcryDigestEntry *r; int algo; if ( !buffer || !nbytes || *nbytes != sizeof (int)) rc = GPG_ERR_INV_ARG; else { algo = *(int*)buffer; *nbytes = 0; for(r=h->ctx->list; r; r = r->next ) { if (r->spec->algo == algo) { *nbytes = 1; break; } } } break; } default: rc = GPG_ERR_INV_OP; } return rc; } /* Explicitly initialize this module. */ gcry_err_code_t _gcry_md_init (void) { return 0; } int _gcry_md_is_secure (gcry_md_hd_t a) { size_t value; if (_gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value)) value = 1; /* It seems to be better to assume secure memory on error. */ return value; } int _gcry_md_is_enabled (gcry_md_hd_t a, int algo) { size_t value; value = sizeof algo; if (_gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value)) value = 0; return value; } /* Run the selftests for digest algorithm ALGO with optional reporting function REPORT. */ gpg_error_t _gcry_md_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec = 0; const gcry_md_spec_t *spec; spec = spec_from_algo (algo); if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()) && spec->selftest) ec = spec->selftest (algo, extended, report); else { ec = (spec && spec->selftest) ? GPG_ERR_DIGEST_ALGO /* */ : GPG_ERR_NOT_IMPLEMENTED; if (report) report ("digest", algo, "module", spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())? "no selftest available" : spec? "algorithm disabled" : "algorithm not found"); } return gpg_error (ec); } diff --git a/cipher/md2.c b/cipher/md2.c index 8fc5a6da..9af9d697 100644 --- a/cipher/md2.c +++ b/cipher/md2.c @@ -1,181 +1,181 @@ /* md2.c - MD2 Message-Digest Algorithm * Copyright (C) 2014 Dmitry Eremin-Solenikov * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include "g10lib.h" #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; unsigned char C[16]; unsigned char L; unsigned char X[48]; } MD2_CONTEXT; static const unsigned char S[] = { 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 }; static void permute (unsigned char *X, const unsigned char *buf) { int i, j; unsigned char t; memcpy (X+16, buf, 16); for (i = 0; i < 16; i++) X[32+i] = X[16+i] ^ X[i]; t = 0; for (i = 0; i < 18; i++) { for (j = 0; j < 48; j++) { t = X[j] ^ S[t]; X[j] = t; } t += i; } } static unsigned int transform_blk (void *c, const unsigned char *data) { MD2_CONTEXT *ctx = c; int j; for (j = 0; j < 16; j++) { ctx->C[j] ^= S[data[j] ^ ctx->L]; ctx->L = ctx->C[j]; } permute(ctx->X, data); return /* burn stack */ 4 + 5 * sizeof(void*); } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 64; } while (--nblks); return burn; } static void md2_init (void *context, unsigned int flags) { MD2_CONTEXT *ctx = context; (void)flags; memset (ctx, 0, sizeof(*ctx)); ctx->bctx.blocksize_shift = _gcry_ctz(16); ctx->bctx.bwrite = transform; } static void md2_final (void *context) { MD2_CONTEXT *hd = context; unsigned int burn; /* pad */ memset (hd->bctx.buf + hd->bctx.count, 16 - hd->bctx.count, 16 - hd->bctx.count); burn = transform_blk (hd, hd->bctx.buf); permute (hd->X, hd->C); } static byte * md2_read (void *context) { MD2_CONTEXT *hd = (MD2_CONTEXT *) context; return hd->X; } -static byte asn[18] = /* Object ID is 1.2.840.113549.2.2 */ +static const byte asn[18] = /* Object ID is 1.2.840.113549.2.2 */ { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 }; -static gcry_md_oid_spec_t oid_spec_md2[] = +static const gcry_md_oid_spec_t oid_spec_md2[] = { /* iso.member-body.us.rsadsi.digestAlgorithm.md2 */ { "1.2.840.113549.2.2" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_md2 = +const gcry_md_spec_t _gcry_digest_spec_md2 = { GCRY_MD_MD2, {0, 0}, "MD2", asn, DIM (asn), oid_spec_md2, 16, md2_init, _gcry_md_block_write, md2_final, md2_read, NULL, NULL, sizeof (MD2_CONTEXT) }; diff --git a/cipher/md4.c b/cipher/md4.c index 46aa8681..49b2af2a 100644 --- a/cipher/md4.c +++ b/cipher/md4.c @@ -1,296 +1,296 @@ /* md4.c - MD4 Message-Digest Algorithm * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * Based on md5.c in libgcrypt, but rewritten to compute md4 checksums * using a public domain md4 implementation with the following comments: * * Modified by Wei Dai from Andrew M. Kuchling's md4.c * The original code and all modifications are in the public domain. * * This is the original introductory comment: * * md4.c : MD4 hash algorithm. * * Part of the Python Cryptography Toolkit, version 1.1 * * Distribute and use freely; there are no restrictions on further * dissemination and usage except those imposed by the laws of your * country of residence. * */ /* MD4 test suite: * MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 * MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 * MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d * MD4 ("message digest") = d9130a8164549fe818874806e1c7014b * MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 * MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = * 043f8582f241db351ce627e153e7f0e4 * MD4 ("123456789012345678901234567890123456789012345678901234567890123456 * 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; u32 A,B,C,D; /* chaining variables */ } MD4_CONTEXT; static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ); static void md4_init (void *context, unsigned int flags) { MD4_CONTEXT *ctx = context; (void)flags; ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->bctx.nblocks = 0; ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize_shift = _gcry_ctz(64); ctx->bctx.bwrite = transform; } #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) /**************** * transform 64 bytes */ static unsigned int transform_blk ( void *c, const unsigned char *data ) { MD4_CONTEXT *ctx = c; u32 in[16]; register u32 A = ctx->A; register u32 B = ctx->B; register u32 C = ctx->C; register u32 D = ctx->D; int i; for ( i = 0; i < 16; i++ ) in[i] = buf_get_le32(data + i * 4); /* Round 1. */ #define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s); function(A,B,C,D, 0, 3); function(D,A,B,C, 1, 7); function(C,D,A,B, 2,11); function(B,C,D,A, 3,19); function(A,B,C,D, 4, 3); function(D,A,B,C, 5, 7); function(C,D,A,B, 6,11); function(B,C,D,A, 7,19); function(A,B,C,D, 8, 3); function(D,A,B,C, 9, 7); function(C,D,A,B,10,11); function(B,C,D,A,11,19); function(A,B,C,D,12, 3); function(D,A,B,C,13, 7); function(C,D,A,B,14,11); function(B,C,D,A,15,19); #undef function /* Round 2. */ #define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s); function(A,B,C,D, 0, 3); function(D,A,B,C, 4, 5); function(C,D,A,B, 8, 9); function(B,C,D,A,12,13); function(A,B,C,D, 1, 3); function(D,A,B,C, 5, 5); function(C,D,A,B, 9, 9); function(B,C,D,A,13,13); function(A,B,C,D, 2, 3); function(D,A,B,C, 6, 5); function(C,D,A,B,10, 9); function(B,C,D,A,14,13); function(A,B,C,D, 3, 3); function(D,A,B,C, 7, 5); function(C,D,A,B,11, 9); function(B,C,D,A,15,13); #undef function /* Round 3. */ #define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s); function(A,B,C,D, 0, 3); function(D,A,B,C, 8, 9); function(C,D,A,B, 4,11); function(B,C,D,A,12,15); function(A,B,C,D, 2, 3); function(D,A,B,C,10, 9); function(C,D,A,B, 6,11); function(B,C,D,A,14,15); function(A,B,C,D, 1, 3); function(D,A,B,C, 9, 9); function(C,D,A,B, 5,11); function(B,C,D,A,13,15); function(A,B,C,D, 3, 3); function(D,A,B,C,11, 9); function(C,D,A,B, 7,11); function(B,C,D,A,15,15); /* Put checksum in context given as argument. */ ctx->A += A; ctx->B += B; ctx->C += C; ctx->D += D; return /*burn_stack*/ 80+6*sizeof(void*); } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 64; } while (--nblks); return burn; } /* The routine final terminates the message-digest computation and * ends with the desired message digest in mdContext->digest[0...15]. * The handle is prepared for a new MD4 cycle. * Returns 16 bytes representing the digest. */ static void md4_final( void *context ) { MD4_CONTEXT *hd = context; u32 t, th, msb, lsb; byte *p; unsigned int burn; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (hd->bctx.count < 56) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 56, lsb); buf_put_le32(hd->bctx.buf + 60, msb); burn = transform (hd, hd->bctx.buf, 1); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 64 + 56, lsb); buf_put_le32(hd->bctx.buf + 64 + 60, msb); burn = transform (hd, hd->bctx.buf, 2); } p = hd->bctx.buf; #define X(a) do { buf_put_le32(p, hd->a); p += 4; } while(0) X(A); X(B); X(C); X(D); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * md4_read (void *context) { MD4_CONTEXT *hd = context; return hd->bctx.buf; } -static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */ +static const byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */ { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 }; -static gcry_md_oid_spec_t oid_spec_md4[] = +static const gcry_md_oid_spec_t oid_spec_md4[] = { /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */ { "1.2.840.113549.2.4" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_md4 = +const gcry_md_spec_t _gcry_digest_spec_md4 = { GCRY_MD_MD4, {0, 0}, "MD4", asn, DIM (asn), oid_spec_md4,16, md4_init, _gcry_md_block_write, md4_final, md4_read, NULL, NULL, sizeof (MD4_CONTEXT) }; diff --git a/cipher/md5.c b/cipher/md5.c index e98aea52..5457fc38 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -1,322 +1,322 @@ /* md5.c - MD5 Message-Digest Algorithm * Copyright (C) 1995,1996,1998,1999,2001,2002, * 2003 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * According to the definition of MD5 in RFC 1321 from April 1992. * NOTE: This is *not* the same file as the one from glibc. * Written by Ulrich Drepper , 1995. * heavily modified for GnuPG by Werner Koch */ /* Test values: * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; u32 A,B,C,D; /* chaining variables */ } MD5_CONTEXT; static unsigned int transform ( void *ctx, const unsigned char *data, size_t datalen ); static void md5_init( void *context, unsigned int flags) { MD5_CONTEXT *ctx = context; (void)flags; ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->bctx.nblocks = 0; ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize_shift = _gcry_ctz(64); ctx->bctx.bwrite = transform; } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /**************** * transform 64 bytes */ static unsigned int transform_blk ( void *c, const unsigned char *data ) { MD5_CONTEXT *ctx = c; u32 correct_words[16]; register u32 A = ctx->A; register u32 B = ctx->B; register u32 C = ctx->C; register u32 D = ctx->D; u32 *cwp = correct_words; int i; for ( i = 0; i < 16; i++ ) correct_words[i] = buf_get_le32(data + i * 4); #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++) + T; \ a = rol(a, s); \ a += b; \ } \ while (0) /* Before we start, one word about the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ a = rol(a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Put checksum in context given as argument. */ ctx->A += A; ctx->B += B; ctx->C += C; ctx->D += D; return /*burn_stack*/ 80+6*sizeof(void*); } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 64; } while (--nblks); return burn; } /* The routine final terminates the message-digest computation and * ends with the desired message digest in mdContext->digest[0...15]. * The handle is prepared for a new MD5 cycle. * Returns 16 bytes representing the digest. */ static void md5_final( void *context) { MD5_CONTEXT *hd = context; u32 t, th, msb, lsb; byte *p; unsigned int burn; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (hd->bctx.count < 56) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 56, lsb); buf_put_le32(hd->bctx.buf + 60, msb); burn = transform (hd, hd->bctx.buf, 1); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 64 + 56, lsb); buf_put_le32(hd->bctx.buf + 64 + 60, msb); burn = transform (hd, hd->bctx.buf, 2); } p = hd->bctx.buf; #define X(a) do { buf_put_le32(p, hd->a); p += 4; } while(0) X(A); X(B); X(C); X(D); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * md5_read( void *context ) { MD5_CONTEXT *hd = (MD5_CONTEXT *) context; return hd->bctx.buf; } -static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ +static const byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; -static gcry_md_oid_spec_t oid_spec_md5[] = +static const gcry_md_oid_spec_t oid_spec_md5[] = { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */ { "1.2.840.113549.1.1.4" }, /* RSADSI digestAlgorithm MD5 */ { "1.2.840.113549.2.5" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_md5 = +const gcry_md_spec_t _gcry_digest_spec_md5 = { GCRY_MD_MD5, {0, 0}, "MD5", asn, DIM (asn), oid_spec_md5, 16, md5_init, _gcry_md_block_write, md5_final, md5_read, NULL, NULL, sizeof (MD5_CONTEXT) }; diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 2d80ee08..7fdb7771 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -1,1241 +1,1253 @@ /* pubkey.c - pubkey dispatcher * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, * 2007, 2008, 2011 Free Software Foundation, Inc. * Copyright (C) 2013 g10 Code GmbH * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "mpi.h" #include "cipher.h" #include "context.h" #include "pubkey-internal.h" /* This is the list of the public-key algorithms included in Libgcrypt. */ static gcry_pk_spec_t * const pubkey_list[] = { #if USE_ECC &_gcry_pubkey_spec_ecc, #endif #if USE_RSA &_gcry_pubkey_spec_rsa, #endif #if USE_DSA &_gcry_pubkey_spec_dsa, #endif #if USE_ELGAMAL &_gcry_pubkey_spec_elg, #endif NULL }; static int map_algo (int algo) { switch (algo) { case GCRY_PK_RSA_E: return GCRY_PK_RSA; case GCRY_PK_RSA_S: return GCRY_PK_RSA; case GCRY_PK_ELG_E: return GCRY_PK_ELG; case GCRY_PK_ECDSA: return GCRY_PK_ECC; case GCRY_PK_EDDSA: return GCRY_PK_ECC; case GCRY_PK_ECDH: return GCRY_PK_ECC; default: return algo; } } /* Return the spec structure for the public key algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_pk_spec_t * spec_from_algo (int algo) { int idx; gcry_pk_spec_t *spec; algo = map_algo (algo); for (idx = 0; (spec = pubkey_list[idx]); idx++) if (algo == spec->algo) return spec; return NULL; } /* Return the spec structure for the public key algorithm with NAME. For an unknown name NULL is returned. */ static gcry_pk_spec_t * spec_from_name (const char *name) { gcry_pk_spec_t *spec; int idx; const char **aliases; for (idx=0; (spec = pubkey_list[idx]); idx++) { if (!stricmp (name, spec->name)) return spec; for (aliases = spec->aliases; *aliases; aliases++) if (!stricmp (name, *aliases)) return spec; } return NULL; } /* Given the s-expression SEXP with the first element be either * "private-key" or "public-key" return the spec structure for it. We * look through the list to find a list beginning with "private-key" * or "public-key" - the first one found is used. If WANT_PRIVATE is * set the function will only succeed if a private key has been given. * On success the spec is stored at R_SPEC. On error NULL is stored * at R_SPEC and an error code returned. If R_PARMS is not NULL and * the function returns success, the parameter list below * "private-key" or "public-key" is stored there and the caller must * call gcry_sexp_release on it. */ static gcry_err_code_t spec_from_sexp (gcry_sexp_t sexp, int want_private, gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms) { gcry_sexp_t list, l2; char *name; gcry_pk_spec_t *spec; *r_spec = NULL; if (r_parms) *r_parms = NULL; /* Check that the first element is valid. If we are looking for a public key but a private key was supplied, we allow the use of the private key anyway. The rationale for this is that the private key is a superset of the public key. */ list = sexp_find_token (sexp, want_private? "private-key":"public-key", 0); if (!list && !want_private) list = sexp_find_token (sexp, "private-key", 0); if (!list) return GPG_ERR_INV_OBJ; /* Does not contain a key object. */ l2 = sexp_cadr (list); sexp_release (list); list = l2; name = sexp_nth_string (list, 0); if (!name) { sexp_release ( list ); return GPG_ERR_INV_OBJ; /* Invalid structure of object. */ } spec = spec_from_name (name); xfree (name); if (!spec) { sexp_release (list); return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ } *r_spec = spec; if (r_parms) *r_parms = list; else sexp_release (list); return 0; } /* Disable the use of the algorithm ALGO. This is not thread safe and should thus be called early. */ static void disable_pubkey_algo (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); if (spec) spec->flags.disabled = 1; } /* * Map a string to the pubkey algo */ int _gcry_pk_map_name (const char *string) { gcry_pk_spec_t *spec; if (!string) return 0; spec = spec_from_name (string); if (!spec) return 0; if (spec->flags.disabled) return 0; + if (!spec->flags.fips && fips_mode ()) + return 0; return spec->algo; } /* Map the public key algorithm whose ID is contained in ALGORITHM to a string representation of the algorithm name. For unknown algorithm IDs this functions returns "?". */ const char * _gcry_pk_algo_name (int algo) { gcry_pk_spec_t *spec; spec = spec_from_algo (algo); if (spec) return spec->name; return "?"; } /**************** * A USE of 0 means: don't care. */ static gcry_err_code_t check_pubkey_algo (int algo, unsigned use) { gcry_err_code_t err = 0; gcry_pk_spec_t *spec; spec = spec_from_algo (algo); - if (spec && !spec->flags.disabled) + if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ())) { if (((use & GCRY_PK_USAGE_SIGN) && (! (spec->use & GCRY_PK_USAGE_SIGN))) || ((use & GCRY_PK_USAGE_ENCR) && (! (spec->use & GCRY_PK_USAGE_ENCR)))) err = GPG_ERR_WRONG_PUBKEY_ALGO; } else err = GPG_ERR_PUBKEY_ALGO; return err; } /**************** * Return the number of public key material numbers */ static int pubkey_get_npkey (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_pkey) : 0; } /**************** * Return the number of secret key material numbers */ static int pubkey_get_nskey (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_skey) : 0; } /**************** * Return the number of signature material numbers */ static int pubkey_get_nsig (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_sig) : 0; } /**************** * Return the number of encryption material numbers */ static int pubkey_get_nenc (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_enc) : 0; } /* Do a PK encrypt operation Caller has to provide a public key as the SEXP pkey and data as a SEXP with just one MPI in it. Alternatively S_DATA might be a complex S-Expression, similar to the one used for signature verification. This provides a flag which allows to handle PKCS#1 block type 2 padding. The function returns a sexp which may be passed to to pk_decrypt. Returns: 0 or an errorcode. s_data = See comment for _gcry_pk_util_data_to_mpi s_pkey = r_ciph = (enc-val ( ( ) ... ( ) )) */ gcry_err_code_t _gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_ciph = NULL; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->encrypt) rc = spec->encrypt (r_ciph, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } /* Do a PK decrypt operation Caller has to provide a secret key as the SEXP skey and data in a format as created by gcry_pk_encrypt. For historic reasons the function returns simply an MPI as an S-expression part; this is deprecated and the new method should be used which returns a real S-expressionl this is selected by adding at least an empty flags list to S_DATA. Returns: 0 or an errorcode. s_data = (enc-val [(flags [raw, pkcs1, oaep])] ( ( ) ... ( ) )) s_skey = r_plain= Either an incomplete S-expression without the parentheses or if the flags list is used (even if empty) a real S-expression: (value PLAIN). In raw mode (or no flags given) the returned value is to be interpreted as a signed MPI, thus it may have an extra leading zero octet even if not included in the original data. With pkcs1 or oaep decoding enabled the returned value is a verbatim octet string. */ gcry_err_code_t _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_plain = NULL; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->decrypt) rc = spec->decrypt (r_plain, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } /* Create a signature. Caller has to provide a secret key as the SEXP skey and data expressed as a SEXP list hash with only one element which should instantly be available as a MPI. Alternatively the structure given below may be used for S_HASH, it provides the abiliy to pass flags to the operation; the flags defined by now are "pkcs1" which does PKCS#1 block type 1 style padding and "pss" for PSS encoding. Returns: 0 or an errorcode. In case of 0 the function returns a new SEXP with the signature value; the structure of this signature depends on the other arguments but is always suitable to be passed to gcry_pk_verify s_hash = See comment for _gcry-pk_util_data_to_mpi s_skey = r_sig = (sig-val ( ( ) ... ( )) [(hash algo)]) Note that (hash algo) in R_SIG is not used. */ gcry_err_code_t _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_sig = NULL; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->sign) rc = spec->sign (r_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } gcry_err_code_t _gcry_pk_sign_md (gcry_sexp_t *r_sig, const char *tmpl, gcry_md_hd_t hd_orig, gcry_sexp_t s_skey, gcry_ctx_t ctx) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; gcry_sexp_t s_hash = NULL; int algo; const unsigned char *digest; gcry_error_t err; gcry_md_hd_t hd; char *s; char *hash_name; *r_sig = NULL; /* Check if it has fixed hash name or %s */ s = strstr (tmpl, "(hash "); if (s == NULL) return GPG_ERR_DIGEST_ALGO; s += 6; if (!strncmp (s, "%s", 2)) hash_name = NULL; else { char *p; for (p = s; *p && *p != ' '; p++) ; hash_name = xtrymalloc (p - s + 1); if (!hash_name) return gpg_error_from_syserror (); memcpy (hash_name, s, p - s); hash_name[p - s] = 0; } err = _gcry_md_copy (&hd, hd_orig); if (err) { xfree (hash_name); return gpg_err_code (err); } if (hash_name) { algo = _gcry_md_map_name (hash_name); if (algo == 0 || (fips_mode () && algo == GCRY_MD_SHA1)) { xfree (hash_name); _gcry_md_close (hd); return GPG_ERR_DIGEST_ALGO; } digest = _gcry_md_read (hd, algo); } else { algo = _gcry_md_get_algo (hd); if (fips_mode () && algo == GCRY_MD_SHA1) return GPG_ERR_DIGEST_ALGO; digest = _gcry_md_read (hd, 0); } if (!digest) { xfree (hash_name); _gcry_md_close (hd); return GPG_ERR_NOT_IMPLEMENTED; } if (!ctx) { if (hash_name) rc = _gcry_sexp_build (&s_hash, NULL, tmpl, (int) _gcry_md_get_algo_dlen (algo), digest); else rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest); } else { const unsigned char *p; size_t len; rc = _gcry_pk_get_random_override (ctx, &p, &len); if (rc) { _gcry_md_close (hd); return rc; } if (hash_name) rc = _gcry_sexp_build (&s_hash, NULL, tmpl, (int) _gcry_md_get_algo_dlen (algo), digest, (int) len, p); else rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest, (int) len, p); } xfree (hash_name); _gcry_md_close (hd); if (rc) return rc; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->sign) rc = spec->sign (r_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (s_hash); sexp_release (keyparms); return rc; } /* Verify a signature. Caller has to supply the public key pkey, the signature sig and his hashvalue data. Public key has to be a standard public key given as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data must be an S-Exp like the one in sign too. */ gcry_err_code_t _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->verify) rc = spec->verify (s_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } gcry_err_code_t _gcry_pk_verify_md (gcry_sexp_t s_sig, const char *tmpl, gcry_md_hd_t hd_orig, gcry_sexp_t s_pkey, gcry_ctx_t ctx) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; gcry_sexp_t s_hash = NULL; int algo; const unsigned char *digest; gcry_error_t err; gcry_md_hd_t hd; err = _gcry_md_copy (&hd, hd_orig); if (err) return gpg_err_code (err); algo = _gcry_md_get_algo (hd); if (fips_mode () && algo == GCRY_MD_SHA1) return GPG_ERR_DIGEST_ALGO; digest = _gcry_md_read (hd, 0); if (!digest) { _gcry_md_close (hd); return GPG_ERR_DIGEST_ALGO; } if (!ctx) rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest); else { const unsigned char *p; size_t len; rc = _gcry_pk_get_random_override (ctx, &p, &len); if (rc) { _gcry_md_close (hd); return rc; } rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest, (int) len, p); } _gcry_md_close (hd); if (rc) return rc; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->verify) rc = spec->verify (s_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (s_hash); sexp_release (keyparms); return rc; } /* Test a key. This may be used either for a public or a secret key to see whether the internal structure is okay. Returns: 0 or an errorcode. NOTE: We currently support only secret key checking. */ gcry_err_code_t _gcry_pk_testkey (gcry_sexp_t s_key) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; rc = spec_from_sexp (s_key, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) - rc = GPG_ERR_CIPHER_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; + else if (!spec->flags.fips && fips_mode ()) + rc = GPG_ERR_PUBKEY_ALGO; else if (spec->check_secret_key) rc = spec->check_secret_key (keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } /* Create a public key pair and return it in r_key. How the key is created depends on s_parms: (genkey (algo (parameter_name_1 ....) .... (parameter_name_n ....) )) The key is returned in a format depending on the algorithm. Both, private and secret keys are returned and optionally some additional informatin. For elgamal we return this structure: (key-data (public-key (elg (p ) (g ) (y ) ) ) (private-key (elg (p ) (g ) (y ) (x ) ) ) (misc-key-info (pm1-factors n1 n2 ... nn) )) */ gcry_err_code_t _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) { gcry_pk_spec_t *spec = NULL; gcry_sexp_t list = NULL; gcry_sexp_t l2 = NULL; char *name = NULL; gcry_err_code_t rc; *r_key = NULL; list = sexp_find_token (s_parms, "genkey", 0); if (!list) { rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */ goto leave; } l2 = sexp_cadr (list); sexp_release (list); list = l2; l2 = NULL; if (! list) { rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */ goto leave; } name = _gcry_sexp_nth_string (list, 0); if (!name) { rc = GPG_ERR_INV_OBJ; /* Algo string missing. */ goto leave; } spec = spec_from_name (name); xfree (name); name = NULL; - if (!spec || spec->flags.disabled) + if (!spec || spec->flags.disabled || (!spec->flags.fips && fips_mode ())) { rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ goto leave; } if (spec->generate) rc = spec->generate (list, r_key); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (list); xfree (name); sexp_release (l2); return rc; } /* Get the number of nbits from the public key. Hmmm: Should we have really this function or is it better to have a more general function to retrieve different properties of the key? */ unsigned int _gcry_pk_get_nbits (gcry_sexp_t key) { gcry_pk_spec_t *spec; gcry_sexp_t parms; unsigned int nbits; /* Parsing KEY might be considered too much overhead. For example for RSA we would only need to look at P and stop parsing right away. However, with ECC things are more complicate in that only a curve name might be specified. Thus we need to tear the sexp apart. */ if (spec_from_sexp (key, 0, &spec, &parms)) return 0; /* Error - 0 is a suitable indication for that. */ if (spec->flags.disabled) return 0; + if (!spec->flags.fips && fips_mode ()) + return 0; nbits = spec->get_nbits (parms); sexp_release (parms); return nbits; } /* Return the so called KEYGRIP which is the SHA-1 hash of the public key parameters expressed in a way depending on the algorithm. ARRAY must either be 20 bytes long or NULL; in the latter case a newly allocated array of that size is returned, otherwise ARRAY or NULL is returned to indicate an error which is most likely an unknown algorithm. The function accepts public or secret keys. */ unsigned char * _gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) { gcry_sexp_t list = NULL; gcry_sexp_t l2 = NULL; gcry_pk_spec_t *spec = NULL; const char *s; char *name = NULL; int idx; const char *elems; gcry_md_hd_t md = NULL; int okay = 0; /* Check that the first element is valid. */ list = sexp_find_token (key, "public-key", 0); if (! list) list = sexp_find_token (key, "private-key", 0); if (! list) list = sexp_find_token (key, "protected-private-key", 0); if (! list) list = sexp_find_token (key, "shadowed-private-key", 0); if (! list) return NULL; /* No public- or private-key object. */ l2 = sexp_cadr (list); sexp_release (list); list = l2; l2 = NULL; name = _gcry_sexp_nth_string (list, 0); if (!name) goto fail; /* Invalid structure of object. */ spec = spec_from_name (name); if (!spec) goto fail; /* Unknown algorithm. */ elems = spec->elements_grip; if (!elems) goto fail; /* No grip parameter. */ if (_gcry_md_open (&md, GCRY_MD_SHA1, 0)) goto fail; if (spec->comp_keygrip) { /* Module specific method to compute a keygrip. */ if (spec->comp_keygrip (md, list)) goto fail; } else { /* Generic method to compute a keygrip. */ for (idx = 0, s = elems; *s; s++, idx++) { const char *data; size_t datalen; char buf[30]; l2 = sexp_find_token (list, s, 1); if (! l2) goto fail; data = sexp_nth_data (l2, 1, &datalen); if (! data) goto fail; snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen); _gcry_md_write (md, buf, strlen (buf)); _gcry_md_write (md, data, datalen); sexp_release (l2); l2 = NULL; _gcry_md_write (md, ")", 1); } } if (!array) { array = xtrymalloc (20); if (! array) goto fail; } memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20); okay = 1; fail: xfree (name); sexp_release (l2); _gcry_md_close (md); sexp_release (list); return okay? array : NULL; } const char * _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) { const char *result = NULL; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; if (r_nbits) *r_nbits = 0; if (key) { iterator = 0; if (spec_from_sexp (key, 0, &spec, &keyparms)) return NULL; } else { spec = spec_from_name ("ecc"); if (!spec) return NULL; } if (spec->flags.disabled) return NULL; + if (!spec->flags.fips && fips_mode ()) + return NULL; if (spec->get_curve) result = spec->get_curve (keyparms, iterator, r_nbits); sexp_release (keyparms); return result; } gcry_sexp_t _gcry_pk_get_param (int algo, const char *name) { gcry_sexp_t result = NULL; gcry_pk_spec_t *spec = NULL; algo = map_algo (algo); if (algo != GCRY_PK_ECC) return NULL; spec = spec_from_name ("ecc"); if (spec) { if (spec && spec->get_curve_param) result = spec->get_curve_param (name); } return result; } gcry_err_code_t _gcry_pk_ctl (int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc = 0; switch (cmd) { case GCRYCTL_DISABLE_ALGO: /* This one expects a buffer pointing to an integer with the algo number. */ if ((! buffer) || (buflen != sizeof (int))) rc = GPG_ERR_INV_ARG; else disable_pubkey_algo (*((int *) buffer)); break; default: rc = GPG_ERR_INV_OP; } return rc; } /* Return information about the given algorithm WHAT selects the kind of information returned: GCRYCTL_TEST_ALGO: Returns 0 when the specified algorithm is available for use. Buffer must be NULL, nbytes may have the address of a variable with the required usage of the algorithm. It may be 0 for don't care or a combination of the GCRY_PK_USAGE_xxx flags; GCRYCTL_GET_ALGO_USAGE: Return the usage flags for the given algo. An invalid algo returns 0. Disabled algos are ignored here because we only want to know whether the algo is at all capable of the usage. 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_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes) { gcry_err_code_t rc = 0; switch (what) { case GCRYCTL_TEST_ALGO: { int use = nbytes ? *nbytes : 0; if (buffer) rc = GPG_ERR_INV_ARG; else if (check_pubkey_algo (algorithm, use)) rc = GPG_ERR_PUBKEY_ALGO; break; } case GCRYCTL_GET_ALGO_USAGE: { gcry_pk_spec_t *spec; spec = spec_from_algo (algorithm); *nbytes = spec? spec->use : 0; break; } case GCRYCTL_GET_ALGO_NPKEY: { /* FIXME? */ int npkey = pubkey_get_npkey (algorithm); *nbytes = npkey; break; } case GCRYCTL_GET_ALGO_NSKEY: { /* FIXME? */ int nskey = pubkey_get_nskey (algorithm); *nbytes = nskey; break; } case GCRYCTL_GET_ALGO_NSIGN: { /* FIXME? */ int nsign = pubkey_get_nsig (algorithm); *nbytes = nsign; break; } case GCRYCTL_GET_ALGO_NENCR: { /* FIXME? */ int nencr = pubkey_get_nenc (algorithm); *nbytes = nencr; break; } default: rc = GPG_ERR_INV_OP; } return rc; } /* Return an S-expression representing the context CTX. Depending on the state of that context, the S-expression may either be a public key, a private key or any other object used with public key operations. On success a new S-expression is stored at R_SEXP and 0 is returned, on error NULL is store there and an error code is returned. MODE is either 0 or one of the GCRY_PK_GET_xxx values. As of now it only support certain ECC operations because a context object is right now only defined for ECC. Over time this function will be extended to cover more algorithms. Note also that the name of the function is gcry_pubkey_xxx and not gcry_pk_xxx. The idea is that we will eventually provide variants of the existing gcry_pk_xxx functions which will take a context parameter. */ gcry_err_code_t _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx) { mpi_ec_t ec; if (!r_sexp) return GPG_ERR_INV_VALUE; *r_sexp = NULL; switch (mode) { case 0: case GCRY_PK_GET_PUBKEY: case GCRY_PK_GET_SECKEY: break; default: return GPG_ERR_INV_VALUE; } if (!ctx) return GPG_ERR_NO_CRYPT_CTX; ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC); if (ec) return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec); return GPG_ERR_WRONG_CRYPT_CTX; } /* Explicitly initialize this module. */ gcry_err_code_t _gcry_pk_init (void) { - if (fips_mode()) - { - /* disable algorithms that are disallowed in fips */ - int idx; - gcry_pk_spec_t *spec; - - for (idx = 0; (spec = pubkey_list[idx]); idx++) - if (!spec->flags.fips) - spec->flags.disabled = 1; - } - return 0; } /* Run the selftests for pubkey algorithm ALGO with optional reporting function REPORT. */ gpg_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec; gcry_pk_spec_t *spec; algo = map_algo (algo); spec = spec_from_algo (algo); - if (spec && !spec->flags.disabled && spec->selftest) + if (spec && !spec->flags.disabled + && (spec->flags.fips || !fips_mode ()) + && spec->selftest) ec = spec->selftest (algo, extended, report); else { ec = GPG_ERR_PUBKEY_ALGO; /* Fixme: We need to change the report function to allow passing of an encryption mode (e.g. pkcs1, ecdsa, or ecdh). */ if (report) report ("pubkey", algo, "module", - spec && !spec->flags.disabled? + spec && !spec->flags.disabled + && (spec->flags.fips || !fips_mode ())? "no selftest available" : spec? "algorithm disabled" : "algorithm not found"); } return gpg_error (ec); } struct pk_random_override { size_t len; unsigned char area[]; }; gpg_err_code_t _gcry_pk_random_override_new (gcry_ctx_t *r_ctx, const unsigned char *p, size_t len) { gcry_ctx_t ctx; struct pk_random_override *pro; *r_ctx = NULL; if (!p) return GPG_ERR_EINVAL; ctx = _gcry_ctx_alloc (CONTEXT_TYPE_RANDOM_OVERRIDE, sizeof (size_t) + len, NULL); if (!ctx) return gpg_err_code_from_syserror (); pro = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_RANDOM_OVERRIDE); pro->len = len; memcpy (pro->area, p, len); *r_ctx = ctx; return 0; } gpg_err_code_t _gcry_pk_get_random_override (gcry_ctx_t ctx, const unsigned char **r_p, size_t *r_len) { struct pk_random_override *pro; pro = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_RANDOM_OVERRIDE); if (!pro) return GPG_ERR_EINVAL; *r_p = pro->area; *r_len = pro->len; return 0; } diff --git a/cipher/rfc2268.c b/cipher/rfc2268.c index b093f022..c270ce9b 100644 --- a/cipher/rfc2268.c +++ b/cipher/rfc2268.c @@ -1,381 +1,381 @@ /* rfc2268.c - The cipher described in rfc2268; aka Ron's Cipher 2. * Copyright (C) 2003 Nikos Mavroyanopoulos * Copyright (C) 2004 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* This implementation was written by Nikos Mavroyanopoulos for GNUTLS * as a Libgcrypt module (gnutls/lib/x509/rc2.c) and later adapted for * direct use by Libgcrypt by Werner Koch. This implementation is * only useful for pkcs#12 decryption. * * The implementation here is based on Peter Gutmann's RRC.2 paper. */ #include #include #include #include #include "g10lib.h" #include "types.h" #include "cipher.h" #include "cipher-internal.h" #define RFC2268_BLOCKSIZE 8 typedef struct { u16 S[64]; } RFC2268_context; static const unsigned char rfc2268_sbox[] = { 217, 120, 249, 196, 25, 221, 181, 237, 40, 233, 253, 121, 74, 160, 216, 157, 198, 126, 55, 131, 43, 118, 83, 142, 98, 76, 100, 136, 68, 139, 251, 162, 23, 154, 89, 245, 135, 179, 79, 19, 97, 69, 109, 141, 9, 129, 125, 50, 189, 143, 64, 235, 134, 183, 123, 11, 240, 149, 33, 34, 92, 107, 78, 130, 84, 214, 101, 147, 206, 96, 178, 28, 115, 86, 192, 20, 167, 140, 241, 220, 18, 117, 202, 31, 59, 190, 228, 209, 66, 61, 212, 48, 163, 60, 182, 38, 111, 191, 14, 218, 70, 105, 7, 87, 39, 242, 29, 155, 188, 148, 67, 3, 248, 17, 199, 246, 144, 239, 62, 231, 6, 195, 213, 47, 200, 102, 30, 215, 8, 232, 234, 222, 128, 82, 238, 247, 132, 170, 114, 172, 53, 77, 106, 42, 150, 26, 210, 113, 90, 21, 73, 116, 75, 159, 208, 94, 4, 24, 164, 236, 194, 224, 65, 110, 15, 81, 203, 204, 36, 145, 175, 80, 161, 244, 112, 57, 153, 124, 58, 133, 35, 184, 180, 122, 252, 2, 54, 91, 37, 85, 151, 49, 45, 93, 250, 152, 227, 138, 146, 174, 5, 223, 41, 16, 103, 108, 186, 201, 211, 0, 230, 207, 225, 158, 168, 44, 99, 22, 1, 63, 88, 226, 137, 169, 13, 56, 52, 27, 171, 51, 255, 176, 187, 72, 12, 95, 185, 177, 205, 46, 197, 243, 219, 71, 229, 165, 156, 119, 10, 166, 32, 104, 254, 127, 193, 173 }; #define rotl16(x,n) (((x) << ((u16)(n))) | ((x) >> (16 - (u16)(n)))) #define rotr16(x,n) (((x) >> ((u16)(n))) | ((x) << (16 - (u16)(n)))) static const char *selftest (void); static void do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) { RFC2268_context *ctx = context; register int i, j; u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; word0 = (word0 << 8) | inbuf[1]; word0 = (word0 << 8) | inbuf[0]; word1 = (word1 << 8) | inbuf[3]; word1 = (word1 << 8) | inbuf[2]; word2 = (word2 << 8) | inbuf[5]; word2 = (word2 << 8) | inbuf[4]; word3 = (word3 << 8) | inbuf[7]; word3 = (word3 << 8) | inbuf[6]; for (i = 0; i < 16; i++) { j = i * 4; /* For some reason I cannot combine those steps. */ word0 += (word1 & ~word3) + (word2 & word3) + ctx->S[j]; word0 = rotl16(word0, 1); word1 += (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; word1 = rotl16(word1, 2); word2 += (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; word2 = rotl16(word2, 3); word3 += (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; word3 = rotl16(word3, 5); if (i == 4 || i == 10) { word0 += ctx->S[word3 & 63]; word1 += ctx->S[word0 & 63]; word2 += ctx->S[word1 & 63]; word3 += ctx->S[word2 & 63]; } } outbuf[0] = word0 & 255; outbuf[1] = word0 >> 8; outbuf[2] = word1 & 255; outbuf[3] = word1 >> 8; outbuf[4] = word2 & 255; outbuf[5] = word2 >> 8; outbuf[6] = word3 & 255; outbuf[7] = word3 >> 8; } static unsigned int encrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf) { do_encrypt (context, outbuf, inbuf); return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4); } static void do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) { RFC2268_context *ctx = context; register int i, j; u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; word0 = (word0 << 8) | inbuf[1]; word0 = (word0 << 8) | inbuf[0]; word1 = (word1 << 8) | inbuf[3]; word1 = (word1 << 8) | inbuf[2]; word2 = (word2 << 8) | inbuf[5]; word2 = (word2 << 8) | inbuf[4]; word3 = (word3 << 8) | inbuf[7]; word3 = (word3 << 8) | inbuf[6]; for (i = 15; i >= 0; i--) { j = i * 4; word3 = rotr16(word3, 5); word3 -= (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; word2 = rotr16(word2, 3); word2 -= (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; word1 = rotr16(word1, 2); word1 -= (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; word0 = rotr16(word0, 1); word0 -= (word1 & ~word3) + (word2 & word3) + ctx->S[j]; if (i == 5 || i == 11) { word3 = word3 - ctx->S[word2 & 63]; word2 = word2 - ctx->S[word1 & 63]; word1 = word1 - ctx->S[word0 & 63]; word0 = word0 - ctx->S[word3 & 63]; } } outbuf[0] = word0 & 255; outbuf[1] = word0 >> 8; outbuf[2] = word1 & 255; outbuf[3] = word1 >> 8; outbuf[4] = word2 & 255; outbuf[5] = word2 >> 8; outbuf[6] = word3 & 255; outbuf[7] = word3 >> 8; } static unsigned int decrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf) { do_decrypt (context, outbuf, inbuf); return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4); } static gpg_err_code_t setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2) { static int initialized; static const char *selftest_failed; RFC2268_context *ctx = context; unsigned int i; unsigned char *S, x; int len; int bits = keylen * 8; if (!initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("RFC2268 selftest failed (%s).\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen < 40 / 8) /* We want at least 40 bits. */ return GPG_ERR_INV_KEYLEN; if (keylen > 128) return GPG_ERR_INV_KEYLEN; S = (unsigned char *) ctx->S; for (i = 0; i < keylen; i++) S[i] = key[i]; for (i = keylen; i < 128; i++) S[i] = rfc2268_sbox[(S[i - keylen] + S[i - 1]) & 255]; S[0] = rfc2268_sbox[S[0]]; /* Phase 2 - reduce effective key size to "bits". This was not * discussed in Gutmann's paper. I've copied that from the public * domain code posted in sci.crypt. */ if (with_phase2) { len = (bits + 7) >> 3; i = 128 - len; x = rfc2268_sbox[S[i] & (255 >> (7 & -bits))]; S[i] = x; while (i--) { x = rfc2268_sbox[x ^ S[i + len]]; S[i] = x; } } /* Make the expanded key, endian independent. */ for (i = 0; i < 64; i++) ctx->S[i] = ( (u16) S[i * 2] | (((u16) S[i * 2 + 1]) << 8)); return 0; } static gpg_err_code_t do_setkey (void *context, const unsigned char *key, unsigned int keylen, cipher_bulk_ops_t *bulk_ops) { (void)bulk_ops; return setkey_core (context, key, keylen, 1); } static const char * selftest (void) { RFC2268_context ctx; unsigned char scratch[16]; /* Test vectors from Peter Gutmann's paper. */ static unsigned char key_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char plaintext_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const unsigned char ciphertext_1[] = { 0x1C, 0x19, 0x8A, 0x83, 0x8D, 0xF0, 0x28, 0xB7 }; static unsigned char key_2[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; static unsigned char plaintext_2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char ciphertext_2[] = { 0x50, 0xDC, 0x01, 0x62, 0xBD, 0x75, 0x7F, 0x31 }; /* This one was checked against libmcrypt's RFC2268. */ static unsigned char key_3[] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char plaintext_3[] = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char ciphertext_3[] = { 0x8f, 0xd1, 0x03, 0x89, 0x33, 0x6b, 0xf9, 0x5e }; /* First test. */ setkey_core (&ctx, key_1, sizeof(key_1), 0); do_encrypt (&ctx, scratch, plaintext_1); if (memcmp (scratch, ciphertext_1, sizeof(ciphertext_1))) return "RFC2268 encryption test 1 failed."; setkey_core (&ctx, key_1, sizeof(key_1), 0); do_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_1, sizeof(plaintext_1))) return "RFC2268 decryption test 1 failed."; /* Second test. */ setkey_core (&ctx, key_2, sizeof(key_2), 0); do_encrypt (&ctx, scratch, plaintext_2); if (memcmp (scratch, ciphertext_2, sizeof(ciphertext_2))) return "RFC2268 encryption test 2 failed."; setkey_core (&ctx, key_2, sizeof(key_2), 0); do_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_2, sizeof(plaintext_2))) return "RFC2268 decryption test 2 failed."; /* Third test. */ setkey_core(&ctx, key_3, sizeof(key_3), 0); do_encrypt(&ctx, scratch, plaintext_3); if (memcmp(scratch, ciphertext_3, sizeof(ciphertext_3))) return "RFC2268 encryption test 3 failed."; setkey_core (&ctx, key_3, sizeof(key_3), 0); do_decrypt (&ctx, scratch, scratch); if (memcmp(scratch, plaintext_3, sizeof(plaintext_3))) return "RFC2268 decryption test 3 failed."; return NULL; } -static gcry_cipher_oid_spec_t oids_rfc2268_40[] = +static const gcry_cipher_oid_spec_t oids_rfc2268_40[] = { /*{ "1.2.840.113549.3.2", GCRY_CIPHER_MODE_CBC },*/ /* pbeWithSHAAnd40BitRC2_CBC */ { "1.2.840.113549.1.12.1.6", GCRY_CIPHER_MODE_CBC }, { NULL } }; -static gcry_cipher_oid_spec_t oids_rfc2268_128[] = +static const gcry_cipher_oid_spec_t oids_rfc2268_128[] = { /* pbeWithSHAAnd128BitRC2_CBC */ { "1.2.840.113549.1.12.1.5", GCRY_CIPHER_MODE_CBC }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = { GCRY_CIPHER_RFC2268_40, {0, 0}, "RFC2268_40", NULL, oids_rfc2268_40, RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context), do_setkey, encrypt_block, decrypt_block }; gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_128 = { GCRY_CIPHER_RFC2268_128, {0, 0}, "RFC2268_128", NULL, oids_rfc2268_128, RFC2268_BLOCKSIZE, 128, sizeof(RFC2268_context), do_setkey, encrypt_block, decrypt_block }; diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 23c4efe3..9b96b616 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -1,2102 +1,2102 @@ /* Rijndael (AES) for GnuPG * Copyright (C) 2000, 2001, 2002, 2003, 2007, * 2008, 2011, 2012 Free Software Foundation, Inc. * * 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 . ******************************************************************* * The code here is based on the optimized implementation taken from * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000, * which carries this notice: *------------------------------------------ * rijndael-alg-fst.c v2.3 April '2000 * * Optimised ANSI C code * * authors: v1.0: Antoon Bosselaers * v2.0: Vincent Rijmen * v2.3: Paulo Barreto * * This code is placed in the public domain. *------------------------------------------ * * The SP800-38a document is available at: * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf * */ #include #include #include #include /* for memcmp() */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "cipher-selftest.h" #include "rijndael-internal.h" #include "./cipher-internal.h" #ifdef USE_AMD64_ASM /* AMD64 assembly implementations of AES */ extern unsigned int _gcry_aes_amd64_encrypt_block(const void *keysched_enc, unsigned char *out, const unsigned char *in, int rounds, const void *encT); extern unsigned int _gcry_aes_amd64_decrypt_block(const void *keysched_dec, unsigned char *out, const unsigned char *in, int rounds, const void *decT); #endif /*USE_AMD64_ASM*/ #ifdef USE_AESNI /* AES-NI (AMD64 & i386) accelerated implementations of AES */ extern void _gcry_aes_aesni_do_setkey(RIJNDAEL_context *ctx, const byte *key); extern void _gcry_aes_aesni_prepare_decryption(RIJNDAEL_context *ctx); extern unsigned int _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern unsigned int _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern void _gcry_aes_aesni_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_aesni_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac); extern void _gcry_aes_aesni_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_aesni_ctr32le_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_aesni_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_aesni_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern size_t _gcry_aes_aesni_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern size_t _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); extern void _gcry_aes_aesni_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); #endif #ifdef USE_VAES /* VAES (AMD64) accelerated implementation of AES */ extern void _gcry_aes_vaes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_vaes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_vaes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_vaes_ctr32le_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern size_t _gcry_aes_vaes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern void _gcry_aes_vaes_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); #endif #ifdef USE_SSSE3 /* SSSE3 (AMD64) vector permutation implementation of AES */ extern void _gcry_aes_ssse3_do_setkey(RIJNDAEL_context *ctx, const byte *key); extern void _gcry_aes_ssse3_prepare_decryption(RIJNDAEL_context *ctx); extern unsigned int _gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern unsigned int _gcry_aes_ssse3_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern void _gcry_aes_ssse3_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ssse3_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac); extern void _gcry_aes_ssse3_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ssse3_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ssse3_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern size_t _gcry_aes_ssse3_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern size_t _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); #endif #ifdef USE_PADLOCK extern unsigned int _gcry_aes_padlock_encrypt (const RIJNDAEL_context *ctx, unsigned char *bx, const unsigned char *ax); extern unsigned int _gcry_aes_padlock_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx, const unsigned char *ax); extern void _gcry_aes_padlock_prepare_decryption (RIJNDAEL_context *ctx); #endif #ifdef USE_ARM_ASM /* ARM assembly implementations of AES */ extern unsigned int _gcry_aes_arm_encrypt_block(const void *keysched_enc, unsigned char *out, const unsigned char *in, int rounds, const void *encT); extern unsigned int _gcry_aes_arm_decrypt_block(const void *keysched_dec, unsigned char *out, const unsigned char *in, int rounds, const void *decT); #endif /*USE_ARM_ASM*/ #ifdef USE_ARM_CE /* ARMv8 Crypto Extension implementations of AES */ extern void _gcry_aes_armv8_ce_setkey(RIJNDAEL_context *ctx, const byte *key); extern void _gcry_aes_armv8_ce_prepare_decryption(RIJNDAEL_context *ctx); extern unsigned int _gcry_aes_armv8_ce_encrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern unsigned int _gcry_aes_armv8_ce_decrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern void _gcry_aes_armv8_ce_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_armv8_ce_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac); extern void _gcry_aes_armv8_ce_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_armv8_ce_ctr32le_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_armv8_ce_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_armv8_ce_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern size_t _gcry_aes_armv8_ce_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern size_t _gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); extern void _gcry_aes_armv8_ce_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); #endif /*USE_ARM_ASM*/ #ifdef USE_PPC_CRYPTO /* PowerPC Crypto implementations of AES */ extern void _gcry_aes_ppc8_setkey(RIJNDAEL_context *ctx, const byte *key); extern void _gcry_aes_ppc8_prepare_decryption(RIJNDAEL_context *ctx); extern unsigned int _gcry_aes_ppc8_encrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern unsigned int _gcry_aes_ppc8_decrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern void _gcry_aes_ppc8_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ppc8_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac); extern void _gcry_aes_ppc8_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ppc8_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ppc8_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern size_t _gcry_aes_ppc8_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern size_t _gcry_aes_ppc8_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); extern void _gcry_aes_ppc8_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); #endif /*USE_PPC_CRYPTO*/ #ifdef USE_PPC_CRYPTO_WITH_PPC9LE /* Power9 little-endian crypto implementations of AES */ extern unsigned int _gcry_aes_ppc9le_encrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern unsigned int _gcry_aes_ppc9le_decrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern void _gcry_aes_ppc9le_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ppc9le_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac); extern void _gcry_aes_ppc9le_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ppc9le_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern void _gcry_aes_ppc9le_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); extern size_t _gcry_aes_ppc9le_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern size_t _gcry_aes_ppc9le_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); extern void _gcry_aes_ppc9le_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); extern size_t _gcry_aes_p10le_gcm_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); #endif /*USE_PPC_CRYPTO_WITH_PPC9LE*/ #ifdef USE_S390X_CRYPTO /* zSeries crypto implementations of AES */ extern int _gcry_aes_s390x_setup_acceleration(RIJNDAEL_context *ctx, unsigned int keylen, unsigned int hwfeatures, cipher_bulk_ops_t *bulk_ops); extern void _gcry_aes_s390x_setkey(RIJNDAEL_context *ctx, const byte *key); extern void _gcry_aes_s390x_prepare_decryption(RIJNDAEL_context *ctx); extern unsigned int _gcry_aes_s390x_encrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); extern unsigned int _gcry_aes_s390x_decrypt(const RIJNDAEL_context *ctx, unsigned char *dst, const unsigned char *src); #endif /*USE_S390X_CRYPTO*/ static unsigned int do_encrypt (const RIJNDAEL_context *ctx, unsigned char *bx, const unsigned char *ax); static unsigned int do_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx, const unsigned char *ax); static void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf, const void *inbuf, size_t nblocks); static void _gcry_aes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_aes_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac); static void _gcry_aes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static size_t _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); static size_t _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); static void _gcry_aes_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); /* All the numbers. */ #include "rijndael-tables.h" /* Function prototypes. */ static const char *selftest(void); static void prepare_decryption(RIJNDAEL_context *ctx); /* Prefetching for encryption/decryption tables. */ static inline void prefetch_table(const volatile byte *tab, size_t len) { size_t i; for (i = 0; len - i >= 8 * 32; i += 8 * 32) { (void)tab[i + 0 * 32]; (void)tab[i + 1 * 32]; (void)tab[i + 2 * 32]; (void)tab[i + 3 * 32]; (void)tab[i + 4 * 32]; (void)tab[i + 5 * 32]; (void)tab[i + 6 * 32]; (void)tab[i + 7 * 32]; } for (; i < len; i += 32) { (void)tab[i]; } (void)tab[len - 1]; } static void prefetch_enc(void) { /* Modify counters to trigger copy-on-write and unsharing if physical pages * of look-up table are shared between processes. Modifying counters also * causes checksums for pages to change and hint same-page merging algorithm * that these pages are frequently changing. */ enc_tables.counter_head++; enc_tables.counter_tail++; /* Prefetch look-up tables to cache. */ prefetch_table((const void *)&enc_tables, sizeof(enc_tables)); } static void prefetch_dec(void) { /* Modify counters to trigger copy-on-write and unsharing if physical pages * of look-up table are shared between processes. Modifying counters also * causes checksums for pages to change and hint same-page merging algorithm * that these pages are frequently changing. */ dec_tables.counter_head++; dec_tables.counter_tail++; /* Prefetch look-up tables to cache. */ prefetch_table((const void *)&dec_tables, sizeof(dec_tables)); } /* Perform the key setup. */ static gcry_err_code_t do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen, cipher_bulk_ops_t *bulk_ops) { static int initialized = 0; static const char *selftest_failed = 0; void (*hw_setkey)(RIJNDAEL_context *ctx, const byte *key) = NULL; int rounds; int i,j, r, t, rconpointer = 0; int KC; unsigned int hwfeatures; /* The on-the-fly self tests are only run in non-fips mode. In fips mode explicit self-tests are required. Actually the on-the-fly self-tests are not fully thread-safe and it might happen that a failed self-test won't get noticed in another thread. FIXME: We might want to have a central registry of succeeded self-tests. */ if (!fips_mode () && !initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("%s\n", selftest_failed ); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if( keylen == 128/8 ) { rounds = 10; KC = 4; } else if ( keylen == 192/8 ) { rounds = 12; KC = 6; } else if ( keylen == 256/8 ) { rounds = 14; KC = 8; } else return GPG_ERR_INV_KEYLEN; ctx->rounds = rounds; hwfeatures = _gcry_get_hw_features (); ctx->decryption_prepared = 0; /* Setup default bulk encryption routines. */ memset (bulk_ops, 0, sizeof(*bulk_ops)); bulk_ops->cfb_enc = _gcry_aes_cfb_enc; bulk_ops->cfb_dec = _gcry_aes_cfb_dec; bulk_ops->cbc_enc = _gcry_aes_cbc_enc; bulk_ops->cbc_dec = _gcry_aes_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_ctr_enc; bulk_ops->ocb_crypt = _gcry_aes_ocb_crypt; bulk_ops->ocb_auth = _gcry_aes_ocb_auth; bulk_ops->xts_crypt = _gcry_aes_xts_crypt; (void)hwfeatures; if (0) { ; } #ifdef USE_AESNI else if (hwfeatures & HWF_INTEL_AESNI) { hw_setkey = _gcry_aes_aesni_do_setkey; ctx->encrypt_fn = _gcry_aes_aesni_encrypt; ctx->decrypt_fn = _gcry_aes_aesni_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_aesni_prepare_decryption; ctx->use_avx = !!(hwfeatures & HWF_INTEL_AVX); ctx->use_avx2 = !!(hwfeatures & HWF_INTEL_AVX2); /* Setup AES-NI bulk encryption routines. */ bulk_ops->cfb_enc = _gcry_aes_aesni_cfb_enc; bulk_ops->cfb_dec = _gcry_aes_aesni_cfb_dec; bulk_ops->cbc_enc = _gcry_aes_aesni_cbc_enc; bulk_ops->cbc_dec = _gcry_aes_aesni_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_aesni_ctr_enc; bulk_ops->ctr32le_enc = _gcry_aes_aesni_ctr32le_enc; bulk_ops->ocb_crypt = _gcry_aes_aesni_ocb_crypt; bulk_ops->ocb_auth = _gcry_aes_aesni_ocb_auth; bulk_ops->xts_crypt = _gcry_aes_aesni_xts_crypt; #ifdef USE_VAES if ((hwfeatures & HWF_INTEL_VAES_VPCLMUL) && (hwfeatures & HWF_INTEL_AVX2)) { /* Setup VAES bulk encryption routines. */ bulk_ops->cfb_dec = _gcry_aes_vaes_cfb_dec; bulk_ops->cbc_dec = _gcry_aes_vaes_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_vaes_ctr_enc; bulk_ops->ctr32le_enc = _gcry_aes_vaes_ctr32le_enc; bulk_ops->ocb_crypt = _gcry_aes_vaes_ocb_crypt; bulk_ops->xts_crypt = _gcry_aes_vaes_xts_crypt; } #endif } #endif #ifdef USE_PADLOCK else if ((hwfeatures & HWF_PADLOCK_AES) && keylen == 128/8) { ctx->encrypt_fn = _gcry_aes_padlock_encrypt; ctx->decrypt_fn = _gcry_aes_padlock_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_padlock_prepare_decryption; memcpy (ctx->padlockkey, key, keylen); } #endif #ifdef USE_SSSE3 else if (hwfeatures & HWF_INTEL_SSSE3) { hw_setkey = _gcry_aes_ssse3_do_setkey; ctx->encrypt_fn = _gcry_aes_ssse3_encrypt; ctx->decrypt_fn = _gcry_aes_ssse3_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_ssse3_prepare_decryption; /* Setup SSSE3 bulk encryption routines. */ bulk_ops->cfb_enc = _gcry_aes_ssse3_cfb_enc; bulk_ops->cfb_dec = _gcry_aes_ssse3_cfb_dec; bulk_ops->cbc_enc = _gcry_aes_ssse3_cbc_enc; bulk_ops->cbc_dec = _gcry_aes_ssse3_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_ssse3_ctr_enc; bulk_ops->ocb_crypt = _gcry_aes_ssse3_ocb_crypt; bulk_ops->ocb_auth = _gcry_aes_ssse3_ocb_auth; } #endif #ifdef USE_ARM_CE else if (hwfeatures & HWF_ARM_AES) { hw_setkey = _gcry_aes_armv8_ce_setkey; ctx->encrypt_fn = _gcry_aes_armv8_ce_encrypt; ctx->decrypt_fn = _gcry_aes_armv8_ce_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_armv8_ce_prepare_decryption; /* Setup ARM-CE bulk encryption routines. */ bulk_ops->cfb_enc = _gcry_aes_armv8_ce_cfb_enc; bulk_ops->cfb_dec = _gcry_aes_armv8_ce_cfb_dec; bulk_ops->cbc_enc = _gcry_aes_armv8_ce_cbc_enc; bulk_ops->cbc_dec = _gcry_aes_armv8_ce_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_armv8_ce_ctr_enc; bulk_ops->ctr32le_enc = _gcry_aes_armv8_ce_ctr32le_enc; bulk_ops->ocb_crypt = _gcry_aes_armv8_ce_ocb_crypt; bulk_ops->ocb_auth = _gcry_aes_armv8_ce_ocb_auth; bulk_ops->xts_crypt = _gcry_aes_armv8_ce_xts_crypt; } #endif #ifdef USE_PPC_CRYPTO_WITH_PPC9LE else if ((hwfeatures & HWF_PPC_VCRYPTO) && (hwfeatures & HWF_PPC_ARCH_3_00)) { hw_setkey = _gcry_aes_ppc8_setkey; ctx->encrypt_fn = _gcry_aes_ppc9le_encrypt; ctx->decrypt_fn = _gcry_aes_ppc9le_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_ppc8_prepare_decryption; /* Setup PPC9LE bulk encryption routines. */ bulk_ops->cfb_enc = _gcry_aes_ppc9le_cfb_enc; bulk_ops->cfb_dec = _gcry_aes_ppc9le_cfb_dec; bulk_ops->cbc_enc = _gcry_aes_ppc9le_cbc_enc; bulk_ops->cbc_dec = _gcry_aes_ppc9le_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_ppc9le_ctr_enc; bulk_ops->ocb_crypt = _gcry_aes_ppc9le_ocb_crypt; bulk_ops->ocb_auth = _gcry_aes_ppc9le_ocb_auth; bulk_ops->xts_crypt = _gcry_aes_ppc9le_xts_crypt; if (hwfeatures & HWF_PPC_ARCH_3_10) /* for P10 */ bulk_ops->gcm_crypt = _gcry_aes_p10le_gcm_crypt; } #endif #ifdef USE_PPC_CRYPTO else if (hwfeatures & HWF_PPC_VCRYPTO) { hw_setkey = _gcry_aes_ppc8_setkey; ctx->encrypt_fn = _gcry_aes_ppc8_encrypt; ctx->decrypt_fn = _gcry_aes_ppc8_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_ppc8_prepare_decryption; /* Setup PPC8 bulk encryption routines. */ bulk_ops->cfb_enc = _gcry_aes_ppc8_cfb_enc; bulk_ops->cfb_dec = _gcry_aes_ppc8_cfb_dec; bulk_ops->cbc_enc = _gcry_aes_ppc8_cbc_enc; bulk_ops->cbc_dec = _gcry_aes_ppc8_cbc_dec; bulk_ops->ctr_enc = _gcry_aes_ppc8_ctr_enc; bulk_ops->ocb_crypt = _gcry_aes_ppc8_ocb_crypt; bulk_ops->ocb_auth = _gcry_aes_ppc8_ocb_auth; bulk_ops->xts_crypt = _gcry_aes_ppc8_xts_crypt; } #endif #ifdef USE_S390X_CRYPTO else if (_gcry_aes_s390x_setup_acceleration (ctx, keylen, hwfeatures, bulk_ops)) { hw_setkey = _gcry_aes_s390x_setkey; ctx->encrypt_fn = _gcry_aes_s390x_encrypt; ctx->decrypt_fn = _gcry_aes_s390x_decrypt; ctx->prefetch_enc_fn = NULL; ctx->prefetch_dec_fn = NULL; ctx->prepare_decryption = _gcry_aes_s390x_prepare_decryption; } #endif else { ctx->encrypt_fn = do_encrypt; ctx->decrypt_fn = do_decrypt; ctx->prefetch_enc_fn = prefetch_enc; ctx->prefetch_dec_fn = prefetch_dec; ctx->prepare_decryption = prepare_decryption; } /* NB: We don't yet support Padlock hardware key generation. */ if (hw_setkey) { hw_setkey (ctx, key); } else { const byte *sbox = ((const byte *)encT) + 1; union { PROPERLY_ALIGNED_TYPE dummy; byte data[MAXKC][4]; u32 data32[MAXKC]; } tkk[2]; #define k tkk[0].data #define k_u32 tkk[0].data32 #define tk tkk[1].data #define tk_u32 tkk[1].data32 #define W (ctx->keyschenc) #define W_u32 (ctx->keyschenc32) prefetch_enc(); for (i = 0; i < keylen; i++) { k[i >> 2][i & 3] = key[i]; } for (j = KC-1; j >= 0; j--) { tk_u32[j] = k_u32[j]; } r = 0; t = 0; /* Copy values into round key array. */ for (j = 0; (j < KC) && (r < rounds + 1); ) { for (; (j < KC) && (t < 4); j++, t++) { W_u32[r][t] = le_bswap32(tk_u32[j]); } if (t == 4) { r++; t = 0; } } while (r < rounds + 1) { /* While not enough round key material calculated calculate new values. */ tk[0][0] ^= sbox[tk[KC-1][1] * 4]; tk[0][1] ^= sbox[tk[KC-1][2] * 4]; tk[0][2] ^= sbox[tk[KC-1][3] * 4]; tk[0][3] ^= sbox[tk[KC-1][0] * 4]; tk[0][0] ^= rcon[rconpointer++]; if (KC != 8) { for (j = 1; j < KC; j++) { tk_u32[j] ^= tk_u32[j-1]; } } else { for (j = 1; j < KC/2; j++) { tk_u32[j] ^= tk_u32[j-1]; } tk[KC/2][0] ^= sbox[tk[KC/2 - 1][0] * 4]; tk[KC/2][1] ^= sbox[tk[KC/2 - 1][1] * 4]; tk[KC/2][2] ^= sbox[tk[KC/2 - 1][2] * 4]; tk[KC/2][3] ^= sbox[tk[KC/2 - 1][3] * 4]; for (j = KC/2 + 1; j < KC; j++) { tk_u32[j] ^= tk_u32[j-1]; } } /* Copy values into round key array. */ for (j = 0; (j < KC) && (r < rounds + 1); ) { for (; (j < KC) && (t < 4); j++, t++) { W_u32[r][t] = le_bswap32(tk_u32[j]); } if (t == 4) { r++; t = 0; } } } #undef W #undef tk #undef k #undef W_u32 #undef tk_u32 #undef k_u32 wipememory(&tkk, sizeof(tkk)); } return 0; } static gcry_err_code_t rijndael_setkey (void *context, const byte *key, const unsigned keylen, cipher_bulk_ops_t *bulk_ops) { RIJNDAEL_context *ctx = context; return do_setkey (ctx, key, keylen, bulk_ops); } /* Make a decryption key from an encryption key. */ static void prepare_decryption( RIJNDAEL_context *ctx ) { const byte *sbox = ((const byte *)encT) + 1; int r; prefetch_enc(); prefetch_dec(); ctx->keyschdec32[0][0] = ctx->keyschenc32[0][0]; ctx->keyschdec32[0][1] = ctx->keyschenc32[0][1]; ctx->keyschdec32[0][2] = ctx->keyschenc32[0][2]; ctx->keyschdec32[0][3] = ctx->keyschenc32[0][3]; for (r = 1; r < ctx->rounds; r++) { u32 *wi = ctx->keyschenc32[r]; u32 *wo = ctx->keyschdec32[r]; u32 wt; wt = wi[0]; wo[0] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0) ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1) ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2) ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3); wt = wi[1]; wo[1] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0) ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1) ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2) ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3); wt = wi[2]; wo[2] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0) ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1) ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2) ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3); wt = wi[3]; wo[3] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0) ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1) ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2) ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3); } ctx->keyschdec32[r][0] = ctx->keyschenc32[r][0]; ctx->keyschdec32[r][1] = ctx->keyschenc32[r][1]; ctx->keyschdec32[r][2] = ctx->keyschenc32[r][2]; ctx->keyschdec32[r][3] = ctx->keyschenc32[r][3]; } #if !defined(USE_ARM_ASM) && !defined(USE_AMD64_ASM) /* Encrypt one block. A and B may be the same. */ static unsigned int do_encrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b, const unsigned char *a) { #define rk (ctx->keyschenc32) const byte *sbox = ((const byte *)encT) + 1; int rounds = ctx->rounds; int r; u32 sa[4]; u32 sb[4]; sb[0] = buf_get_le32(a + 0); sb[1] = buf_get_le32(a + 4); sb[2] = buf_get_le32(a + 8); sb[3] = buf_get_le32(a + 12); sa[0] = sb[0] ^ rk[0][0]; sa[1] = sb[1] ^ rk[0][1]; sa[2] = sb[2] ^ rk[0][2]; sa[3] = sb[3] ^ rk[0][3]; sb[0] = rol(encT[(byte)(sa[0] >> (0 * 8))], (0 * 8)); sb[3] = rol(encT[(byte)(sa[0] >> (1 * 8))], (1 * 8)); sb[2] = rol(encT[(byte)(sa[0] >> (2 * 8))], (2 * 8)); sb[1] = rol(encT[(byte)(sa[0] >> (3 * 8))], (3 * 8)); sa[0] = rk[1][0] ^ sb[0]; sb[1] ^= rol(encT[(byte)(sa[1] >> (0 * 8))], (0 * 8)); sa[0] ^= rol(encT[(byte)(sa[1] >> (1 * 8))], (1 * 8)); sb[3] ^= rol(encT[(byte)(sa[1] >> (2 * 8))], (2 * 8)); sb[2] ^= rol(encT[(byte)(sa[1] >> (3 * 8))], (3 * 8)); sa[1] = rk[1][1] ^ sb[1]; sb[2] ^= rol(encT[(byte)(sa[2] >> (0 * 8))], (0 * 8)); sa[1] ^= rol(encT[(byte)(sa[2] >> (1 * 8))], (1 * 8)); sa[0] ^= rol(encT[(byte)(sa[2] >> (2 * 8))], (2 * 8)); sb[3] ^= rol(encT[(byte)(sa[2] >> (3 * 8))], (3 * 8)); sa[2] = rk[1][2] ^ sb[2]; sb[3] ^= rol(encT[(byte)(sa[3] >> (0 * 8))], (0 * 8)); sa[2] ^= rol(encT[(byte)(sa[3] >> (1 * 8))], (1 * 8)); sa[1] ^= rol(encT[(byte)(sa[3] >> (2 * 8))], (2 * 8)); sa[0] ^= rol(encT[(byte)(sa[3] >> (3 * 8))], (3 * 8)); sa[3] = rk[1][3] ^ sb[3]; for (r = 2; r < rounds; r++) { sb[0] = rol(encT[(byte)(sa[0] >> (0 * 8))], (0 * 8)); sb[3] = rol(encT[(byte)(sa[0] >> (1 * 8))], (1 * 8)); sb[2] = rol(encT[(byte)(sa[0] >> (2 * 8))], (2 * 8)); sb[1] = rol(encT[(byte)(sa[0] >> (3 * 8))], (3 * 8)); sa[0] = rk[r][0] ^ sb[0]; sb[1] ^= rol(encT[(byte)(sa[1] >> (0 * 8))], (0 * 8)); sa[0] ^= rol(encT[(byte)(sa[1] >> (1 * 8))], (1 * 8)); sb[3] ^= rol(encT[(byte)(sa[1] >> (2 * 8))], (2 * 8)); sb[2] ^= rol(encT[(byte)(sa[1] >> (3 * 8))], (3 * 8)); sa[1] = rk[r][1] ^ sb[1]; sb[2] ^= rol(encT[(byte)(sa[2] >> (0 * 8))], (0 * 8)); sa[1] ^= rol(encT[(byte)(sa[2] >> (1 * 8))], (1 * 8)); sa[0] ^= rol(encT[(byte)(sa[2] >> (2 * 8))], (2 * 8)); sb[3] ^= rol(encT[(byte)(sa[2] >> (3 * 8))], (3 * 8)); sa[2] = rk[r][2] ^ sb[2]; sb[3] ^= rol(encT[(byte)(sa[3] >> (0 * 8))], (0 * 8)); sa[2] ^= rol(encT[(byte)(sa[3] >> (1 * 8))], (1 * 8)); sa[1] ^= rol(encT[(byte)(sa[3] >> (2 * 8))], (2 * 8)); sa[0] ^= rol(encT[(byte)(sa[3] >> (3 * 8))], (3 * 8)); sa[3] = rk[r][3] ^ sb[3]; r++; sb[0] = rol(encT[(byte)(sa[0] >> (0 * 8))], (0 * 8)); sb[3] = rol(encT[(byte)(sa[0] >> (1 * 8))], (1 * 8)); sb[2] = rol(encT[(byte)(sa[0] >> (2 * 8))], (2 * 8)); sb[1] = rol(encT[(byte)(sa[0] >> (3 * 8))], (3 * 8)); sa[0] = rk[r][0] ^ sb[0]; sb[1] ^= rol(encT[(byte)(sa[1] >> (0 * 8))], (0 * 8)); sa[0] ^= rol(encT[(byte)(sa[1] >> (1 * 8))], (1 * 8)); sb[3] ^= rol(encT[(byte)(sa[1] >> (2 * 8))], (2 * 8)); sb[2] ^= rol(encT[(byte)(sa[1] >> (3 * 8))], (3 * 8)); sa[1] = rk[r][1] ^ sb[1]; sb[2] ^= rol(encT[(byte)(sa[2] >> (0 * 8))], (0 * 8)); sa[1] ^= rol(encT[(byte)(sa[2] >> (1 * 8))], (1 * 8)); sa[0] ^= rol(encT[(byte)(sa[2] >> (2 * 8))], (2 * 8)); sb[3] ^= rol(encT[(byte)(sa[2] >> (3 * 8))], (3 * 8)); sa[2] = rk[r][2] ^ sb[2]; sb[3] ^= rol(encT[(byte)(sa[3] >> (0 * 8))], (0 * 8)); sa[2] ^= rol(encT[(byte)(sa[3] >> (1 * 8))], (1 * 8)); sa[1] ^= rol(encT[(byte)(sa[3] >> (2 * 8))], (2 * 8)); sa[0] ^= rol(encT[(byte)(sa[3] >> (3 * 8))], (3 * 8)); sa[3] = rk[r][3] ^ sb[3]; } /* Last round is special. */ sb[0] = ((u32)sbox[(byte)(sa[0] >> (0 * 8)) * 4]) << (0 * 8); sb[3] = ((u32)sbox[(byte)(sa[0] >> (1 * 8)) * 4]) << (1 * 8); sb[2] = ((u32)sbox[(byte)(sa[0] >> (2 * 8)) * 4]) << (2 * 8); sb[1] = ((u32)sbox[(byte)(sa[0] >> (3 * 8)) * 4]) << (3 * 8); sa[0] = rk[r][0] ^ sb[0]; sb[1] ^= ((u32)sbox[(byte)(sa[1] >> (0 * 8)) * 4]) << (0 * 8); sa[0] ^= ((u32)sbox[(byte)(sa[1] >> (1 * 8)) * 4]) << (1 * 8); sb[3] ^= ((u32)sbox[(byte)(sa[1] >> (2 * 8)) * 4]) << (2 * 8); sb[2] ^= ((u32)sbox[(byte)(sa[1] >> (3 * 8)) * 4]) << (3 * 8); sa[1] = rk[r][1] ^ sb[1]; sb[2] ^= ((u32)sbox[(byte)(sa[2] >> (0 * 8)) * 4]) << (0 * 8); sa[1] ^= ((u32)sbox[(byte)(sa[2] >> (1 * 8)) * 4]) << (1 * 8); sa[0] ^= ((u32)sbox[(byte)(sa[2] >> (2 * 8)) * 4]) << (2 * 8); sb[3] ^= ((u32)sbox[(byte)(sa[2] >> (3 * 8)) * 4]) << (3 * 8); sa[2] = rk[r][2] ^ sb[2]; sb[3] ^= ((u32)sbox[(byte)(sa[3] >> (0 * 8)) * 4]) << (0 * 8); sa[2] ^= ((u32)sbox[(byte)(sa[3] >> (1 * 8)) * 4]) << (1 * 8); sa[1] ^= ((u32)sbox[(byte)(sa[3] >> (2 * 8)) * 4]) << (2 * 8); sa[0] ^= ((u32)sbox[(byte)(sa[3] >> (3 * 8)) * 4]) << (3 * 8); sa[3] = rk[r][3] ^ sb[3]; buf_put_le32(b + 0, sa[0]); buf_put_le32(b + 4, sa[1]); buf_put_le32(b + 8, sa[2]); buf_put_le32(b + 12, sa[3]); #undef rk return (56 + 2*sizeof(int)); } #endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/ static unsigned int do_encrypt (const RIJNDAEL_context *ctx, unsigned char *bx, const unsigned char *ax) { #ifdef USE_AMD64_ASM return _gcry_aes_amd64_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds, enc_tables.T); #elif defined(USE_ARM_ASM) return _gcry_aes_arm_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds, enc_tables.T); #else return do_encrypt_fn (ctx, bx, ax); #endif /* !USE_ARM_ASM && !USE_AMD64_ASM*/ } static unsigned int rijndael_encrypt (void *context, byte *b, const byte *a) { RIJNDAEL_context *ctx = context; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); return ctx->encrypt_fn (ctx, b, a); } /* Bulk encryption of complete blocks in CFB mode. Caller needs to make sure that IV is aligned on an unsigned long boundary. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned int burn_depth = 0; rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); for ( ;nblocks; nblocks-- ) { /* Encrypt the IV. */ burn_depth = encrypt_fn (ctx, iv, iv); /* XOR the input with the IV and store input into IV. */ cipher_block_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; } if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); } /* Bulk encryption of complete blocks in CBC mode. Caller needs to make sure that IV is aligned on an unsigned long boundary. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_aes_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int cbc_mac) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char *last_iv; unsigned int burn_depth = 0; rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); last_iv = iv; for ( ;nblocks; nblocks-- ) { cipher_block_xor(outbuf, inbuf, last_iv, BLOCKSIZE); burn_depth = encrypt_fn (ctx, outbuf, outbuf); last_iv = outbuf; inbuf += BLOCKSIZE; if (!cbc_mac) outbuf += BLOCKSIZE; } if (last_iv != iv) cipher_block_cpy (iv, last_iv, BLOCKSIZE); if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); } /* Bulk encryption of complete blocks in CTR mode. Caller needs to make sure that CTR is aligned on a 16 byte boundary if AESNI; the minimum alignment is for an u32. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size BLOCKSIZE. */ static void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned int burn_depth = 0; union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } tmp; rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ burn_depth = encrypt_fn (ctx, tmp.x1, ctr); /* XOR the input with the encrypted counter and store in output. */ cipher_block_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; /* Increment the counter. */ cipher_block_add(ctr, 1, BLOCKSIZE); } wipememory(&tmp, sizeof(tmp)); if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); } #if !defined(USE_ARM_ASM) && !defined(USE_AMD64_ASM) /* Decrypt one block. A and B may be the same. */ static unsigned int do_decrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b, const unsigned char *a) { #define rk (ctx->keyschdec32) int rounds = ctx->rounds; int r; u32 sa[4]; u32 sb[4]; sb[0] = buf_get_le32(a + 0); sb[1] = buf_get_le32(a + 4); sb[2] = buf_get_le32(a + 8); sb[3] = buf_get_le32(a + 12); sa[0] = sb[0] ^ rk[rounds][0]; sa[1] = sb[1] ^ rk[rounds][1]; sa[2] = sb[2] ^ rk[rounds][2]; sa[3] = sb[3] ^ rk[rounds][3]; for (r = rounds - 1; r > 1; r--) { sb[0] = rol(decT[(byte)(sa[0] >> (0 * 8))], (0 * 8)); sb[1] = rol(decT[(byte)(sa[0] >> (1 * 8))], (1 * 8)); sb[2] = rol(decT[(byte)(sa[0] >> (2 * 8))], (2 * 8)); sb[3] = rol(decT[(byte)(sa[0] >> (3 * 8))], (3 * 8)); sa[0] = rk[r][0] ^ sb[0]; sb[1] ^= rol(decT[(byte)(sa[1] >> (0 * 8))], (0 * 8)); sb[2] ^= rol(decT[(byte)(sa[1] >> (1 * 8))], (1 * 8)); sb[3] ^= rol(decT[(byte)(sa[1] >> (2 * 8))], (2 * 8)); sa[0] ^= rol(decT[(byte)(sa[1] >> (3 * 8))], (3 * 8)); sa[1] = rk[r][1] ^ sb[1]; sb[2] ^= rol(decT[(byte)(sa[2] >> (0 * 8))], (0 * 8)); sb[3] ^= rol(decT[(byte)(sa[2] >> (1 * 8))], (1 * 8)); sa[0] ^= rol(decT[(byte)(sa[2] >> (2 * 8))], (2 * 8)); sa[1] ^= rol(decT[(byte)(sa[2] >> (3 * 8))], (3 * 8)); sa[2] = rk[r][2] ^ sb[2]; sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8)); sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8)); sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8)); sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8)); sa[3] = rk[r][3] ^ sb[3]; r--; sb[0] = rol(decT[(byte)(sa[0] >> (0 * 8))], (0 * 8)); sb[1] = rol(decT[(byte)(sa[0] >> (1 * 8))], (1 * 8)); sb[2] = rol(decT[(byte)(sa[0] >> (2 * 8))], (2 * 8)); sb[3] = rol(decT[(byte)(sa[0] >> (3 * 8))], (3 * 8)); sa[0] = rk[r][0] ^ sb[0]; sb[1] ^= rol(decT[(byte)(sa[1] >> (0 * 8))], (0 * 8)); sb[2] ^= rol(decT[(byte)(sa[1] >> (1 * 8))], (1 * 8)); sb[3] ^= rol(decT[(byte)(sa[1] >> (2 * 8))], (2 * 8)); sa[0] ^= rol(decT[(byte)(sa[1] >> (3 * 8))], (3 * 8)); sa[1] = rk[r][1] ^ sb[1]; sb[2] ^= rol(decT[(byte)(sa[2] >> (0 * 8))], (0 * 8)); sb[3] ^= rol(decT[(byte)(sa[2] >> (1 * 8))], (1 * 8)); sa[0] ^= rol(decT[(byte)(sa[2] >> (2 * 8))], (2 * 8)); sa[1] ^= rol(decT[(byte)(sa[2] >> (3 * 8))], (3 * 8)); sa[2] = rk[r][2] ^ sb[2]; sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8)); sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8)); sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8)); sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8)); sa[3] = rk[r][3] ^ sb[3]; } sb[0] = rol(decT[(byte)(sa[0] >> (0 * 8))], (0 * 8)); sb[1] = rol(decT[(byte)(sa[0] >> (1 * 8))], (1 * 8)); sb[2] = rol(decT[(byte)(sa[0] >> (2 * 8))], (2 * 8)); sb[3] = rol(decT[(byte)(sa[0] >> (3 * 8))], (3 * 8)); sa[0] = rk[1][0] ^ sb[0]; sb[1] ^= rol(decT[(byte)(sa[1] >> (0 * 8))], (0 * 8)); sb[2] ^= rol(decT[(byte)(sa[1] >> (1 * 8))], (1 * 8)); sb[3] ^= rol(decT[(byte)(sa[1] >> (2 * 8))], (2 * 8)); sa[0] ^= rol(decT[(byte)(sa[1] >> (3 * 8))], (3 * 8)); sa[1] = rk[1][1] ^ sb[1]; sb[2] ^= rol(decT[(byte)(sa[2] >> (0 * 8))], (0 * 8)); sb[3] ^= rol(decT[(byte)(sa[2] >> (1 * 8))], (1 * 8)); sa[0] ^= rol(decT[(byte)(sa[2] >> (2 * 8))], (2 * 8)); sa[1] ^= rol(decT[(byte)(sa[2] >> (3 * 8))], (3 * 8)); sa[2] = rk[1][2] ^ sb[2]; sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8)); sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8)); sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8)); sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8)); sa[3] = rk[1][3] ^ sb[3]; /* Last round is special. */ sb[0] = (u32)inv_sbox[(byte)(sa[0] >> (0 * 8))] << (0 * 8); sb[1] = (u32)inv_sbox[(byte)(sa[0] >> (1 * 8))] << (1 * 8); sb[2] = (u32)inv_sbox[(byte)(sa[0] >> (2 * 8))] << (2 * 8); sb[3] = (u32)inv_sbox[(byte)(sa[0] >> (3 * 8))] << (3 * 8); sa[0] = sb[0] ^ rk[0][0]; sb[1] ^= (u32)inv_sbox[(byte)(sa[1] >> (0 * 8))] << (0 * 8); sb[2] ^= (u32)inv_sbox[(byte)(sa[1] >> (1 * 8))] << (1 * 8); sb[3] ^= (u32)inv_sbox[(byte)(sa[1] >> (2 * 8))] << (2 * 8); sa[0] ^= (u32)inv_sbox[(byte)(sa[1] >> (3 * 8))] << (3 * 8); sa[1] = sb[1] ^ rk[0][1]; sb[2] ^= (u32)inv_sbox[(byte)(sa[2] >> (0 * 8))] << (0 * 8); sb[3] ^= (u32)inv_sbox[(byte)(sa[2] >> (1 * 8))] << (1 * 8); sa[0] ^= (u32)inv_sbox[(byte)(sa[2] >> (2 * 8))] << (2 * 8); sa[1] ^= (u32)inv_sbox[(byte)(sa[2] >> (3 * 8))] << (3 * 8); sa[2] = sb[2] ^ rk[0][2]; sb[3] ^= (u32)inv_sbox[(byte)(sa[3] >> (0 * 8))] << (0 * 8); sa[0] ^= (u32)inv_sbox[(byte)(sa[3] >> (1 * 8))] << (1 * 8); sa[1] ^= (u32)inv_sbox[(byte)(sa[3] >> (2 * 8))] << (2 * 8); sa[2] ^= (u32)inv_sbox[(byte)(sa[3] >> (3 * 8))] << (3 * 8); sa[3] = sb[3] ^ rk[0][3]; buf_put_le32(b + 0, sa[0]); buf_put_le32(b + 4, sa[1]); buf_put_le32(b + 8, sa[2]); buf_put_le32(b + 12, sa[3]); #undef rk return (56+2*sizeof(int)); } #endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/ /* Decrypt one block. AX and BX may be the same. */ static unsigned int do_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx, const unsigned char *ax) { #ifdef USE_AMD64_ASM return _gcry_aes_amd64_decrypt_block(ctx->keyschdec, bx, ax, ctx->rounds, dec_tables.T); #elif defined(USE_ARM_ASM) return _gcry_aes_arm_decrypt_block(ctx->keyschdec, bx, ax, ctx->rounds, dec_tables.T); #else return do_decrypt_fn (ctx, bx, ax); #endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/ } static inline void check_decryption_preparation (RIJNDAEL_context *ctx) { if ( !ctx->decryption_prepared ) { ctx->prepare_decryption ( ctx ); ctx->decryption_prepared = 1; } } static unsigned int rijndael_decrypt (void *context, byte *b, const byte *a) { RIJNDAEL_context *ctx = context; check_decryption_preparation (ctx); if (ctx->prefetch_dec_fn) ctx->prefetch_dec_fn(); return ctx->decrypt_fn (ctx, b, a); } /* Bulk decryption of complete blocks in CFB mode. Caller needs to make sure that IV is aligned on an unsigned long boundary. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_aes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned int burn_depth = 0; rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); for ( ;nblocks; nblocks-- ) { burn_depth = encrypt_fn (ctx, iv, iv); cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; } if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); } /* Bulk decryption of complete blocks in CBC mode. Caller needs to make sure that IV is aligned on an unsigned long boundary. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_aes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned int burn_depth = 0; unsigned char savebuf[BLOCKSIZE] ATTR_ALIGNED_16; rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn; check_decryption_preparation (ctx); if (ctx->prefetch_dec_fn) ctx->prefetch_dec_fn(); for ( ;nblocks; nblocks-- ) { /* INBUF is needed later and it may be identical to OUTBUF, so store the intermediate result to SAVEBUF. */ burn_depth = decrypt_fn (ctx, savebuf, inbuf); cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; } wipememory(savebuf, sizeof(savebuf)); if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); } /* Bulk encryption/decryption of complete blocks in OCB mode. */ static size_t _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt) { RIJNDAEL_context *ctx = (void *)&c->context.c; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned int burn_depth = 0; if (encrypt) { union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp; rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); for ( ;nblocks; nblocks-- ) { u64 i = ++c->u_mode.ocb.data_nblocks; const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE); cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE); /* Checksum_i = Checksum_{i-1} xor P_i */ cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1); cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; } } else { union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp; rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn; check_decryption_preparation (ctx); if (ctx->prefetch_dec_fn) ctx->prefetch_dec_fn(); for ( ;nblocks; nblocks-- ) { u64 i = ++c->u_mode.ocb.data_nblocks; const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE); cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); burn_depth = decrypt_fn (ctx, l_tmp.x1, l_tmp.x1); cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); /* Checksum_i = Checksum_{i-1} xor P_i */ cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; } } if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); return 0; } /* Bulk authentication of complete blocks in OCB mode. */ static size_t _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks) { RIJNDAEL_context *ctx = (void *)&c->context.c; const unsigned char *abuf = abuf_arg; unsigned int burn_depth = 0; union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp; rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn; if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); for ( ;nblocks; nblocks-- ) { u64 i = ++c->u_mode.ocb.aad_nblocks; const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ cipher_block_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf, BLOCKSIZE); burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1); cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE); abuf += BLOCKSIZE; } wipememory(&l_tmp, sizeof(l_tmp)); if (burn_depth) _gcry_burn_stack (burn_depth + 4 * sizeof(void *)); return 0; } /* Bulk encryption/decryption of complete blocks in XTS mode. */ static void _gcry_aes_xts_crypt (void *context, unsigned char *tweak, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned int burn_depth = 0; rijndael_cryptfn_t crypt_fn; u64 tweak_lo, tweak_hi, tweak_next_lo, tweak_next_hi, tmp_lo, tmp_hi, carry; if (encrypt) { if (ctx->prefetch_enc_fn) ctx->prefetch_enc_fn(); crypt_fn = ctx->encrypt_fn; } else { check_decryption_preparation (ctx); if (ctx->prefetch_dec_fn) ctx->prefetch_dec_fn(); crypt_fn = ctx->decrypt_fn; } tweak_next_lo = buf_get_le64 (tweak + 0); tweak_next_hi = buf_get_le64 (tweak + 8); while (nblocks) { tweak_lo = tweak_next_lo; tweak_hi = tweak_next_hi; /* Xor-Encrypt/Decrypt-Xor block. */ tmp_lo = buf_get_le64 (inbuf + 0) ^ tweak_lo; tmp_hi = buf_get_le64 (inbuf + 8) ^ tweak_hi; buf_put_le64 (outbuf + 0, tmp_lo); buf_put_le64 (outbuf + 8, tmp_hi); /* Generate next tweak. */ carry = -(tweak_next_hi >> 63) & 0x87; tweak_next_hi = (tweak_next_hi << 1) + (tweak_next_lo >> 63); tweak_next_lo = (tweak_next_lo << 1) ^ carry; burn_depth = crypt_fn (ctx, outbuf, outbuf); buf_put_le64 (outbuf + 0, buf_get_le64 (outbuf + 0) ^ tweak_lo); buf_put_le64 (outbuf + 8, buf_get_le64 (outbuf + 8) ^ tweak_hi); outbuf += GCRY_XTS_BLOCK_LEN; inbuf += GCRY_XTS_BLOCK_LEN; nblocks--; } buf_put_le64 (tweak + 0, tweak_next_lo); buf_put_le64 (tweak + 8, tweak_next_hi); if (burn_depth) _gcry_burn_stack (burn_depth + 5 * sizeof(void *)); } /* Run the self-tests for AES 128. Returns NULL on success. */ static const char* selftest_basic_128 (void) { RIJNDAEL_context *ctx; unsigned char *ctxmem; unsigned char scratch[16]; cipher_bulk_ops_t bulk_ops; /* The test vectors are from the AES supplied ones; more or less randomly taken from ecb_tbl.txt (I=42,81,14) */ #if 1 static const unsigned char plaintext_128[16] = { 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33, 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A }; static const unsigned char key_128[16] = { 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0, 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA }; static const unsigned char ciphertext_128[16] = { 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2, 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD }; #else /* Test vectors from fips-197, appendix C. */ # warning debug test vectors in use static const unsigned char plaintext_128[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, 0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; static const unsigned char key_128[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f /* 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, */ /* 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c */ }; static const unsigned char ciphertext_128[16] = { 0x69,0xc4,0xe0,0xd8,0x6a,0x7b,0x04,0x30, 0xd8,0xcd,0xb7,0x80,0x70,0xb4,0xc5,0x5a }; #endif /* Because gcc/ld can only align the CTX struct on 8 bytes on the stack, we need to allocate that context on the heap. */ ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem); if (!ctx) return "failed to allocate memory"; rijndael_setkey (ctx, key_128, sizeof (key_128), &bulk_ops); rijndael_encrypt (ctx, scratch, plaintext_128); if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128))) { xfree (ctxmem); return "AES-128 test encryption failed."; } rijndael_decrypt (ctx, scratch, scratch); xfree (ctxmem); if (memcmp (scratch, plaintext_128, sizeof (plaintext_128))) return "AES-128 test decryption failed."; return NULL; } /* Run the self-tests for AES 192. Returns NULL on success. */ static const char* selftest_basic_192 (void) { RIJNDAEL_context *ctx; unsigned char *ctxmem; unsigned char scratch[16]; cipher_bulk_ops_t bulk_ops; static unsigned char plaintext_192[16] = { 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4, 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72 }; static unsigned char key_192[24] = { 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C, 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16, 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20 }; static const unsigned char ciphertext_192[16] = { 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC, 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA }; ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem); if (!ctx) return "failed to allocate memory"; rijndael_setkey (ctx, key_192, sizeof(key_192), &bulk_ops); rijndael_encrypt (ctx, scratch, plaintext_192); if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192))) { xfree (ctxmem); return "AES-192 test encryption failed."; } rijndael_decrypt (ctx, scratch, scratch); xfree (ctxmem); if (memcmp (scratch, plaintext_192, sizeof (plaintext_192))) return "AES-192 test decryption failed."; return NULL; } /* Run the self-tests for AES 256. Returns NULL on success. */ static const char* selftest_basic_256 (void) { RIJNDAEL_context *ctx; unsigned char *ctxmem; unsigned char scratch[16]; cipher_bulk_ops_t bulk_ops; static unsigned char plaintext_256[16] = { 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 }; static unsigned char key_256[32] = { 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10, 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A, 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24, 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E }; static const unsigned char ciphertext_256[16] = { 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71, 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3 }; ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem); if (!ctx) return "failed to allocate memory"; rijndael_setkey (ctx, key_256, sizeof(key_256), &bulk_ops); rijndael_encrypt (ctx, scratch, plaintext_256); if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) { xfree (ctxmem); return "AES-256 test encryption failed."; } rijndael_decrypt (ctx, scratch, scratch); xfree (ctxmem); if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) return "AES-256 test decryption failed."; return NULL; } /* Run the self-tests for AES-CTR-128, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char* selftest_ctr_128 (void) { #ifdef USE_VAES const int nblocks = 16+1; #else const int nblocks = 8+1; #endif const int blocksize = BLOCKSIZE; const int context_size = sizeof(RIJNDAEL_context); return _gcry_selftest_helper_ctr("AES", &rijndael_setkey, &rijndael_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for AES-CBC-128, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cbc_128 (void) { #ifdef USE_VAES const int nblocks = 16+2; #else const int nblocks = 8+2; #endif const int blocksize = BLOCKSIZE; const int context_size = sizeof(RIJNDAEL_context); return _gcry_selftest_helper_cbc("AES", &rijndael_setkey, &rijndael_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for AES-CFB-128, tests bulk CFB decryption. Returns NULL on success. */ static const char* selftest_cfb_128 (void) { #ifdef USE_VAES const int nblocks = 16+2; #else const int nblocks = 8+2; #endif const int blocksize = BLOCKSIZE; const int context_size = sizeof(RIJNDAEL_context); return _gcry_selftest_helper_cfb("AES", &rijndael_setkey, &rijndael_encrypt, nblocks, blocksize, context_size); } /* Run all the self-tests and return NULL on success. This function is used for the on-the-fly self-tests. */ static const char * selftest (void) { const char *r; if ( (r = selftest_basic_128 ()) || (r = selftest_basic_192 ()) || (r = selftest_basic_256 ()) ) return r; if ( (r = selftest_ctr_128 ()) ) return r; if ( (r = selftest_cbc_128 ()) ) return r; if ( (r = selftest_cfb_128 ()) ) return r; return r; } /* SP800-38a.pdf for AES-128. */ static const char * selftest_fips_128_38a (int requested_mode) { static const struct tv { int mode; const unsigned char key[16]; const unsigned char iv[16]; struct { const unsigned char input[16]; const unsigned char output[16]; } data[4]; } tv[2] = { { GCRY_CIPHER_MODE_CFB, /* F.3.13, CFB128-AES128 */ { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } }, { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 }, { 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b } }, { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef }, { 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf } }, { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, { 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 } } } }, { GCRY_CIPHER_MODE_OFB, { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } }, { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 }, { 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25 } }, { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef }, { 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc } }, { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, { 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e } }, } } }; unsigned char scratch[16]; gpg_error_t err; int tvi, idx; gcry_cipher_hd_t hdenc = NULL; gcry_cipher_hd_t hddec = NULL; #define Fail(a) do { \ _gcry_cipher_close (hdenc); \ _gcry_cipher_close (hddec); \ return a; \ } while (0) gcry_assert (sizeof tv[0].data[0].input == sizeof scratch); gcry_assert (sizeof tv[0].data[0].output == sizeof scratch); for (tvi=0; tvi < DIM (tv); tvi++) if (tv[tvi].mode == requested_mode) break; if (tvi == DIM (tv)) Fail ("no test data for this mode"); err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0); if (err) Fail ("open"); err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0); if (err) Fail ("open"); err = _gcry_cipher_setkey (hdenc, tv[tvi].key, sizeof tv[tvi].key); if (!err) err = _gcry_cipher_setkey (hddec, tv[tvi].key, sizeof tv[tvi].key); if (err) Fail ("set key"); err = _gcry_cipher_setiv (hdenc, tv[tvi].iv, sizeof tv[tvi].iv); if (!err) err = _gcry_cipher_setiv (hddec, tv[tvi].iv, sizeof tv[tvi].iv); if (err) Fail ("set IV"); for (idx=0; idx < DIM (tv[tvi].data); idx++) { err = _gcry_cipher_encrypt (hdenc, scratch, sizeof scratch, tv[tvi].data[idx].input, sizeof tv[tvi].data[idx].input); if (err) Fail ("encrypt command"); if (memcmp (scratch, tv[tvi].data[idx].output, sizeof scratch)) Fail ("encrypt mismatch"); err = _gcry_cipher_decrypt (hddec, scratch, sizeof scratch, tv[tvi].data[idx].output, sizeof tv[tvi].data[idx].output); if (err) Fail ("decrypt command"); if (memcmp (scratch, tv[tvi].data[idx].input, sizeof scratch)) Fail ("decrypt mismatch"); } #undef Fail _gcry_cipher_close (hdenc); _gcry_cipher_close (hddec); return NULL; } /* Complete selftest for AES-128 with all modes and driver code. */ static gpg_err_code_t selftest_fips_128 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "low-level"; errtxt = selftest_basic_128 (); if (errtxt) goto failed; if (extended) { what = "cfb"; errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_CFB); if (errtxt) goto failed; what = "ofb"; errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_OFB); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("cipher", GCRY_CIPHER_AES128, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Complete selftest for AES-192. */ static gpg_err_code_t selftest_fips_192 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; (void)extended; /* No extended tests available. */ what = "low-level"; errtxt = selftest_basic_192 (); if (errtxt) goto failed; return 0; /* Succeeded. */ failed: if (report) report ("cipher", GCRY_CIPHER_AES192, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Complete selftest for AES-256. */ static gpg_err_code_t selftest_fips_256 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; (void)extended; /* No extended tests available. */ what = "low-level"; errtxt = selftest_basic_256 (); if (errtxt) goto failed; return 0; /* Succeeded. */ failed: if (report) report ("cipher", GCRY_CIPHER_AES256, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_CIPHER_AES128: ec = selftest_fips_128 (extended, report); break; case GCRY_CIPHER_AES192: ec = selftest_fips_192 (extended, report); break; case GCRY_CIPHER_AES256: ec = selftest_fips_256 (extended, report); break; default: ec = GPG_ERR_CIPHER_ALGO; break; } return ec; } static const char *rijndael_names[] = { "RIJNDAEL", "AES128", "AES-128", NULL }; -static gcry_cipher_oid_spec_t rijndael_oids[] = +static const gcry_cipher_oid_spec_t rijndael_oids[] = { { "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB }, { "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC }, { "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB }, { "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB }, { "2.16.840.1.101.3.4.1.6", GCRY_CIPHER_MODE_GCM }, { "2.16.840.1.101.3.4.1.7", GCRY_CIPHER_MODE_CCM }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_aes = { GCRY_CIPHER_AES, {0, 1}, "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context), rijndael_setkey, rijndael_encrypt, rijndael_decrypt, NULL, NULL, run_selftests }; static const char *rijndael192_names[] = { "RIJNDAEL192", "AES-192", NULL }; -static gcry_cipher_oid_spec_t rijndael192_oids[] = +static const gcry_cipher_oid_spec_t rijndael192_oids[] = { { "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB }, { "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC }, { "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB }, { "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB }, { "2.16.840.1.101.3.4.1.26", GCRY_CIPHER_MODE_GCM }, { "2.16.840.1.101.3.4.1.27", GCRY_CIPHER_MODE_CCM }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_aes192 = { GCRY_CIPHER_AES192, {0, 1}, "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context), rijndael_setkey, rijndael_encrypt, rijndael_decrypt, NULL, NULL, run_selftests }; static const char *rijndael256_names[] = { "RIJNDAEL256", "AES-256", NULL }; -static gcry_cipher_oid_spec_t rijndael256_oids[] = +static const gcry_cipher_oid_spec_t rijndael256_oids[] = { { "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB }, { "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC }, { "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB }, { "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB }, { "2.16.840.1.101.3.4.1.46", GCRY_CIPHER_MODE_GCM }, { "2.16.840.1.101.3.4.1.47", GCRY_CIPHER_MODE_CCM }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_aes256 = { GCRY_CIPHER_AES256, {0, 1}, "AES256", rijndael256_names, rijndael256_oids, 16, 256, sizeof (RIJNDAEL_context), rijndael_setkey, rijndael_encrypt, rijndael_decrypt, NULL, NULL, run_selftests }; diff --git a/cipher/rmd160.c b/cipher/rmd160.c index 1861205e..5c54fdff 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -1,520 +1,520 @@ /* rmd160.c - RIPE-MD160 * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include "g10lib.h" #include "hash-common.h" #include "cipher.h" /* Only used for the rmd160_hash_buffer() prototype. */ #include "bithelp.h" #include "bufhelp.h" /********************************* * RIPEMD-160 is not patented, see (as of 25.10.97) * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html * Note that the code uses Little Endian byteorder, which is good for * 386 etc, but we must add some conversion when used on a big endian box. * * * Pseudo-code for RIPEMD-160 * * RIPEMD-160 is an iterative hash function that operates on 32-bit words. * The round function takes as input a 5-word chaining variable and a 16-word * message block and maps this to a new chaining variable. All operations are * defined on 32-bit words. Padding is identical to that of MD4. * * * RIPEMD-160: definitions * * * nonlinear functions at bit level: exor, mux, -, mux, - * * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) * * * added constants (hexadecimal) * * K(j) = 0x00000000 (0 <= j <= 15) * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) * K'(j) = 0x00000000 (64 <= j <= 79) * * * selection of message word * * r(j) = j (0 <= j <= 15) * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 * * * amount for rotate left (rol) * * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 * * * initial value (hexadecimal) * * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; * h4 = 0xC3D2E1F0; * * * RIPEMD-160: pseudo-code * * It is assumed that the message after padding consists of t 16-word blocks * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left * shift (rotate) over s positions. * * * for i := 0 to t-1 { * A := h0; B := h1; C := h2; D = h3; E = h4; * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; * for j := 0 to 79 { * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; * A := E; E := D; D := rol_10(C); C := B; B := T; * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] [+] K'(j)) [+] E'; * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; * } * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; * } */ /* Some examples: * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 */ typedef struct { gcry_md_block_ctx_t bctx; u32 h0,h1,h2,h3,h4; } RMD160_CONTEXT; static unsigned int transform ( void *ctx, const unsigned char *data, size_t nblks ); static void rmd160_init (void *context, unsigned int flags) { RMD160_CONTEXT *hd = context; (void)flags; hd->h0 = 0x67452301; hd->h1 = 0xEFCDAB89; hd->h2 = 0x98BADCFE; hd->h3 = 0x10325476; hd->h4 = 0xC3D2E1F0; hd->bctx.nblocks = 0; hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize_shift = _gcry_ctz(64); hd->bctx.bwrite = transform; } /**************** * Transform the message X which consists of 16 32-bit-words */ static unsigned int transform_blk ( void *ctx, const unsigned char *data ) { RMD160_CONTEXT *hd = ctx; register u32 al, ar, bl, br, cl, cr, dl, dr, el, er; u32 x[16]; int i; for ( i = 0; i < 16; i++ ) x[i] = buf_get_le32(data + i * 4); #define K0 0x00000000 #define K1 0x5A827999 #define K2 0x6ED9EBA1 #define K3 0x8F1BBCDC #define K4 0xA953FD4E #define KK0 0x50A28BE6 #define KK1 0x5C4DD124 #define KK2 0x6D703EF3 #define KK3 0x7A6D76E9 #define KK4 0x00000000 #define F0(x,y,z) ( (x) ^ (y) ^ (z) ) #define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) #define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) #define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) #define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) #define R(a,b,c,d,e,f,k,r,s) do { a += f(b,c,d) + k + x[r]; \ a = rol(a,s) + e; \ c = rol(c,10); \ } while(0) /* left lane and right lanes interleaved */ al = ar = hd->h0; bl = br = hd->h1; cl = cr = hd->h2; dl = dr = hd->h3; el = er = hd->h4; R( al, bl, cl, dl, el, F0, K0, 0, 11 ); R( ar, br, cr, dr, er, F4, KK0, 5, 8); R( el, al, bl, cl, dl, F0, K0, 1, 14 ); R( er, ar, br, cr, dr, F4, KK0, 14, 9); R( dl, el, al, bl, cl, F0, K0, 2, 15 ); R( dr, er, ar, br, cr, F4, KK0, 7, 9); R( cl, dl, el, al, bl, F0, K0, 3, 12 ); R( cr, dr, er, ar, br, F4, KK0, 0, 11); R( bl, cl, dl, el, al, F0, K0, 4, 5 ); R( br, cr, dr, er, ar, F4, KK0, 9, 13); R( al, bl, cl, dl, el, F0, K0, 5, 8 ); R( ar, br, cr, dr, er, F4, KK0, 2, 15); R( el, al, bl, cl, dl, F0, K0, 6, 7 ); R( er, ar, br, cr, dr, F4, KK0, 11, 15); R( dl, el, al, bl, cl, F0, K0, 7, 9 ); R( dr, er, ar, br, cr, F4, KK0, 4, 5); R( cl, dl, el, al, bl, F0, K0, 8, 11 ); R( cr, dr, er, ar, br, F4, KK0, 13, 7); R( bl, cl, dl, el, al, F0, K0, 9, 13 ); R( br, cr, dr, er, ar, F4, KK0, 6, 7); R( al, bl, cl, dl, el, F0, K0, 10, 14 ); R( ar, br, cr, dr, er, F4, KK0, 15, 8); R( el, al, bl, cl, dl, F0, K0, 11, 15 ); R( er, ar, br, cr, dr, F4, KK0, 8, 11); R( dl, el, al, bl, cl, F0, K0, 12, 6 ); R( dr, er, ar, br, cr, F4, KK0, 1, 14); R( cl, dl, el, al, bl, F0, K0, 13, 7 ); R( cr, dr, er, ar, br, F4, KK0, 10, 14); R( bl, cl, dl, el, al, F0, K0, 14, 9 ); R( br, cr, dr, er, ar, F4, KK0, 3, 12); R( al, bl, cl, dl, el, F0, K0, 15, 8 ); R( ar, br, cr, dr, er, F4, KK0, 12, 6); R( el, al, bl, cl, dl, F1, K1, 7, 7 ); R( er, ar, br, cr, dr, F3, KK1, 6, 9); R( dl, el, al, bl, cl, F1, K1, 4, 6 ); R( dr, er, ar, br, cr, F3, KK1, 11, 13); R( cl, dl, el, al, bl, F1, K1, 13, 8 ); R( cr, dr, er, ar, br, F3, KK1, 3, 15); R( bl, cl, dl, el, al, F1, K1, 1, 13 ); R( br, cr, dr, er, ar, F3, KK1, 7, 7); R( al, bl, cl, dl, el, F1, K1, 10, 11 ); R( ar, br, cr, dr, er, F3, KK1, 0, 12); R( el, al, bl, cl, dl, F1, K1, 6, 9 ); R( er, ar, br, cr, dr, F3, KK1, 13, 8); R( dl, el, al, bl, cl, F1, K1, 15, 7 ); R( dr, er, ar, br, cr, F3, KK1, 5, 9); R( cl, dl, el, al, bl, F1, K1, 3, 15 ); R( cr, dr, er, ar, br, F3, KK1, 10, 11); R( bl, cl, dl, el, al, F1, K1, 12, 7 ); R( br, cr, dr, er, ar, F3, KK1, 14, 7); R( al, bl, cl, dl, el, F1, K1, 0, 12 ); R( ar, br, cr, dr, er, F3, KK1, 15, 7); R( el, al, bl, cl, dl, F1, K1, 9, 15 ); R( er, ar, br, cr, dr, F3, KK1, 8, 12); R( dl, el, al, bl, cl, F1, K1, 5, 9 ); R( dr, er, ar, br, cr, F3, KK1, 12, 7); R( cl, dl, el, al, bl, F1, K1, 2, 11 ); R( cr, dr, er, ar, br, F3, KK1, 4, 6); R( bl, cl, dl, el, al, F1, K1, 14, 7 ); R( br, cr, dr, er, ar, F3, KK1, 9, 15); R( al, bl, cl, dl, el, F1, K1, 11, 13 ); R( ar, br, cr, dr, er, F3, KK1, 1, 13); R( el, al, bl, cl, dl, F1, K1, 8, 12 ); R( er, ar, br, cr, dr, F3, KK1, 2, 11); R( dl, el, al, bl, cl, F2, K2, 3, 11 ); R( dr, er, ar, br, cr, F2, KK2, 15, 9); R( cl, dl, el, al, bl, F2, K2, 10, 13 ); R( cr, dr, er, ar, br, F2, KK2, 5, 7); R( bl, cl, dl, el, al, F2, K2, 14, 6 ); R( br, cr, dr, er, ar, F2, KK2, 1, 15); R( al, bl, cl, dl, el, F2, K2, 4, 7 ); R( ar, br, cr, dr, er, F2, KK2, 3, 11); R( el, al, bl, cl, dl, F2, K2, 9, 14 ); R( er, ar, br, cr, dr, F2, KK2, 7, 8); R( dl, el, al, bl, cl, F2, K2, 15, 9 ); R( dr, er, ar, br, cr, F2, KK2, 14, 6); R( cl, dl, el, al, bl, F2, K2, 8, 13 ); R( cr, dr, er, ar, br, F2, KK2, 6, 6); R( bl, cl, dl, el, al, F2, K2, 1, 15 ); R( br, cr, dr, er, ar, F2, KK2, 9, 14); R( al, bl, cl, dl, el, F2, K2, 2, 14 ); R( ar, br, cr, dr, er, F2, KK2, 11, 12); R( el, al, bl, cl, dl, F2, K2, 7, 8 ); R( er, ar, br, cr, dr, F2, KK2, 8, 13); R( dl, el, al, bl, cl, F2, K2, 0, 13 ); R( dr, er, ar, br, cr, F2, KK2, 12, 5); R( cl, dl, el, al, bl, F2, K2, 6, 6 ); R( cr, dr, er, ar, br, F2, KK2, 2, 14); R( bl, cl, dl, el, al, F2, K2, 13, 5 ); R( br, cr, dr, er, ar, F2, KK2, 10, 13); R( al, bl, cl, dl, el, F2, K2, 11, 12 ); R( ar, br, cr, dr, er, F2, KK2, 0, 13); R( el, al, bl, cl, dl, F2, K2, 5, 7 ); R( er, ar, br, cr, dr, F2, KK2, 4, 7); R( dl, el, al, bl, cl, F2, K2, 12, 5 ); R( dr, er, ar, br, cr, F2, KK2, 13, 5); R( cl, dl, el, al, bl, F3, K3, 1, 11 ); R( cr, dr, er, ar, br, F1, KK3, 8, 15); R( bl, cl, dl, el, al, F3, K3, 9, 12 ); R( br, cr, dr, er, ar, F1, KK3, 6, 5); R( al, bl, cl, dl, el, F3, K3, 11, 14 ); R( ar, br, cr, dr, er, F1, KK3, 4, 8); R( el, al, bl, cl, dl, F3, K3, 10, 15 ); R( er, ar, br, cr, dr, F1, KK3, 1, 11); R( dl, el, al, bl, cl, F3, K3, 0, 14 ); R( dr, er, ar, br, cr, F1, KK3, 3, 14); R( cl, dl, el, al, bl, F3, K3, 8, 15 ); R( cr, dr, er, ar, br, F1, KK3, 11, 14); R( bl, cl, dl, el, al, F3, K3, 12, 9 ); R( br, cr, dr, er, ar, F1, KK3, 15, 6); R( al, bl, cl, dl, el, F3, K3, 4, 8 ); R( ar, br, cr, dr, er, F1, KK3, 0, 14); R( el, al, bl, cl, dl, F3, K3, 13, 9 ); R( er, ar, br, cr, dr, F1, KK3, 5, 6); R( dl, el, al, bl, cl, F3, K3, 3, 14 ); R( dr, er, ar, br, cr, F1, KK3, 12, 9); R( cl, dl, el, al, bl, F3, K3, 7, 5 ); R( cr, dr, er, ar, br, F1, KK3, 2, 12); R( bl, cl, dl, el, al, F3, K3, 15, 6 ); R( br, cr, dr, er, ar, F1, KK3, 13, 9); R( al, bl, cl, dl, el, F3, K3, 14, 8 ); R( ar, br, cr, dr, er, F1, KK3, 9, 12); R( el, al, bl, cl, dl, F3, K3, 5, 6 ); R( er, ar, br, cr, dr, F1, KK3, 7, 5); R( dl, el, al, bl, cl, F3, K3, 6, 5 ); R( dr, er, ar, br, cr, F1, KK3, 10, 15); R( cl, dl, el, al, bl, F3, K3, 2, 12 ); R( cr, dr, er, ar, br, F1, KK3, 14, 8); R( bl, cl, dl, el, al, F4, K4, 4, 9 ); R( br, cr, dr, er, ar, F0, KK4, 12, 8); R( al, bl, cl, dl, el, F4, K4, 0, 15 ); R( ar, br, cr, dr, er, F0, KK4, 15, 5); R( el, al, bl, cl, dl, F4, K4, 5, 5 ); R( er, ar, br, cr, dr, F0, KK4, 10, 12); R( dl, el, al, bl, cl, F4, K4, 9, 11 ); R( dr, er, ar, br, cr, F0, KK4, 4, 9); R( cl, dl, el, al, bl, F4, K4, 7, 6 ); R( cr, dr, er, ar, br, F0, KK4, 1, 12); R( bl, cl, dl, el, al, F4, K4, 12, 8 ); R( br, cr, dr, er, ar, F0, KK4, 5, 5); R( al, bl, cl, dl, el, F4, K4, 2, 13 ); R( ar, br, cr, dr, er, F0, KK4, 8, 14); R( el, al, bl, cl, dl, F4, K4, 10, 12 ); R( er, ar, br, cr, dr, F0, KK4, 7, 6); R( dl, el, al, bl, cl, F4, K4, 14, 5 ); R( dr, er, ar, br, cr, F0, KK4, 6, 8); R( cl, dl, el, al, bl, F4, K4, 1, 12 ); R( cr, dr, er, ar, br, F0, KK4, 2, 13); R( bl, cl, dl, el, al, F4, K4, 3, 13 ); R( br, cr, dr, er, ar, F0, KK4, 13, 6); R( al, bl, cl, dl, el, F4, K4, 8, 14 ); R( ar, br, cr, dr, er, F0, KK4, 14, 5); R( el, al, bl, cl, dl, F4, K4, 11, 11 ); R( er, ar, br, cr, dr, F0, KK4, 0, 15); R( dl, el, al, bl, cl, F4, K4, 6, 8 ); R( dr, er, ar, br, cr, F0, KK4, 3, 13); R( cl, dl, el, al, bl, F4, K4, 15, 5 ); R( cr, dr, er, ar, br, F0, KK4, 9, 11); R( bl, cl, dl, el, al, F4, K4, 13, 6 ); R( br, cr, dr, er, ar, F0, KK4, 11, 11); dr += cl + hd->h1; hd->h1 = hd->h2 + dl + er; hd->h2 = hd->h3 + el + ar; hd->h3 = hd->h4 + al + br; hd->h4 = hd->h0 + bl + cr; hd->h0 = dr; return /*burn_stack*/ 104+5*sizeof(void*); } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 64; } while (--nblks); return burn; } /* * The routine terminates the computation */ static void rmd160_final( void *context ) { RMD160_CONTEXT *hd = context; u32 t, th, msb, lsb; byte *p; unsigned int burn; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (hd->bctx.count < 56) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 56, lsb); buf_put_le32(hd->bctx.buf + 60, msb); burn = transform (hd, hd->bctx.buf, 1); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 64 + 56, lsb); buf_put_le32(hd->bctx.buf + 64 + 60, msb); burn = transform (hd, hd->bctx.buf, 2); } p = hd->bctx.buf; #define X(a) do { buf_put_le32(p, hd->h##a); p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * rmd160_read( void *context ) { RMD160_CONTEXT *hd = context; return hd->bctx.buf; } /**************** * Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 20 bytes. */ static void _gcry_rmd160_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { RMD160_CONTEXT hd; (void)nbytes; rmd160_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); rmd160_final ( &hd ); memcpy ( outbuf, hd.bctx.buf, 20 ); } -static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ +static const byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; -static gcry_md_oid_spec_t oid_spec_rmd160[] = +static const gcry_md_oid_spec_t oid_spec_rmd160[] = { /* rsaSignatureWithripemd160 */ { "1.3.36.3.3.1.2" }, /* TeleTrust hash algorithm. */ { "1.3.36.3.2.1" }, { NULL } }; -gcry_md_spec_t _gcry_digest_spec_rmd160 = +const gcry_md_spec_t _gcry_digest_spec_rmd160 = { GCRY_MD_RMD160, {0, 0}, "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20, rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read, NULL, _gcry_rmd160_hash_buffers, sizeof (RMD160_CONTEXT) }; diff --git a/cipher/seed.c b/cipher/seed.c index 2c8958fa..4fd93d75 100644 --- a/cipher/seed.c +++ b/cipher/seed.c @@ -1,478 +1,478 @@ /* SEED for libgcrypt * Copyright (C) 2006 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * -- * This implementation was provided for libgcrypt in public domain * by Hye-Shik Chang , July 2006. */ #include #include #include #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "cipher-internal.h" #define NUMKC 16 #define GETU32(pt) buf_get_be32(pt) #define PUTU32(ct, st) buf_put_be32(ct, st) union wordbuf { u32 w; byte b[4]; }; #ifdef WORDS_BIGENDIAN #define b0 b[3] #define b1 b[2] #define b2 b[1] #define b3 b[0] #else #define b0 b[0] #define b1 b[1] #define b2 b[2] #define b3 b[3] #endif static const char *selftest(void); typedef struct { u32 keyschedule[32]; } SEED_context; static const u32 SS0[256] = { 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038, 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330, 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298, }; static const u32 SS1[256] = { 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3, }; static const u32 SS2[256] = { 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808, 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303, 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a, }; static const u32 SS3[256] = { 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437, }; static const u32 KC[NUMKC] = { 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b, }; /* Perform the key setup. */ static gcry_err_code_t do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen) { static int initialized = 0; static const char *selftest_failed=0; u32 x1, x2, x3, x4; union wordbuf t0, t1; u32 *keyout = ctx->keyschedule; int i; if (!initialized) { initialized = 1; selftest_failed = selftest (); if( selftest_failed ) log_error ("%s\n", selftest_failed ); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen != 16) return GPG_ERR_INV_KEYLEN; x1 = GETU32 (key); x2 = GETU32 (key+4); x3 = GETU32 (key+8); x4 = GETU32 (key+12); for (i = 0; i < NUMKC; i++) { t0.w = x1 + x3 - KC[i]; t1.w = x2 + KC[i] - x4; *(keyout++) = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; *(keyout++) = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; if (i % 2 == 0) { t0.w = x1; x1 = (x1>>8) ^ (x2<<24); x2 = (x2>>8) ^ (t0.w<<24); } else { t0.w = x3; x3 = (x3<<8) ^ (x4>>24); x4 = (x4<<8) ^ (t0.w>>24); } } return 0; } static gcry_err_code_t seed_setkey (void *context, const byte *key, const unsigned keylen, cipher_bulk_ops_t *bulk_ops) { SEED_context *ctx = context; int rc = do_setkey (ctx, key, keylen); (void)bulk_ops; _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2); return rc; } #define OP(X1, X2, X3, X4, rbase) \ t0.w = X3 ^ ctx->keyschedule[rbase]; \ t1.w = X4 ^ ctx->keyschedule[rbase+1]; \ t1.w ^= t0.w; \ t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ t0.w += t1.w; \ t0.w = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; \ t1.w += t0.w; \ t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ t0.w += t1.w; \ X1 ^= t0.w; \ X2 ^= t1.w; /* Encrypt one block. inbuf and outbuf may be the same. */ static void do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf) { u32 x1, x2, x3, x4; union wordbuf t0, t1; x1 = GETU32 (inbuf); x2 = GETU32 (inbuf+4); x3 = GETU32 (inbuf+8); x4 = GETU32 (inbuf+12); OP (x1, x2, x3, x4, 0); OP (x3, x4, x1, x2, 2); OP (x1, x2, x3, x4, 4); OP (x3, x4, x1, x2, 6); OP (x1, x2, x3, x4, 8); OP (x3, x4, x1, x2, 10); OP (x1, x2, x3, x4, 12); OP (x3, x4, x1, x2, 14); OP (x1, x2, x3, x4, 16); OP (x3, x4, x1, x2, 18); OP (x1, x2, x3, x4, 20); OP (x3, x4, x1, x2, 22); OP (x1, x2, x3, x4, 24); OP (x3, x4, x1, x2, 26); OP (x1, x2, x3, x4, 28); OP (x3, x4, x1, x2, 30); PUTU32 (outbuf, x3); PUTU32 (outbuf+4, x4); PUTU32 (outbuf+8, x1); PUTU32 (outbuf+12, x2); } static unsigned int seed_encrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_encrypt (ctx, outbuf, inbuf); return /*burn_stack*/ (4*6); } /* Decrypt one block. inbuf and outbuf may be the same. */ static void do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf) { u32 x1, x2, x3, x4; union wordbuf t0, t1; x1 = GETU32 (inbuf); x2 = GETU32 (inbuf+4); x3 = GETU32 (inbuf+8); x4 = GETU32 (inbuf+12); OP (x1, x2, x3, x4, 30); OP (x3, x4, x1, x2, 28); OP (x1, x2, x3, x4, 26); OP (x3, x4, x1, x2, 24); OP (x1, x2, x3, x4, 22); OP (x3, x4, x1, x2, 20); OP (x1, x2, x3, x4, 18); OP (x3, x4, x1, x2, 16); OP (x1, x2, x3, x4, 14); OP (x3, x4, x1, x2, 12); OP (x1, x2, x3, x4, 10); OP (x3, x4, x1, x2, 8); OP (x1, x2, x3, x4, 6); OP (x3, x4, x1, x2, 4); OP (x1, x2, x3, x4, 2); OP (x3, x4, x1, x2, 0); PUTU32 (outbuf, x3); PUTU32 (outbuf+4, x4); PUTU32 (outbuf+8, x1); PUTU32 (outbuf+12, x2); } static unsigned int seed_decrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_decrypt (ctx, outbuf, inbuf); return /*burn_stack*/ (4*6); } /* Test a single encryption and decryption with each key size. */ static const char* selftest (void) { SEED_context ctx; byte scratch[16]; /* The test vector is taken from the appendix section B.3 of RFC4269. */ static const byte plaintext[16] = { 0x83, 0xA2, 0xF8, 0xA2, 0x88, 0x64, 0x1F, 0xB9, 0xA4, 0xE9, 0xA5, 0xCC, 0x2F, 0x13, 0x1C, 0x7D }; static const byte key[16] = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xE6, 0x1B, 0xE8, 0x5D, 0x74, 0xBF, 0xB3, 0xFD, 0x95, 0x61, 0x85 }; static const byte ciphertext[16] = { 0xEE, 0x54, 0xD1, 0x3E, 0xBC, 0xAE, 0x70, 0x6D, 0x22, 0x6B, 0xC3, 0x14, 0x2C, 0xD4, 0x0D, 0x4A, }; seed_setkey (&ctx, key, sizeof(key), NULL); seed_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "SEED test encryption failed."; seed_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "SEED test decryption failed."; return NULL; } -static gcry_cipher_oid_spec_t seed_oids[] = +static const gcry_cipher_oid_spec_t seed_oids[] = { { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB }, { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC }, { "1.2.410.200004.1.5", GCRY_CIPHER_MODE_CFB }, { "1.2.410.200004.1.6", GCRY_CIPHER_MODE_OFB }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_seed = { GCRY_CIPHER_SEED, {0, 0}, "SEED", NULL, seed_oids, 16, 128, sizeof (SEED_context), seed_setkey, seed_encrypt, seed_decrypt, }; diff --git a/cipher/serpent.c b/cipher/serpent.c index d2f7f16e..159d889f 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -1,1811 +1,1811 @@ /* serpent.c - Implementation of the Serpent encryption algorithm. * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher-internal.h" #include "cipher-selftest.h" /* USE_SSE2 indicates whether to compile with AMD64 SSE2 code. */ #undef USE_SSE2 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_SSE2 1 #endif /* USE_AVX2 indicates whether to compile with AMD64 AVX2 code. */ #undef USE_AVX2 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # if defined(ENABLE_AVX2_SUPPORT) # define USE_AVX2 1 # endif #endif /* USE_NEON indicates whether to enable ARM NEON assembly code. */ #undef USE_NEON #ifdef ENABLE_NEON_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_NEON) # define USE_NEON 1 # endif #endif /*ENABLE_NEON_SUPPORT*/ /* Number of rounds per Serpent encrypt/decrypt operation. */ #define ROUNDS 32 /* Magic number, used during generating of the subkeys. */ #define PHI 0x9E3779B9 /* Serpent works on 128 bit blocks. */ typedef u32 serpent_block_t[4]; /* Serpent key, provided by the user. If the original key is shorter than 256 bits, it is padded. */ typedef u32 serpent_key_t[8]; /* The key schedule consists of 33 128 bit subkeys. */ typedef u32 serpent_subkeys_t[ROUNDS + 1][4]; /* A Serpent context. */ typedef struct serpent_context { serpent_subkeys_t keys; /* Generated subkeys. */ #ifdef USE_AVX2 int use_avx2; #endif #ifdef USE_NEON int use_neon; #endif } serpent_context_t; /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #if defined(USE_SSE2) || defined(USE_AVX2) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # else # define ASM_FUNC_ABI # endif #endif #ifdef USE_SSE2 /* Assembler implementations of Serpent using SSE2. Process 8 block in parallel. */ extern void _gcry_serpent_sse2_ctr_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr) ASM_FUNC_ABI; extern void _gcry_serpent_sse2_cbc_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_serpent_sse2_cfb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_serpent_sse2_ocb_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[8]) ASM_FUNC_ABI; extern void _gcry_serpent_sse2_ocb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[8]) ASM_FUNC_ABI; extern void _gcry_serpent_sse2_ocb_auth(serpent_context_t *ctx, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[8]) ASM_FUNC_ABI; #endif #ifdef USE_AVX2 /* Assembler implementations of Serpent using AVX2. Process 16 block in parallel. */ extern void _gcry_serpent_avx2_ctr_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr) ASM_FUNC_ABI; extern void _gcry_serpent_avx2_cbc_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_serpent_avx2_cfb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv) ASM_FUNC_ABI; extern void _gcry_serpent_avx2_ocb_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_serpent_avx2_ocb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_serpent_avx2_ocb_auth(serpent_context_t *ctx, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; #endif #ifdef USE_NEON /* Assembler implementations of Serpent using ARM NEON. Process 8 block in parallel. */ extern void _gcry_serpent_neon_ctr_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr); extern void _gcry_serpent_neon_cbc_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); extern void _gcry_serpent_neon_cfb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); extern void _gcry_serpent_neon_ocb_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const void *Ls[8]); extern void _gcry_serpent_neon_ocb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const void *Ls[8]); extern void _gcry_serpent_neon_ocb_auth(serpent_context_t *ctx, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const void *Ls[8]); #endif /* Prototypes. */ static const char *serpent_test (void); static void _gcry_serpent_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_serpent_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_serpent_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static size_t _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); static size_t _gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); /* * These are the S-Boxes of Serpent from following research paper. * * D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference, * (New York, New York, USA), p. 317–329, National Institute of Standards and * Technology, 2000. * * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf * */ #define SBOX0(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r3 ^= r0; r4 = r1; \ r1 &= r3; r4 ^= r2; \ r1 ^= r0; r0 |= r3; \ r0 ^= r4; r4 ^= r3; \ r3 ^= r2; r2 |= r1; \ r2 ^= r4; r4 = ~r4; \ r4 |= r1; r1 ^= r3; \ r1 ^= r4; r3 |= r0; \ r1 ^= r3; r4 ^= r3; \ \ w = r1; x = r4; y = r2; z = r0; \ } #define SBOX0_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r2 = ~r2; r4 = r1; \ r1 |= r0; r4 = ~r4; \ r1 ^= r2; r2 |= r4; \ r1 ^= r3; r0 ^= r4; \ r2 ^= r0; r0 &= r3; \ r4 ^= r0; r0 |= r1; \ r0 ^= r2; r3 ^= r4; \ r2 ^= r1; r3 ^= r0; \ r3 ^= r1; \ r2 &= r3; \ r4 ^= r2; \ \ w = r0; x = r4; y = r1; z = r3; \ } #define SBOX1(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r0 = ~r0; r2 = ~r2; \ r4 = r0; r0 &= r1; \ r2 ^= r0; r0 |= r3; \ r3 ^= r2; r1 ^= r0; \ r0 ^= r4; r4 |= r1; \ r1 ^= r3; r2 |= r0; \ r2 &= r4; r0 ^= r1; \ r1 &= r2; \ r1 ^= r0; r0 &= r2; \ r0 ^= r4; \ \ w = r2; x = r0; y = r3; z = r1; \ } #define SBOX1_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r1; r1 ^= r3; \ r3 &= r1; r4 ^= r2; \ r3 ^= r0; r0 |= r1; \ r2 ^= r3; r0 ^= r4; \ r0 |= r2; r1 ^= r3; \ r0 ^= r1; r1 |= r3; \ r1 ^= r0; r4 = ~r4; \ r4 ^= r1; r1 |= r0; \ r1 ^= r0; \ r1 |= r4; \ r3 ^= r1; \ \ w = r4; x = r0; y = r3; z = r2; \ } #define SBOX2(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r0; r0 &= r2; \ r0 ^= r3; r2 ^= r1; \ r2 ^= r0; r3 |= r4; \ r3 ^= r1; r4 ^= r2; \ r1 = r3; r3 |= r4; \ r3 ^= r0; r0 &= r1; \ r4 ^= r0; r1 ^= r3; \ r1 ^= r4; r4 = ~r4; \ \ w = r2; x = r3; y = r1; z = r4; \ } #define SBOX2_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r2 ^= r3; r3 ^= r0; \ r4 = r3; r3 &= r2; \ r3 ^= r1; r1 |= r2; \ r1 ^= r4; r4 &= r3; \ r2 ^= r3; r4 &= r0; \ r4 ^= r2; r2 &= r1; \ r2 |= r0; r3 = ~r3; \ r2 ^= r3; r0 ^= r3; \ r0 &= r1; r3 ^= r4; \ r3 ^= r0; \ \ w = r1; x = r4; y = r2; z = r3; \ } #define SBOX3(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r0; r0 |= r3; \ r3 ^= r1; r1 &= r4; \ r4 ^= r2; r2 ^= r3; \ r3 &= r0; r4 |= r1; \ r3 ^= r4; r0 ^= r1; \ r4 &= r0; r1 ^= r3; \ r4 ^= r2; r1 |= r0; \ r1 ^= r2; r0 ^= r3; \ r2 = r1; r1 |= r3; \ r1 ^= r0; \ \ w = r1; x = r2; y = r3; z = r4; \ } #define SBOX3_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r2; r2 ^= r1; \ r0 ^= r2; r4 &= r2; \ r4 ^= r0; r0 &= r1; \ r1 ^= r3; r3 |= r4; \ r2 ^= r3; r0 ^= r3; \ r1 ^= r4; r3 &= r2; \ r3 ^= r1; r1 ^= r0; \ r1 |= r2; r0 ^= r3; \ r1 ^= r4; \ r0 ^= r1; \ \ w = r2; x = r1; y = r3; z = r0; \ } #define SBOX4(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r1 ^= r3; r3 = ~r3; \ r2 ^= r3; r3 ^= r0; \ r4 = r1; r1 &= r3; \ r1 ^= r2; r4 ^= r3; \ r0 ^= r4; r2 &= r4; \ r2 ^= r0; r0 &= r1; \ r3 ^= r0; r4 |= r1; \ r4 ^= r0; r0 |= r3; \ r0 ^= r2; r2 &= r3; \ r0 = ~r0; r4 ^= r2; \ \ w = r1; x = r4; y = r0; z = r3; \ } #define SBOX4_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r2; r2 &= r3; \ r2 ^= r1; r1 |= r3; \ r1 &= r0; r4 ^= r2; \ r4 ^= r1; r1 &= r2; \ r0 = ~r0; r3 ^= r4; \ r1 ^= r3; r3 &= r0; \ r3 ^= r2; r0 ^= r1; \ r2 &= r0; r3 ^= r0; \ r2 ^= r4; \ r2 |= r3; r3 ^= r0; \ r2 ^= r1; \ \ w = r0; x = r3; y = r2; z = r4; \ } #define SBOX5(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r0 ^= r1; r1 ^= r3; \ r3 = ~r3; r4 = r1; \ r1 &= r0; r2 ^= r3; \ r1 ^= r2; r2 |= r4; \ r4 ^= r3; r3 &= r1; \ r3 ^= r0; r4 ^= r1; \ r4 ^= r2; r2 ^= r0; \ r0 &= r3; r2 = ~r2; \ r0 ^= r4; r4 |= r3; \ r2 ^= r4; \ \ w = r1; x = r3; y = r0; z = r2; \ } #define SBOX5_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r1 = ~r1; r4 = r3; \ r2 ^= r1; r3 |= r0; \ r3 ^= r2; r2 |= r1; \ r2 &= r0; r4 ^= r3; \ r2 ^= r4; r4 |= r0; \ r4 ^= r1; r1 &= r2; \ r1 ^= r3; r4 ^= r2; \ r3 &= r4; r4 ^= r1; \ r3 ^= r4; r4 = ~r4; \ r3 ^= r0; \ \ w = r1; x = r4; y = r3; z = r2; \ } #define SBOX6(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r2 = ~r2; r4 = r3; \ r3 &= r0; r0 ^= r4; \ r3 ^= r2; r2 |= r4; \ r1 ^= r3; r2 ^= r0; \ r0 |= r1; r2 ^= r1; \ r4 ^= r0; r0 |= r3; \ r0 ^= r2; r4 ^= r3; \ r4 ^= r0; r3 = ~r3; \ r2 &= r4; \ r2 ^= r3; \ \ w = r0; x = r1; y = r4; z = r2; \ } #define SBOX6_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r0 ^= r2; r4 = r2; \ r2 &= r0; r4 ^= r3; \ r2 = ~r2; r3 ^= r1; \ r2 ^= r3; r4 |= r0; \ r0 ^= r2; r3 ^= r4; \ r4 ^= r1; r1 &= r3; \ r1 ^= r0; r0 ^= r3; \ r0 |= r2; r3 ^= r1; \ r4 ^= r0; \ \ w = r1; x = r2; y = r4; z = r3; \ } #define SBOX7(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r1; r1 |= r2; \ r1 ^= r3; r4 ^= r2; \ r2 ^= r1; r3 |= r4; \ r3 &= r0; r4 ^= r2; \ r3 ^= r1; r1 |= r4; \ r1 ^= r0; r0 |= r4; \ r0 ^= r2; r1 ^= r4; \ r2 ^= r1; r1 &= r0; \ r1 ^= r4; r2 = ~r2; \ r2 |= r0; \ r4 ^= r2; \ \ w = r4; x = r3; y = r1; z = r0; \ } #define SBOX7_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r2; r2 ^= r0; \ r0 &= r3; r4 |= r3; \ r2 = ~r2; r3 ^= r1; \ r1 |= r0; r0 ^= r2; \ r2 &= r4; r3 &= r4; \ r1 ^= r2; r2 ^= r0; \ r0 |= r2; r4 ^= r1; \ r0 ^= r3; r3 ^= r4; \ r4 |= r0; r3 ^= r2; \ r4 ^= r2; \ \ w = r3; x = r0; y = r1; z = r4; \ } /* XOR BLOCK1 into BLOCK0. */ #define BLOCK_XOR(block0, block1) \ { \ block0[0] ^= block1[0]; \ block0[1] ^= block1[1]; \ block0[2] ^= block1[2]; \ block0[3] ^= block1[3]; \ } /* Copy BLOCK_SRC to BLOCK_DST. */ #define BLOCK_COPY(block_dst, block_src) \ { \ block_dst[0] = block_src[0]; \ block_dst[1] = block_src[1]; \ block_dst[2] = block_src[2]; \ block_dst[3] = block_src[3]; \ } /* Apply SBOX number WHICH to to the block found in ARRAY0, writing the output to the block found in ARRAY1. */ #define SBOX(which, array0, array1) \ SBOX##which (array0[0], array0[1], array0[2], array0[3], \ array1[0], array1[1], array1[2], array1[3]); /* Apply inverse SBOX number WHICH to to the block found in ARRAY0, writing the output to the block found in ARRAY1. */ #define SBOX_INVERSE(which, array0, array1) \ SBOX##which##_INVERSE (array0[0], array0[1], array0[2], array0[3], \ array1[0], array1[1], array1[2], array1[3]); /* Apply the linear transformation to BLOCK. */ #define LINEAR_TRANSFORMATION(block) \ { \ block[0] = rol (block[0], 13); \ block[2] = rol (block[2], 3); \ block[1] = block[1] ^ block[0] ^ block[2]; \ block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ block[1] = rol (block[1], 1); \ block[3] = rol (block[3], 7); \ block[0] = block[0] ^ block[1] ^ block[3]; \ block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ block[0] = rol (block[0], 5); \ block[2] = rol (block[2], 22); \ } /* Apply the inverse linear transformation to BLOCK. */ #define LINEAR_TRANSFORMATION_INVERSE(block) \ { \ block[2] = ror (block[2], 22); \ block[0] = ror (block[0] , 5); \ block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ block[0] = block[0] ^ block[1] ^ block[3]; \ block[3] = ror (block[3], 7); \ block[1] = ror (block[1], 1); \ block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ block[1] = block[1] ^ block[0] ^ block[2]; \ block[2] = ror (block[2], 3); \ block[0] = ror (block[0], 13); \ } /* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. This macro increments `round'. */ #define ROUND(which, subkeys, block, block_tmp) \ { \ BLOCK_XOR (block, subkeys[round]); \ round++; \ SBOX (which, block, block_tmp); \ LINEAR_TRANSFORMATION (block_tmp); \ BLOCK_COPY (block, block_tmp); \ } /* Apply the last Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. The result will be stored in BLOCK_TMP. This macro increments `round'. */ #define ROUND_LAST(which, subkeys, block, block_tmp) \ { \ BLOCK_XOR (block, subkeys[round]); \ round++; \ SBOX (which, block, block_tmp); \ BLOCK_XOR (block_tmp, subkeys[round]); \ round++; \ } /* Apply an inverse Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. This macro increments `round'. */ #define ROUND_INVERSE(which, subkey, block, block_tmp) \ { \ LINEAR_TRANSFORMATION_INVERSE (block); \ SBOX_INVERSE (which, block, block_tmp); \ BLOCK_XOR (block_tmp, subkey[round]); \ round--; \ BLOCK_COPY (block, block_tmp); \ } /* Apply the first Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. The result will be stored in BLOCK_TMP. This macro increments `round'. */ #define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \ { \ BLOCK_XOR (block, subkeys[round]); \ round--; \ SBOX_INVERSE (which, block, block_tmp); \ BLOCK_XOR (block_tmp, subkeys[round]); \ round--; \ } /* Convert the user provided key KEY of KEY_LENGTH bytes into the internally used format. */ static void serpent_key_prepare (const byte *key, unsigned int key_length, serpent_key_t key_prepared) { int i; /* Copy key. */ key_length /= 4; for (i = 0; i < key_length; i++) key_prepared[i] = buf_get_le32 (key + i * 4); if (i < 8) { /* Key must be padded according to the Serpent specification. */ key_prepared[i] = 0x00000001; for (i++; i < 8; i++) key_prepared[i] = 0; } } /* Derive the 33 subkeys from KEY and store them in SUBKEYS. */ static void serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) { u32 w[8]; /* The `prekey'. */ u32 ws[4]; u32 wt[4]; /* Initialize with key values. */ w[0] = key[0]; w[1] = key[1]; w[2] = key[2]; w[3] = key[3]; w[4] = key[4]; w[5] = key[5]; w[6] = key[6]; w[7] = key[7]; /* Expand to intermediate key using the affine recurrence. */ #define EXPAND_KEY4(wo, r) \ wo[0] = w[(r+0)%8] = \ rol (w[(r+0)%8] ^ w[(r+3)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ PHI ^ (r+0), 11); \ wo[1] = w[(r+1)%8] = \ rol (w[(r+1)%8] ^ w[(r+4)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ PHI ^ (r+1), 11); \ wo[2] = w[(r+2)%8] = \ rol (w[(r+2)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ w[(r+1)%8] ^ PHI ^ (r+2), 11); \ wo[3] = w[(r+3)%8] = \ rol (w[(r+3)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ w[(r+2)%8] ^ PHI ^ (r+3), 11); #define EXPAND_KEY(r) \ EXPAND_KEY4(ws, (r)); \ EXPAND_KEY4(wt, (r + 4)); /* Calculate subkeys via S-Boxes, in bitslice mode. */ EXPAND_KEY (0); SBOX (3, ws, subkeys[0]); SBOX (2, wt, subkeys[1]); EXPAND_KEY (8); SBOX (1, ws, subkeys[2]); SBOX (0, wt, subkeys[3]); EXPAND_KEY (16); SBOX (7, ws, subkeys[4]); SBOX (6, wt, subkeys[5]); EXPAND_KEY (24); SBOX (5, ws, subkeys[6]); SBOX (4, wt, subkeys[7]); EXPAND_KEY (32); SBOX (3, ws, subkeys[8]); SBOX (2, wt, subkeys[9]); EXPAND_KEY (40); SBOX (1, ws, subkeys[10]); SBOX (0, wt, subkeys[11]); EXPAND_KEY (48); SBOX (7, ws, subkeys[12]); SBOX (6, wt, subkeys[13]); EXPAND_KEY (56); SBOX (5, ws, subkeys[14]); SBOX (4, wt, subkeys[15]); EXPAND_KEY (64); SBOX (3, ws, subkeys[16]); SBOX (2, wt, subkeys[17]); EXPAND_KEY (72); SBOX (1, ws, subkeys[18]); SBOX (0, wt, subkeys[19]); EXPAND_KEY (80); SBOX (7, ws, subkeys[20]); SBOX (6, wt, subkeys[21]); EXPAND_KEY (88); SBOX (5, ws, subkeys[22]); SBOX (4, wt, subkeys[23]); EXPAND_KEY (96); SBOX (3, ws, subkeys[24]); SBOX (2, wt, subkeys[25]); EXPAND_KEY (104); SBOX (1, ws, subkeys[26]); SBOX (0, wt, subkeys[27]); EXPAND_KEY (112); SBOX (7, ws, subkeys[28]); SBOX (6, wt, subkeys[29]); EXPAND_KEY (120); SBOX (5, ws, subkeys[30]); SBOX (4, wt, subkeys[31]); EXPAND_KEY4 (ws, 128); SBOX (3, ws, subkeys[32]); wipememory (ws, sizeof (ws)); wipememory (wt, sizeof (wt)); wipememory (w, sizeof (w)); } /* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ static gcry_err_code_t serpent_setkey_internal (serpent_context_t *context, const byte *key, unsigned int key_length) { serpent_key_t key_prepared; if (key_length > 32) return GPG_ERR_INV_KEYLEN; serpent_key_prepare (key, key_length, key_prepared); serpent_subkeys_generate (key_prepared, context->keys); #ifdef USE_AVX2 context->use_avx2 = 0; if ((_gcry_get_hw_features () & HWF_INTEL_AVX2)) { context->use_avx2 = 1; } #endif #ifdef USE_NEON context->use_neon = 0; if ((_gcry_get_hw_features () & HWF_ARM_NEON)) { context->use_neon = 1; } #endif wipememory (key_prepared, sizeof(key_prepared)); return 0; } /* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ static gcry_err_code_t serpent_setkey (void *ctx, const byte *key, unsigned int key_length, cipher_bulk_ops_t *bulk_ops) { serpent_context_t *context = ctx; static const char *serpent_test_ret; static int serpent_init_done; gcry_err_code_t ret = GPG_ERR_NO_ERROR; if (! serpent_init_done) { /* Execute a self-test the first time, Serpent is used. */ serpent_init_done = 1; serpent_test_ret = serpent_test (); if (serpent_test_ret) log_error ("Serpent test failure: %s\n", serpent_test_ret); } /* Setup bulk encryption routines. */ memset (bulk_ops, 0, sizeof(*bulk_ops)); bulk_ops->cbc_dec = _gcry_serpent_cbc_dec; bulk_ops->cfb_dec = _gcry_serpent_cfb_dec; bulk_ops->ctr_enc = _gcry_serpent_ctr_enc; bulk_ops->ocb_crypt = _gcry_serpent_ocb_crypt; bulk_ops->ocb_auth = _gcry_serpent_ocb_auth; if (serpent_test_ret) ret = GPG_ERR_SELFTEST_FAILED; else ret = serpent_setkey_internal (context, key, key_length); return ret; } static void serpent_encrypt_internal (serpent_context_t *context, const byte *input, byte *output) { serpent_block_t b, b_next; int round = 0; b[0] = buf_get_le32 (input + 0); b[1] = buf_get_le32 (input + 4); b[2] = buf_get_le32 (input + 8); b[3] = buf_get_le32 (input + 12); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND (7, context->keys, b, b_next); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND (7, context->keys, b, b_next); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND (7, context->keys, b, b_next); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND_LAST (7, context->keys, b, b_next); buf_put_le32 (output + 0, b_next[0]); buf_put_le32 (output + 4, b_next[1]); buf_put_le32 (output + 8, b_next[2]); buf_put_le32 (output + 12, b_next[3]); } static void serpent_decrypt_internal (serpent_context_t *context, const byte *input, byte *output) { serpent_block_t b, b_next; int round = ROUNDS; b_next[0] = buf_get_le32 (input + 0); b_next[1] = buf_get_le32 (input + 4); b_next[2] = buf_get_le32 (input + 8); b_next[3] = buf_get_le32 (input + 12); ROUND_FIRST_INVERSE (7, context->keys, b_next, b); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); ROUND_INVERSE (7, context->keys, b, b_next); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); ROUND_INVERSE (7, context->keys, b, b_next); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); ROUND_INVERSE (7, context->keys, b, b_next); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); buf_put_le32 (output + 0, b_next[0]); buf_put_le32 (output + 4, b_next[1]); buf_put_le32 (output + 8, b_next[2]); buf_put_le32 (output + 12, b_next[3]); } static unsigned int serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_encrypt_internal (context, buffer_in, buffer_out); return /*burn_stack*/ (2 * sizeof (serpent_block_t)); } static unsigned int serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_decrypt_internal (context, buffer_in, buffer_out); return /*burn_stack*/ (2 * sizeof (serpent_block_t)); } /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size sizeof(serpent_block_t). */ static void _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[sizeof(serpent_block_t)]; int burn_stack_depth = 2 * sizeof (serpent_block_t); #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_serpent_avx2_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic/sse2 code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_sse2_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif #ifdef USE_NEON if (ctx->use_neon) { int did_use_neon = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_neon_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_neon = 1; } if (did_use_neon) { /* serpent-neon assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ serpent_encrypt_internal(ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ cipher_block_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); /* Increment the counter. */ cipher_block_add(ctr, 1, sizeof(serpent_block_t)); } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_serpent_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[sizeof(serpent_block_t)]; int burn_stack_depth = 2 * sizeof (serpent_block_t); #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_serpent_avx2_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic/sse2 code to handle smaller chunks... */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_sse2_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_NEON if (ctx->use_neon) { int did_use_neon = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_neon_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_neon = 1; } if (did_use_neon) { /* serpent-neon assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* INBUF is needed later and it may be identical to OUTBUF, so store the intermediate result to SAVEBUF. */ serpent_decrypt_internal (ctx, inbuf, savebuf); cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t)); inbuf += sizeof(serpent_block_t); outbuf += sizeof(serpent_block_t); } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_serpent_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 2 * sizeof (serpent_block_t); #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_serpent_avx2_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic/sse2 code to handle smaller chunks... */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_sse2_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_NEON if (ctx->use_neon) { int did_use_neon = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_neon_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_neon = 1; } if (did_use_neon) { /* serpent-neon assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { serpent_encrypt_internal(ctx, iv, iv); cipher_block_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); } _gcry_burn_stack(burn_stack_depth); } /* Bulk encryption/decryption of complete blocks in OCB mode. */ static size_t _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt) { #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON) serpent_context_t *ctx = (void *)&c->context.c; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 2 * sizeof (serpent_block_t); u64 blkn = c->u_mode.ocb.data_nblocks; #else (void)c; (void)outbuf_arg; (void)inbuf_arg; (void)encrypt; #endif #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; u64 Ls[16]; unsigned int n = 16 - (blkn % 16); u64 *l; int i; if (nblocks >= 16) { for (i = 0; i < 16; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(15 + n) % 16]; /* Process data in 16 block chunks. */ while (nblocks >= 16) { blkn += 16; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16); if (encrypt) _gcry_serpent_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_serpent_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; u64 Ls[8]; unsigned int n = 8 - (blkn % 8); u64 *l; if (nblocks >= 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; l = &Ls[(7 + n) % 8]; /* Process data in 8 block chunks. */ while (nblocks >= 8) { blkn += 8; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8); if (encrypt) _gcry_serpent_sse2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_serpent_sse2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_NEON if (ctx->use_neon) { int did_use_neon = 0; const void *Ls[8]; unsigned int n = 8 - (blkn % 8); const void **l; if (nblocks >= 8) { Ls[(0 + n) % 8] = c->u_mode.ocb.L[0]; Ls[(1 + n) % 8] = c->u_mode.ocb.L[1]; Ls[(2 + n) % 8] = c->u_mode.ocb.L[0]; Ls[(3 + n) % 8] = c->u_mode.ocb.L[2]; Ls[(4 + n) % 8] = c->u_mode.ocb.L[0]; Ls[(5 + n) % 8] = c->u_mode.ocb.L[1]; Ls[(6 + n) % 8] = c->u_mode.ocb.L[0]; l = &Ls[(7 + n) % 8]; /* Process data in 8 block chunks. */ while (nblocks >= 8) { blkn += 8; *l = ocb_get_l(c, blkn - blkn % 8); if (encrypt) _gcry_serpent_neon_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_serpent_neon_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_neon = 1; } } if (did_use_neon) { /* serpent-neon assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON) c->u_mode.ocb.data_nblocks = blkn; if (burn_stack_depth) _gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *)); #endif return nblocks; } /* Bulk authentication of complete blocks in OCB mode. */ static size_t _gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks) { #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON) serpent_context_t *ctx = (void *)&c->context.c; const unsigned char *abuf = abuf_arg; int burn_stack_depth = 2 * sizeof(serpent_block_t); u64 blkn = c->u_mode.ocb.aad_nblocks; #else (void)c; (void)abuf_arg; #endif #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; u64 Ls[16]; unsigned int n = 16 - (blkn % 16); u64 *l; int i; if (nblocks >= 16) { for (i = 0; i < 16; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(15 + n) % 16]; /* Process data in 16 block chunks. */ while (nblocks >= 16) { blkn += 16; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16); _gcry_serpent_avx2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 16; abuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; u64 Ls[8]; unsigned int n = 8 - (blkn % 8); u64 *l; if (nblocks >= 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; l = &Ls[(7 + n) % 8]; /* Process data in 8 block chunks. */ while (nblocks >= 8) { blkn += 8; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8); _gcry_serpent_sse2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 8; abuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } } if (did_use_sse2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #ifdef USE_NEON if (ctx->use_neon) { int did_use_neon = 0; const void *Ls[8]; unsigned int n = 8 - (blkn % 8); const void **l; if (nblocks >= 8) { Ls[(0 + n) % 8] = c->u_mode.ocb.L[0]; Ls[(1 + n) % 8] = c->u_mode.ocb.L[1]; Ls[(2 + n) % 8] = c->u_mode.ocb.L[0]; Ls[(3 + n) % 8] = c->u_mode.ocb.L[2]; Ls[(4 + n) % 8] = c->u_mode.ocb.L[0]; Ls[(5 + n) % 8] = c->u_mode.ocb.L[1]; Ls[(6 + n) % 8] = c->u_mode.ocb.L[0]; l = &Ls[(7 + n) % 8]; /* Process data in 8 block chunks. */ while (nblocks >= 8) { blkn += 8; *l = ocb_get_l(c, blkn - blkn % 8); _gcry_serpent_neon_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 8; abuf += 8 * sizeof(serpent_block_t); did_use_neon = 1; } } if (did_use_neon) { /* serpent-neon assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON) c->u_mode.ocb.aad_nblocks = blkn; if (burn_stack_depth) _gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *)); #endif return nblocks; } /* Run the self-tests for SERPENT-CTR-128, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char* selftest_ctr_128 (void) { const int nblocks = 16+8+1; const int blocksize = sizeof(serpent_block_t); const int context_size = sizeof(serpent_context_t); return _gcry_selftest_helper_ctr("SERPENT", &serpent_setkey, &serpent_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cbc_128 (void) { const int nblocks = 16+8+2; const int blocksize = sizeof(serpent_block_t); const int context_size = sizeof(serpent_context_t); return _gcry_selftest_helper_cbc("SERPENT", &serpent_setkey, &serpent_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cfb_128 (void) { const int nblocks = 16+8+2; const int blocksize = sizeof(serpent_block_t); const int context_size = sizeof(serpent_context_t); return _gcry_selftest_helper_cfb("SERPENT", &serpent_setkey, &serpent_encrypt, nblocks, blocksize, context_size); } /* Serpent test. */ static const char * serpent_test (void) { serpent_context_t context; unsigned char scratch[16]; unsigned int i; const char *r; static struct test { int key_length; unsigned char key[32]; unsigned char text_plain[16]; unsigned char text_cipher[16]; } test_data[] = { { 16, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E", "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D" }, { 24, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00", "\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E", "\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9" }, { 32, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E", "\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B" }, { 32, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00", "\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C" }, { 0 }, }; for (i = 0; test_data[i].key_length; i++) { serpent_setkey_internal (&context, test_data[i].key, test_data[i].key_length); serpent_encrypt_internal (&context, test_data[i].text_plain, scratch); if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) switch (test_data[i].key_length) { case 16: return "Serpent-128 test encryption failed."; case 24: return "Serpent-192 test encryption failed."; case 32: return "Serpent-256 test encryption failed."; } serpent_decrypt_internal (&context, test_data[i].text_cipher, scratch); if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) switch (test_data[i].key_length) { case 16: return "Serpent-128 test decryption failed."; case 24: return "Serpent-192 test decryption failed."; case 32: return "Serpent-256 test decryption failed."; } } if ( (r = selftest_ctr_128 ()) ) return r; if ( (r = selftest_cbc_128 ()) ) return r; if ( (r = selftest_cfb_128 ()) ) return r; return NULL; } -static gcry_cipher_oid_spec_t serpent128_oids[] = +static const gcry_cipher_oid_spec_t serpent128_oids[] = { {"1.3.6.1.4.1.11591.13.2.1", GCRY_CIPHER_MODE_ECB }, {"1.3.6.1.4.1.11591.13.2.2", GCRY_CIPHER_MODE_CBC }, {"1.3.6.1.4.1.11591.13.2.3", GCRY_CIPHER_MODE_OFB }, {"1.3.6.1.4.1.11591.13.2.4", GCRY_CIPHER_MODE_CFB }, { NULL } }; -static gcry_cipher_oid_spec_t serpent192_oids[] = +static const gcry_cipher_oid_spec_t serpent192_oids[] = { {"1.3.6.1.4.1.11591.13.2.21", GCRY_CIPHER_MODE_ECB }, {"1.3.6.1.4.1.11591.13.2.22", GCRY_CIPHER_MODE_CBC }, {"1.3.6.1.4.1.11591.13.2.23", GCRY_CIPHER_MODE_OFB }, {"1.3.6.1.4.1.11591.13.2.24", GCRY_CIPHER_MODE_CFB }, { NULL } }; -static gcry_cipher_oid_spec_t serpent256_oids[] = +static const gcry_cipher_oid_spec_t serpent256_oids[] = { {"1.3.6.1.4.1.11591.13.2.41", GCRY_CIPHER_MODE_ECB }, {"1.3.6.1.4.1.11591.13.2.42", GCRY_CIPHER_MODE_CBC }, {"1.3.6.1.4.1.11591.13.2.43", GCRY_CIPHER_MODE_OFB }, {"1.3.6.1.4.1.11591.13.2.44", GCRY_CIPHER_MODE_CFB }, { NULL } }; static const char *serpent128_aliases[] = { "SERPENT", "SERPENT-128", NULL }; static const char *serpent192_aliases[] = { "SERPENT-192", NULL }; static const char *serpent256_aliases[] = { "SERPENT-256", NULL }; gcry_cipher_spec_t _gcry_cipher_spec_serpent128 = { GCRY_CIPHER_SERPENT128, {0, 0}, "SERPENT128", serpent128_aliases, serpent128_oids, 16, 128, sizeof (serpent_context_t), serpent_setkey, serpent_encrypt, serpent_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_serpent192 = { GCRY_CIPHER_SERPENT192, {0, 0}, "SERPENT192", serpent192_aliases, serpent192_oids, 16, 192, sizeof (serpent_context_t), serpent_setkey, serpent_encrypt, serpent_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_serpent256 = { GCRY_CIPHER_SERPENT256, {0, 0}, "SERPENT256", serpent256_aliases, serpent256_oids, 16, 256, sizeof (serpent_context_t), serpent_setkey, serpent_encrypt, serpent_decrypt }; diff --git a/cipher/sha1.c b/cipher/sha1.c index 3bb24c7e..b83b9de0 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -1,768 +1,768 @@ /* sha1.c - SHA1 hash function * Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. * * 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 . */ /* Test vectors: * * "abc" * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D * * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 */ #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "sha1.h" /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ #undef USE_SSSE3 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_SSSE3 1 #endif /* USE_AVX indicates whether to compile with Intel AVX code. */ #undef USE_AVX #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX 1 #endif /* USE_BMI2 indicates whether to compile with Intel AVX/BMI2 code. */ #undef USE_BMI2 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \ defined(HAVE_GCC_INLINE_ASM_BMI2) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_BMI2 1 #endif /* USE_AVX2 indicates whether to compile with Intel AVX2/BMI2 code. */ #undef USE_AVX2 #if defined(USE_BMI2) && defined(HAVE_GCC_INLINE_ASM_AVX2) # define USE_AVX2 1 #endif /* USE_SHAEXT indicates whether to compile with Intel SHA Extension code. */ #undef USE_SHAEXT #if defined(HAVE_GCC_INLINE_ASM_SHAEXT) && \ defined(HAVE_GCC_INLINE_ASM_SSE41) && \ defined(ENABLE_SHAEXT_SUPPORT) # define USE_SHAEXT 1 #endif /* USE_NEON indicates whether to enable ARM NEON assembly code. */ #undef USE_NEON #ifdef ENABLE_NEON_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_NEON) # define USE_NEON 1 # endif #endif /* USE_ARM_CE indicates whether to enable ARMv8 Crypto Extension assembly * code. */ #undef USE_ARM_CE #ifdef ENABLE_ARM_CRYPTO_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO) # define USE_ARM_CE 1 # elif defined(__AARCH64EL__) \ && defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO) # define USE_ARM_CE 1 # endif #endif /* A macro to test whether P is properly aligned for an u32 type. Note that config.h provides a suitable replacement for uintptr_t if it does not exist in stdint.h. */ /* #if __GNUC__ >= 2 */ /* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % __alignof__ (u32))) */ /* #else */ /* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */ /* #endif */ /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #undef ASM_EXTRA_STACK #if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_BMI2) || \ defined(USE_SHAEXT) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16 + sizeof(void *) * 4) # else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 # endif #endif #ifdef USE_SSSE3 unsigned int _gcry_sha1_transform_amd64_ssse3 (void *state, const unsigned char *data, size_t nblks) ASM_FUNC_ABI; static unsigned int do_sha1_transform_amd64_ssse3 (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; return _gcry_sha1_transform_amd64_ssse3 (&hd->h0, data, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_AVX unsigned int _gcry_sha1_transform_amd64_avx (void *state, const unsigned char *data, size_t nblks) ASM_FUNC_ABI; static unsigned int do_sha1_transform_amd64_avx (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; return _gcry_sha1_transform_amd64_avx (&hd->h0, data, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_BMI2 unsigned int _gcry_sha1_transform_amd64_avx_bmi2 (void *state, const unsigned char *data, size_t nblks) ASM_FUNC_ABI; static unsigned int do_sha1_transform_amd64_avx_bmi2 (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; return _gcry_sha1_transform_amd64_avx_bmi2 (&hd->h0, data, nblks) + ASM_EXTRA_STACK; } #ifdef USE_AVX2 unsigned int _gcry_sha1_transform_amd64_avx2_bmi2 (void *state, const unsigned char *data, size_t nblks) ASM_FUNC_ABI; static unsigned int do_sha1_transform_amd64_avx2_bmi2 (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; /* AVX2/BMI2 function only handles pair of blocks so nblks needs to be * multiple of 2 and function does not handle zero nblks. Use AVX/BMI2 * code to handle these cases. */ if (nblks <= 1) return do_sha1_transform_amd64_avx_bmi2 (ctx, data, nblks); if (nblks & 1) { (void)_gcry_sha1_transform_amd64_avx_bmi2 (&hd->h0, data, 1); nblks--; data += 64; } return _gcry_sha1_transform_amd64_avx2_bmi2 (&hd->h0, data, nblks) + ASM_EXTRA_STACK; } #endif /* USE_AVX2 */ #endif /* USE_BMI2 */ #ifdef USE_SHAEXT /* Does not need ASM_FUNC_ABI */ unsigned int _gcry_sha1_transform_intel_shaext (void *state, const unsigned char *data, size_t nblks); static unsigned int do_sha1_transform_intel_shaext (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; return _gcry_sha1_transform_intel_shaext (&hd->h0, data, nblks); } #endif #ifdef USE_NEON unsigned int _gcry_sha1_transform_armv7_neon (void *state, const unsigned char *data, size_t nblks); static unsigned int do_sha1_transform_armv7_neon (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; return _gcry_sha1_transform_armv7_neon (&hd->h0, data, nblks); } #endif #ifdef USE_ARM_CE unsigned int _gcry_sha1_transform_armv8_ce (void *state, const unsigned char *data, size_t nblks); static unsigned int do_sha1_transform_armv8_ce (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; return _gcry_sha1_transform_armv8_ce (&hd->h0, data, nblks); } #endif #ifdef SHA1_USE_S390X_CRYPTO #include "asm-inline-s390x.h" static unsigned int do_sha1_transform_s390x (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; kimd_execute (KMID_FUNCTION_SHA1, &hd->h0, data, nblks * 64); return 0; } static unsigned int do_sha1_final_s390x (void *ctx, const unsigned char *data, size_t datalen, u32 len_msb, u32 len_lsb) { SHA1_CONTEXT *hd = ctx; /* Make sure that 'final_len' is positioned at correct offset relative * to 'h0'. This is because we are passing 'h0' pointer as start of * parameter block to 'klmd' instruction. */ gcry_assert (offsetof (SHA1_CONTEXT, final_len_msb) - offsetof (SHA1_CONTEXT, h0) == 5 * sizeof(u32)); gcry_assert (offsetof (SHA1_CONTEXT, final_len_lsb) - offsetof (SHA1_CONTEXT, final_len_msb) == 1 * sizeof(u32)); hd->final_len_msb = len_msb; hd->final_len_lsb = len_lsb; klmd_execute (KMID_FUNCTION_SHA1, &hd->h0, data, datalen); return 0; } #endif static unsigned int do_transform_generic (void *c, const unsigned char *data, size_t nblks); static void sha1_init (void *context, unsigned int flags) { SHA1_CONTEXT *hd = context; unsigned int features = _gcry_get_hw_features (); (void)flags; hd->h0 = 0x67452301; hd->h1 = 0xefcdab89; hd->h2 = 0x98badcfe; hd->h3 = 0x10325476; hd->h4 = 0xc3d2e1f0; hd->bctx.nblocks = 0; hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize_shift = _gcry_ctz(64); /* Order of feature checks is important here; last match will be * selected. Keep slower implementations at the top and faster at * the bottom. */ hd->bctx.bwrite = do_transform_generic; #ifdef USE_SSSE3 if ((features & HWF_INTEL_SSSE3) != 0) hd->bctx.bwrite = do_sha1_transform_amd64_ssse3; #endif #ifdef USE_AVX /* AVX implementation uses SHLD which is known to be slow on non-Intel CPUs. * Therefore use this implementation on Intel CPUs only. */ if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD)) hd->bctx.bwrite = do_sha1_transform_amd64_avx; #endif #ifdef USE_BMI2 if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_BMI2)) hd->bctx.bwrite = do_sha1_transform_amd64_avx_bmi2; #endif #ifdef USE_AVX2 if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_AVX) && (features & HWF_INTEL_BMI2)) hd->bctx.bwrite = do_sha1_transform_amd64_avx2_bmi2; #endif #ifdef USE_SHAEXT if ((features & HWF_INTEL_SHAEXT) && (features & HWF_INTEL_SSE4_1)) hd->bctx.bwrite = do_sha1_transform_intel_shaext; #endif #ifdef USE_NEON if ((features & HWF_ARM_NEON) != 0) hd->bctx.bwrite = do_sha1_transform_armv7_neon; #endif #ifdef USE_ARM_CE if ((features & HWF_ARM_SHA1) != 0) hd->bctx.bwrite = do_sha1_transform_armv8_ce; #endif #ifdef SHA1_USE_S390X_CRYPTO hd->use_s390x_crypto = 0; if ((features & HWF_S390X_MSA) != 0) { if ((kimd_query () & km_function_to_mask (KMID_FUNCTION_SHA1)) && (klmd_query () & km_function_to_mask (KMID_FUNCTION_SHA1))) { hd->bctx.bwrite = do_sha1_transform_s390x; hd->use_s390x_crypto = 1; } } #endif (void)features; } /* * Initialize the context HD. This is used to prepare the use of * _gcry_sha1_mixblock. WARNING: This is a special purpose function * for exclusive use by random-csprng.c. */ void _gcry_sha1_mixblock_init (SHA1_CONTEXT *hd) { sha1_init (hd, 0); } /* Round function macros. */ #define K1 0x5A827999L #define K2 0x6ED9EBA1L #define K3 0x8F1BBCDCL #define K4 0xCA62C1D6L #define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) #define F2(x,y,z) ( x ^ y ^ z ) #define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) #define F4(x,y,z) ( x ^ y ^ z ) #define M(i) ( tm = x[ i &0x0f] \ ^ x[(i-14)&0x0f] \ ^ x[(i-8) &0x0f] \ ^ x[(i-3) &0x0f], \ (x[i&0x0f] = rol(tm, 1))) #define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + f( b, c, d ) \ + k \ + m; \ b = rol( b, 30 ); \ } while(0) /* * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA. */ static unsigned int do_transform_generic (void *ctx, const unsigned char *data, size_t nblks) { SHA1_CONTEXT *hd = ctx; do { const u32 *idata = (const void *)data; u32 a, b, c, d, e; /* Local copies of the chaining variables. */ u32 tm; /* Helper. */ u32 x[16]; /* The array we work on. */ #define I(i) (x[i] = buf_get_be32(idata + i)) /* Get the values of the chaining variables. */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; /* Transform. */ R( a, b, c, d, e, F1, K1, I( 0) ); R( e, a, b, c, d, F1, K1, I( 1) ); R( d, e, a, b, c, F1, K1, I( 2) ); R( c, d, e, a, b, F1, K1, I( 3) ); R( b, c, d, e, a, F1, K1, I( 4) ); R( a, b, c, d, e, F1, K1, I( 5) ); R( e, a, b, c, d, F1, K1, I( 6) ); R( d, e, a, b, c, F1, K1, I( 7) ); R( c, d, e, a, b, F1, K1, I( 8) ); R( b, c, d, e, a, F1, K1, I( 9) ); R( a, b, c, d, e, F1, K1, I(10) ); R( e, a, b, c, d, F1, K1, I(11) ); R( d, e, a, b, c, F1, K1, I(12) ); R( c, d, e, a, b, F1, K1, I(13) ); R( b, c, d, e, a, F1, K1, I(14) ); R( a, b, c, d, e, F1, K1, I(15) ); R( e, a, b, c, d, F1, K1, M(16) ); R( d, e, a, b, c, F1, K1, M(17) ); R( c, d, e, a, b, F1, K1, M(18) ); R( b, c, d, e, a, F1, K1, M(19) ); R( a, b, c, d, e, F2, K2, M(20) ); R( e, a, b, c, d, F2, K2, M(21) ); R( d, e, a, b, c, F2, K2, M(22) ); R( c, d, e, a, b, F2, K2, M(23) ); R( b, c, d, e, a, F2, K2, M(24) ); R( a, b, c, d, e, F2, K2, M(25) ); R( e, a, b, c, d, F2, K2, M(26) ); R( d, e, a, b, c, F2, K2, M(27) ); R( c, d, e, a, b, F2, K2, M(28) ); R( b, c, d, e, a, F2, K2, M(29) ); R( a, b, c, d, e, F2, K2, M(30) ); R( e, a, b, c, d, F2, K2, M(31) ); R( d, e, a, b, c, F2, K2, M(32) ); R( c, d, e, a, b, F2, K2, M(33) ); R( b, c, d, e, a, F2, K2, M(34) ); R( a, b, c, d, e, F2, K2, M(35) ); R( e, a, b, c, d, F2, K2, M(36) ); R( d, e, a, b, c, F2, K2, M(37) ); R( c, d, e, a, b, F2, K2, M(38) ); R( b, c, d, e, a, F2, K2, M(39) ); R( a, b, c, d, e, F3, K3, M(40) ); R( e, a, b, c, d, F3, K3, M(41) ); R( d, e, a, b, c, F3, K3, M(42) ); R( c, d, e, a, b, F3, K3, M(43) ); R( b, c, d, e, a, F3, K3, M(44) ); R( a, b, c, d, e, F3, K3, M(45) ); R( e, a, b, c, d, F3, K3, M(46) ); R( d, e, a, b, c, F3, K3, M(47) ); R( c, d, e, a, b, F3, K3, M(48) ); R( b, c, d, e, a, F3, K3, M(49) ); R( a, b, c, d, e, F3, K3, M(50) ); R( e, a, b, c, d, F3, K3, M(51) ); R( d, e, a, b, c, F3, K3, M(52) ); R( c, d, e, a, b, F3, K3, M(53) ); R( b, c, d, e, a, F3, K3, M(54) ); R( a, b, c, d, e, F3, K3, M(55) ); R( e, a, b, c, d, F3, K3, M(56) ); R( d, e, a, b, c, F3, K3, M(57) ); R( c, d, e, a, b, F3, K3, M(58) ); R( b, c, d, e, a, F3, K3, M(59) ); R( a, b, c, d, e, F4, K4, M(60) ); R( e, a, b, c, d, F4, K4, M(61) ); R( d, e, a, b, c, F4, K4, M(62) ); R( c, d, e, a, b, F4, K4, M(63) ); R( b, c, d, e, a, F4, K4, M(64) ); R( a, b, c, d, e, F4, K4, M(65) ); R( e, a, b, c, d, F4, K4, M(66) ); R( d, e, a, b, c, F4, K4, M(67) ); R( c, d, e, a, b, F4, K4, M(68) ); R( b, c, d, e, a, F4, K4, M(69) ); R( a, b, c, d, e, F4, K4, M(70) ); R( e, a, b, c, d, F4, K4, M(71) ); R( d, e, a, b, c, F4, K4, M(72) ); R( c, d, e, a, b, F4, K4, M(73) ); R( b, c, d, e, a, F4, K4, M(74) ); R( a, b, c, d, e, F4, K4, M(75) ); R( e, a, b, c, d, F4, K4, M(76) ); R( d, e, a, b, c, F4, K4, M(77) ); R( c, d, e, a, b, F4, K4, M(78) ); R( b, c, d, e, a, F4, K4, M(79) ); /* Update the chaining variables. */ hd->h0 += a; hd->h1 += b; hd->h2 += c; hd->h3 += d; hd->h4 += e; data += 64; } while (--nblks); return 88+4*sizeof(void*); } /* * Apply the SHA-1 transform function on the buffer BLOCKOF64BYTE * which must have a length 64 bytes. BLOCKOF64BYTE must be 32-bit * aligned. Updates the 20 bytes in BLOCKOF64BYTE with its mixed * content. Returns the number of bytes which should be burned on the * stack. You need to use _gcry_sha1_mixblock_init to initialize the * context. * WARNING: This is a special purpose function for exclusive use by * random-csprng.c. */ unsigned int _gcry_sha1_mixblock (SHA1_CONTEXT *hd, void *blockof64byte) { u32 *p = blockof64byte; unsigned int nburn; nburn = (*hd->bctx.bwrite) (hd, blockof64byte, 1); p[0] = hd->h0; p[1] = hd->h1; p[2] = hd->h2; p[3] = hd->h3; p[4] = hd->h4; return nburn; } /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the * handle will the destroy the returned buffer. * Returns: 20 bytes representing the digest. */ static void sha1_final(void *context) { SHA1_CONTEXT *hd = context; u32 t, th, msb, lsb; unsigned char *p; unsigned int burn; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (0) { } #ifdef SHA1_USE_S390X_CRYPTO else if (hd->use_s390x_crypto) { burn = do_sha1_final_s390x (hd, hd->bctx.buf, hd->bctx.count, msb, lsb); } #endif else if (hd->bctx.count < 56) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_be32(hd->bctx.buf + 56, msb); buf_put_be32(hd->bctx.buf + 60, lsb); burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 1 ); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_be32(hd->bctx.buf + 64 + 56, msb); buf_put_be32(hd->bctx.buf + 64 + 60, lsb); burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 2 ); } p = hd->bctx.buf; #define X(a) do { buf_put_be32(p, hd->h##a); p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static unsigned char * sha1_read( void *context ) { SHA1_CONTEXT *hd = context; return hd->bctx.buf; } /**************** * Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 20 bytes. */ static void _gcry_sha1_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA1_CONTEXT hd; (void)nbytes; sha1_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha1_final (&hd); memcpy (outbuf, hd.bctx.buf, 20); } /* Variant of the above shortcut function using a single buffer. */ void _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) { gcry_buffer_t iov = { 0 }; iov.data = (void *)buffer; iov.len = length; _gcry_sha1_hash_buffers (outbuf, 20, &iov, 1); } /* Self-test section. */ static gpg_err_code_t selftests_sha1 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA1, 0, "abc", 3, "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", 20); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA1, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE" "\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", 20); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA1, 1, NULL, 0, "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F", 20); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA1, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA1: ec = selftests_sha1 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } -static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */ +static const unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; -static gcry_md_oid_spec_t oid_spec_sha1[] = +static const gcry_md_oid_spec_t oid_spec_sha1[] = { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */ { "1.2.840.113549.1.1.5" }, /* iso.member-body.us.x9-57.x9cm.3 (dsaWithSha1)*/ { "1.2.840.10040.4.3" }, /* from NIST's OIW (sha1) */ { "1.3.14.3.2.26" }, /* from NIST OIW (sha-1WithRSAEncryption) */ { "1.3.14.3.2.29" }, /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */ { "1.2.840.10045.4.1" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_sha1 = +const gcry_md_spec_t _gcry_digest_spec_sha1 = { GCRY_MD_SHA1, {0, 1}, "SHA1", asn, DIM (asn), oid_spec_sha1, 20, sha1_init, _gcry_md_block_write, sha1_final, sha1_read, NULL, _gcry_sha1_hash_buffers, sizeof (SHA1_CONTEXT), run_selftests }; diff --git a/cipher/sha256.c b/cipher/sha256.c index 74f7fdf0..642711af 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -1,837 +1,837 @@ /* sha256.c - SHA256 hash function * Copyright (C) 2003, 2006, 2008, 2009 Free Software Foundation, Inc. * * 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 . */ /* Test vectors: "abc" SHA224: 23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7 SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" SHA224: 75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525 SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 "a" one million times SHA224: 20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67 SHA256: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0 */ #include #include #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ #undef USE_SSSE3 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \ defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_SSSE3 1 #endif /* USE_AVX indicates whether to compile with Intel AVX code. */ #undef USE_AVX #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \ defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX 1 #endif /* USE_AVX2 indicates whether to compile with Intel AVX2/BMI2 code. */ #undef USE_AVX2 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \ defined(HAVE_GCC_INLINE_ASM_BMI2) && \ defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX2 1 #endif /* USE_SHAEXT indicates whether to compile with Intel SHA Extension code. */ #undef USE_SHAEXT #if defined(HAVE_GCC_INLINE_ASM_SHAEXT) && \ defined(HAVE_GCC_INLINE_ASM_SSE41) && \ defined(ENABLE_SHAEXT_SUPPORT) # define USE_SHAEXT 1 #endif /* USE_ARM_CE indicates whether to enable ARMv8 Crypto Extension assembly * code. */ #undef USE_ARM_CE #ifdef ENABLE_ARM_CRYPTO_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO) # define USE_ARM_CE 1 # elif defined(__AARCH64EL__) \ && defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO) # define USE_ARM_CE 1 # endif #endif /* USE_PPC_CRYPTO indicates whether to enable PowerPC vector crypto * accelerated code. */ #undef USE_PPC_CRYPTO #ifdef ENABLE_PPC_CRYPTO_SUPPORT # if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) # if __GNUC__ >= 4 # define USE_PPC_CRYPTO 1 # endif # endif #endif /* USE_S390X_CRYPTO indicates whether to enable zSeries code. */ #undef USE_S390X_CRYPTO #if defined(HAVE_GCC_INLINE_ASM_S390X) # define USE_S390X_CRYPTO 1 #endif /* USE_S390X_CRYPTO */ typedef struct { gcry_md_block_ctx_t bctx; u32 h[8]; #ifdef USE_S390X_CRYPTO u32 final_len_msb, final_len_lsb; /* needs to be right after h[7]. */ int use_s390x_crypto; #endif } SHA256_CONTEXT; /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #undef ASM_EXTRA_STACK #if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_AVX2) || \ defined(USE_SHAEXT) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16 + sizeof(void *) * 4) # else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 # endif #endif #ifdef USE_SSSE3 unsigned int _gcry_sha256_transform_amd64_ssse3(const void *input_data, u32 state[8], size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sha256_transform_amd64_ssse3(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_amd64_ssse3 (data, hd->h, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_AVX unsigned int _gcry_sha256_transform_amd64_avx(const void *input_data, u32 state[8], size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sha256_transform_amd64_avx(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_amd64_avx (data, hd->h, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_AVX2 unsigned int _gcry_sha256_transform_amd64_avx2(const void *input_data, u32 state[8], size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sha256_transform_amd64_avx2(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_amd64_avx2 (data, hd->h, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_SHAEXT /* Does not need ASM_FUNC_ABI */ unsigned int _gcry_sha256_transform_intel_shaext(u32 state[8], const unsigned char *input_data, size_t num_blks); static unsigned int do_sha256_transform_intel_shaext(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_intel_shaext (hd->h, data, nblks); } #endif #ifdef USE_ARM_CE unsigned int _gcry_sha256_transform_armv8_ce(u32 state[8], const void *input_data, size_t num_blks); static unsigned int do_sha256_transform_armv8_ce(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_armv8_ce (hd->h, data, nblks); } #endif #ifdef USE_PPC_CRYPTO unsigned int _gcry_sha256_transform_ppc8(u32 state[8], const unsigned char *input_data, size_t num_blks); unsigned int _gcry_sha256_transform_ppc9(u32 state[8], const unsigned char *input_data, size_t num_blks); static unsigned int do_sha256_transform_ppc8(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_ppc8 (hd->h, data, nblks); } static unsigned int do_sha256_transform_ppc9(void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; return _gcry_sha256_transform_ppc9 (hd->h, data, nblks); } #endif #ifdef USE_S390X_CRYPTO #include "asm-inline-s390x.h" static unsigned int do_sha256_transform_s390x (void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; kimd_execute (KMID_FUNCTION_SHA256, hd->h, data, nblks * 64); return 0; } static unsigned int do_sha256_final_s390x (void *ctx, const unsigned char *data, size_t datalen, u32 len_msb, u32 len_lsb) { SHA256_CONTEXT *hd = ctx; /* Make sure that 'final_len' is positioned at correct offset relative * to 'h[0]'. This is because we are passing 'h[0]' pointer as start of * parameter block to 'klmd' instruction. */ gcry_assert (offsetof (SHA256_CONTEXT, final_len_msb) - offsetof (SHA256_CONTEXT, h[0]) == 8 * sizeof(u32)); gcry_assert (offsetof (SHA256_CONTEXT, final_len_lsb) - offsetof (SHA256_CONTEXT, final_len_msb) == 1 * sizeof(u32)); hd->final_len_msb = len_msb; hd->final_len_lsb = len_lsb; klmd_execute (KMID_FUNCTION_SHA256, hd->h, data, datalen); return 0; } #endif static unsigned int do_transform_generic (void *ctx, const unsigned char *data, size_t nblks); static void sha256_common_init (SHA256_CONTEXT *hd) { unsigned int features = _gcry_get_hw_features (); hd->bctx.nblocks = 0; hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize_shift = _gcry_ctz(64); /* Order of feature checks is important here; last match will be * selected. Keep slower implementations at the top and faster at * the bottom. */ hd->bctx.bwrite = do_transform_generic; #ifdef USE_SSSE3 if ((features & HWF_INTEL_SSSE3) != 0) hd->bctx.bwrite = do_sha256_transform_amd64_ssse3; #endif #ifdef USE_AVX /* AVX implementation uses SHLD which is known to be slow on non-Intel CPUs. * Therefore use this implementation on Intel CPUs only. */ if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD)) hd->bctx.bwrite = do_sha256_transform_amd64_avx; #endif #ifdef USE_AVX2 if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2)) hd->bctx.bwrite = do_sha256_transform_amd64_avx2; #endif #ifdef USE_SHAEXT if ((features & HWF_INTEL_SHAEXT) && (features & HWF_INTEL_SSE4_1)) hd->bctx.bwrite = do_sha256_transform_intel_shaext; #endif #ifdef USE_ARM_CE if ((features & HWF_ARM_SHA2) != 0) hd->bctx.bwrite = do_sha256_transform_armv8_ce; #endif #ifdef USE_PPC_CRYPTO if ((features & HWF_PPC_VCRYPTO) != 0) hd->bctx.bwrite = do_sha256_transform_ppc8; if ((features & HWF_PPC_VCRYPTO) != 0 && (features & HWF_PPC_ARCH_3_00) != 0) hd->bctx.bwrite = do_sha256_transform_ppc9; #endif #ifdef USE_S390X_CRYPTO hd->use_s390x_crypto = 0; if ((features & HWF_S390X_MSA) != 0) { if ((kimd_query () & km_function_to_mask (KMID_FUNCTION_SHA256)) && (klmd_query () & km_function_to_mask (KMID_FUNCTION_SHA256))) { hd->bctx.bwrite = do_sha256_transform_s390x; hd->use_s390x_crypto = 1; } } #endif (void)features; } static void sha256_init (void *context, unsigned int flags) { SHA256_CONTEXT *hd = context; (void)flags; hd->h[0] = 0x6a09e667; hd->h[1] = 0xbb67ae85; hd->h[2] = 0x3c6ef372; hd->h[3] = 0xa54ff53a; hd->h[4] = 0x510e527f; hd->h[5] = 0x9b05688c; hd->h[6] = 0x1f83d9ab; hd->h[7] = 0x5be0cd19; sha256_common_init (hd); } static void sha224_init (void *context, unsigned int flags) { SHA256_CONTEXT *hd = context; (void)flags; hd->h[0] = 0xc1059ed8; hd->h[1] = 0x367cd507; hd->h[2] = 0x3070dd17; hd->h[3] = 0xf70e5939; hd->h[4] = 0xffc00b31; hd->h[5] = 0x68581511; hd->h[6] = 0x64f98fa7; hd->h[7] = 0xbefa4fa4; sha256_common_init (hd); } /* Transform the message X which consists of 16 32-bit-words. See FIPS 180-2 for details. */ #define R(a,b,c,d,e,f,g,h,k,w) do \ { \ t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \ t2 = Sum0((a)) + Maj((a),(b),(c)); \ d += t1; \ h = t1 + t2; \ } while (0) /* (4.2) same as SHA-1's F1. */ #define Cho(x, y, z) (z ^ (x & (y ^ z))) /* (4.3) same as SHA-1's F3 */ #define Maj(x, y, z) ((x & y) + (z & (x ^ y))) /* (4.4) */ #define Sum0(x) (ror (x, 2) ^ ror (x, 13) ^ ror (x, 22)) /* (4.5) */ #define Sum1(x) (ror (x, 6) ^ ror (x, 11) ^ ror (x, 25)) /* Message expansion */ #define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ #define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ #define I(i) ( w[i] = buf_get_be32(data + i * 4) ) #define W(i) ( w[i&0x0f] = S1(w[(i-2) &0x0f]) \ + w[(i-7) &0x0f] \ + S0(w[(i-15)&0x0f]) \ + w[(i-16)&0x0f] ) static unsigned int do_transform_generic (void *ctx, const unsigned char *data, size_t nblks) { SHA256_CONTEXT *hd = ctx; static const u32 K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; do { u32 a,b,c,d,e,f,g,h,t1,t2; u32 w[16]; a = hd->h[0]; b = hd->h[1]; c = hd->h[2]; d = hd->h[3]; e = hd->h[4]; f = hd->h[5]; g = hd->h[6]; h = hd->h[7]; R(a, b, c, d, e, f, g, h, K[0], I(0)); R(h, a, b, c, d, e, f, g, K[1], I(1)); R(g, h, a, b, c, d, e, f, K[2], I(2)); R(f, g, h, a, b, c, d, e, K[3], I(3)); R(e, f, g, h, a, b, c, d, K[4], I(4)); R(d, e, f, g, h, a, b, c, K[5], I(5)); R(c, d, e, f, g, h, a, b, K[6], I(6)); R(b, c, d, e, f, g, h, a, K[7], I(7)); R(a, b, c, d, e, f, g, h, K[8], I(8)); R(h, a, b, c, d, e, f, g, K[9], I(9)); R(g, h, a, b, c, d, e, f, K[10], I(10)); R(f, g, h, a, b, c, d, e, K[11], I(11)); R(e, f, g, h, a, b, c, d, K[12], I(12)); R(d, e, f, g, h, a, b, c, K[13], I(13)); R(c, d, e, f, g, h, a, b, K[14], I(14)); R(b, c, d, e, f, g, h, a, K[15], I(15)); R(a, b, c, d, e, f, g, h, K[16], W(16)); R(h, a, b, c, d, e, f, g, K[17], W(17)); R(g, h, a, b, c, d, e, f, K[18], W(18)); R(f, g, h, a, b, c, d, e, K[19], W(19)); R(e, f, g, h, a, b, c, d, K[20], W(20)); R(d, e, f, g, h, a, b, c, K[21], W(21)); R(c, d, e, f, g, h, a, b, K[22], W(22)); R(b, c, d, e, f, g, h, a, K[23], W(23)); R(a, b, c, d, e, f, g, h, K[24], W(24)); R(h, a, b, c, d, e, f, g, K[25], W(25)); R(g, h, a, b, c, d, e, f, K[26], W(26)); R(f, g, h, a, b, c, d, e, K[27], W(27)); R(e, f, g, h, a, b, c, d, K[28], W(28)); R(d, e, f, g, h, a, b, c, K[29], W(29)); R(c, d, e, f, g, h, a, b, K[30], W(30)); R(b, c, d, e, f, g, h, a, K[31], W(31)); R(a, b, c, d, e, f, g, h, K[32], W(32)); R(h, a, b, c, d, e, f, g, K[33], W(33)); R(g, h, a, b, c, d, e, f, K[34], W(34)); R(f, g, h, a, b, c, d, e, K[35], W(35)); R(e, f, g, h, a, b, c, d, K[36], W(36)); R(d, e, f, g, h, a, b, c, K[37], W(37)); R(c, d, e, f, g, h, a, b, K[38], W(38)); R(b, c, d, e, f, g, h, a, K[39], W(39)); R(a, b, c, d, e, f, g, h, K[40], W(40)); R(h, a, b, c, d, e, f, g, K[41], W(41)); R(g, h, a, b, c, d, e, f, K[42], W(42)); R(f, g, h, a, b, c, d, e, K[43], W(43)); R(e, f, g, h, a, b, c, d, K[44], W(44)); R(d, e, f, g, h, a, b, c, K[45], W(45)); R(c, d, e, f, g, h, a, b, K[46], W(46)); R(b, c, d, e, f, g, h, a, K[47], W(47)); R(a, b, c, d, e, f, g, h, K[48], W(48)); R(h, a, b, c, d, e, f, g, K[49], W(49)); R(g, h, a, b, c, d, e, f, K[50], W(50)); R(f, g, h, a, b, c, d, e, K[51], W(51)); R(e, f, g, h, a, b, c, d, K[52], W(52)); R(d, e, f, g, h, a, b, c, K[53], W(53)); R(c, d, e, f, g, h, a, b, K[54], W(54)); R(b, c, d, e, f, g, h, a, K[55], W(55)); R(a, b, c, d, e, f, g, h, K[56], W(56)); R(h, a, b, c, d, e, f, g, K[57], W(57)); R(g, h, a, b, c, d, e, f, K[58], W(58)); R(f, g, h, a, b, c, d, e, K[59], W(59)); R(e, f, g, h, a, b, c, d, K[60], W(60)); R(d, e, f, g, h, a, b, c, K[61], W(61)); R(c, d, e, f, g, h, a, b, K[62], W(62)); R(b, c, d, e, f, g, h, a, K[63], W(63)); hd->h[0] += a; hd->h[1] += b; hd->h[2] += c; hd->h[3] += d; hd->h[4] += e; hd->h[5] += f; hd->h[6] += g; hd->h[7] += h; data += 64; } while (--nblks); return 26*4 + 32 + 3 * sizeof(void*); } #undef S0 #undef S1 #undef R /* The routine finally terminates the computation and returns the digest. The handle is prepared for a new cycle, but adding bytes to the handle will the destroy the returned buffer. Returns: 32 bytes with the message the digest. */ static void sha256_final(void *context) { SHA256_CONTEXT *hd = context; u32 t, th, msb, lsb; byte *p; unsigned int burn; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (0) { } #ifdef USE_S390X_CRYPTO else if (hd->use_s390x_crypto) { burn = do_sha256_final_s390x (hd, hd->bctx.buf, hd->bctx.count, msb, lsb); } #endif else if (hd->bctx.count < 56) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_be32(hd->bctx.buf + 56, msb); buf_put_be32(hd->bctx.buf + 60, lsb); burn = (*hd->bctx.bwrite) (hd, hd->bctx.buf, 1); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_be32(hd->bctx.buf + 64 + 56, msb); buf_put_be32(hd->bctx.buf + 64 + 60, lsb); burn = (*hd->bctx.bwrite) (hd, hd->bctx.buf, 2); } p = hd->bctx.buf; #define X(a) do { buf_put_be32(p, hd->h[a]); p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * sha256_read (void *context) { SHA256_CONTEXT *hd = context; return hd->bctx.buf; } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void _gcry_sha256_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA256_CONTEXT hd; (void)nbytes; sha256_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha256_final (&hd); memcpy (outbuf, hd.bctx.buf, 32); } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 28 bytes. */ static void _gcry_sha224_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA256_CONTEXT hd; (void)nbytes; sha224_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha256_final (&hd); memcpy (outbuf, hd.bctx.buf, 28); } /* Self-test section. */ static gpg_err_code_t selftests_sha224 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA224, 0, "abc", 3, "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3" "\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA224, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50" "\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25", 28); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA224, 1, NULL, 0, "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67", 28); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA224, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha256 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA256, 0, "abc", 3, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA256, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", 32); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA256, 1, NULL, 0, "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0", 32); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA256, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA224: ec = selftests_sha224 (extended, report); break; case GCRY_MD_SHA256: ec = selftests_sha256 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } -static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */ +static const byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */ { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C }; -static gcry_md_oid_spec_t oid_spec_sha224[] = +static const gcry_md_oid_spec_t oid_spec_sha224[] = { /* From RFC3874, Section 4 */ { "2.16.840.1.101.3.4.2.4" }, { NULL }, }; -static byte asn256[19] = /* Object ID is 2.16.840.1.101.3.4.2.1 */ +static const byte asn256[19] = /* Object ID is 2.16.840.1.101.3.4.2.1 */ { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; -static gcry_md_oid_spec_t oid_spec_sha256[] = +static const gcry_md_oid_spec_t oid_spec_sha256[] = { /* According to the OpenPGP draft rfc2440-bis06 */ { "2.16.840.1.101.3.4.2.1" }, /* PKCS#1 sha256WithRSAEncryption */ { "1.2.840.113549.1.1.11" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_sha224 = +const gcry_md_spec_t _gcry_digest_spec_sha224 = { GCRY_MD_SHA224, {0, 1}, "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28, sha224_init, _gcry_md_block_write, sha256_final, sha256_read, NULL, _gcry_sha224_hash_buffers, sizeof (SHA256_CONTEXT), run_selftests }; -gcry_md_spec_t _gcry_digest_spec_sha256 = +const gcry_md_spec_t _gcry_digest_spec_sha256 = { GCRY_MD_SHA256, {0, 1}, "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32, sha256_init, _gcry_md_block_write, sha256_final, sha256_read, NULL, _gcry_sha256_hash_buffers, sizeof (SHA256_CONTEXT), run_selftests }; diff --git a/cipher/sha512.c b/cipher/sha512.c index 2d4f58e0..9cab33d6 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -1,1284 +1,1284 @@ /* sha512.c - SHA384 and SHA512 hash functions * Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc. * * 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 . */ /* Test vectors from FIPS-180-2: * * "abc" * 384: * CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163 * 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7 * 512: * DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A * 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F * * "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" * 384: * 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2 * 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039 * 512: * 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018 * 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909 * * "a" x 1000000 * 384: * 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852 * 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985 * 512: * E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB * DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B */ #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */ #undef USE_ARM_NEON_ASM #ifdef ENABLE_NEON_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_NEON) # define USE_ARM_NEON_ASM 1 # endif #endif /*ENABLE_NEON_SUPPORT*/ /* USE_ARM_ASM indicates whether to enable ARM assembly code. */ #undef USE_ARM_ASM #if defined(__ARMEL__) && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) # define USE_ARM_ASM 1 #endif /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ #undef USE_SSSE3 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \ defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_SSSE3 1 #endif /* USE_AVX indicates whether to compile with Intel AVX code. */ #undef USE_AVX #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \ defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX 1 #endif /* USE_AVX2 indicates whether to compile with Intel AVX2/rorx code. */ #undef USE_AVX2 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \ defined(HAVE_GCC_INLINE_ASM_BMI2) && \ defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX2 1 #endif /* USE_SSSE3_I386 indicates whether to compile with Intel SSSE3/i386 code. */ #undef USE_SSSE3_I386 #if defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \ defined(HAVE_GCC_INLINE_ASM_SSSE3) # define USE_SSSE3_I386 1 #endif /* USE_PPC_CRYPTO indicates whether to enable PowerPC vector crypto * accelerated code. */ #undef USE_PPC_CRYPTO #ifdef ENABLE_PPC_CRYPTO_SUPPORT # if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \ defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) # if __GNUC__ >= 4 # define USE_PPC_CRYPTO 1 # endif # endif #endif /* USE_S390X_CRYPTO indicates whether to enable zSeries code. */ #undef USE_S390X_CRYPTO #if defined(HAVE_GCC_INLINE_ASM_S390X) # define USE_S390X_CRYPTO 1 #endif /* USE_S390X_CRYPTO */ typedef struct { u64 h[8]; } SHA512_STATE; typedef struct { gcry_md_block_ctx_t bctx; SHA512_STATE state; #ifdef USE_S390X_CRYPTO u64 final_len_msb, final_len_lsb; /* needs to be right after state.h[7]. */ int use_s390x_crypto; #endif } SHA512_CONTEXT; static const u64 k[] = { U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc), U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019), U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118), U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe), U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2), U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1), U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694), U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3), U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65), U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483), U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5), U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210), U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4), U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725), U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70), U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926), U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df), U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8), U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b), U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001), U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30), U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910), U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8), U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53), U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8), U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb), U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3), U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60), U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec), U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9), U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b), U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207), U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178), U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6), U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b), U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493), U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c), U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a), U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) }; /* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #undef ASM_EXTRA_STACK #if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_AVX2) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16 + 4 * sizeof(void *)) # else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 # endif #endif #ifdef USE_ARM_NEON_ASM unsigned int _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd, const unsigned char *data, const u64 k[], size_t num_blks); static unsigned int do_sha512_transform_armv7_neon(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_armv7_neon (&hd->state, data, k, nblks); } #endif #ifdef USE_SSSE3 unsigned int _gcry_sha512_transform_amd64_ssse3(const void *input_data, void *state, size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sha512_transform_amd64_ssse3(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_amd64_ssse3 (data, &hd->state, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_AVX unsigned int _gcry_sha512_transform_amd64_avx(const void *input_data, void *state, size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sha512_transform_amd64_avx(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_amd64_avx (data, &hd->state, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_AVX2 unsigned int _gcry_sha512_transform_amd64_avx2(const void *input_data, void *state, size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sha512_transform_amd64_avx2(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_amd64_avx2 (data, &hd->state, nblks) + ASM_EXTRA_STACK; } #endif #ifdef USE_SSSE3_I386 unsigned int _gcry_sha512_transform_i386_ssse3(u64 state[8], const unsigned char *input_data, size_t num_blks); static unsigned int do_sha512_transform_i386_ssse3(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_i386_ssse3 (hd->state.h, data, nblks); } #endif #ifdef USE_ARM_ASM unsigned int _gcry_sha512_transform_arm (SHA512_STATE *hd, const unsigned char *data, const u64 k[], size_t num_blks); static unsigned int do_transform_generic (void *context, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = context; return _gcry_sha512_transform_arm (&hd->state, data, k, nblks); } #else static unsigned int do_transform_generic (void *context, const unsigned char *data, size_t nblks); #endif #ifdef USE_PPC_CRYPTO unsigned int _gcry_sha512_transform_ppc8(u64 state[8], const unsigned char *input_data, size_t num_blks); unsigned int _gcry_sha512_transform_ppc9(u64 state[8], const unsigned char *input_data, size_t num_blks); static unsigned int do_sha512_transform_ppc8(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_ppc8 (hd->state.h, data, nblks); } static unsigned int do_sha512_transform_ppc9(void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; return _gcry_sha512_transform_ppc9 (hd->state.h, data, nblks); } #endif #ifdef USE_S390X_CRYPTO #include "asm-inline-s390x.h" static unsigned int do_sha512_transform_s390x (void *ctx, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *hd = ctx; kimd_execute (KMID_FUNCTION_SHA512, hd->state.h, data, nblks * 128); return 0; } static unsigned int do_sha512_final_s390x (void *ctx, const unsigned char *data, size_t datalen, u64 len_msb, u64 len_lsb) { SHA512_CONTEXT *hd = ctx; /* Make sure that 'final_len' is positioned at correct offset relative * to 'state.h[0]'. This is because we are passing 'state.h[0]' pointer as * start of parameter block to 'klmd' instruction. */ gcry_assert (offsetof (SHA512_CONTEXT, final_len_msb) - offsetof (SHA512_CONTEXT, state.h[0]) == 8 * sizeof(u64)); gcry_assert (offsetof (SHA512_CONTEXT, final_len_lsb) - offsetof (SHA512_CONTEXT, final_len_msb) == 1 * sizeof(u64)); hd->final_len_msb = len_msb; hd->final_len_lsb = len_lsb; klmd_execute (KMID_FUNCTION_SHA512, hd->state.h, data, datalen); return 0; } #endif static void sha512_init_common (SHA512_CONTEXT *ctx, unsigned int flags) { unsigned int features = _gcry_get_hw_features (); (void)flags; (void)k; ctx->bctx.nblocks = 0; ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize_shift = _gcry_ctz(128); /* Order of feature checks is important here; last match will be * selected. Keep slower implementations at the top and faster at * the bottom. */ ctx->bctx.bwrite = do_transform_generic; #ifdef USE_ARM_NEON_ASM if ((features & HWF_ARM_NEON) != 0) ctx->bctx.bwrite = do_sha512_transform_armv7_neon; #endif #ifdef USE_SSSE3 if ((features & HWF_INTEL_SSSE3) != 0) ctx->bctx.bwrite = do_sha512_transform_amd64_ssse3; #endif #ifdef USE_AVX if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD)) ctx->bctx.bwrite = do_sha512_transform_amd64_avx; #endif #ifdef USE_AVX2 if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2)) ctx->bctx.bwrite = do_sha512_transform_amd64_avx2; #endif #ifdef USE_PPC_CRYPTO if ((features & HWF_PPC_VCRYPTO) != 0) ctx->bctx.bwrite = do_sha512_transform_ppc8; if ((features & HWF_PPC_VCRYPTO) != 0 && (features & HWF_PPC_ARCH_3_00) != 0) ctx->bctx.bwrite = do_sha512_transform_ppc9; #endif #ifdef USE_SSSE3_I386 if ((features & HWF_INTEL_SSSE3) != 0) ctx->bctx.bwrite = do_sha512_transform_i386_ssse3; #endif #ifdef USE_S390X_CRYPTO ctx->use_s390x_crypto = 0; if ((features & HWF_S390X_MSA) != 0) { if ((kimd_query () & km_function_to_mask (KMID_FUNCTION_SHA512)) && (klmd_query () & km_function_to_mask (KMID_FUNCTION_SHA512))) { ctx->bctx.bwrite = do_sha512_transform_s390x; ctx->use_s390x_crypto = 1; } } #endif (void)features; } static void sha512_init (void *context, unsigned int flags) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; hd->h[0] = U64_C(0x6a09e667f3bcc908); hd->h[1] = U64_C(0xbb67ae8584caa73b); hd->h[2] = U64_C(0x3c6ef372fe94f82b); hd->h[3] = U64_C(0xa54ff53a5f1d36f1); hd->h[4] = U64_C(0x510e527fade682d1); hd->h[5] = U64_C(0x9b05688c2b3e6c1f); hd->h[6] = U64_C(0x1f83d9abfb41bd6b); hd->h[7] = U64_C(0x5be0cd19137e2179); sha512_init_common (ctx, flags); } static void sha384_init (void *context, unsigned int flags) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; hd->h[0] = U64_C(0xcbbb9d5dc1059ed8); hd->h[1] = U64_C(0x629a292a367cd507); hd->h[2] = U64_C(0x9159015a3070dd17); hd->h[3] = U64_C(0x152fecd8f70e5939); hd->h[4] = U64_C(0x67332667ffc00b31); hd->h[5] = U64_C(0x8eb44a8768581511); hd->h[6] = U64_C(0xdb0c2e0d64f98fa7); hd->h[7] = U64_C(0x47b5481dbefa4fa4); sha512_init_common (ctx, flags); } static void sha512_256_init (void *context, unsigned int flags) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; hd->h[0] = U64_C(0x22312194fc2bf72c); hd->h[1] = U64_C(0x9f555fa3c84c64c2); hd->h[2] = U64_C(0x2393b86b6f53b151); hd->h[3] = U64_C(0x963877195940eabd); hd->h[4] = U64_C(0x96283ee2a88effe3); hd->h[5] = U64_C(0xbe5e1e2553863992); hd->h[6] = U64_C(0x2b0199fc2c85b8aa); hd->h[7] = U64_C(0x0eb72ddc81c52ca2); sha512_init_common (ctx, flags); } static void sha512_224_init (void *context, unsigned int flags) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; hd->h[0] = U64_C(0x8c3d37c819544da2); hd->h[1] = U64_C(0x73e1996689dcd4d6); hd->h[2] = U64_C(0x1dfab7ae32ff9c82); hd->h[3] = U64_C(0x679dd514582f9fcf); hd->h[4] = U64_C(0x0f6d2b697bd44da8); hd->h[5] = U64_C(0x77e36f7304c48942); hd->h[6] = U64_C(0x3f9d85a86a1d36c8); hd->h[7] = U64_C(0x1112e6ad91d692a1); sha512_init_common (ctx, flags); } #ifndef USE_ARM_ASM static inline u64 ROTR (u64 x, u64 n) { return ((x >> n) | (x << (64 - n))); } static inline u64 Ch (u64 x, u64 y, u64 z) { return ((x & y) ^ ( ~x & z)); } static inline u64 Maj (u64 x, u64 y, u64 z) { return ((x & y) ^ (x & z) ^ (y & z)); } static inline u64 Sum0 (u64 x) { return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39)); } static inline u64 Sum1 (u64 x) { return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); } /**************** * Transform the message W which consists of 16 64-bit-words */ static unsigned int do_transform_generic (void *context, const unsigned char *data, size_t nblks) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; do { u64 a, b, c, d, e, f, g, h; u64 w[16]; int t; /* get values from the chaining vars */ a = hd->h[0]; b = hd->h[1]; c = hd->h[2]; d = hd->h[3]; e = hd->h[4]; f = hd->h[5]; g = hd->h[6]; h = hd->h[7]; for ( t = 0; t < 16; t++ ) w[t] = buf_get_be64(data + t * 8); #define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) #define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) for (t = 0; t < 80 - 16; ) { u64 t1, t2; t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0]; w[0] += S1 (w[14]) + w[9] + S0 (w[1]); t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1]; w[1] += S1 (w[15]) + w[10] + S0 (w[2]); t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2]; w[2] += S1 (w[0]) + w[11] + S0 (w[3]); t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3]; w[3] += S1 (w[1]) + w[12] + S0 (w[4]); t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4]; w[4] += S1 (w[2]) + w[13] + S0 (w[5]); t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5]; w[5] += S1 (w[3]) + w[14] + S0 (w[6]); t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6]; w[6] += S1 (w[4]) + w[15] + S0 (w[7]); t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7]; w[7] += S1 (w[5]) + w[0] + S0 (w[8]); t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8]; w[8] += S1 (w[6]) + w[1] + S0 (w[9]); t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9]; w[9] += S1 (w[7]) + w[2] + S0 (w[10]); t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10]; w[10] += S1 (w[8]) + w[3] + S0 (w[11]); t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11]; w[11] += S1 (w[9]) + w[4] + S0 (w[12]); t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12]; w[12] += S1 (w[10]) + w[5] + S0 (w[13]); t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13]; w[13] += S1 (w[11]) + w[6] + S0 (w[14]); t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14]; w[14] += S1 (w[12]) + w[7] + S0 (w[15]); t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15]; w[15] += S1 (w[13]) + w[8] + S0 (w[0]); t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t += 16; } for (; t < 80; ) { u64 t1, t2; t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0]; t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1]; t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2]; t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3]; t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4]; t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5]; t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6]; t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7]; t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8]; t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9]; t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10]; t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11]; t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12]; t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13]; t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14]; t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15]; t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t += 16; } /* Update chaining vars. */ hd->h[0] += a; hd->h[1] += b; hd->h[2] += c; hd->h[3] += d; hd->h[4] += e; hd->h[5] += f; hd->h[6] += g; hd->h[7] += h; data += 128; } while (--nblks); return (8 + 16) * sizeof(u64) + sizeof(u32) + 3 * sizeof(void*); } #endif /*!USE_ARM_ASM*/ /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the * handle will the destroy the returned buffer. * Returns: 64 bytes representing the digest. When used for sha384, * we take the leftmost 48 of those bytes. */ static void sha512_final (void *context) { SHA512_CONTEXT *hd = context; unsigned int burn; u64 t, th, msb, lsb; byte *p; t = hd->bctx.nblocks; /* if (sizeof t == sizeof hd->bctx.nblocks) */ th = hd->bctx.nblocks_high; /* else */ /* th = hd->bctx.nblocks >> 64; In case we ever use u128 */ /* multiply by 128 to make a byte count */ lsb = t << 7; msb = (th << 7) | (t >> 57); /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 61; if (0) { } #ifdef USE_S390X_CRYPTO else if (hd->use_s390x_crypto) { burn = do_sha512_final_s390x (hd, hd->bctx.buf, hd->bctx.count, msb, lsb); } #endif else { if (hd->bctx.count < 112) { /* enough room */ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 112) memset (&hd->bctx.buf[hd->bctx.count], 0, 112 - hd->bctx.count); } else { /* need one extra block */ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ if (hd->bctx.count < 128) memset (&hd->bctx.buf[hd->bctx.count], 0, 128 - hd->bctx.count); hd->bctx.count = 128; _gcry_md_block_write (context, NULL, 0); /* flush */ memset (hd->bctx.buf, 0, 112); /* fill next block with zeroes */ } /* append the 128 bit count */ buf_put_be64(hd->bctx.buf + 112, msb); buf_put_be64(hd->bctx.buf + 120, lsb); burn = (*hd->bctx.bwrite) (hd, hd->bctx.buf, 1); } p = hd->bctx.buf; #define X(a) do { buf_put_be64(p, hd->state.h[a]); p += 8; } while (0) X (0); X (1); X (2); X (3); X (4); X (5); /* Note that these last two chunks are included even for SHA384. We just ignore them. */ X (6); X (7); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * sha512_read (void *context) { SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context; return hd->bctx.buf; } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 64 bytes. */ static void _gcry_sha512_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; (void)nbytes; sha512_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha512_final (&hd); memcpy (outbuf, hd.bctx.buf, 64); } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 48 bytes. */ static void _gcry_sha384_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; (void)nbytes; sha384_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha512_final (&hd); memcpy (outbuf, hd.bctx.buf, 48); } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void _gcry_sha512_256_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; (void)nbytes; sha512_256_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha512_final (&hd); memcpy (outbuf, hd.bctx.buf, 32); } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 28 bytes. */ static void _gcry_sha512_224_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; (void)nbytes; sha512_224_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha512_final (&hd); memcpy (outbuf, hd.bctx.buf, 28); } /* Self-test section. */ static gpg_err_code_t selftests_sha384 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA384, 0, "abc", 3, "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed" "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA384, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, "\x09\x33\x0C\x33\xF7\x11\x47\xE8\x3D\x19\x2F\xC7\x82\xCD\x1B\x47" "\x53\x11\x1B\x17\x3B\x3B\x05\xD2\x2F\xA0\x80\x86\xE3\xB0\xF7\x12" "\xFC\xC7\xC7\x1A\x55\x7E\x2D\xB9\x66\xC3\xE9\xFA\x91\x74\x60\x39", 48); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA384, 1, NULL, 0, "\x9D\x0E\x18\x09\x71\x64\x74\xCB\x08\x6E\x83\x4E\x31\x0A\x4A\x1C" "\xED\x14\x9E\x9C\x00\xF2\x48\x52\x79\x72\xCE\xC5\x70\x4C\x2A\x5B" "\x07\xB8\xB3\xDC\x38\xEC\xC4\xEB\xAE\x97\xDD\xD8\x7F\x3D\x89\x85", 48); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA384, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha512 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512, 0, "abc", 3, "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD" "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F", 64); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, "\x8E\x95\x9B\x75\xDA\xE3\x13\xDA\x8C\xF4\xF7\x28\x14\xFC\x14\x3F" "\x8F\x77\x79\xC6\xEB\x9F\x7F\xA1\x72\x99\xAE\xAD\xB6\x88\x90\x18" "\x50\x1D\x28\x9E\x49\x00\xF7\xE4\x33\x1B\x99\xDE\xC4\xB5\x43\x3A" "\xC7\xD3\x29\xEE\xB6\xDD\x26\x54\x5E\x96\xE5\x5B\x87\x4B\xE9\x09", 64); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512, 1, NULL, 0, "\xE7\x18\x48\x3D\x0C\xE7\x69\x64\x4E\x2E\x42\xC7\xBC\x15\xB4\x63" "\x8E\x1F\x98\xB1\x3B\x20\x44\x28\x56\x32\xA8\x03\xAF\xA9\x73\xEB" "\xDE\x0F\xF2\x44\x87\x7E\xA6\x0A\x4C\xB0\x43\x2C\xE5\x77\xC3\x1B" "\xEB\x00\x9C\x5C\x2C\x49\xAA\x2E\x4E\xAD\xB2\x17\xAD\x8C\xC0\x9B", 64); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA512, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha512_224 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512_224, 0, "abc", 3, "\x46\x34\x27\x0F\x70\x7B\x6A\x54\xDA\xAE\x75\x30\x46\x08\x42\xE2" "\x0E\x37\xED\x26\x5C\xEE\xE9\xA4\x3E\x89\x24\xAA", 28); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512_224, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, "\x23\xFE\xC5\xBB\x94\xD6\x0B\x23\x30\x81\x92\x64\x0B\x0C\x45\x33" "\x35\xD6\x64\x73\x4F\xE4\x0E\x72\x68\x67\x4A\xF9", 28); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512_224, 1, NULL, 0, "\x37\xab\x33\x1d\x76\xf0\xd3\x6d\xe4\x22\xbd\x0e\xde\xb2\x2a\x28" "\xac\xcd\x48\x7b\x7a\x84\x53\xae\x96\x5d\xd2\x87", 28); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA512_224, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha512_256 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512_256, 0, "abc", 3, "\x53\x04\x8E\x26\x81\x94\x1E\xF9\x9B\x2E\x29\xB7\x6B\x4C\x7D\xAB" "\xE4\xC2\xD0\xC6\x34\xFC\x6D\x46\xE0\xE2\xF1\x31\x07\xE7\xAF\x23", 32); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512_256, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, "\x39\x28\xE1\x84\xFB\x86\x90\xF8\x40\xDA\x39\x88\x12\x1D\x31\xBE" "\x65\xCB\x9D\x3E\xF8\x3E\xE6\x14\x6F\xEA\xC8\x61\xE1\x9B\x56\x3A", 32); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512_256, 1, NULL, 0, "\x9a\x59\xa0\x52\x93\x01\x87\xa9\x70\x38\xca\xe6\x92\xf3\x07\x08" "\xaa\x64\x91\x92\x3e\xf5\x19\x43\x94\xdc\x68\xd5\x6c\x74\xfb\x21", 32); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA512_256, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA384: ec = selftests_sha384 (extended, report); break; case GCRY_MD_SHA512: ec = selftests_sha512 (extended, report); break; case GCRY_MD_SHA512_224: ec = selftests_sha512_224 (extended, report); break; case GCRY_MD_SHA512_256: ec = selftests_sha512_256 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } -static byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */ +static const byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */ { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; -static gcry_md_oid_spec_t oid_spec_sha512[] = +static const gcry_md_oid_spec_t oid_spec_sha512[] = { { "2.16.840.1.101.3.4.2.3" }, /* PKCS#1 sha512WithRSAEncryption */ { "1.2.840.113549.1.1.13" }, { NULL } }; -gcry_md_spec_t _gcry_digest_spec_sha512 = +const gcry_md_spec_t _gcry_digest_spec_sha512 = { GCRY_MD_SHA512, {0, 1}, "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64, sha512_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, _gcry_sha512_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; -static byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */ +static const byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */ { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 }; -static gcry_md_oid_spec_t oid_spec_sha384[] = +static const gcry_md_oid_spec_t oid_spec_sha384[] = { { "2.16.840.1.101.3.4.2.2" }, /* PKCS#1 sha384WithRSAEncryption */ { "1.2.840.113549.1.1.12" }, /* SHA384WithECDSA: RFC 7427 (A.3.3.) */ { "1.2.840.10045.4.3.3" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_sha384 = +const gcry_md_spec_t _gcry_digest_spec_sha384 = { GCRY_MD_SHA384, {0, 1}, "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48, sha384_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, _gcry_sha384_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; -static byte sha512_256_asn[] = +static const byte sha512_256_asn[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20 }; -static gcry_md_oid_spec_t oid_spec_sha512_256[] = +static const gcry_md_oid_spec_t oid_spec_sha512_256[] = { { "2.16.840.1.101.3.4.2.6" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_sha512_256 = +const gcry_md_spec_t _gcry_digest_spec_sha512_256 = { GCRY_MD_SHA512_256, {0, 1}, "SHA512_256", sha512_256_asn, DIM (sha512_256_asn), oid_spec_sha512_256, 32, sha512_256_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, _gcry_sha512_256_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; -static byte sha512_224_asn[] = +static const byte sha512_224_asn[] = { 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05, 0x00, 0x04, 0x1c }; -static gcry_md_oid_spec_t oid_spec_sha512_224[] = +static const gcry_md_oid_spec_t oid_spec_sha512_224[] = { { "2.16.840.1.101.3.4.2.5" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_sha512_224 = +const gcry_md_spec_t _gcry_digest_spec_sha512_224 = { GCRY_MD_SHA512_224, {0, 1}, "SHA512_224", sha512_224_asn, DIM (sha512_224_asn), oid_spec_sha512_224, 28, sha512_224_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, _gcry_sha512_224_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; diff --git a/cipher/sm3.c b/cipher/sm3.c index 05b7b259..c4897687 100644 --- a/cipher/sm3.c +++ b/cipher/sm3.c @@ -1,510 +1,510 @@ /* sm3.c - SM3 hash function * Copyright (C) 2017 Jia Zhang * * 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 . */ /* Test vectors: "abc" SM3: 66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0 "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" SM3: debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" SM3: 639b6cc5 e64d9e37 a390b192 df4fa1ea 0720ab74 7ff692b9 f38c4e66 ad7b8c05 "a" one million times SM3: c8aaf894 29554029 e231941a 2acc0ad6 1ff2a5ac d8fadd25 847a3a73 2b3b02c3 */ #include #include #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* USE_AVX_BMI2 indicates whether to compile with Intel AVX/BMI2 code. */ #undef USE_AVX_BMI2 #if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \ defined(HAVE_GCC_INLINE_ASM_BMI2) && \ (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AVX_BMI2 1 #endif typedef struct { gcry_md_block_ctx_t bctx; u32 h[8]; } SM3_CONTEXT; /* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #undef ASM_EXTRA_STACK #if defined(USE_AVX_BMI2) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16 + 4 * sizeof(void *)) # else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 # endif #endif #ifdef USE_AVX_BMI2 unsigned int _gcry_sm3_transform_amd64_avx_bmi2(void *state, const void *input_data, size_t num_blks) ASM_FUNC_ABI; static unsigned int do_sm3_transform_amd64_avx_bmi2(void *context, const unsigned char *data, size_t nblks) { SM3_CONTEXT *hd = context; unsigned int nburn = _gcry_sm3_transform_amd64_avx_bmi2 (hd->h, data, nblks); nburn += nburn ? ASM_EXTRA_STACK : 0; return nburn; } #endif /* USE_AVX_BMI2 */ static unsigned int transform (void *c, const unsigned char *data, size_t nblks); static void sm3_init (void *context, unsigned int flags) { SM3_CONTEXT *hd = context; unsigned int features = _gcry_get_hw_features (); (void)flags; hd->h[0] = 0x7380166f; hd->h[1] = 0x4914b2b9; hd->h[2] = 0x172442d7; hd->h[3] = 0xda8a0600; hd->h[4] = 0xa96f30bc; hd->h[5] = 0x163138aa; hd->h[6] = 0xe38dee4d; hd->h[7] = 0xb0fb0e4e; hd->bctx.nblocks = 0; hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize_shift = _gcry_ctz(64); hd->bctx.bwrite = transform; #ifdef USE_AVX_BMI2 if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2)) hd->bctx.bwrite = do_sm3_transform_amd64_avx_bmi2; #endif (void)features; } /* Transform the message X which consists of 16 32-bit-words. See GM/T 004-2012 for details. */ #define R(i,a,b,c,d,e,f,g,h,t,w1,w2) do \ { \ ss1 = rol ((rol ((a), 12) + (e) + (t)), 7); \ ss2 = ss1 ^ rol ((a), 12); \ d += FF##i(a,b,c) + ss2 + ((w1) ^ (w2)); \ h += GG##i(e,f,g) + ss1 + (w1); \ b = rol ((b), 9); \ f = rol ((f), 19); \ h = P0 ((h)); \ } while (0) #define R1(a,b,c,d,e,f,g,h,t,w1,w2) R(1,a,b,c,d,e,f,g,h,t,w1,w2) #define R2(a,b,c,d,e,f,g,h,t,w1,w2) R(2,a,b,c,d,e,f,g,h,t,w1,w2) #define FF1(x, y, z) (x ^ y ^ z) #define FF2(x, y, z) ((x & y) | (x & z) | (y & z)) #define GG1(x, y, z) (x ^ y ^ z) #define GG2(x, y, z) ((x & y) | ( ~x & z)) /* Message expansion */ #define P0(x) ((x) ^ rol ((x), 9) ^ rol ((x), 17)) #define P1(x) ((x) ^ rol ((x), 15) ^ rol ((x), 23)) #define I(i) ( w[i] = buf_get_be32(data + i * 4) ) #define W1(i) ( w[i&0x0f] ) #define W2(i) ( w[i&0x0f] = P1(w[i &0x0f] \ ^ w[(i-9)&0x0f] \ ^ rol (w[(i-3)&0x0f], 15)) \ ^ rol (w[(i-13)&0x0f], 7) \ ^ w[(i-6)&0x0f] ) static unsigned int transform_blk (void *ctx, const unsigned char *data) { SM3_CONTEXT *hd = ctx; static const u32 K[64] = { 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb, 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc, 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce, 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6, 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5, 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53, 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d, 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4, 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43, 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5 }; u32 a,b,c,d,e,f,g,h,ss1,ss2; u32 w[16]; a = hd->h[0]; b = hd->h[1]; c = hd->h[2]; d = hd->h[3]; e = hd->h[4]; f = hd->h[5]; g = hd->h[6]; h = hd->h[7]; R1(a, b, c, d, e, f, g, h, K[0], I(0), I(4)); R1(d, a, b, c, h, e, f, g, K[1], I(1), I(5)); R1(c, d, a, b, g, h, e, f, K[2], I(2), I(6)); R1(b, c, d, a, f, g, h, e, K[3], I(3), I(7)); R1(a, b, c, d, e, f, g, h, K[4], W1(4), I(8)); R1(d, a, b, c, h, e, f, g, K[5], W1(5), I(9)); R1(c, d, a, b, g, h, e, f, K[6], W1(6), I(10)); R1(b, c, d, a, f, g, h, e, K[7], W1(7), I(11)); R1(a, b, c, d, e, f, g, h, K[8], W1(8), I(12)); R1(d, a, b, c, h, e, f, g, K[9], W1(9), I(13)); R1(c, d, a, b, g, h, e, f, K[10], W1(10), I(14)); R1(b, c, d, a, f, g, h, e, K[11], W1(11), I(15)); R1(a, b, c, d, e, f, g, h, K[12], W1(12), W2(16)); R1(d, a, b, c, h, e, f, g, K[13], W1(13), W2(17)); R1(c, d, a, b, g, h, e, f, K[14], W1(14), W2(18)); R1(b, c, d, a, f, g, h, e, K[15], W1(15), W2(19)); R2(a, b, c, d, e, f, g, h, K[16], W1(16), W2(20)); R2(d, a, b, c, h, e, f, g, K[17], W1(17), W2(21)); R2(c, d, a, b, g, h, e, f, K[18], W1(18), W2(22)); R2(b, c, d, a, f, g, h, e, K[19], W1(19), W2(23)); R2(a, b, c, d, e, f, g, h, K[20], W1(20), W2(24)); R2(d, a, b, c, h, e, f, g, K[21], W1(21), W2(25)); R2(c, d, a, b, g, h, e, f, K[22], W1(22), W2(26)); R2(b, c, d, a, f, g, h, e, K[23], W1(23), W2(27)); R2(a, b, c, d, e, f, g, h, K[24], W1(24), W2(28)); R2(d, a, b, c, h, e, f, g, K[25], W1(25), W2(29)); R2(c, d, a, b, g, h, e, f, K[26], W1(26), W2(30)); R2(b, c, d, a, f, g, h, e, K[27], W1(27), W2(31)); R2(a, b, c, d, e, f, g, h, K[28], W1(28), W2(32)); R2(d, a, b, c, h, e, f, g, K[29], W1(29), W2(33)); R2(c, d, a, b, g, h, e, f, K[30], W1(30), W2(34)); R2(b, c, d, a, f, g, h, e, K[31], W1(31), W2(35)); R2(a, b, c, d, e, f, g, h, K[32], W1(32), W2(36)); R2(d, a, b, c, h, e, f, g, K[33], W1(33), W2(37)); R2(c, d, a, b, g, h, e, f, K[34], W1(34), W2(38)); R2(b, c, d, a, f, g, h, e, K[35], W1(35), W2(39)); R2(a, b, c, d, e, f, g, h, K[36], W1(36), W2(40)); R2(d, a, b, c, h, e, f, g, K[37], W1(37), W2(41)); R2(c, d, a, b, g, h, e, f, K[38], W1(38), W2(42)); R2(b, c, d, a, f, g, h, e, K[39], W1(39), W2(43)); R2(a, b, c, d, e, f, g, h, K[40], W1(40), W2(44)); R2(d, a, b, c, h, e, f, g, K[41], W1(41), W2(45)); R2(c, d, a, b, g, h, e, f, K[42], W1(42), W2(46)); R2(b, c, d, a, f, g, h, e, K[43], W1(43), W2(47)); R2(a, b, c, d, e, f, g, h, K[44], W1(44), W2(48)); R2(d, a, b, c, h, e, f, g, K[45], W1(45), W2(49)); R2(c, d, a, b, g, h, e, f, K[46], W1(46), W2(50)); R2(b, c, d, a, f, g, h, e, K[47], W1(47), W2(51)); R2(a, b, c, d, e, f, g, h, K[48], W1(48), W2(52)); R2(d, a, b, c, h, e, f, g, K[49], W1(49), W2(53)); R2(c, d, a, b, g, h, e, f, K[50], W1(50), W2(54)); R2(b, c, d, a, f, g, h, e, K[51], W1(51), W2(55)); R2(a, b, c, d, e, f, g, h, K[52], W1(52), W2(56)); R2(d, a, b, c, h, e, f, g, K[53], W1(53), W2(57)); R2(c, d, a, b, g, h, e, f, K[54], W1(54), W2(58)); R2(b, c, d, a, f, g, h, e, K[55], W1(55), W2(59)); R2(a, b, c, d, e, f, g, h, K[56], W1(56), W2(60)); R2(d, a, b, c, h, e, f, g, K[57], W1(57), W2(61)); R2(c, d, a, b, g, h, e, f, K[58], W1(58), W2(62)); R2(b, c, d, a, f, g, h, e, K[59], W1(59), W2(63)); R2(a, b, c, d, e, f, g, h, K[60], W1(60), W2(64)); R2(d, a, b, c, h, e, f, g, K[61], W1(61), W2(65)); R2(c, d, a, b, g, h, e, f, K[62], W1(62), W2(66)); R2(b, c, d, a, f, g, h, e, K[63], W1(63), W2(67)); hd->h[0] ^= a; hd->h[1] ^= b; hd->h[2] ^= c; hd->h[3] ^= d; hd->h[4] ^= e; hd->h[5] ^= f; hd->h[6] ^= g; hd->h[7] ^= h; return /*burn_stack*/ 26*4+32; } #undef P0 #undef P1 #undef R #undef R1 #undef R2 static unsigned int transform (void *ctx, const unsigned char *data, size_t nblks) { SM3_CONTEXT *hd = ctx; unsigned int burn; do { burn = transform_blk (hd, data); data += 64; } while (--nblks); return burn; } /* The routine finally terminates the computation and returns the digest. The handle is prepared for a new cycle, but adding bytes to the handle will the destroy the returned buffer. Returns: 32 bytes with the message the digest. */ static void sm3_final(void *context) { SM3_CONTEXT *hd = context; u32 t, th, msb, lsb; byte *p; unsigned int burn; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (hd->bctx.count < 56) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_be32(hd->bctx.buf + 56, msb); buf_put_be32(hd->bctx.buf + 60, lsb); burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 1 ); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_be32(hd->bctx.buf + 64 + 56, msb); buf_put_be32(hd->bctx.buf + 64 + 60, lsb); burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 2 ); } p = hd->bctx.buf; #define X(a) do { buf_put_be32(p, hd->h[a]); p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); #undef X hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * sm3_read (void *context) { SM3_CONTEXT *hd = context; return hd->bctx.buf; } /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void _gcry_sm3_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt) { SM3_CONTEXT hd; (void)nbytes; sm3_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sm3_final (&hd); memcpy (outbuf, hd.bctx.buf, 32); } /* Self-test section. */ static gpg_err_code_t selftests_sm3 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string (spec example 1)"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SM3, 0, "abc", 3, "\x66\xc7\xf0\xf4\x62\xee\xed\xd9\xd1\xf2\xd4\x6b\xdc\x10\xe4\xe2" "\x41\x67\xc4\x87\x5c\xf2\xf7\xa2\x29\x7d\xa0\x2b\x8f\x4b\xa8\xe0", 32); if (errtxt) goto failed; if (extended) { what = "long string (spec example 2)"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SM3, 0, "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", 64, "\xde\xbe\x9f\xf9\x22\x75\xb8\xa1\x38\x60\x48\x89\xc1\x8e\x5a\x4d" "\x6f\xdb\x70\xe5\x38\x7e\x57\x65\x29\x3d\xcb\xa3\x9c\x0c\x57\x32", 32); if (errtxt) goto failed; what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SM3, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x63\x9b\x6c\xc5\xe6\x4d\x9e\x37\xa3\x90\xb1\x92\xdf\x4f\xa1\xea" "\x07\x20\xab\x74\x7f\xf6\x92\xb9\xf3\x8c\x4e\x66\xad\x7b\x8c\x05", 32); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SM3, 1, NULL, 0, "\xc8\xaa\xf8\x94\x29\x55\x40\x29\xe2\x31\x94\x1a\x2a\xcc\x0a\xd6" "\x1f\xf2\xa5\xac\xd8\xfa\xdd\x25\x84\x7a\x3a\x73\x2b\x3b\x02\xc3", 32); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SM3, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SM3: ec = selftests_sm3 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } -static byte asn_sm3[] = /* Object ID is 1.2.156.10197.401 */ +static const byte asn_sm3[] = /* Object ID is 1.2.156.10197.401 */ { 0x30, 0x2F, 0x30, 0x0B, 0x06, 0x07, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x83, 0x11, 0x05, 0x00, 0x04, 0x20 }; -static gcry_md_oid_spec_t oid_spec_sm3[] = +static const gcry_md_oid_spec_t oid_spec_sm3[] = { /* China Electronics Standardization Instutute, OID White paper (2015), Table 6 */ { "1.2.156.10197.401" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_sm3 = +const gcry_md_spec_t _gcry_digest_spec_sm3 = { GCRY_MD_SM3, {0, 0}, "SM3", asn_sm3, DIM (asn_sm3), oid_spec_sm3, 32, sm3_init, _gcry_md_block_write, sm3_final, sm3_read, NULL, _gcry_sm3_hash_buffers, sizeof (SM3_CONTEXT), run_selftests }; diff --git a/cipher/sm4.c b/cipher/sm4.c index c8dd0406..81662988 100644 --- a/cipher/sm4.c +++ b/cipher/sm4.c @@ -1,1251 +1,1251 @@ /* sm4.c - SM4 Cipher Algorithm * Copyright (C) 2020 Alibaba Group. * Copyright (C) 2020 Tianjia Zhang * Copyright (C) 2020 Jussi Kivilinna * * 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 . */ #include #include #include #include "types.h" /* for byte and u32 typedefs */ #include "bithelp.h" #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "cipher-internal.h" #include "cipher-selftest.h" /* Helper macro to force alignment to 64 bytes. */ #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED # define ATTR_ALIGNED_64 __attribute__ ((aligned (64))) #else # define ATTR_ALIGNED_64 #endif /* USE_AESNI_AVX inidicates whether to compile with Intel AES-NI/AVX code. */ #undef USE_AESNI_AVX #if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT) # if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AESNI_AVX 1 # endif #endif /* USE_AESNI_AVX inidicates whether to compile with Intel AES-NI/AVX2 code. */ #undef USE_AESNI_AVX2 #if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) # if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AESNI_AVX2 1 # endif #endif /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # else # define ASM_FUNC_ABI # endif #endif static const char *sm4_selftest (void); static void _gcry_sm4_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_sm4_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static void _gcry_sm4_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks); static size_t _gcry_sm4_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt); static size_t _gcry_sm4_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks); typedef struct { u32 rkey_enc[32]; u32 rkey_dec[32]; #ifdef USE_AESNI_AVX unsigned int use_aesni_avx:1; #endif #ifdef USE_AESNI_AVX2 unsigned int use_aesni_avx2:1; #endif } SM4_context; static const u32 fk[4] = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc }; static struct { volatile u32 counter_head; u32 cacheline_align[64 / 4 - 1]; byte S[256]; volatile u32 counter_tail; } sbox_table ATTR_ALIGNED_64 = { 0, { 0, }, { 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 }, 0 }; static const u32 ck[] = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 }; #ifdef USE_AESNI_AVX extern void _gcry_sm4_aesni_avx_expand_key(const byte *key, u32 *rk_enc, u32 *rk_dec, const u32 *fk, const u32 *ck) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx_ctr_enc(const u32 *rk_enc, byte *out, const byte *in, byte *ctr) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx_cbc_dec(const u32 *rk_dec, byte *out, const byte *in, byte *iv) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx_cfb_dec(const u32 *rk_enc, byte *out, const byte *in, byte *iv) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx_ocb_enc(const u32 *rk_enc, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[8]) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx_ocb_dec(const u32 *rk_dec, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[8]) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx_ocb_auth(const u32 *rk_enc, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[8]) ASM_FUNC_ABI; extern unsigned int _gcry_sm4_aesni_avx_crypt_blk1_8(const u32 *rk, byte *out, const byte *in, unsigned int num_blks) ASM_FUNC_ABI; static inline unsigned int sm4_aesni_avx_crypt_blk1_8(const u32 *rk, byte *out, const byte *in, unsigned int num_blks) { return _gcry_sm4_aesni_avx_crypt_blk1_8(rk, out, in, num_blks); } #endif /* USE_AESNI_AVX */ #ifdef USE_AESNI_AVX2 extern void _gcry_sm4_aesni_avx2_ctr_enc(const u32 *rk_enc, byte *out, const byte *in, byte *ctr) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx2_cbc_dec(const u32 *rk_dec, byte *out, const byte *in, byte *iv) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx2_cfb_dec(const u32 *rk_enc, byte *out, const byte *in, byte *iv) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx2_ocb_enc(const u32 *rk_enc, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx2_ocb_dec(const u32 *rk_dec, unsigned char *out, const unsigned char *in, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; extern void _gcry_sm4_aesni_avx2_ocb_auth(const u32 *rk_enc, const unsigned char *abuf, unsigned char *offset, unsigned char *checksum, const u64 Ls[16]) ASM_FUNC_ABI; #endif /* USE_AESNI_AVX2 */ static inline void prefetch_sbox_table(void) { const volatile byte *vtab = (void *)&sbox_table; /* Modify counters to trigger copy-on-write and unsharing if physical pages * of look-up table are shared between processes. Modifying counters also * causes checksums for pages to change and hint same-page merging algorithm * that these pages are frequently changing. */ sbox_table.counter_head++; sbox_table.counter_tail++; /* Prefetch look-up table to cache. */ (void)vtab[0 * 32]; (void)vtab[1 * 32]; (void)vtab[2 * 32]; (void)vtab[3 * 32]; (void)vtab[4 * 32]; (void)vtab[5 * 32]; (void)vtab[6 * 32]; (void)vtab[7 * 32]; (void)vtab[8 * 32 - 1]; } static inline u32 sm4_t_non_lin_sub(u32 x) { u32 out; out = (u32)sbox_table.S[(x >> 0) & 0xff] << 0; out |= (u32)sbox_table.S[(x >> 8) & 0xff] << 8; out |= (u32)sbox_table.S[(x >> 16) & 0xff] << 16; out |= (u32)sbox_table.S[(x >> 24) & 0xff] << 24; return out; } static inline u32 sm4_key_lin_sub(u32 x) { return x ^ rol(x, 13) ^ rol(x, 23); } static inline u32 sm4_enc_lin_sub(u32 x) { u32 xrol2 = rol(x, 2); return x ^ xrol2 ^ rol(xrol2, 8) ^ rol(xrol2, 16) ^ rol(x, 24); } static inline u32 sm4_key_sub(u32 x) { return sm4_key_lin_sub(sm4_t_non_lin_sub(x)); } static inline u32 sm4_enc_sub(u32 x) { return sm4_enc_lin_sub(sm4_t_non_lin_sub(x)); } static inline u32 sm4_round(const u32 x0, const u32 x1, const u32 x2, const u32 x3, const u32 rk) { return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ rk); } static void sm4_expand_key (SM4_context *ctx, const byte *key) { u32 rk[4]; int i; #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { _gcry_sm4_aesni_avx_expand_key (key, ctx->rkey_enc, ctx->rkey_dec, fk, ck); return; } #endif rk[0] = buf_get_be32(key + 4 * 0) ^ fk[0]; rk[1] = buf_get_be32(key + 4 * 1) ^ fk[1]; rk[2] = buf_get_be32(key + 4 * 2) ^ fk[2]; rk[3] = buf_get_be32(key + 4 * 3) ^ fk[3]; for (i = 0; i < 32; i += 4) { rk[0] = rk[0] ^ sm4_key_sub(rk[1] ^ rk[2] ^ rk[3] ^ ck[i + 0]); rk[1] = rk[1] ^ sm4_key_sub(rk[2] ^ rk[3] ^ rk[0] ^ ck[i + 1]); rk[2] = rk[2] ^ sm4_key_sub(rk[3] ^ rk[0] ^ rk[1] ^ ck[i + 2]); rk[3] = rk[3] ^ sm4_key_sub(rk[0] ^ rk[1] ^ rk[2] ^ ck[i + 3]); ctx->rkey_enc[i + 0] = rk[0]; ctx->rkey_enc[i + 1] = rk[1]; ctx->rkey_enc[i + 2] = rk[2]; ctx->rkey_enc[i + 3] = rk[3]; ctx->rkey_dec[31 - i - 0] = rk[0]; ctx->rkey_dec[31 - i - 1] = rk[1]; ctx->rkey_dec[31 - i - 2] = rk[2]; ctx->rkey_dec[31 - i - 3] = rk[3]; } wipememory (rk, sizeof(rk)); } static gcry_err_code_t sm4_setkey (void *context, const byte *key, const unsigned keylen, cipher_bulk_ops_t *bulk_ops) { SM4_context *ctx = context; static int init = 0; static const char *selftest_failed = NULL; unsigned int hwf = _gcry_get_hw_features (); (void)hwf; if (!init) { init = 1; selftest_failed = sm4_selftest(); if (selftest_failed) log_error("%s\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen != 16) return GPG_ERR_INV_KEYLEN; #ifdef USE_AESNI_AVX ctx->use_aesni_avx = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX); #endif #ifdef USE_AESNI_AVX2 ctx->use_aesni_avx2 = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX2); #endif /* Setup bulk encryption routines. */ memset (bulk_ops, 0, sizeof(*bulk_ops)); bulk_ops->cbc_dec = _gcry_sm4_cbc_dec; bulk_ops->cfb_dec = _gcry_sm4_cfb_dec; bulk_ops->ctr_enc = _gcry_sm4_ctr_enc; bulk_ops->ocb_crypt = _gcry_sm4_ocb_crypt; bulk_ops->ocb_auth = _gcry_sm4_ocb_auth; sm4_expand_key (ctx, key); return 0; } static unsigned int sm4_do_crypt (const u32 *rk, byte *out, const byte *in) { u32 x[4]; int i; x[0] = buf_get_be32(in + 0 * 4); x[1] = buf_get_be32(in + 1 * 4); x[2] = buf_get_be32(in + 2 * 4); x[3] = buf_get_be32(in + 3 * 4); for (i = 0; i < 32; i += 4) { x[0] = sm4_round(x[0], x[1], x[2], x[3], rk[i + 0]); x[1] = sm4_round(x[1], x[2], x[3], x[0], rk[i + 1]); x[2] = sm4_round(x[2], x[3], x[0], x[1], rk[i + 2]); x[3] = sm4_round(x[3], x[0], x[1], x[2], rk[i + 3]); } buf_put_be32(out + 0 * 4, x[3 - 0]); buf_put_be32(out + 1 * 4, x[3 - 1]); buf_put_be32(out + 2 * 4, x[3 - 2]); buf_put_be32(out + 3 * 4, x[3 - 3]); return /*burn_stack*/ 4*6+sizeof(void*)*4; } static unsigned int sm4_encrypt (void *context, byte *outbuf, const byte *inbuf) { SM4_context *ctx = context; prefetch_sbox_table (); return sm4_do_crypt (ctx->rkey_enc, outbuf, inbuf); } static unsigned int sm4_decrypt (void *context, byte *outbuf, const byte *inbuf) { SM4_context *ctx = context; prefetch_sbox_table (); return sm4_do_crypt (ctx->rkey_dec, outbuf, inbuf); } static unsigned int sm4_do_crypt_blks2 (const u32 *rk, byte *out, const byte *in) { u32 x[4]; u32 y[4]; u32 k; int i; /* Encrypts/Decrypts two blocks for higher instruction level * parallelism. */ x[0] = buf_get_be32(in + 0 * 4); x[1] = buf_get_be32(in + 1 * 4); x[2] = buf_get_be32(in + 2 * 4); x[3] = buf_get_be32(in + 3 * 4); y[0] = buf_get_be32(in + 4 * 4); y[1] = buf_get_be32(in + 5 * 4); y[2] = buf_get_be32(in + 6 * 4); y[3] = buf_get_be32(in + 7 * 4); for (i = 0; i < 32; i += 4) { k = rk[i + 0]; x[0] = sm4_round(x[0], x[1], x[2], x[3], k); y[0] = sm4_round(y[0], y[1], y[2], y[3], k); k = rk[i + 1]; x[1] = sm4_round(x[1], x[2], x[3], x[0], k); y[1] = sm4_round(y[1], y[2], y[3], y[0], k); k = rk[i + 2]; x[2] = sm4_round(x[2], x[3], x[0], x[1], k); y[2] = sm4_round(y[2], y[3], y[0], y[1], k); k = rk[i + 3]; x[3] = sm4_round(x[3], x[0], x[1], x[2], k); y[3] = sm4_round(y[3], y[0], y[1], y[2], k); } buf_put_be32(out + 0 * 4, x[3 - 0]); buf_put_be32(out + 1 * 4, x[3 - 1]); buf_put_be32(out + 2 * 4, x[3 - 2]); buf_put_be32(out + 3 * 4, x[3 - 3]); buf_put_be32(out + 4 * 4, y[3 - 0]); buf_put_be32(out + 5 * 4, y[3 - 1]); buf_put_be32(out + 6 * 4, y[3 - 2]); buf_put_be32(out + 7 * 4, y[3 - 3]); return /*burn_stack*/ 4*10+sizeof(void*)*4; } static unsigned int sm4_crypt_blocks (const u32 *rk, byte *out, const byte *in, unsigned int num_blks) { unsigned int burn_depth = 0; unsigned int nburn; while (num_blks >= 2) { nburn = sm4_do_crypt_blks2 (rk, out, in); burn_depth = nburn > burn_depth ? nburn : burn_depth; out += 2 * 16; in += 2 * 16; num_blks -= 2; } while (num_blks) { nburn = sm4_do_crypt (rk, out, in); burn_depth = nburn > burn_depth ? nburn : burn_depth; out += 16; in += 16; num_blks--; } if (burn_depth) burn_depth += sizeof(void *) * 5; return burn_depth; } /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size 16. */ static void _gcry_sm4_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { SM4_context *ctx = context; byte *outbuf = outbuf_arg; const byte *inbuf = inbuf_arg; int burn_stack_depth = 0; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_sm4_aesni_avx2_ctr_enc(ctx->rkey_enc, outbuf, inbuf, ctr); nblocks -= 16; outbuf += 16 * 16; inbuf += 16 * 16; } } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_sm4_aesni_avx_ctr_enc(ctx->rkey_enc, outbuf, inbuf, ctr); nblocks -= 8; outbuf += 8 * 16; inbuf += 8 * 16; } } #endif /* Process remaining blocks. */ if (nblocks) { unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in, unsigned int num_blks); byte tmpbuf[16 * 8]; unsigned int tmp_used = 16; if (0) ; #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) { crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8; } #endif else { prefetch_sbox_table (); crypt_blk1_8 = sm4_crypt_blocks; } /* Process remaining blocks. */ while (nblocks) { size_t curr_blks = nblocks > 8 ? 8 : nblocks; size_t i; if (curr_blks * 16 > tmp_used) tmp_used = curr_blks * 16; cipher_block_cpy (tmpbuf + 0 * 16, ctr, 16); for (i = 1; i < curr_blks; i++) { cipher_block_cpy (&tmpbuf[i * 16], ctr, 16); cipher_block_add (&tmpbuf[i * 16], i, 16); } cipher_block_add (ctr, curr_blks, 16); burn_stack_depth = crypt_blk1_8 (ctx->rkey_enc, tmpbuf, tmpbuf, curr_blks); for (i = 0; i < curr_blks; i++) { cipher_block_xor (outbuf, &tmpbuf[i * 16], inbuf, 16); outbuf += 16; inbuf += 16; } nblocks -= curr_blks; } wipememory(tmpbuf, tmp_used); } if (burn_stack_depth) _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_sm4_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { SM4_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 0; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_sm4_aesni_avx2_cbc_dec(ctx->rkey_dec, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * 16; inbuf += 16 * 16; } } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_sm4_aesni_avx_cbc_dec(ctx->rkey_dec, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * 16; inbuf += 8 * 16; } } #endif /* Process remaining blocks. */ if (nblocks) { unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in, unsigned int num_blks); unsigned char savebuf[16 * 8]; unsigned int tmp_used = 16; if (0) ; #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) { crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8; } #endif else { prefetch_sbox_table (); crypt_blk1_8 = sm4_crypt_blocks; } /* Process remaining blocks. */ while (nblocks) { size_t curr_blks = nblocks > 8 ? 8 : nblocks; size_t i; if (curr_blks * 16 > tmp_used) tmp_used = curr_blks * 16; burn_stack_depth = crypt_blk1_8 (ctx->rkey_dec, savebuf, inbuf, curr_blks); for (i = 0; i < curr_blks; i++) { cipher_block_xor_n_copy_2(outbuf, &savebuf[i * 16], iv, inbuf, 16); outbuf += 16; inbuf += 16; } nblocks -= curr_blks; } wipememory(savebuf, tmp_used); } if (burn_stack_depth) _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ static void _gcry_sm4_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, size_t nblocks) { SM4_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 0; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_sm4_aesni_avx2_cfb_dec(ctx->rkey_enc, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * 16; inbuf += 16 * 16; } } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_sm4_aesni_avx_cfb_dec(ctx->rkey_enc, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * 16; inbuf += 8 * 16; } } #endif /* Process remaining blocks. */ if (nblocks) { unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in, unsigned int num_blks); unsigned char ivbuf[16 * 8]; unsigned int tmp_used = 16; if (0) ; #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) { crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8; } #endif else { prefetch_sbox_table (); crypt_blk1_8 = sm4_crypt_blocks; } /* Process remaining blocks. */ while (nblocks) { size_t curr_blks = nblocks > 8 ? 8 : nblocks; size_t i; if (curr_blks * 16 > tmp_used) tmp_used = curr_blks * 16; cipher_block_cpy (&ivbuf[0 * 16], iv, 16); for (i = 1; i < curr_blks; i++) cipher_block_cpy (&ivbuf[i * 16], &inbuf[(i - 1) * 16], 16); cipher_block_cpy (iv, &inbuf[(i - 1) * 16], 16); burn_stack_depth = crypt_blk1_8 (ctx->rkey_enc, ivbuf, ivbuf, curr_blks); for (i = 0; i < curr_blks; i++) { cipher_block_xor (outbuf, inbuf, &ivbuf[i * 16], 16); outbuf += 16; inbuf += 16; } nblocks -= curr_blks; } wipememory(ivbuf, tmp_used); } if (burn_stack_depth) _gcry_burn_stack(burn_stack_depth); } /* Bulk encryption/decryption of complete blocks in OCB mode. */ static size_t _gcry_sm4_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const void *inbuf_arg, size_t nblocks, int encrypt) { SM4_context *ctx = (void *)&c->context.c; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; u64 blkn = c->u_mode.ocb.data_nblocks; int burn_stack_depth = 0; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { u64 Ls[16]; unsigned int n = 16 - (blkn % 16); u64 *l; int i; if (nblocks >= 16) { for (i = 0; i < 16; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(15 + n) % 16]; /* Process data in 16 block chunks. */ while (nblocks >= 16) { blkn += 16; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16); if (encrypt) _gcry_sm4_aesni_avx2_ocb_enc(ctx->rkey_enc, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_sm4_aesni_avx2_ocb_dec(ctx->rkey_dec, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 16; outbuf += 16 * 16; inbuf += 16 * 16; } } } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { u64 Ls[8]; unsigned int n = 8 - (blkn % 8); u64 *l; if (nblocks >= 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(7 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(7 + n) % 8]; /* Process data in 8 block chunks. */ while (nblocks >= 8) { blkn += 8; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8); if (encrypt) _gcry_sm4_aesni_avx_ocb_enc(ctx->rkey_enc, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); else _gcry_sm4_aesni_avx_ocb_dec(ctx->rkey_dec, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr, Ls); nblocks -= 8; outbuf += 8 * 16; inbuf += 8 * 16; } } } #endif if (nblocks) { unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in, unsigned int num_blks); const u32 *rk = encrypt ? ctx->rkey_enc : ctx->rkey_dec; unsigned char tmpbuf[16 * 8]; unsigned int tmp_used = 16; if (0) ; #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) { crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8; } #endif else { prefetch_sbox_table (); crypt_blk1_8 = sm4_crypt_blocks; } while (nblocks) { size_t curr_blks = nblocks > 8 ? 8 : nblocks; size_t i; if (curr_blks * 16 > tmp_used) tmp_used = curr_blks * 16; for (i = 0; i < curr_blks; i++) { const unsigned char *l = ocb_get_l(c, ++blkn); /* Checksum_i = Checksum_{i-1} xor P_i */ if (encrypt) cipher_block_xor_1(c->u_ctr.ctr, &inbuf[i * 16], 16); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ cipher_block_xor_2dst (&tmpbuf[i * 16], c->u_iv.iv, l, 16); cipher_block_xor (&outbuf[i * 16], &inbuf[i * 16], c->u_iv.iv, 16); } /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ crypt_blk1_8 (rk, outbuf, outbuf, curr_blks); for (i = 0; i < curr_blks; i++) { cipher_block_xor_1 (&outbuf[i * 16], &tmpbuf[i * 16], 16); /* Checksum_i = Checksum_{i-1} xor P_i */ if (!encrypt) cipher_block_xor_1(c->u_ctr.ctr, &outbuf[i * 16], 16); } outbuf += curr_blks * 16; inbuf += curr_blks * 16; nblocks -= curr_blks; } wipememory(tmpbuf, tmp_used); } c->u_mode.ocb.data_nblocks = blkn; if (burn_stack_depth) _gcry_burn_stack(burn_stack_depth); return 0; } /* Bulk authentication of complete blocks in OCB mode. */ static size_t _gcry_sm4_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks) { SM4_context *ctx = (void *)&c->context.c; const unsigned char *abuf = abuf_arg; u64 blkn = c->u_mode.ocb.aad_nblocks; #ifdef USE_AESNI_AVX2 if (ctx->use_aesni_avx2) { u64 Ls[16]; unsigned int n = 16 - (blkn % 16); u64 *l; int i; if (nblocks >= 16) { for (i = 0; i < 16; i += 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; } Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(15 + n) % 16]; /* Process data in 16 block chunks. */ while (nblocks >= 16) { blkn += 16; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16); _gcry_sm4_aesni_avx2_ocb_auth(ctx->rkey_enc, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 16; abuf += 16 * 16; } } } #endif #ifdef USE_AESNI_AVX if (ctx->use_aesni_avx) { u64 Ls[8]; unsigned int n = 8 - (blkn % 8); u64 *l; if (nblocks >= 8) { /* Use u64 to store pointers for x32 support (assembly function * assumes 64-bit pointers). */ Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2]; Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1]; Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0]; Ls[(7 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[3]; l = &Ls[(7 + n) % 8]; /* Process data in 8 block chunks. */ while (nblocks >= 8) { blkn += 8; *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8); _gcry_sm4_aesni_avx_ocb_auth(ctx->rkey_enc, abuf, c->u_mode.ocb.aad_offset, c->u_mode.ocb.aad_sum, Ls); nblocks -= 8; abuf += 8 * 16; } } } #endif if (nblocks) { unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in, unsigned int num_blks); unsigned char tmpbuf[16 * 8]; unsigned int tmp_used = 16; if (0) ; #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) { crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8; } #endif else { prefetch_sbox_table (); crypt_blk1_8 = sm4_crypt_blocks; } while (nblocks) { size_t curr_blks = nblocks > 8 ? 8 : nblocks; size_t i; if (curr_blks * 16 > tmp_used) tmp_used = curr_blks * 16; for (i = 0; i < curr_blks; i++) { const unsigned char *l = ocb_get_l(c, ++blkn); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ cipher_block_xor_2dst (&tmpbuf[i * 16], c->u_mode.ocb.aad_offset, l, 16); cipher_block_xor_1 (&tmpbuf[i * 16], &abuf[i * 16], 16); } /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ crypt_blk1_8 (ctx->rkey_enc, tmpbuf, tmpbuf, curr_blks); for (i = 0; i < curr_blks; i++) { cipher_block_xor_1 (c->u_mode.ocb.aad_sum, &tmpbuf[i * 16], 16); } abuf += curr_blks * 16; nblocks -= curr_blks; } wipememory(tmpbuf, tmp_used); } c->u_mode.ocb.aad_nblocks = blkn; return 0; } /* Run the self-tests for SM4-CTR, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char* selftest_ctr_128 (void) { const int nblocks = 16 - 1; const int blocksize = 16; const int context_size = sizeof(SM4_context); return _gcry_selftest_helper_ctr("SM4", &sm4_setkey, &sm4_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for SM4-CBC, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cbc_128 (void) { const int nblocks = 16 - 1; const int blocksize = 16; const int context_size = sizeof(SM4_context); return _gcry_selftest_helper_cbc("SM4", &sm4_setkey, &sm4_encrypt, nblocks, blocksize, context_size); } /* Run the self-tests for SM4-CFB, tests bulk CFB decryption. Returns NULL on success. */ static const char* selftest_cfb_128 (void) { const int nblocks = 16 - 1; const int blocksize = 16; const int context_size = sizeof(SM4_context); return _gcry_selftest_helper_cfb("SM4", &sm4_setkey, &sm4_encrypt, nblocks, blocksize, context_size); } static const char * sm4_selftest (void) { SM4_context ctx; byte scratch[16]; const char *r; static const byte plaintext[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, }; static const byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, }; static const byte ciphertext[16] = { 0x68, 0x1E, 0xDF, 0x34, 0xD2, 0x06, 0x96, 0x5E, 0x86, 0xB3, 0xE9, 0x4F, 0x53, 0x6E, 0x42, 0x46 }; memset (&ctx, 0, sizeof(ctx)); sm4_expand_key (&ctx, key); sm4_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "SM4 test encryption failed."; sm4_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "SM4 test decryption failed."; if ( (r = selftest_ctr_128 ()) ) return r; if ( (r = selftest_cbc_128 ()) ) return r; if ( (r = selftest_cfb_128 ()) ) return r; return NULL; } static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { const char *what; const char *errtxt; (void)extended; if (algo != GCRY_CIPHER_SM4) return GPG_ERR_CIPHER_ALGO; what = "selftest"; errtxt = sm4_selftest (); if (errtxt) goto failed; return 0; failed: if (report) report ("cipher", GCRY_CIPHER_SM4, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } -static gcry_cipher_oid_spec_t sm4_oids[] = +static const gcry_cipher_oid_spec_t sm4_oids[] = { { "1.2.156.10197.1.104.1", GCRY_CIPHER_MODE_ECB }, { "1.2.156.10197.1.104.2", GCRY_CIPHER_MODE_CBC }, { "1.2.156.10197.1.104.3", GCRY_CIPHER_MODE_OFB }, { "1.2.156.10197.1.104.4", GCRY_CIPHER_MODE_CFB }, { "1.2.156.10197.1.104.7", GCRY_CIPHER_MODE_CTR }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_sm4 = { GCRY_CIPHER_SM4, {0, 0}, "SM4", NULL, sm4_oids, 16, 128, sizeof (SM4_context), sm4_setkey, sm4_encrypt, sm4_decrypt, NULL, NULL, run_selftests }; diff --git a/cipher/stribog.c b/cipher/stribog.c index e0ee1515..21e385ae 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -1,1362 +1,1362 @@ /* stribog.c - GOST R 34.11-2012 (Stribog) hash function * Copyright (C) 2013 Dmitry Eremin-Solenikov * * 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 . */ #include #include #include #include #include "g10lib.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; union { u64 h[8]; unsigned char result[64]; }; u64 N[8]; u64 Sigma[8]; } STRIBOG_CONTEXT; /* Pre-computed results of multiplication of bytes on A and reordered with Pi[]. */ static const u64 stribog_table[8][256] = { /* 0 */ { U64_C(0xd01f715b5c7ef8e6), U64_C(0x16fa240980778325), U64_C(0xa8a42e857ee049c8), U64_C(0x6ac1068fa186465b), U64_C(0x6e417bd7a2e9320b), U64_C(0x665c8167a437daab), U64_C(0x7666681aa89617f6), U64_C(0x4b959163700bdcf5), U64_C(0xf14be6b78df36248), U64_C(0xc585bd689a625cff), U64_C(0x9557d7fca67d82cb), U64_C(0x89f0b969af6dd366), U64_C(0xb0833d48749f6c35), U64_C(0xa1998c23b1ecbc7c), U64_C(0x8d70c431ac02a736), U64_C(0xd6dfbc2fd0a8b69e), U64_C(0x37aeb3e551fa198b), U64_C(0x0b7d128a40b5cf9c), U64_C(0x5a8f2008b5780cbc), U64_C(0xedec882284e333e5), U64_C(0xd25fc177d3c7c2ce), U64_C(0x5e0f5d50b61778ec), U64_C(0x1d873683c0c24cb9), U64_C(0xad040bcbb45d208c), U64_C(0x2f89a0285b853c76), U64_C(0x5732fff6791b8d58), U64_C(0x3e9311439ef6ec3f), U64_C(0xc9183a809fd3c00f), U64_C(0x83adf3f5260a01ee), U64_C(0xa6791941f4e8ef10), U64_C(0x103ae97d0ca1cd5d), U64_C(0x2ce948121dee1b4a), U64_C(0x39738421dbf2bf53), U64_C(0x093da2a6cf0cf5b4), U64_C(0xcd9847d89cbcb45f), U64_C(0xf9561c078b2d8ae8), U64_C(0x9c6a755a6971777f), U64_C(0xbc1ebaa0712ef0c5), U64_C(0x72e61542abf963a6), U64_C(0x78bb5fde229eb12e), U64_C(0x14ba94250fceb90d), U64_C(0x844d6697630e5282), U64_C(0x98ea08026a1e032f), U64_C(0xf06bbea144217f5c), U64_C(0xdb6263d11ccb377a), U64_C(0x641c314b2b8ee083), U64_C(0x320e96ab9b4770cf), U64_C(0x1ee7deb986a96b85), U64_C(0xe96cf57a878c47b5), U64_C(0xfdd6615f8842feb8), U64_C(0xc83862965601dd1b), U64_C(0x2ea9f83e92572162), U64_C(0xf876441142ff97fc), U64_C(0xeb2c455608357d9d), U64_C(0x5612a7e0b0c9904c), U64_C(0x6c01cbfb2d500823), U64_C(0x4548a6a7fa037a2d), U64_C(0xabc4c6bf388b6ef4), U64_C(0xbade77d4fdf8bebd), U64_C(0x799b07c8eb4cac3a), U64_C(0x0c9d87e805b19cf0), U64_C(0xcb588aac106afa27), U64_C(0xea0c1d40c1e76089), U64_C(0x2869354a1e816f1a), U64_C(0xff96d17307fbc490), U64_C(0x9f0a9d602f1a5043), U64_C(0x96373fc6e016a5f7), U64_C(0x5292dab8b3a6e41c), U64_C(0x9b8ae0382c752413), U64_C(0x4f15ec3b7364a8a5), U64_C(0x3fb349555724f12b), U64_C(0xc7c50d4415db66d7), U64_C(0x92b7429ee379d1a7), U64_C(0xd37f99611a15dfda), U64_C(0x231427c05e34a086), U64_C(0xa439a96d7b51d538), U64_C(0xb403401077f01865), U64_C(0xdda2aea5901d7902), U64_C(0x0a5d4a9c8967d288), U64_C(0xc265280adf660f93), U64_C(0x8bb0094520d4e94e), U64_C(0x2a29856691385532), U64_C(0x42a833c5bf072941), U64_C(0x73c64d54622b7eb2), U64_C(0x07e095624504536c), U64_C(0x8a905153e906f45a), U64_C(0x6f6123c16b3b2f1f), U64_C(0xc6e55552dc097bc3), U64_C(0x4468feb133d16739), U64_C(0xe211e7f0c7398829), U64_C(0xa2f96419f7879b40), U64_C(0x19074bdbc3ad38e9), U64_C(0xf4ebc3f9474e0b0c), U64_C(0x43886bd376d53455), U64_C(0xd8028beb5aa01046), U64_C(0x51f23282f5cdc320), U64_C(0xe7b1c2be0d84e16d), U64_C(0x081dfab006dee8a0), U64_C(0x3b33340d544b857b), U64_C(0x7f5bcabc679ae242), U64_C(0x0edd37c48a08a6d8), U64_C(0x81ed43d9a9b33bc6), U64_C(0xb1a3655ebd4d7121), U64_C(0x69a1eeb5e7ed6167), U64_C(0xf6ab73d5c8f73124), U64_C(0x1a67a3e185c61fd5), U64_C(0x2dc91004d43c065e), U64_C(0x0240b02c8fb93a28), U64_C(0x90f7f2b26cc0eb8f), U64_C(0x3cd3a16f114fd617), U64_C(0xaae49ea9f15973e0), U64_C(0x06c0cd748cd64e78), U64_C(0xda423bc7d5192a6e), U64_C(0xc345701c16b41287), U64_C(0x6d2193ede4821537), U64_C(0xfcf639494190e3ac), U64_C(0x7c3b228621f1c57e), U64_C(0xfb16ac2b0494b0c0), U64_C(0xbf7e529a3745d7f9), U64_C(0x6881b6a32e3f7c73), U64_C(0xca78d2bad9b8e733), U64_C(0xbbfe2fc2342aa3a9), U64_C(0x0dbddffecc6381e4), U64_C(0x70a6a56e2440598e), U64_C(0xe4d12a844befc651), U64_C(0x8c509c2765d0ba22), U64_C(0xee8c6018c28814d9), U64_C(0x17da7c1f49a59e31), U64_C(0x609c4c1328e194d3), U64_C(0xb3e3d57232f44b09), U64_C(0x91d7aaa4a512f69b), U64_C(0x0ffd6fd243dabbcc), U64_C(0x50d26a943c1fde34), U64_C(0x6be15e9968545b4f), U64_C(0x94778fea6faf9fdf), U64_C(0x2b09dd7058ea4826), U64_C(0x677cd9716de5c7bf), U64_C(0x49d5214fffb2e6dd), U64_C(0x0360e83a466b273c), U64_C(0x1fc786af4f7b7691), U64_C(0xa0b9d435783ea168), U64_C(0xd49f0c035f118cb6), U64_C(0x01205816c9d21d14), U64_C(0xac2453dd7d8f3d98), U64_C(0x545217cc3f70aa64), U64_C(0x26b4028e9489c9c2), U64_C(0xdec2469fd6765e3e), U64_C(0x04807d58036f7450), U64_C(0xe5f17292823ddb45), U64_C(0xf30b569b024a5860), U64_C(0x62dcfc3fa758aefb), U64_C(0xe84cad6c4e5e5aa1), U64_C(0xccb81fce556ea94b), U64_C(0x53b282ae7a74f908), U64_C(0x1b47fbf74c1402c1), U64_C(0x368eebf39828049f), U64_C(0x7afbeff2ad278b06), U64_C(0xbe5e0a8cfe97caed), U64_C(0xcfd8f7f413058e77), U64_C(0xf78b2bc301252c30), U64_C(0x4d555c17fcdd928d), U64_C(0x5f2f05467fc565f8), U64_C(0x24f4b2a21b30f3ea), U64_C(0x860dd6bbecb768aa), U64_C(0x4c750401350f8f99), U64_C(0x0000000000000000), U64_C(0xecccd0344d312ef1), U64_C(0xb5231806be220571), U64_C(0xc105c030990d28af), U64_C(0x653c695de25cfd97), U64_C(0x159acc33c61ca419), U64_C(0xb89ec7f872418495), U64_C(0xa9847693b73254dc), U64_C(0x58cf90243ac13694), U64_C(0x59efc832f3132b80), U64_C(0x5c4fed7c39ae42c4), U64_C(0x828dabe3efd81cfa), U64_C(0xd13f294d95ace5f2), U64_C(0x7d1b7a90e823d86a), U64_C(0xb643f03cf849224d), U64_C(0x3df3f979d89dcb03), U64_C(0x7426d836272f2dde), U64_C(0xdfe21e891fa4432a), U64_C(0x3a136c1b9d99986f), U64_C(0xfa36f43dcd46add4), U64_C(0xc025982650df35bb), U64_C(0x856d3e81aadc4f96), U64_C(0xc4a5e57e53b041eb), U64_C(0x4708168b75ba4005), U64_C(0xaf44bbe73be41aa4), U64_C(0x971767d029c4b8e3), U64_C(0xb9be9feebb939981), U64_C(0x215497ecd18d9aae), U64_C(0x316e7e91dd2c57f3), U64_C(0xcef8afe2dad79363), U64_C(0x3853dc371220a247), U64_C(0x35ee03c9de4323a3), U64_C(0xe6919aa8c456fc79), U64_C(0xe05157dc4880b201), U64_C(0x7bdbb7e464f59612), U64_C(0x127a59518318f775), U64_C(0x332ecebd52956ddb), U64_C(0x8f30741d23bb9d1e), U64_C(0xd922d3fd93720d52), U64_C(0x7746300c61440ae2), U64_C(0x25d4eab4d2e2eefe), U64_C(0x75068020eefd30ca), U64_C(0x135a01474acaea61), U64_C(0x304e268714fe4ae7), U64_C(0xa519f17bb283c82c), U64_C(0xdc82f6b359cf6416), U64_C(0x5baf781e7caa11a8), U64_C(0xb2c38d64fb26561d), U64_C(0x34ce5bdf17913eb7), U64_C(0x5d6fb56af07c5fd0), U64_C(0x182713cd0a7f25fd), U64_C(0x9e2ac576e6c84d57), U64_C(0x9aaab82ee5a73907), U64_C(0xa3d93c0f3e558654), U64_C(0x7e7b92aaae48ff56), U64_C(0x872d8ead256575be), U64_C(0x41c8dbfff96c0e7d), U64_C(0x99ca5014a3cc1e3b), U64_C(0x40e883e930be1369), U64_C(0x1ca76e95091051ad), U64_C(0x4e35b42dbab6b5b1), U64_C(0x05a0254ecabd6944), U64_C(0xe1710fca8152af15), U64_C(0xf22b0e8dcb984574), U64_C(0xb763a82a319b3f59), U64_C(0x63fca4296e8ab3ef), U64_C(0x9d4a2d4ca0a36a6b), U64_C(0xe331bfe60eeb953d), U64_C(0xd5bf541596c391a2), U64_C(0xf5cb9bef8e9c1618), U64_C(0x46284e9dbc685d11), U64_C(0x2074cffa185f87ba), U64_C(0xbd3ee2b6b8fcedd1), U64_C(0xae64e3f1f23607b0), U64_C(0xfeb68965ce29d984), U64_C(0x55724fdaf6a2b770), U64_C(0x29496d5cd753720e), U64_C(0xa75941573d3af204), U64_C(0x8e102c0bea69800a), U64_C(0x111ab16bc573d049), U64_C(0xd7ffe439197aab8a), U64_C(0xefac380e0b5a09cd), U64_C(0x48f579593660fbc9), U64_C(0x22347fd697e6bd92), U64_C(0x61bc1405e13389c7), U64_C(0x4ab5c975b9d9c1e1), U64_C(0x80cd1bcf606126d2), U64_C(0x7186fd78ed92449a), U64_C(0x93971a882aabccb3), U64_C(0x88d0e17f66bfce72), U64_C(0x27945a985d5bd4d6) }, /* 1 */ { U64_C(0xde553f8c05a811c8), U64_C(0x1906b59631b4f565), U64_C(0x436e70d6b1964ff7), U64_C(0x36d343cb8b1e9d85), U64_C(0x843dfacc858aab5a), U64_C(0xfdfc95c299bfc7f9), U64_C(0x0f634bdea1d51fa2), U64_C(0x6d458b3b76efb3cd), U64_C(0x85c3f77cf8593f80), U64_C(0x3c91315fbe737cb2), U64_C(0x2148b03366ace398), U64_C(0x18f8b8264c6761bf), U64_C(0xc830c1c495c9fb0f), U64_C(0x981a76102086a0aa), U64_C(0xaa16012142f35760), U64_C(0x35cc54060c763cf6), U64_C(0x42907d66cc45db2d), U64_C(0x8203d44b965af4bc), U64_C(0x3d6f3cefc3a0e868), U64_C(0xbc73ff69d292bda7), U64_C(0x8722ed0102e20a29), U64_C(0x8f8185e8cd34deb7), U64_C(0x9b0561dda7ee01d9), U64_C(0x5335a0193227fad6), U64_C(0xc9cecc74e81a6fd5), U64_C(0x54f5832e5c2431ea), U64_C(0x99e47ba05d553470), U64_C(0xf7bee756acd226ce), U64_C(0x384e05a5571816fd), U64_C(0xd1367452a47d0e6a), U64_C(0xf29fde1c386ad85b), U64_C(0x320c77316275f7ca), U64_C(0xd0c879e2d9ae9ab0), U64_C(0xdb7406c69110ef5d), U64_C(0x45505e51a2461011), U64_C(0xfc029872e46c5323), U64_C(0xfa3cb6f5f7bc0cc5), U64_C(0x031f17cd8768a173), U64_C(0xbd8df2d9af41297d), U64_C(0x9d3b4f5ab43e5e3f), U64_C(0x4071671b36feee84), U64_C(0x716207e7d3e3b83d), U64_C(0x48d20ff2f9283a1a), U64_C(0x27769eb4757cbc7e), U64_C(0x5c56ebc793f2e574), U64_C(0xa48b474f9ef5dc18), U64_C(0x52cbada94ff46e0c), U64_C(0x60c7da982d8199c6), U64_C(0x0e9d466edc068b78), U64_C(0x4eec2175eaf865fc), U64_C(0x550b8e9e21f7a530), U64_C(0x6b7ba5bc653fec2b), U64_C(0x5eb7f1ba6949d0dd), U64_C(0x57ea94e3db4c9099), U64_C(0xf640eae6d101b214), U64_C(0xdd4a284182c0b0bb), U64_C(0xff1d8fbf6304f250), U64_C(0xb8accb933bf9d7e8), U64_C(0xe8867c478eb68c4d), U64_C(0x3f8e2692391bddc1), U64_C(0xcb2fd60912a15a7c), U64_C(0xaec935dbab983d2f), U64_C(0xf55ffd2b56691367), U64_C(0x80e2ce366ce1c115), U64_C(0x179bf3f8edb27e1d), U64_C(0x01fe0db07dd394da), U64_C(0xda8a0b76ecc37b87), U64_C(0x44ae53e1df9584cb), U64_C(0xb310b4b77347a205), U64_C(0xdfab323c787b8512), U64_C(0x3b511268d070b78e), U64_C(0x65e6e3d2b9396753), U64_C(0x6864b271e2574d58), U64_C(0x259784c98fc789d7), U64_C(0x02e11a7dfabb35a9), U64_C(0x8841a6dfa337158b), U64_C(0x7ade78c39b5dcdd0), U64_C(0xb7cf804d9a2cc84a), U64_C(0x20b6bd831b7f7742), U64_C(0x75bd331d3a88d272), U64_C(0x418f6aab4b2d7a5e), U64_C(0xd9951cbb6babdaf4), U64_C(0xb6318dfde7ff5c90), U64_C(0x1f389b112264aa83), U64_C(0x492c024284fbaec0), U64_C(0xe33a0363c608f9a0), U64_C(0x2688930408af28a4), U64_C(0xc7538a1a341ce4ad), U64_C(0x5da8e677ee2171ae), U64_C(0x8c9e92254a5c7fc4), U64_C(0x63d8cd55aae938b5), U64_C(0x29ebd8daa97a3706), U64_C(0x959827b37be88aa1), U64_C(0x1484e4356adadf6e), U64_C(0xa7945082199d7d6b), U64_C(0xbf6ce8a455fa1cd4), U64_C(0x9cc542eac9edcae5), U64_C(0x79c16f0e1c356ca3), U64_C(0x89bfab6fdee48151), U64_C(0xd4174d1830c5f0ff), U64_C(0x9258048415eb419d), U64_C(0x6139d72850520d1c), U64_C(0x6a85a80c18ec78f1), U64_C(0xcd11f88e0171059a), U64_C(0xcceff53e7ca29140), U64_C(0xd229639f2315af19), U64_C(0x90b91ef9ef507434), U64_C(0x5977d28d074a1be1), U64_C(0x311360fce51d56b9), U64_C(0xc093a92d5a1f2f91), U64_C(0x1a19a25bb6dc5416), U64_C(0xeb996b8a09de2d3e), U64_C(0xfee3820f1ed7668a), U64_C(0xd7085ad5b7ad518c), U64_C(0x7fff41890fe53345), U64_C(0xec5948bd67dde602), U64_C(0x2fd5f65dbaaa68e0), U64_C(0xa5754affe32648c2), U64_C(0xf8ddac880d07396c), U64_C(0x6fa491468c548664), U64_C(0x0c7c5c1326bdbed1), U64_C(0x4a33158f03930fb3), U64_C(0x699abfc19f84d982), U64_C(0xe4fa2054a80b329c), U64_C(0x6707f9af438252fa), U64_C(0x08a368e9cfd6d49e), U64_C(0x47b1442c58fd25b8), U64_C(0xbbb3dc5ebc91769b), U64_C(0x1665fe489061eac7), U64_C(0x33f27a811fa66310), U64_C(0x93a609346838d547), U64_C(0x30ed6d4c98cec263), U64_C(0x1dd9816cd8df9f2a), U64_C(0x94662a03063b1e7b), U64_C(0x83fdd9fbeb896066), U64_C(0x7b207573e68e590a), U64_C(0x5f49fc0a149a4407), U64_C(0x343259b671a5a82c), U64_C(0xfbc2bb458a6f981f), U64_C(0xc272b350a0a41a38), U64_C(0x3aaf1fd8ada32354), U64_C(0x6cbb868b0b3c2717), U64_C(0xa2b569c88d2583fe), U64_C(0xf180c9d1bf027928), U64_C(0xaf37386bd64ba9f5), U64_C(0x12bacab2790a8088), U64_C(0x4c0d3b0810435055), U64_C(0xb2eeb9070e9436df), U64_C(0xc5b29067cea7d104), U64_C(0xdcb425f1ff132461), U64_C(0x4f122cc5972bf126), U64_C(0xac282fa651230886), U64_C(0xe7e537992f6393ef), U64_C(0xe61b3a2952b00735), U64_C(0x709c0a57ae302ce7), U64_C(0xe02514ae416058d3), U64_C(0xc44c9dd7b37445de), U64_C(0x5a68c5408022ba92), U64_C(0x1c278cdca50c0bf0), U64_C(0x6e5a9cf6f18712be), U64_C(0x86dce0b17f319ef3), U64_C(0x2d34ec2040115d49), U64_C(0x4bcd183f7e409b69), U64_C(0x2815d56ad4a9a3dc), U64_C(0x24698979f2141d0d), U64_C(0x0000000000000000), U64_C(0x1ec696a15fb73e59), U64_C(0xd86b110b16784e2e), U64_C(0x8e7f8858b0e74a6d), U64_C(0x063e2e8713d05fe6), U64_C(0xe2c40ed3bbdb6d7a), U64_C(0xb1f1aeca89fc97ac), U64_C(0xe1db191e3cb3cc09), U64_C(0x6418ee62c4eaf389), U64_C(0xc6ad87aa49cf7077), U64_C(0xd6f65765ca7ec556), U64_C(0x9afb6c6dda3d9503), U64_C(0x7ce05644888d9236), U64_C(0x8d609f95378feb1e), U64_C(0x23a9aa4e9c17d631), U64_C(0x6226c0e5d73aac6f), U64_C(0x56149953a69f0443), U64_C(0xeeb852c09d66d3ab), U64_C(0x2b0ac2a753c102af), U64_C(0x07c023376e03cb3c), U64_C(0x2ccae1903dc2c993), U64_C(0xd3d76e2f5ec63bc3), U64_C(0x9e2458973356ff4c), U64_C(0xa66a5d32644ee9b1), U64_C(0x0a427294356de137), U64_C(0x783f62be61e6f879), U64_C(0x1344c70204d91452), U64_C(0x5b96c8f0fdf12e48), U64_C(0xa90916ecc59bf613), U64_C(0xbe92e5142829880e), U64_C(0x727d102a548b194e), U64_C(0x1be7afebcb0fc0cc), U64_C(0x3e702b2244c8491b), U64_C(0xd5e940a84d166425), U64_C(0x66f9f41f3e51c620), U64_C(0xabe80c913f20c3ba), U64_C(0xf07ec461c2d1edf2), U64_C(0xf361d3ac45b94c81), U64_C(0x0521394a94b8fe95), U64_C(0xadd622162cf09c5c), U64_C(0xe97871f7f3651897), U64_C(0xf4a1f09b2bba87bd), U64_C(0x095d6559b2054044), U64_C(0x0bbc7f2448be75ed), U64_C(0x2af4cf172e129675), U64_C(0x157ae98517094bb4), U64_C(0x9fda55274e856b96), U64_C(0x914713499283e0ee), U64_C(0xb952c623462a4332), U64_C(0x74433ead475b46a8), U64_C(0x8b5eb112245fb4f8), U64_C(0xa34b6478f0f61724), U64_C(0x11a5dd7ffe6221fb), U64_C(0xc16da49d27ccbb4b), U64_C(0x76a224d0bde07301), U64_C(0x8aa0bca2598c2022), U64_C(0x4df336b86d90c48f), U64_C(0xea67663a740db9e4), U64_C(0xef465f70e0b54771), U64_C(0x39b008152acb8227), U64_C(0x7d1e5bf4f55e06ec), U64_C(0x105bd0cf83b1b521), U64_C(0x775c2960c033e7db), U64_C(0x7e014c397236a79f), U64_C(0x811cc386113255cf), U64_C(0xeda7450d1a0e72d8), U64_C(0x5889df3d7a998f3b), U64_C(0x2e2bfbedc779fc3a), U64_C(0xce0eef438619a4e9), U64_C(0x372d4e7bf6cd095f), U64_C(0x04df34fae96b6a4f), U64_C(0xf923a13870d4adb6), U64_C(0xa1aa7e050a4d228d), U64_C(0xa8f71b5cb84862c9), U64_C(0xb52e9a306097fde3), U64_C(0x0d8251a35b6e2a0b), U64_C(0x2257a7fee1c442eb), U64_C(0x73831d9a29588d94), U64_C(0x51d4ba64c89ccf7f), U64_C(0x502ab7d4b54f5ba5), U64_C(0x97793dce8153bf08), U64_C(0xe5042de4d5d8a646), U64_C(0x9687307efc802bd2), U64_C(0xa05473b5779eb657), U64_C(0xb4d097801d446939), U64_C(0xcff0e2f3fbca3033), U64_C(0xc38cbee0dd778ee2), U64_C(0x464f499c252eb162), U64_C(0xcad1dbb96f72cea6), U64_C(0xba4dd1eec142e241), U64_C(0xb00fa37af42f0376) }, /* 2 */ { U64_C(0xcce4cd3aa968b245), U64_C(0x089d5484e80b7faf), U64_C(0x638246c1b3548304), U64_C(0xd2fe0ec8c2355492), U64_C(0xa7fbdf7ff2374eee), U64_C(0x4df1600c92337a16), U64_C(0x84e503ea523b12fb), U64_C(0x0790bbfd53ab0c4a), U64_C(0x198a780f38f6ea9d), U64_C(0x2ab30c8f55ec48cb), U64_C(0xe0f7fed6b2c49db5), U64_C(0xb6ecf3f422cadbdc), U64_C(0x409c9a541358df11), U64_C(0xd3ce8a56dfde3fe3), U64_C(0xc3e9224312c8c1a0), U64_C(0x0d6dfa58816ba507), U64_C(0xddf3e1b179952777), U64_C(0x04c02a42748bb1d9), U64_C(0x94c2abff9f2decb8), U64_C(0x4f91752da8f8acf4), U64_C(0x78682befb169bf7b), U64_C(0xe1c77a48af2ff6c4), U64_C(0x0c5d7ec69c80ce76), U64_C(0x4cc1e4928fd81167), U64_C(0xfeed3d24d9997b62), U64_C(0x518bb6dfc3a54a23), U64_C(0x6dbf2d26151f9b90), U64_C(0xb5bc624b05ea664f), U64_C(0xe86aaa525acfe21a), U64_C(0x4801ced0fb53a0be), U64_C(0xc91463e6c00868ed), U64_C(0x1027a815cd16fe43), U64_C(0xf67069a0319204cd), U64_C(0xb04ccc976c8abce7), U64_C(0xc0b9b3fc35e87c33), U64_C(0xf380c77c58f2de65), U64_C(0x50bb3241de4e2152), U64_C(0xdf93f490435ef195), U64_C(0xf1e0d25d62390887), U64_C(0xaf668bfb1a3c3141), U64_C(0xbc11b251f00a7291), U64_C(0x73a5eed47e427d47), U64_C(0x25bee3f6ee4c3b2e), U64_C(0x43cc0beb34786282), U64_C(0xc824e778dde3039c), U64_C(0xf97d86d98a327728), U64_C(0xf2b043e24519b514), U64_C(0xe297ebf7880f4b57), U64_C(0x3a94a49a98fab688), U64_C(0x868516cb68f0c419), U64_C(0xeffa11af0964ee50), U64_C(0xa4ab4ec0d517f37d), U64_C(0xa9c6b498547c567a), U64_C(0x8e18424f80fbbbb6), U64_C(0x0bcdc53bcf2bc23c), U64_C(0x137739aaea3643d0), U64_C(0x2c1333ec1bac2ff0), U64_C(0x8d48d3f0a7db0625), U64_C(0x1e1ac3f26b5de6d7), U64_C(0xf520f81f16b2b95e), U64_C(0x9f0f6ec450062e84), U64_C(0x0130849e1deb6b71), U64_C(0xd45e31ab8c7533a9), U64_C(0x652279a2fd14e43f), U64_C(0x3209f01e70f1c927), U64_C(0xbe71a770cac1a473), U64_C(0x0e3d6be7a64b1894), U64_C(0x7ec8148cff29d840), U64_C(0xcb7476c7fac3be0f), U64_C(0x72956a4a63a91636), U64_C(0x37f95ec21991138f), U64_C(0x9e3fea5a4ded45f5), U64_C(0x7b38ba50964902e8), U64_C(0x222e580bbde73764), U64_C(0x61e253e0899f55e6), U64_C(0xfc8d2805e352ad80), U64_C(0x35994be3235ac56d), U64_C(0x09add01af5e014de), U64_C(0x5e8659a6780539c6), U64_C(0xb17c48097161d796), U64_C(0x026015213acbd6e2), U64_C(0xd1ae9f77e515e901), U64_C(0xb7dc776a3f21b0ad), U64_C(0xaba6a1b96eb78098), U64_C(0x9bcf4486248d9f5d), U64_C(0x582666c536455efd), U64_C(0xfdbdac9bfeb9c6f1), U64_C(0xc47999be4163cdea), U64_C(0x765540081722a7ef), U64_C(0x3e548ed8ec710751), U64_C(0x3d041f67cb51bac2), U64_C(0x7958af71ac82d40a), U64_C(0x36c9da5c047a78fe), U64_C(0xed9a048e33af38b2), U64_C(0x26ee7249c96c86bd), U64_C(0x900281bdeba65d61), U64_C(0x11172c8bd0fd9532), U64_C(0xea0abf73600434f8), U64_C(0x42fc8f75299309f3), U64_C(0x34a9cf7d3eb1ae1c), U64_C(0x2b838811480723ba), U64_C(0x5ce64c8742ceef24), U64_C(0x1adae9b01fd6570e), U64_C(0x3c349bf9d6bad1b3), U64_C(0x82453c891c7b75c0), U64_C(0x97923a40b80d512b), U64_C(0x4a61dbf1c198765c), U64_C(0xb48ce6d518010d3e), U64_C(0xcfb45c858e480fd6), U64_C(0xd933cbf30d1e96ae), U64_C(0xd70ea014ab558e3a), U64_C(0xc189376228031742), U64_C(0x9262949cd16d8b83), U64_C(0xeb3a3bed7def5f89), U64_C(0x49314a4ee6b8cbcf), U64_C(0xdcc3652f647e4c06), U64_C(0xda635a4c2a3e2b3d), U64_C(0x470c21a940f3d35b), U64_C(0x315961a157d174b4), U64_C(0x6672e81dda3459ac), U64_C(0x5b76f77a1165e36e), U64_C(0x445cb01667d36ec8), U64_C(0xc5491d205c88a69b), U64_C(0x456c34887a3805b9), U64_C(0xffddb9bac4721013), U64_C(0x99af51a71e4649bf), U64_C(0xa15be01cbc7729d5), U64_C(0x52db2760e485f7b0), U64_C(0x8c78576eba306d54), U64_C(0xae560f6507d75a30), U64_C(0x95f22f6182c687c9), U64_C(0x71c5fbf54489aba5), U64_C(0xca44f259e728d57e), U64_C(0x88b87d2ccebbdc8d), U64_C(0xbab18d32be4a15aa), U64_C(0x8be8ec93e99b611e), U64_C(0x17b713e89ebdf209), U64_C(0xb31c5d284baa0174), U64_C(0xeeca9531148f8521), U64_C(0xb8d198138481c348), U64_C(0x8988f9b2d350b7fc), U64_C(0xb9e11c8d996aa839), U64_C(0x5a4673e40c8e881f), U64_C(0x1687977683569978), U64_C(0xbf4123eed72acf02), U64_C(0x4ea1f1b3b513c785), U64_C(0xe767452be16f91ff), U64_C(0x7505d1b730021a7c), U64_C(0xa59bca5ec8fc980c), U64_C(0xad069eda20f7e7a3), U64_C(0x38f4b1bba231606a), U64_C(0x60d2d77e94743e97), U64_C(0x9affc0183966f42c), U64_C(0x248e6768f3a7505f), U64_C(0xcdd449a4b483d934), U64_C(0x87b59255751baf68), U64_C(0x1bea6d2e023d3c7f), U64_C(0x6b1f12455b5ffcab), U64_C(0x743555292de9710d), U64_C(0xd8034f6d10f5fddf), U64_C(0xc6198c9f7ba81b08), U64_C(0xbb8109aca3a17edb), U64_C(0xfa2d1766ad12cabb), U64_C(0xc729080166437079), U64_C(0x9c5fff7b77269317), U64_C(0x0000000000000000), U64_C(0x15d706c9a47624eb), U64_C(0x6fdf38072fd44d72), U64_C(0x5fb6dd3865ee52b7), U64_C(0xa33bf53d86bcff37), U64_C(0xe657c1b5fc84fa8e), U64_C(0xaa962527735cebe9), U64_C(0x39c43525bfda0b1b), U64_C(0x204e4d2a872ce186), U64_C(0x7a083ece8ba26999), U64_C(0x554b9c9db72efbfa), U64_C(0xb22cd9b656416a05), U64_C(0x96a2bedea5e63a5a), U64_C(0x802529a826b0a322), U64_C(0x8115ad363b5bc853), U64_C(0x8375b81701901eb1), U64_C(0x3069e53f4a3a1fc5), U64_C(0xbd2136cfede119e0), U64_C(0x18bafc91251d81ec), U64_C(0x1d4a524d4c7d5b44), U64_C(0x05f0aedc6960daa8), U64_C(0x29e39d3072ccf558), U64_C(0x70f57f6b5962c0d4), U64_C(0x989fd53903ad22ce), U64_C(0xf84d024797d91c59), U64_C(0x547b1803aac5908b), U64_C(0xf0d056c37fd263f6), U64_C(0xd56eb535919e58d8), U64_C(0x1c7ad6d351963035), U64_C(0x2e7326cd2167f912), U64_C(0xac361a443d1c8cd2), U64_C(0x697f076461942a49), U64_C(0x4b515f6fdc731d2d), U64_C(0x8ad8680df4700a6f), U64_C(0x41ac1eca0eb3b460), U64_C(0x7d988533d80965d3), U64_C(0xa8f6300649973d0b), U64_C(0x7765c4960ac9cc9e), U64_C(0x7ca801adc5e20ea2), U64_C(0xdea3700e5eb59ae4), U64_C(0xa06b6482a19c42a4), U64_C(0x6a2f96db46b497da), U64_C(0x27def6d7d487edcc), U64_C(0x463ca5375d18b82a), U64_C(0xa6cb5be1efdc259f), U64_C(0x53eba3fef96e9cc1), U64_C(0xce84d81b93a364a7), U64_C(0xf4107c810b59d22f), U64_C(0x333974806d1aa256), U64_C(0x0f0def79bba073e5), U64_C(0x231edc95a00c5c15), U64_C(0xe437d494c64f2c6c), U64_C(0x91320523f64d3610), U64_C(0x67426c83c7df32dd), U64_C(0x6eefbc99323f2603), U64_C(0x9d6f7be56acdf866), U64_C(0x5916e25b2bae358c), U64_C(0x7ff89012e2c2b331), U64_C(0x035091bf2720bd93), U64_C(0x561b0d22900e4669), U64_C(0x28d319ae6f279e29), U64_C(0x2f43a2533c8c9263), U64_C(0xd09e1be9f8fe8270), U64_C(0xf740ed3e2c796fbc), U64_C(0xdb53ded237d5404c), U64_C(0x62b2c25faebfe875), U64_C(0x0afd41a5d2c0a94d), U64_C(0x6412fd3ce0ff8f4e), U64_C(0xe3a76f6995e42026), U64_C(0x6c8fa9b808f4f0e1), U64_C(0xc2d9a6dd0f23aad1), U64_C(0x8f28c6d19d10d0c7), U64_C(0x85d587744fd0798a), U64_C(0xa20b71a39b579446), U64_C(0x684f83fa7c7f4138), U64_C(0xe507500adba4471d), U64_C(0x3f640a46f19a6c20), U64_C(0x1247bd34f7dd28a1), U64_C(0x2d23b77206474481), U64_C(0x93521002cc86e0f2), U64_C(0x572b89bc8de52d18), U64_C(0xfb1d93f8b0f9a1ca), U64_C(0xe95a2ecc4724896b), U64_C(0x3ba420048511ddf9), U64_C(0xd63e248ab6bee54b), U64_C(0x5dd6c8195f258455), U64_C(0x06a03f634e40673b), U64_C(0x1f2a476c76b68da6), U64_C(0x217ec9b49ac78af7), U64_C(0xecaa80102e4453c3), U64_C(0x14e78257b99d4f9a) }, /* 3 */ { U64_C(0x20329b2cc87bba05), U64_C(0x4f5eb6f86546a531), U64_C(0xd4f44775f751b6b1), U64_C(0x8266a47b850dfa8b), U64_C(0xbb986aa15a6ca985), U64_C(0xc979eb08f9ae0f99), U64_C(0x2da6f447a2375ea1), U64_C(0x1e74275dcd7d8576), U64_C(0xbc20180a800bc5f8), U64_C(0xb4a2f701b2dc65be), U64_C(0xe726946f981b6d66), U64_C(0x48e6c453bf21c94c), U64_C(0x42cad9930f0a4195), U64_C(0xefa47b64aacccd20), U64_C(0x71180a8960409a42), U64_C(0x8bb3329bf6a44e0c), U64_C(0xd34c35de2d36dacc), U64_C(0xa92f5b7cbc23dc96), U64_C(0xb31a85aa68bb09c3), U64_C(0x13e04836a73161d2), U64_C(0xb24dfc4129c51d02), U64_C(0x8ae44b70b7da5acd), U64_C(0xe671ed84d96579a7), U64_C(0xa4bb3417d66f3832), U64_C(0x4572ab38d56d2de8), U64_C(0xb1b47761ea47215c), U64_C(0xe81c09cf70aba15d), U64_C(0xffbdb872ce7f90ac), U64_C(0xa8782297fd5dc857), U64_C(0x0d946f6b6a4ce4a4), U64_C(0xe4df1f4f5b995138), U64_C(0x9ebc71edca8c5762), U64_C(0x0a2c1dc0b02b88d9), U64_C(0x3b503c115d9d7b91), U64_C(0xc64376a8111ec3a2), U64_C(0xcec199a323c963e4), U64_C(0xdc76a87ec58616f7), U64_C(0x09d596e073a9b487), U64_C(0x14583a9d7d560daf), U64_C(0xf4c6dc593f2a0cb4), U64_C(0xdd21d19584f80236), U64_C(0x4a4836983ddde1d3), U64_C(0xe58866a41ae745f9), U64_C(0xf591a5b27e541875), U64_C(0x891dc05074586693), U64_C(0x5b068c651810a89e), U64_C(0xa30346bc0c08544f), U64_C(0x3dbf3751c684032d), U64_C(0x2a1e86ec785032dc), U64_C(0xf73f5779fca830ea), U64_C(0xb60c05ca30204d21), U64_C(0x0cc316802b32f065), U64_C(0x8770241bdd96be69), U64_C(0xb861e18199ee95db), U64_C(0xf805cad91418fcd1), U64_C(0x29e70dccbbd20e82), U64_C(0xc7140f435060d763), U64_C(0x0f3a9da0e8b0cc3b), U64_C(0xa2543f574d76408e), U64_C(0xbd7761e1c175d139), U64_C(0x4b1f4f737ca3f512), U64_C(0x6dc2df1f2fc137ab), U64_C(0xf1d05c3967b14856), U64_C(0xa742bf3715ed046c), U64_C(0x654030141d1697ed), U64_C(0x07b872abda676c7d), U64_C(0x3ce84eba87fa17ec), U64_C(0xc1fb0403cb79afdf), U64_C(0x3e46bc7105063f73), U64_C(0x278ae987121cd678), U64_C(0xa1adb4778ef47cd0), U64_C(0x26dd906c5362c2b9), U64_C(0x05168060589b44e2), U64_C(0xfbfc41f9d79ac08f), U64_C(0x0e6de44ba9ced8fa), U64_C(0x9feb08068bf243a3), U64_C(0x7b341749d06b129b), U64_C(0x229c69e74a87929a), U64_C(0xe09ee6c4427c011b), U64_C(0x5692e30e725c4c3a), U64_C(0xda99a33e5e9f6e4b), U64_C(0x353dd85af453a36b), U64_C(0x25241b4c90e0fee7), U64_C(0x5de987258309d022), U64_C(0xe230140fc0802984), U64_C(0x93281e86a0c0b3c6), U64_C(0xf229d719a4337408), U64_C(0x6f6c2dd4ad3d1f34), U64_C(0x8ea5b2fbae3f0aee), U64_C(0x8331dd90c473ee4a), U64_C(0x346aa1b1b52db7aa), U64_C(0xdf8f235e06042aa9), U64_C(0xcc6f6b68a1354b7b), U64_C(0x6c95a6f46ebf236a), U64_C(0x52d31a856bb91c19), U64_C(0x1a35ded6d498d555), U64_C(0xf37eaef2e54d60c9), U64_C(0x72e181a9a3c2a61c), U64_C(0x98537aad51952fde), U64_C(0x16f6c856ffaa2530), U64_C(0xd960281e9d1d5215), U64_C(0x3a0745fa1ce36f50), U64_C(0x0b7b642bf1559c18), U64_C(0x59a87eae9aec8001), U64_C(0x5e100c05408bec7c), U64_C(0x0441f98b19e55023), U64_C(0xd70dcc5534d38aef), U64_C(0x927f676de1bea707), U64_C(0x9769e70db925e3e5), U64_C(0x7a636ea29115065a), U64_C(0x468b201816ef11b6), U64_C(0xab81a9b73edff409), U64_C(0xc0ac7de88a07bb1e), U64_C(0x1f235eb68c0391b7), U64_C(0x6056b074458dd30f), U64_C(0xbe8eeac102f7ed67), U64_C(0xcd381283e04b5fba), U64_C(0x5cbefecec277c4e3), U64_C(0xd21b4c356c48ce0d), U64_C(0x1019c31664b35d8c), U64_C(0x247362a7d19eea26), U64_C(0xebe582efb3299d03), U64_C(0x02aef2cb82fc289f), U64_C(0x86275df09ce8aaa8), U64_C(0x28b07427faac1a43), U64_C(0x38a9b7319e1f47cf), U64_C(0xc82e92e3b8d01b58), U64_C(0x06ef0b409b1978bc), U64_C(0x62f842bfc771fb90), U64_C(0x9904034610eb3b1f), U64_C(0xded85ab5477a3e68), U64_C(0x90d195a663428f98), U64_C(0x5384636e2ac708d8), U64_C(0xcbd719c37b522706), U64_C(0xae9729d76644b0eb), U64_C(0x7c8c65e20a0c7ee6), U64_C(0x80c856b007f1d214), U64_C(0x8c0b40302cc32271), U64_C(0xdbcedad51fe17a8a), U64_C(0x740e8ae938dbdea0), U64_C(0xa615c6dc549310ad), U64_C(0x19cc55f6171ae90b), U64_C(0x49b1bdb8fe5fdd8d), U64_C(0xed0a89af2830e5bf), U64_C(0x6a7aadb4f5a65bd6), U64_C(0x7e22972988f05679), U64_C(0xf952b3325566e810), U64_C(0x39fecedadf61530e), U64_C(0x6101c99f04f3c7ce), U64_C(0x2e5f7f6761b562ff), U64_C(0xf08725d226cf5c97), U64_C(0x63af3b54860fef51), U64_C(0x8ff2cb10ef411e2f), U64_C(0x884ab9bb35267252), U64_C(0x4df04433e7ba8dae), U64_C(0x9afd8866d3690741), U64_C(0x66b9bb34de94abb3), U64_C(0x9baaf18d92171380), U64_C(0x543c11c5f0a064a5), U64_C(0x17a1b1bdbed431f1), U64_C(0xb5f58eeaf3a2717f), U64_C(0xc355f6c849858740), U64_C(0xec5df044694ef17e), U64_C(0xd83751f5dc6346d4), U64_C(0xfc4433520dfdacf2), U64_C(0x0000000000000000), U64_C(0x5a51f58e596ebc5f), U64_C(0x3285aaf12e34cf16), U64_C(0x8d5c39db6dbd36b0), U64_C(0x12b731dde64f7513), U64_C(0x94906c2d7aa7dfbb), U64_C(0x302b583aacc8e789), U64_C(0x9d45facd090e6b3c), U64_C(0x2165e2c78905aec4), U64_C(0x68d45f7f775a7349), U64_C(0x189b2c1d5664fdca), U64_C(0xe1c99f2f030215da), U64_C(0x6983269436246788), U64_C(0x8489af3b1e148237), U64_C(0xe94b702431d5b59c), U64_C(0x33d2d31a6f4adbd7), U64_C(0xbfd9932a4389f9a6), U64_C(0xb0e30e8aab39359d), U64_C(0xd1e2c715afcaf253), U64_C(0x150f43763c28196e), U64_C(0xc4ed846393e2eb3d), U64_C(0x03f98b20c3823c5e), U64_C(0xfd134ab94c83b833), U64_C(0x556b682eb1de7064), U64_C(0x36c4537a37d19f35), U64_C(0x7559f30279a5ca61), U64_C(0x799ae58252973a04), U64_C(0x9c12832648707ffd), U64_C(0x78cd9c6913e92ec5), U64_C(0x1d8dac7d0effb928), U64_C(0x439da0784e745554), U64_C(0x413352b3cc887dcb), U64_C(0xbacf134a1b12bd44), U64_C(0x114ebafd25cd494d), U64_C(0x2f08068c20cb763e), U64_C(0x76a07822ba27f63f), U64_C(0xeab2fb04f25789c2), U64_C(0xe3676de481fe3d45), U64_C(0x1b62a73d95e6c194), U64_C(0x641749ff5c68832c), U64_C(0xa5ec4dfc97112cf3), U64_C(0xf6682e92bdd6242b), U64_C(0x3f11c59a44782bb2), U64_C(0x317c21d1edb6f348), U64_C(0xd65ab5be75ad9e2e), U64_C(0x6b2dd45fb4d84f17), U64_C(0xfaab381296e4d44e), U64_C(0xd0b5befeeeb4e692), U64_C(0x0882ef0b32d7a046), U64_C(0x512a91a5a83b2047), U64_C(0x963e9ee6f85bf724), U64_C(0x4e09cf132438b1f0), U64_C(0x77f701c9fb59e2fe), U64_C(0x7ddb1c094b726a27), U64_C(0x5f4775ee01f5f8bd), U64_C(0x9186ec4d223c9b59), U64_C(0xfeeac1998f01846d), U64_C(0xac39db1ce4b89874), U64_C(0xb75b7c21715e59e0), U64_C(0xafc0503c273aa42a), U64_C(0x6e3b543fec430bf5), U64_C(0x704f7362213e8e83), U64_C(0x58ff0745db9294c0), U64_C(0x67eec2df9feabf72), U64_C(0xa0facd9ccf8a6811), U64_C(0xb936986ad890811a), U64_C(0x95c715c63bd9cb7a), U64_C(0xca8060283a2c33c7), U64_C(0x507de84ee9453486), U64_C(0x85ded6d05f6a96f6), U64_C(0x1cdad5964f81ade9), U64_C(0xd5a33e9eb62fa270), U64_C(0x40642b588df6690a), U64_C(0x7f75eec2c98e42b8), U64_C(0x2cf18dace3494a60), U64_C(0x23cb100c0bf9865b), U64_C(0xeef3028febb2d9e1), U64_C(0x4425d2d394133929), U64_C(0xaad6d05c7fa1e0c8), U64_C(0xad6ea2f7a5c68cb5), U64_C(0xc2028f2308fb9381), U64_C(0x819f2f5b468fc6d5), U64_C(0xc5bafd88d29cfffc), U64_C(0x47dc59f357910577), U64_C(0x2b49ff07392e261d), U64_C(0x57c59ae5332258fb), U64_C(0x73b6f842e2bcb2dd), U64_C(0xcf96e04862b77725), U64_C(0x4ca73dd8a6c4996f), U64_C(0x015779eb417e14c1), U64_C(0x37932a9176af8bf4) }, /* 4 */ { U64_C(0x190a2c9b249df23e), U64_C(0x2f62f8b62263e1e9), U64_C(0x7a7f754740993655), U64_C(0x330b7ba4d5564d9f), U64_C(0x4c17a16a46672582), U64_C(0xb22f08eb7d05f5b8), U64_C(0x535f47f40bc148cc), U64_C(0x3aec5d27d4883037), U64_C(0x10ed0a1825438f96), U64_C(0x516101f72c233d17), U64_C(0x13cc6f949fd04eae), U64_C(0x739853c441474bfd), U64_C(0x653793d90d3f5b1b), U64_C(0x5240647b96b0fc2f), U64_C(0x0c84890ad27623e0), U64_C(0xd7189b32703aaea3), U64_C(0x2685de3523bd9c41), U64_C(0x99317c5b11bffefa), U64_C(0x0d9baa854f079703), U64_C(0x70b93648fbd48ac5), U64_C(0xa80441fce30bc6be), U64_C(0x7287704bdc36ff1e), U64_C(0xb65384ed33dc1f13), U64_C(0xd36417343ee34408), U64_C(0x39cd38ab6e1bf10f), U64_C(0x5ab861770a1f3564), U64_C(0x0ebacf09f594563b), U64_C(0xd04572b884708530), U64_C(0x3cae9722bdb3af47), U64_C(0x4a556b6f2f5cbaf2), U64_C(0xe1704f1f76c4bd74), U64_C(0x5ec4ed7144c6dfcf), U64_C(0x16afc01d4c7810e6), U64_C(0x283f113cd629ca7a), U64_C(0xaf59a8761741ed2d), U64_C(0xeed5a3991e215fac), U64_C(0x3bf37ea849f984d4), U64_C(0xe413e096a56ce33c), U64_C(0x2c439d3a98f020d1), U64_C(0x637559dc6404c46b), U64_C(0x9e6c95d1e5f5d569), U64_C(0x24bb9836045fe99a), U64_C(0x44efa466dac8ecc9), U64_C(0xc6eab2a5c80895d6), U64_C(0x803b50c035220cc4), U64_C(0x0321658cba93c138), U64_C(0x8f9ebc465dc7ee1c), U64_C(0xd15a5137190131d3), U64_C(0x0fa5ec8668e5e2d8), U64_C(0x91c979578d1037b1), U64_C(0x0642ca05693b9f70), U64_C(0xefca80168350eb4f), U64_C(0x38d21b24f36a45ec), U64_C(0xbeab81e1af73d658), U64_C(0x8cbfd9cae7542f24), U64_C(0xfd19cc0d81f11102), U64_C(0x0ac6430fbb4dbc90), U64_C(0x1d76a09d6a441895), U64_C(0x2a01573ff1cbbfa1), U64_C(0xb572e161894fde2b), U64_C(0x8124734fa853b827), U64_C(0x614b1fdf43e6b1b0), U64_C(0x68ac395c4238cc18), U64_C(0x21d837bfd7f7b7d2), U64_C(0x20c714304a860331), U64_C(0x5cfaab726324aa14), U64_C(0x74c5ba4eb50d606e), U64_C(0xf3a3030474654739), U64_C(0x23e671bcf015c209), U64_C(0x45f087e947b9582a), U64_C(0xd8bd77b418df4c7b), U64_C(0xe06f6c90ebb50997), U64_C(0x0bd96080263c0873), U64_C(0x7e03f9410e40dcfe), U64_C(0xb8e94be4c6484928), U64_C(0xfb5b0608e8ca8e72), U64_C(0x1a2b49179e0e3306), U64_C(0x4e29e76961855059), U64_C(0x4f36c4e6fcf4e4ba), U64_C(0x49740ee395cf7bca), U64_C(0xc2963ea386d17f7d), U64_C(0x90d65ad810618352), U64_C(0x12d34c1b02a1fa4d), U64_C(0xfa44258775bb3a91), U64_C(0x18150f14b9ec46dd), U64_C(0x1491861e6b9a653d), U64_C(0x9a1019d7ab2c3fc2), U64_C(0x3668d42d06fe13d7), U64_C(0xdcc1fbb25606a6d0), U64_C(0x969490dd795a1c22), U64_C(0x3549b1a1bc6dd2ef), U64_C(0xc94f5e23a0ed770e), U64_C(0xb9f6686b5b39fdcb), U64_C(0xc4d4f4a6efeae00d), U64_C(0xe732851a1fff2204), U64_C(0x94aad6de5eb869f9), U64_C(0x3f8ff2ae07206e7f), U64_C(0xfe38a9813b62d03a), U64_C(0xa7a1ad7a8bee2466), U64_C(0x7b6056c8dde882b6), U64_C(0x302a1e286fc58ca7), U64_C(0x8da0fa457a259bc7), U64_C(0xb3302b64e074415b), U64_C(0x5402ae7eff8b635f), U64_C(0x08f8050c9cafc94b), U64_C(0xae468bf98a3059ce), U64_C(0x88c355cca98dc58f), U64_C(0xb10e6d67c7963480), U64_C(0xbad70de7e1aa3cf3), U64_C(0xbfb4a26e320262bb), U64_C(0xcb711820870f02d5), U64_C(0xce12b7a954a75c9d), U64_C(0x563ce87dd8691684), U64_C(0x9f73b65e7884618a), U64_C(0x2b1e74b06cba0b42), U64_C(0x47cec1ea605b2df1), U64_C(0x1c698312f735ac76), U64_C(0x5fdbcefed9b76b2c), U64_C(0x831a354c8fb1cdfc), U64_C(0x820516c312c0791f), U64_C(0xb74ca762aeadabf0), U64_C(0xfc06ef821c80a5e1), U64_C(0x5723cbf24518a267), U64_C(0x9d4df05d5f661451), U64_C(0x588627742dfd40bf), U64_C(0xda8331b73f3d39a0), U64_C(0x17b0e392d109a405), U64_C(0xf965400bcf28fba9), U64_C(0x7c3dbf4229a2a925), U64_C(0x023e460327e275db), U64_C(0x6cd0b55a0ce126b3), U64_C(0xe62da695828e96e7), U64_C(0x42ad6e63b3f373b9), U64_C(0xe50cc319381d57df), U64_C(0xc5cbd729729b54ee), U64_C(0x46d1e265fd2a9912), U64_C(0x6428b056904eeff8), U64_C(0x8be23040131e04b7), U64_C(0x6709d5da2add2ec0), U64_C(0x075de98af44a2b93), U64_C(0x8447dcc67bfbe66f), U64_C(0x6616f655b7ac9a23), U64_C(0xd607b8bded4b1a40), U64_C(0x0563af89d3a85e48), U64_C(0x3db1b4ad20c21ba4), U64_C(0x11f22997b8323b75), U64_C(0x292032b34b587e99), U64_C(0x7f1cdace9331681d), U64_C(0x8e819fc9c0b65aff), U64_C(0xa1e3677fe2d5bb16), U64_C(0xcd33d225ee349da5), U64_C(0xd9a2543b85aef898), U64_C(0x795e10cbfa0af76d), U64_C(0x25a4bbb9992e5d79), U64_C(0x78413344677b438e), U64_C(0xf0826688cef68601), U64_C(0xd27b34bba392f0eb), U64_C(0x551d8df162fad7bc), U64_C(0x1e57c511d0d7d9ad), U64_C(0xdeffbdb171e4d30b), U64_C(0xf4feea8e802f6caa), U64_C(0xa480c8f6317de55e), U64_C(0xa0fc44f07fa40ff5), U64_C(0x95b5f551c3c9dd1a), U64_C(0x22f952336d6476ea), U64_C(0x0000000000000000), U64_C(0xa6be8ef5169f9085), U64_C(0xcc2cf1aa73452946), U64_C(0x2e7ddb39bf12550a), U64_C(0xd526dd3157d8db78), U64_C(0x486b2d6c08becf29), U64_C(0x9b0f3a58365d8b21), U64_C(0xac78cdfaadd22c15), U64_C(0xbc95c7e28891a383), U64_C(0x6a927f5f65dab9c3), U64_C(0xc3891d2c1ba0cb9e), U64_C(0xeaa92f9f50f8b507), U64_C(0xcf0d9426c9d6e87e), U64_C(0xca6e3baf1a7eb636), U64_C(0xab25247059980786), U64_C(0x69b31ad3df4978fb), U64_C(0xe2512a93cc577c4c), U64_C(0xff278a0ea61364d9), U64_C(0x71a615c766a53e26), U64_C(0x89dc764334fc716c), U64_C(0xf87a638452594f4a), U64_C(0xf2bc208be914f3da), U64_C(0x8766b94ac1682757), U64_C(0xbbc82e687cdb8810), U64_C(0x626a7a53f9757088), U64_C(0xa2c202f358467a2e), U64_C(0x4d0882e5db169161), U64_C(0x09e7268301de7da8), U64_C(0xe897699c771ac0dc), U64_C(0xc8507dac3d9cc3ed), U64_C(0xc0a878a0a1330aa6), U64_C(0x978bb352e42ba8c1), U64_C(0xe9884a13ea6b743f), U64_C(0x279afdbabecc28a2), U64_C(0x047c8c064ed9eaab), U64_C(0x507e2278b15289f4), U64_C(0x599904fbb08cf45c), U64_C(0xbd8ae46d15e01760), U64_C(0x31353da7f2b43844), U64_C(0x8558ff49e68a528c), U64_C(0x76fbfc4d92ef15b5), U64_C(0x3456922e211c660c), U64_C(0x86799ac55c1993b4), U64_C(0x3e90d1219a51da9c), U64_C(0x2d5cbeb505819432), U64_C(0x982e5fd48cce4a19), U64_C(0xdb9c1238a24c8d43), U64_C(0xd439febecaa96f9b), U64_C(0x418c0bef0960b281), U64_C(0x158ea591f6ebd1de), U64_C(0x1f48e69e4da66d4e), U64_C(0x8afd13cf8e6fb054), U64_C(0xf5e1c9011d5ed849), U64_C(0xe34e091c5126c8af), U64_C(0xad67ee7530a398f6), U64_C(0x43b24dec2e82c75a), U64_C(0x75da99c1287cd48d), U64_C(0x92e81cdb3783f689), U64_C(0xa3dd217cc537cecd), U64_C(0x60543c50de970553), U64_C(0x93f73f54aaf2426a), U64_C(0xa91b62737e7a725d), U64_C(0xf19d4507538732e2), U64_C(0x77e4dfc20f9ea156), U64_C(0x7d229ccdb4d31dc6), U64_C(0x1b346a98037f87e5), U64_C(0xedf4c615a4b29e94), U64_C(0x4093286094110662), U64_C(0xb0114ee85ae78063), U64_C(0x6ff1d0d6b672e78b), U64_C(0x6dcf96d591909250), U64_C(0xdfe09e3eec9567e8), U64_C(0x3214582b4827f97c), U64_C(0xb46dc2ee143e6ac8), U64_C(0xf6c0ac8da7cd1971), U64_C(0xebb60c10cd8901e4), U64_C(0xf7df8f023abcad92), U64_C(0x9c52d3d2c217a0b2), U64_C(0x6b8d5cd0f8ab0d20), U64_C(0x3777f7a29b8fa734), U64_C(0x011f238f9d71b4e3), U64_C(0xc1b75b2f3c42be45), U64_C(0x5de588fdfe551ef7), U64_C(0x6eeef3592b035368), U64_C(0xaa3a07ffc4e9b365), U64_C(0xecebe59a39c32a77), U64_C(0x5ba742f8976e8187), U64_C(0x4b4a48e0b22d0e11), U64_C(0xddded83dcb771233), U64_C(0xa59feb79ac0c51bd), U64_C(0xc7f5912a55792135) }, /* 5 */ { U64_C(0x6d6ae04668a9b08a), U64_C(0x3ab3f04b0be8c743), U64_C(0xe51e166b54b3c908), U64_C(0xbe90a9eb35c2f139), U64_C(0xb2c7066637f2bec1), U64_C(0xaa6945613392202c), U64_C(0x9a28c36f3b5201eb), U64_C(0xddce5a93ab536994), U64_C(0x0e34133ef6382827), U64_C(0x52a02ba1ec55048b), U64_C(0xa2f88f97c4b2a177), U64_C(0x8640e513ca2251a5), U64_C(0xcdf1d36258137622), U64_C(0xfe6cb708dedf8ddb), U64_C(0x8a174a9ec8121e5d), U64_C(0x679896036b81560e), U64_C(0x59ed033395795fee), U64_C(0x1dd778ab8b74edaf), U64_C(0xee533ef92d9f926d), U64_C(0x2a8c79baf8a8d8f5), U64_C(0x6bcf398e69b119f6), U64_C(0xe20491742fafdd95), U64_C(0x276488e0809c2aec), U64_C(0xea955b82d88f5cce), U64_C(0x7102c63a99d9e0c4), U64_C(0xf9763017a5c39946), U64_C(0x429fa2501f151b3d), U64_C(0x4659c72bea05d59e), U64_C(0x984b7fdccf5a6634), U64_C(0xf742232953fbb161), U64_C(0x3041860e08c021c7), U64_C(0x747bfd9616cd9386), U64_C(0x4bb1367192312787), U64_C(0x1b72a1638a6c44d3), U64_C(0x4a0e68a6e8359a66), U64_C(0x169a5039f258b6ca), U64_C(0xb98a2ef44edee5a4), U64_C(0xd9083fe85e43a737), U64_C(0x967f6ce239624e13), U64_C(0x8874f62d3c1a7982), U64_C(0x3c1629830af06e3f), U64_C(0x9165ebfd427e5a8e), U64_C(0xb5dd81794ceeaa5c), U64_C(0x0de8f15a7834f219), U64_C(0x70bd98ede3dd5d25), U64_C(0xaccc9ca9328a8950), U64_C(0x56664eda1945ca28), U64_C(0x221db34c0f8859ae), U64_C(0x26dbd637fa98970d), U64_C(0x1acdffb4f068f932), U64_C(0x4585254f64090fa0), U64_C(0x72de245e17d53afa), U64_C(0x1546b25d7c546cf4), U64_C(0x207e0ffffb803e71), U64_C(0xfaaad2732bcf4378), U64_C(0xb462dfae36ea17bd), U64_C(0xcf926fd1ac1b11fd), U64_C(0xe0672dc7dba7ba4a), U64_C(0xd3fa49ad5d6b41b3), U64_C(0x8ba81449b216a3bc), U64_C(0x14f9ec8a0650d115), U64_C(0x40fc1ee3eb1d7ce2), U64_C(0x23a2ed9b758ce44f), U64_C(0x782c521b14fddc7e), U64_C(0x1c68267cf170504e), U64_C(0xbcf31558c1ca96e6), U64_C(0xa781b43b4ba6d235), U64_C(0xf6fd7dfe29ff0c80), U64_C(0xb0a4bad5c3fad91e), U64_C(0xd199f51ea963266c), U64_C(0x414340349119c103), U64_C(0x5405f269ed4dadf7), U64_C(0xabd61bb649969dcd), U64_C(0x6813dbeae7bdc3c8), U64_C(0x65fb2ab09f8931d1), U64_C(0xf1e7fae152e3181d), U64_C(0xc1a67cef5a2339da), U64_C(0x7a4feea8e0f5bba1), U64_C(0x1e0b9acf05783791), U64_C(0x5b8ebf8061713831), U64_C(0x80e53cdbcb3af8d9), U64_C(0x7e898bd315e57502), U64_C(0xc6bcfbf0213f2d47), U64_C(0x95a38e86b76e942d), U64_C(0x092e94218d243cba), U64_C(0x8339debf453622e7), U64_C(0xb11be402b9fe64ff), U64_C(0x57d9100d634177c9), U64_C(0xcc4e8db52217cbc3), U64_C(0x3b0cae9c71ec7aa2), U64_C(0xfb158ca451cbfe99), U64_C(0x2b33276d82ac6514), U64_C(0x01bf5ed77a04bde1), U64_C(0xc5601994af33f779), U64_C(0x75c4a3416cc92e67), U64_C(0xf3844652a6eb7fc2), U64_C(0x3487e375fdd0ef64), U64_C(0x18ae430704609eed), U64_C(0x4d14efb993298efb), U64_C(0x815a620cb13e4538), U64_C(0x125c354207487869), U64_C(0x9eeea614ce42cf48), U64_C(0xce2d3106d61fac1c), U64_C(0xbbe99247bad6827b), U64_C(0x071a871f7b1c149d), U64_C(0x2e4a1cc10db81656), U64_C(0x77a71ff298c149b8), U64_C(0x06a5d9c80118a97c), U64_C(0xad73c27e488e34b1), U64_C(0x443a7b981e0db241), U64_C(0xe3bbcfa355ab6074), U64_C(0x0af276450328e684), U64_C(0x73617a896dd1871b), U64_C(0x58525de4ef7de20f), U64_C(0xb7be3dcab8e6cd83), U64_C(0x19111dd07e64230c), U64_C(0x842359a03e2a367a), U64_C(0x103f89f1f3401fb6), U64_C(0xdc710444d157d475), U64_C(0xb835702334da5845), U64_C(0x4320fc876511a6dc), U64_C(0xd026abc9d3679b8d), U64_C(0x17250eee885c0b2b), U64_C(0x90dab52a387ae76f), U64_C(0x31fed8d972c49c26), U64_C(0x89cba8fa461ec463), U64_C(0x2ff5421677bcabb7), U64_C(0x396f122f85e41d7d), U64_C(0xa09b332430bac6a8), U64_C(0xc888e8ced7070560), U64_C(0xaeaf201ac682ee8f), U64_C(0x1180d7268944a257), U64_C(0xf058a43628e7a5fc), U64_C(0xbd4c4b8fbbce2b07), U64_C(0xa1246df34abe7b49), U64_C(0x7d5569b79be9af3c), U64_C(0xa9b5a705bd9efa12), U64_C(0xdb6b835baa4bc0e8), U64_C(0x05793bac8f147342), U64_C(0x21c1512881848390), U64_C(0xfdb0556c50d357e5), U64_C(0x613d4fcb6a99ff72), U64_C(0x03dce2648e0cda3e), U64_C(0xe949b9e6568386f0), U64_C(0xfc0f0bbb2ad7ea04), U64_C(0x6a70675913b5a417), U64_C(0x7f36d5046fe1c8e3), U64_C(0x0c57af8d02304ff8), U64_C(0x32223abdfcc84618), U64_C(0x0891caf6f720815b), U64_C(0xa63eeaec31a26fd4), U64_C(0x2507345374944d33), U64_C(0x49d28ac266394058), U64_C(0xf5219f9aa7f3d6be), U64_C(0x2d96fea583b4cc68), U64_C(0x5a31e1571b7585d0), U64_C(0x8ed12fe53d02d0fe), U64_C(0xdfade6205f5b0e4b), U64_C(0x4cabb16ee92d331a), U64_C(0x04c6657bf510cea3), U64_C(0xd73c2cd6a87b8f10), U64_C(0xe1d87310a1a307ab), U64_C(0x6cd5be9112ad0d6b), U64_C(0x97c032354366f3f2), U64_C(0xd4e0ceb22677552e), U64_C(0x0000000000000000), U64_C(0x29509bde76a402cb), U64_C(0xc27a9e8bd42fe3e4), U64_C(0x5ef7842cee654b73), U64_C(0xaf107ecdbc86536e), U64_C(0x3fcacbe784fcb401), U64_C(0xd55f90655c73e8cf), U64_C(0xe6c2f40fdabf1336), U64_C(0xe8f6e7312c873b11), U64_C(0xeb2a0555a28be12f), U64_C(0xe4a148bc2eb774e9), U64_C(0x9b979db84156bc0a), U64_C(0x6eb60222e6a56ab4), U64_C(0x87ffbbc4b026ec44), U64_C(0xc703a5275b3b90a6), U64_C(0x47e699fc9001687f), U64_C(0x9c8d1aa73a4aa897), U64_C(0x7cea3760e1ed12dd), U64_C(0x4ec80ddd1d2554c5), U64_C(0x13e36b957d4cc588), U64_C(0x5d2b66486069914d), U64_C(0x92b90999cc7280b0), U64_C(0x517cc9c56259deb5), U64_C(0xc937b619ad03b881), U64_C(0xec30824ad997f5b2), U64_C(0xa45d565fc5aa080b), U64_C(0xd6837201d27f32f1), U64_C(0x635ef3789e9198ad), U64_C(0x531f75769651b96a), U64_C(0x4f77530a6721e924), U64_C(0x486dd4151c3dfdb9), U64_C(0x5f48dafb9461f692), U64_C(0x375b011173dc355a), U64_C(0x3da9775470f4d3de), U64_C(0x8d0dcd81b30e0ac0), U64_C(0x36e45fc609d888bb), U64_C(0x55baacbe97491016), U64_C(0x8cb29356c90ab721), U64_C(0x76184125e2c5f459), U64_C(0x99f4210bb55edbd5), U64_C(0x6f095cf59ca1d755), U64_C(0x9f51f8c3b44672a9), U64_C(0x3538bda287d45285), U64_C(0x50c39712185d6354), U64_C(0xf23b1885dcefc223), U64_C(0x79930ccc6ef9619f), U64_C(0xed8fdc9da3934853), U64_C(0xcb540aaa590bdf5e), U64_C(0x5c94389f1a6d2cac), U64_C(0xe77daad8a0bbaed7), U64_C(0x28efc5090ca0bf2a), U64_C(0xbf2ff73c4fc64cd8), U64_C(0xb37858b14df60320), U64_C(0xf8c96ec0dfc724a7), U64_C(0x828680683f329f06), U64_C(0x941cd051cd6a29cc), U64_C(0xc3c5c05cae2b5e05), U64_C(0xb601631dc2e27062), U64_C(0xc01922382027843b), U64_C(0x24b86a840e90f0d2), U64_C(0xd245177a276ffc52), U64_C(0x0f8b4de98c3c95c6), U64_C(0x3e759530fef809e0), U64_C(0x0b4d2892792c5b65), U64_C(0xc4df4743d5374a98), U64_C(0xa5e20888bfaeb5ea), U64_C(0xba56cc90c0d23f9a), U64_C(0x38d04cf8ffe0a09c), U64_C(0x62e1adafe495254c), U64_C(0x0263bcb3f40867df), U64_C(0xcaeb547d230f62bf), U64_C(0x6082111c109d4293), U64_C(0xdad4dd8cd04f7d09), U64_C(0xefec602e579b2f8c), U64_C(0x1fb4c4187f7c8a70), U64_C(0xffd3e9dfa4db303a), U64_C(0x7bf0b07f9af10640), U64_C(0xf49ec14dddf76b5f), U64_C(0x8f6e713247066d1f), U64_C(0x339d646a86ccfbf9), U64_C(0x64447467e58d8c30), U64_C(0x2c29a072f9b07189), U64_C(0xd8b7613f24471ad6), U64_C(0x6627c8d41185ebef), U64_C(0xa347d140beb61c96), U64_C(0xde12b8f7255fb3aa), U64_C(0x9d324470404e1576), U64_C(0x9306574eb6763d51), U64_C(0xa80af9d2c79a47f3), U64_C(0x859c0777442e8b9b), U64_C(0x69ac853d9db97e29) }, /* 6 */ { U64_C(0xc3407dfc2de6377e), U64_C(0x5b9e93eea4256f77), U64_C(0xadb58fdd50c845e0), U64_C(0x5219ff11a75bed86), U64_C(0x356b61cfd90b1de9), U64_C(0xfb8f406e25abe037), U64_C(0x7a5a0231c0f60796), U64_C(0x9d3cd216e1f5020b), U64_C(0x0c6550fb6b48d8f3), U64_C(0xf57508c427ff1c62), U64_C(0x4ad35ffa71cb407d), U64_C(0x6290a2da1666aa6d), U64_C(0xe284ec2349355f9f), U64_C(0xb3c307c53d7c84ec), U64_C(0x05e23c0468365a02), U64_C(0x190bac4d6c9ebfa8), U64_C(0x94bbbee9e28b80fa), U64_C(0xa34fc777529cb9b5), U64_C(0xcc7b39f095bcd978), U64_C(0x2426addb0ce532e3), U64_C(0x7e79329312ce4fc7), U64_C(0xab09a72eebec2917), U64_C(0xf8d15499f6b9d6c2), U64_C(0x1a55b8babf8c895d), U64_C(0xdb8add17fb769a85), U64_C(0xb57f2f368658e81b), U64_C(0x8acd36f18f3f41f6), U64_C(0x5ce3b7bba50f11d3), U64_C(0x114dcc14d5ee2f0a), U64_C(0xb91a7fcded1030e8), U64_C(0x81d5425fe55de7a1), U64_C(0xb6213bc1554adeee), U64_C(0x80144ef95f53f5f2), U64_C(0x1e7688186db4c10c), U64_C(0x3b912965db5fe1bc), U64_C(0xc281715a97e8252d), U64_C(0x54a5d7e21c7f8171), U64_C(0x4b12535ccbc5522e), U64_C(0x1d289cefbea6f7f9), U64_C(0x6ef5f2217d2e729e), U64_C(0xe6a7dc819b0d17ce), U64_C(0x1b94b41c05829b0e), U64_C(0x33d7493c622f711e), U64_C(0xdcf7f942fa5ce421), U64_C(0x600fba8b7f7a8ecb), U64_C(0x46b60f011a83988e), U64_C(0x235b898e0dcf4c47), U64_C(0x957ab24f588592a9), U64_C(0x4354330572b5c28c), U64_C(0xa5f3ef84e9b8d542), U64_C(0x8c711e02341b2d01), U64_C(0x0b1874ae6a62a657), U64_C(0x1213d8e306fc19ff), U64_C(0xfe6d7c6a4d9dba35), U64_C(0x65ed868f174cd4c9), U64_C(0x88522ea0e6236550), U64_C(0x899322065c2d7703), U64_C(0xc01e690bfef4018b), U64_C(0x915982ed8abddaf8), U64_C(0xbe675b98ec3a4e4c), U64_C(0xa996bf7f82f00db1), U64_C(0xe1daf8d49a27696a), U64_C(0x2effd5d3dc8986e7), U64_C(0xd153a51f2b1a2e81), U64_C(0x18caa0ebd690adfb), U64_C(0x390e3134b243c51a), U64_C(0x2778b92cdff70416), U64_C(0x029f1851691c24a6), U64_C(0x5e7cafeacc133575), U64_C(0xfa4e4cc89fa5f264), U64_C(0x5a5f9f481e2b7d24), U64_C(0x484c47ab18d764db), U64_C(0x400a27f2a1a7f479), U64_C(0xaeeb9b2a83da7315), U64_C(0x721c626879869734), U64_C(0x042330a2d2384851), U64_C(0x85f672fd3765aff0), U64_C(0xba446b3a3e02061d), U64_C(0x73dd6ecec3888567), U64_C(0xffac70ccf793a866), U64_C(0xdfa9edb5294ed2d4), U64_C(0x6c6aea7014325638), U64_C(0x834a5a0e8c41c307), U64_C(0xcdba35562fb2cb2b), U64_C(0x0ad97808d06cb404), U64_C(0x0f3b440cb85aee06), U64_C(0xe5f9c876481f213b), U64_C(0x98deee1289c35809), U64_C(0x59018bbfcd394bd1), U64_C(0xe01bf47220297b39), U64_C(0xde68e1139340c087), U64_C(0x9fa3ca4788e926ad), U64_C(0xbb85679c840c144e), U64_C(0x53d8f3b71d55ffd5), U64_C(0x0da45c5dd146caa0), U64_C(0x6f34fe87c72060cd), U64_C(0x57fbc315cf6db784), U64_C(0xcee421a1fca0fdde), U64_C(0x3d2d0196607b8d4b), U64_C(0x642c8a29ad42c69a), U64_C(0x14aff010bdd87508), U64_C(0xac74837beac657b3), U64_C(0x3216459ad821634d), U64_C(0x3fb219c70967a9ed), U64_C(0x06bc28f3bb246cf7), U64_C(0xf2082c9126d562c6), U64_C(0x66b39278c45ee23c), U64_C(0xbd394f6f3f2878b9), U64_C(0xfd33689d9e8f8cc0), U64_C(0x37f4799eb017394f), U64_C(0x108cc0b26fe03d59), U64_C(0xda4bd1b1417888d6), U64_C(0xb09d1332ee6eb219), U64_C(0x2f3ed975668794b4), U64_C(0x58c0871977375982), U64_C(0x7561463d78ace990), U64_C(0x09876cff037e82f1), U64_C(0x7fb83e35a8c05d94), U64_C(0x26b9b58a65f91645), U64_C(0xef20b07e9873953f), U64_C(0x3148516d0b3355b8), U64_C(0x41cb2b541ba9e62a), U64_C(0x790416c613e43163), U64_C(0xa011d380818e8f40), U64_C(0x3a5025c36151f3ef), U64_C(0xd57095bdf92266d0), U64_C(0x498d4b0da2d97688), U64_C(0x8b0c3a57353153a5), U64_C(0x21c491df64d368e1), U64_C(0x8f2f0af5e7091bf4), U64_C(0x2da1c1240f9bb012), U64_C(0xc43d59a92ccc49da), U64_C(0xbfa6573e56345c1f), U64_C(0x828b56a8364fd154), U64_C(0x9a41f643e0df7caf), U64_C(0xbcf843c985266aea), U64_C(0x2b1de9d7b4bfdce5), U64_C(0x20059d79dedd7ab2), U64_C(0x6dabe6d6ae3c446b), U64_C(0x45e81bf6c991ae7b), U64_C(0x6351ae7cac68b83e), U64_C(0xa432e32253b6c711), U64_C(0xd092a9b991143cd2), U64_C(0xcac711032e98b58f), U64_C(0xd8d4c9e02864ac70), U64_C(0xc5fc550f96c25b89), U64_C(0xd7ef8dec903e4276), U64_C(0x67729ede7e50f06f), U64_C(0xeac28c7af045cf3d), U64_C(0xb15c1f945460a04a), U64_C(0x9cfddeb05bfb1058), U64_C(0x93c69abce3a1fe5e), U64_C(0xeb0380dc4a4bdd6e), U64_C(0xd20db1e8f8081874), U64_C(0x229a8528b7c15e14), U64_C(0x44291750739fbc28), U64_C(0xd3ccbd4e42060a27), U64_C(0xf62b1c33f4ed2a97), U64_C(0x86a8660ae4779905), U64_C(0xd62e814a2a305025), U64_C(0x477703a7a08d8add), U64_C(0x7b9b0e977af815c5), U64_C(0x78c51a60a9ea2330), U64_C(0xa6adfb733aaae3b7), U64_C(0x97e5aa1e3199b60f), U64_C(0x0000000000000000), U64_C(0xf4b404629df10e31), U64_C(0x5564db44a6719322), U64_C(0x9207961a59afec0d), U64_C(0x9624a6b88b97a45c), U64_C(0x363575380a192b1c), U64_C(0x2c60cd82b595a241), U64_C(0x7d272664c1dc7932), U64_C(0x7142769faa94a1c1), U64_C(0xa1d0df263b809d13), U64_C(0x1630e841d4c451ae), U64_C(0xc1df65ad44fa13d8), U64_C(0x13d2d445bcf20bac), U64_C(0xd915c546926abe23), U64_C(0x38cf3d92084dd749), U64_C(0xe766d0272103059d), U64_C(0xc7634d5effde7f2f), U64_C(0x077d2455012a7ea4), U64_C(0xedbfa82ff16fb199), U64_C(0xaf2a978c39d46146), U64_C(0x42953fa3c8bbd0df), U64_C(0xcb061da59496a7dc), U64_C(0x25e7a17db6eb20b0), U64_C(0x34aa6d6963050fba), U64_C(0xa76cf7d580a4f1e4), U64_C(0xf7ea10954ee338c4), U64_C(0xfcf2643b24819e93), U64_C(0xcf252d0746aeef8d), U64_C(0x4ef06f58a3f3082c), U64_C(0x563acfb37563a5d7), U64_C(0x5086e740ce47c920), U64_C(0x2982f186dda3f843), U64_C(0x87696aac5e798b56), U64_C(0x5d22bb1d1f010380), U64_C(0x035e14f7d31236f5), U64_C(0x3cec0d30da759f18), U64_C(0xf3c920379cdb7095), U64_C(0xb8db736b571e22bb), U64_C(0xdd36f5e44052f672), U64_C(0xaac8ab8851e23b44), U64_C(0xa857b3d938fe1fe2), U64_C(0x17f1e4e76eca43fd), U64_C(0xec7ea4894b61a3ca), U64_C(0x9e62c6e132e734fe), U64_C(0xd4b1991b432c7483), U64_C(0x6ad6c283af163acf), U64_C(0x1ce9904904a8e5aa), U64_C(0x5fbda34c761d2726), U64_C(0xf910583f4cb7c491), U64_C(0xc6a241f845d06d7c), U64_C(0x4f3163fe19fd1a7f), U64_C(0xe99c988d2357f9c8), U64_C(0x8eee06535d0709a7), U64_C(0x0efa48aa0254fc55), U64_C(0xb4be23903c56fa48), U64_C(0x763f52caabbedf65), U64_C(0xeee1bcd8227d876c), U64_C(0xe345e085f33b4dcc), U64_C(0x3e731561b369bbbe), U64_C(0x2843fd2067adea10), U64_C(0x2adce5710eb1ceb6), U64_C(0xb7e03767ef44ccbd), U64_C(0x8db012a48e153f52), U64_C(0x61ceb62dc5749c98), U64_C(0xe85d942b9959eb9b), U64_C(0x4c6f7709caef2c8a), U64_C(0x84377e5b8d6bbda3), U64_C(0x30895dcbb13d47eb), U64_C(0x74a04a9bc2a2fbc3), U64_C(0x6b17ce251518289c), U64_C(0xe438c4d0f2113368), U64_C(0x1fb784bed7bad35f), U64_C(0x9b80fae55ad16efc), U64_C(0x77fe5e6c11b0cd36), U64_C(0xc858095247849129), U64_C(0x08466059b97090a2), U64_C(0x01c10ca6ba0e1253), U64_C(0x6988d6747c040c3a), U64_C(0x6849dad2c60a1e69), U64_C(0x5147ebe67449db73), U64_C(0xc99905f4fd8a837a), U64_C(0x991fe2b433cd4a5a), U64_C(0xf09734c04fc94660), U64_C(0xa28ecbd1e892abe6), U64_C(0xf1563866f5c75433), U64_C(0x4dae7baf70e13ed9), U64_C(0x7ce62ac27bd26b61), U64_C(0x70837a39109ab392), U64_C(0x90988e4b30b3c8ab), U64_C(0xb2020b63877296bf), U64_C(0x156efcb607d6675b) }, /* 7 */ { U64_C(0xe63f55ce97c331d0), U64_C(0x25b506b0015bba16), U64_C(0xc8706e29e6ad9ba8), U64_C(0x5b43d3775d521f6a), U64_C(0x0bfa3d577035106e), U64_C(0xab95fc172afb0e66), U64_C(0xf64b63979e7a3276), U64_C(0xf58b4562649dad4b), U64_C(0x48f7c3dbae0c83f1), U64_C(0xff31916642f5c8c5), U64_C(0xcbb048dc1c4a0495), U64_C(0x66b8f83cdf622989), U64_C(0x35c130e908e2b9b0), U64_C(0x7c761a61f0b34fa1), U64_C(0x3601161cf205268d), U64_C(0x9e54ccfe2219b7d6), U64_C(0x8b7d90a538940837), U64_C(0x9cd403588ea35d0b), U64_C(0xbc3c6fea9ccc5b5a), U64_C(0xe5ff733b6d24aeed), U64_C(0xceed22de0f7eb8d2), U64_C(0xec8581cab1ab545e), U64_C(0xb96105e88ff8e71d), U64_C(0x8ca03501871a5ead), U64_C(0x76ccce65d6db2a2f), U64_C(0x5883f582a7b58057), U64_C(0x3f7be4ed2e8adc3e), U64_C(0x0fe7be06355cd9c9), U64_C(0xee054e6c1d11be83), U64_C(0x1074365909b903a6), U64_C(0x5dde9f80b4813c10), U64_C(0x4a770c7d02b6692c), U64_C(0x5379c8d5d7809039), U64_C(0xb4067448161ed409), U64_C(0x5f5e5026183bd6cd), U64_C(0xe898029bf4c29df9), U64_C(0x7fb63c940a54d09c), U64_C(0xc5171f897f4ba8bc), U64_C(0xa6f28db7b31d3d72), U64_C(0x2e4f3be7716eaa78), U64_C(0x0d6771a099e63314), U64_C(0x82076254e41bf284), U64_C(0x2f0fd2b42733df98), U64_C(0x5c9e76d3e2dc49f0), U64_C(0x7aeb569619606cdb), U64_C(0x83478b07b2468764), U64_C(0xcfadcb8d5923cd32), U64_C(0x85dac7f05b95a41e), U64_C(0xb5469d1b4043a1e9), U64_C(0xb821ecbbd9a592fd), U64_C(0x1b8e0b0e798c13c8), U64_C(0x62a57b6d9a0be02e), U64_C(0xfcf1b793b81257f8), U64_C(0x9d94ea0bd8fe28eb), U64_C(0x4cea408aeb654a56), U64_C(0x23284a47e888996c), U64_C(0x2d8f1d128b893545), U64_C(0xf4cbac3132c0d8ab), U64_C(0xbd7c86b9ca912eba), U64_C(0x3a268eef3dbe6079), U64_C(0xf0d62f6077a9110c), U64_C(0x2735c916ade150cb), U64_C(0x89fd5f03942ee2ea), U64_C(0x1acee25d2fd16628), U64_C(0x90f39bab41181bff), U64_C(0x430dfe8cde39939f), U64_C(0xf70b8ac4c8274796), U64_C(0x1c53aeaac6024552), U64_C(0x13b410acf35e9c9b), U64_C(0xa532ab4249faa24f), U64_C(0x2b1251e5625a163f), U64_C(0xd7e3e676da4841c7), U64_C(0xa7b264e4e5404892), U64_C(0xda8497d643ae72d3), U64_C(0x861ae105a1723b23), U64_C(0x38a6414991048aa4), U64_C(0x6578dec92585b6b4), U64_C(0x0280cfa6acbaeadd), U64_C(0x88bdb650c273970a), U64_C(0x9333bd5ebbff84c2), U64_C(0x4e6a8f2c47dfa08b), U64_C(0x321c954db76cef2a), U64_C(0x418d312a72837942), U64_C(0xb29b38bfffcdf773), U64_C(0x6c022c38f90a4c07), U64_C(0x5a033a240b0f6a8a), U64_C(0x1f93885f3ce5da6f), U64_C(0xc38a537e96988bc6), U64_C(0x39e6a81ac759ff44), U64_C(0x29929e43cee0fce2), U64_C(0x40cdd87924de0ca2), U64_C(0xe9d8ebc8a29fe819), U64_C(0x0c2798f3cfbb46f4), U64_C(0x55e484223e53b343), U64_C(0x4650948ecd0d2fd8), U64_C(0x20e86cb2126f0651), U64_C(0x6d42c56baf5739e7), U64_C(0xa06fc1405ace1e08), U64_C(0x7babbfc54f3d193b), U64_C(0x424d17df8864e67f), U64_C(0xd8045870ef14980e), U64_C(0xc6d7397c85ac3781), U64_C(0x21a885e1443273b1), U64_C(0x67f8116f893f5c69), U64_C(0x24f5efe35706cff6), U64_C(0xd56329d076f2ab1a), U64_C(0x5e1eb9754e66a32d), U64_C(0x28d2771098bd8902), U64_C(0x8f6013f47dfdc190), U64_C(0x17a993fdb637553c), U64_C(0xe0a219397e1012aa), U64_C(0x786b9930b5da8606), U64_C(0x6e82e39e55b0a6da), U64_C(0x875a0856f72f4ec3), U64_C(0x3741ff4fa458536d), U64_C(0xac4859b3957558fc), U64_C(0x7ef6d5c75c09a57c), U64_C(0xc04a758b6c7f14fb), U64_C(0xf9acdd91ab26ebbf), U64_C(0x7391a467c5ef9668), U64_C(0x335c7c1ee1319aca), U64_C(0xa91533b18641e4bb), U64_C(0xe4bf9a683b79db0d), U64_C(0x8e20faa72ba0b470), U64_C(0x51f907737b3a7ae4), U64_C(0x2268a314bed5ec8c), U64_C(0xd944b123b949edee), U64_C(0x31dcb3b84d8b7017), U64_C(0xd3fe65279f218860), U64_C(0x097af2f1dc8ffab3), U64_C(0x9b09a6fc312d0b91), U64_C(0xcc6ded78a3c4520f), U64_C(0x3481d9ba5ebfcc50), U64_C(0x4f2a667f1182d56b), U64_C(0xdfd9fdd4509ace94), U64_C(0x26752045fbbc252b), U64_C(0xbffc491f662bc467), U64_C(0xdd593272fc202449), U64_C(0x3cbbc218d46d4303), U64_C(0x91b372f817456e1f), U64_C(0x681faf69bc6385a0), U64_C(0xb686bbeebaa43ed4), U64_C(0x1469b5084cd0ca01), U64_C(0x98c98009cbca94ac), U64_C(0x6438379a73d8c354), U64_C(0xc2caba2dc0c5fe26), U64_C(0x3e3b0dbe78d7a9de), U64_C(0x50b9ee202d670f04), U64_C(0x4590b27b37eab0e5), U64_C(0x6025b4cb36b10af3), U64_C(0xfb2c1237079c0162), U64_C(0xa12f28130c936be8), U64_C(0x4b37e52e54eb1ccc), U64_C(0x083a1ba28ad28f53), U64_C(0xc10a9cd83a22611b), U64_C(0x9f1425ad7444c236), U64_C(0x069d4cf7e9d3237a), U64_C(0xedc56899e7f621be), U64_C(0x778c273680865fcf), U64_C(0x309c5aeb1bd605f7), U64_C(0x8de0dc52d1472b4d), U64_C(0xf8ec34c2fd7b9e5f), U64_C(0xea18cd3d58787724), U64_C(0xaad515447ca67b86), U64_C(0x9989695a9d97e14c), U64_C(0x0000000000000000), U64_C(0xf196c63321f464ec), U64_C(0x71116bc169557cb5), U64_C(0xaf887f466f92c7c1), U64_C(0x972e3e0ffe964d65), U64_C(0x190ec4a8d536f915), U64_C(0x95aef1a9522ca7b8), U64_C(0xdc19db21aa7d51a9), U64_C(0x94ee18fa0471d258), U64_C(0x8087adf248a11859), U64_C(0xc457f6da2916dd5c), U64_C(0xfa6cfb6451c17482), U64_C(0xf256e0c6db13fbd1), U64_C(0x6a9f60cf10d96f7d), U64_C(0x4daaa9d9bd383fb6), U64_C(0x03c026f5fae79f3d), U64_C(0xde99148706c7bb74), U64_C(0x2a52b8b6340763df), U64_C(0x6fc20acd03edd33a), U64_C(0xd423c08320afdefa), U64_C(0xbbe1ca4e23420dc0), U64_C(0x966ed75ca8cb3885), U64_C(0xeb58246e0e2502c4), U64_C(0x055d6a021334bc47), U64_C(0xa47242111fa7d7af), U64_C(0xe3623fcc84f78d97), U64_C(0x81c744a11efc6db9), U64_C(0xaec8961539cfb221), U64_C(0xf31609958d4e8e31), U64_C(0x63e5923ecc5695ce), U64_C(0x47107ddd9b505a38), U64_C(0xa3afe7b5a0298135), U64_C(0x792b7063e387f3e6), U64_C(0x0140e953565d75e0), U64_C(0x12f4f9ffa503e97b), U64_C(0x750ce8902c3cb512), U64_C(0xdbc47e8515f30733), U64_C(0x1ed3610c6ab8af8f), U64_C(0x5239218681dde5d9), U64_C(0xe222d69fd2aaf877), U64_C(0xfe71783514a8bd25), U64_C(0xcaf0a18f4a177175), U64_C(0x61655d9860ec7f13), U64_C(0xe77fbc9dc19e4430), U64_C(0x2ccff441ddd440a5), U64_C(0x16e97aaee06a20dc), U64_C(0xa855dae2d01c915b), U64_C(0x1d1347f9905f30b2), U64_C(0xb7c652bdecf94b34), U64_C(0xd03e43d265c6175d), U64_C(0xfdb15ec0ee4f2218), U64_C(0x57644b8492e9599e), U64_C(0x07dda5a4bf8e569a), U64_C(0x54a46d71680ec6a3), U64_C(0x5624a2d7c4b42c7e), U64_C(0xbebca04c3076b187), U64_C(0x7d36f332a6ee3a41), U64_C(0x3b6667bc6be31599), U64_C(0x695f463aea3ef040), U64_C(0xad08b0e0c3282d1c), U64_C(0xb15b1e4a052a684e), U64_C(0x44d05b2861b7c505), U64_C(0x15295c5b1a8dbfe1), U64_C(0x744c01c37a61c0f2), U64_C(0x59c31cd1f1e8f5b7), U64_C(0xef45a73f4b4ccb63), U64_C(0x6bdf899c46841a9d), U64_C(0x3dfb2b4b823036e3), U64_C(0xa2ef0ee6f674f4d5), U64_C(0x184e2dfb836b8cf5), U64_C(0x1134df0a5fe47646), U64_C(0xbaa1231d751f7820), U64_C(0xd17eaa81339b62bd), U64_C(0xb01bf71953771dae), U64_C(0x849a2ea30dc8d1fe), U64_C(0x705182923f080955), U64_C(0x0ea757556301ac29), U64_C(0x041d83514569c9a7), U64_C(0x0abad4042668658e), U64_C(0x49b72a88f851f611), U64_C(0x8a3d79f66ec97dd7), U64_C(0xcd2d042bf59927ef), U64_C(0xc930877ab0f0ee48), U64_C(0x9273540deda2f122), U64_C(0xc797d02fd3f14261), U64_C(0xe1e2f06a284d674a), U64_C(0xd2be8c74c97cfd80), U64_C(0x9a494faf67707e71), U64_C(0xb3dbd1eca9908293), U64_C(0x72d14d3493b2e388), U64_C(0xd6a30f258c153427) }, }; static const u64 C16[12][8] = { { U64_C(0xdd806559f2a64507), U64_C(0x05767436cc744d23), U64_C(0xa2422a08a460d315), U64_C(0x4b7ce09192676901), U64_C(0x714eb88d7585c4fc), U64_C(0x2f6a76432e45d016), U64_C(0xebcb2f81c0657c1f), U64_C(0xb1085bda1ecadae9) }, { U64_C(0xe679047021b19bb7), U64_C(0x55dda21bd7cbcd56), U64_C(0x5cb561c2db0aa7ca), U64_C(0x9ab5176b12d69958), U64_C(0x61d55e0f16b50131), U64_C(0xf3feea720a232b98), U64_C(0x4fe39d460f70b5d7), U64_C(0x6fa3b58aa99d2f1a) }, { U64_C(0x991e96f50aba0ab2), U64_C(0xc2b6f443867adb31), U64_C(0xc1c93a376062db09), U64_C(0xd3e20fe490359eb1), U64_C(0xf2ea7514b1297b7b), U64_C(0x06f15e5f529c1f8b), U64_C(0x0a39fc286a3d8435), U64_C(0xf574dcac2bce2fc7) }, { U64_C(0x220cbebc84e3d12e), U64_C(0x3453eaa193e837f1), U64_C(0xd8b71333935203be), U64_C(0xa9d72c82ed03d675), U64_C(0x9d721cad685e353f), U64_C(0x488e857e335c3c7d), U64_C(0xf948e1a05d71e4dd), U64_C(0xef1fdfb3e81566d2) }, { U64_C(0x601758fd7c6cfe57), U64_C(0x7a56a27ea9ea63f5), U64_C(0xdfff00b723271a16), U64_C(0xbfcd1747253af5a3), U64_C(0x359e35d7800fffbd), U64_C(0x7f151c1f1686104a), U64_C(0x9a3f410c6ca92363), U64_C(0x4bea6bacad474799) }, { U64_C(0xfa68407a46647d6e), U64_C(0xbf71c57236904f35), U64_C(0x0af21f66c2bec6b6), U64_C(0xcffaa6b71c9ab7b4), U64_C(0x187f9ab49af08ec6), U64_C(0x2d66c4f95142a46c), U64_C(0x6fa4c33b7a3039c0), U64_C(0xae4faeae1d3ad3d9) }, { U64_C(0x8886564d3a14d493), U64_C(0x3517454ca23c4af3), U64_C(0x06476983284a0504), U64_C(0x0992abc52d822c37), U64_C(0xd3473e33197a93c9), U64_C(0x399ec6c7e6bf87c9), U64_C(0x51ac86febf240954), U64_C(0xf4c70e16eeaac5ec) }, { U64_C(0xa47f0dd4bf02e71e), U64_C(0x36acc2355951a8d9), U64_C(0x69d18d2bd1a5c42f), U64_C(0xf4892bcb929b0690), U64_C(0x89b4443b4ddbc49a), U64_C(0x4eb7f8719c36de1e), U64_C(0x03e7aa020c6e4141), U64_C(0x9b1f5b424d93c9a7) }, { U64_C(0x7261445183235adb), U64_C(0x0e38dc92cb1f2a60), U64_C(0x7b2b8a9aa6079c54), U64_C(0x800a440bdbb2ceb1), U64_C(0x3cd955b7e00d0984), U64_C(0x3a7d3a1b25894224), U64_C(0x944c9ad8ec165fde), U64_C(0x378f5a541631229b) }, { U64_C(0x74b4c7fb98459ced), U64_C(0x3698fad1153bb6c3), U64_C(0x7a1e6c303b7652f4), U64_C(0x9fe76702af69334b), U64_C(0x1fffe18a1b336103), U64_C(0x8941e71cff8a78db), U64_C(0x382ae548b2e4f3f3), U64_C(0xabbedea680056f52) }, { U64_C(0x6bcaa4cd81f32d1b), U64_C(0xdea2594ac06fd85d), U64_C(0xefbacd1d7d476e98), U64_C(0x8a1d71efea48b9ca), U64_C(0x2001802114846679), U64_C(0xd8fa6bbbebab0761), U64_C(0x3002c6cd635afe94), U64_C(0x7bcd9ed0efc889fb) }, { U64_C(0x48bc924af11bd720), U64_C(0xfaf417d5d9b21b99), U64_C(0xe71da4aa88e12852), U64_C(0x5d80ef9d1891cc86), U64_C(0xf82012d430219f9b), U64_C(0xcda43c32bcdf1d77), U64_C(0xd21380b00449b17a), U64_C(0x378ee767f11631ba) }, }; #define strido(out, temp, i) do { \ u64 t; \ t = stribog_table[0][(temp[0] >> (i * 8)) & 0xff]; \ t ^= stribog_table[1][(temp[1] >> (i * 8)) & 0xff]; \ t ^= stribog_table[2][(temp[2] >> (i * 8)) & 0xff]; \ t ^= stribog_table[3][(temp[3] >> (i * 8)) & 0xff]; \ t ^= stribog_table[4][(temp[4] >> (i * 8)) & 0xff]; \ t ^= stribog_table[5][(temp[5] >> (i * 8)) & 0xff]; \ t ^= stribog_table[6][(temp[6] >> (i * 8)) & 0xff]; \ t ^= stribog_table[7][(temp[7] >> (i * 8)) & 0xff]; \ out[i] = t; } while(0) static void LPSX (u64 *out, const u64 *a, const u64 *b) { u64 temp[8]; temp[0] = a[0] ^ b[0]; temp[1] = a[1] ^ b[1]; temp[2] = a[2] ^ b[2]; temp[3] = a[3] ^ b[3]; temp[4] = a[4] ^ b[4]; temp[5] = a[5] ^ b[5]; temp[6] = a[6] ^ b[6]; temp[7] = a[7] ^ b[7]; strido (out, temp, 0); strido (out, temp, 1); strido (out, temp, 2); strido (out, temp, 3); strido (out, temp, 4); strido (out, temp, 5); strido (out, temp, 6); strido (out, temp, 7); } static inline void g (u64 *h, u64 *m, u64 *N) { u64 K[8]; u64 T[8]; int i; LPSX (K, h, N); LPSX (T, K, m); LPSX (K, K, C16[0]); for (i = 1; i < 12; i++) { LPSX (T, K, T); LPSX (K, K, C16[i]); } h[0] ^= T[0] ^ K[0] ^ m[0]; h[1] ^= T[1] ^ K[1] ^ m[1]; h[2] ^= T[2] ^ K[2] ^ m[2]; h[3] ^= T[3] ^ K[3] ^ m[3]; h[4] ^= T[4] ^ K[4] ^ m[4]; h[5] ^= T[5] ^ K[5] ^ m[5]; h[6] ^= T[6] ^ K[6] ^ m[6]; h[7] ^= T[7] ^ K[7] ^ m[7]; } static unsigned int transform (void *context, const unsigned char *inbuf_arg, size_t datalen); static void stribog_init_512 (void *context, unsigned int flags) { STRIBOG_CONTEXT *hd = context; (void)flags; memset (hd, 0, sizeof (*hd)); hd->bctx.blocksize_shift = _gcry_ctz(64); hd->bctx.bwrite = transform; } static void stribog_init_256 (void *context, unsigned int flags) { STRIBOG_CONTEXT *hd = context; stribog_init_512 (context, flags); memset (hd->h, 1, 64); } static void transform_bits (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count) { u64 M[8]; u64 l, cf; int i; for (i = 0; i < 8; i++) M[i] = buf_get_le64(data + i * 8); g (hd->h, M, hd->N); l = hd->N[0]; hd->N[0] += count; if (hd->N[0] < l) { /* overflow */ for (i = 1; i < 8; i++) { hd->N[i]++; if (hd->N[i] != 0) break; } } hd->Sigma[0] += M[0]; cf = 0; for (i = 1; i < 8; i++) { if (hd->Sigma[i-1] != M[i-1]) cf = (hd->Sigma[i-1] < M[i-1]); hd->Sigma[i] += M[i] + cf; } } static unsigned int transform_blk (void *context, const unsigned char *inbuf_arg) { STRIBOG_CONTEXT *hd = context; transform_bits (hd, inbuf_arg, 64 * 8); return /* burn_stack */ 768; } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 64; } while (--nblks); return burn; } /* The routine finally terminates the computation and returns the digest. The handle is prepared for a new cycle, but adding bytes to the handle will the destroy the returned buffer. Returns: 32 bytes with the message the digest. */ static void stribog_final (void *context) { STRIBOG_CONTEXT *hd = context; u64 Z[8] = {}; int i; /* PAD. It does not count towards message length */ i = hd->bctx.count; /* After flush we have at least one byte free) */ hd->bctx.buf[i++] = 1; if (i < 64) memset (&hd->bctx.buf[i], 0, 64 - i); i = 64; transform_bits (hd, hd->bctx.buf, hd->bctx.count * 8); g (hd->h, hd->N, Z); g (hd->h, hd->Sigma, Z); for (i = 0; i < 8; i++) hd->h[i] = le_bswap64(hd->h[i]); hd->bctx.count = 0; _gcry_burn_stack (768); } static byte * stribog_read_512 (void *context) { STRIBOG_CONTEXT *hd = context; return hd->result; } static byte * stribog_read_256 (void *context) { STRIBOG_CONTEXT *hd = context; return hd->result + 32; } -static gcry_md_oid_spec_t oid_spec_stribog256[] = +static const gcry_md_oid_spec_t oid_spec_stribog256[] = { /* id-tc26-signwithdigest-gost3410-12-256 */ { "1.2.643.7.1.1.3.2" }, /* id-tc26-gost3411-12-256 */ { "1.2.643.7.1.1.2.2" }, { NULL }, }; -static gcry_md_oid_spec_t oid_spec_stribog512[] = +static const gcry_md_oid_spec_t oid_spec_stribog512[] = { /* id-tc26-signwithdigest-gost3410-12-512 */ { "1.2.643.7.1.1.3.3" }, /* id-tc26-gost3411-12-512 */ { "1.2.643.7.1.1.2.3" }, { NULL }, }; -gcry_md_spec_t _gcry_digest_spec_stribog_256 = +const gcry_md_spec_t _gcry_digest_spec_stribog_256 = { GCRY_MD_STRIBOG256, {0, 0}, "STRIBOG256", NULL, 0, oid_spec_stribog256, 32, stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read_256, NULL, NULL, sizeof (STRIBOG_CONTEXT) }; -gcry_md_spec_t _gcry_digest_spec_stribog_512 = +const gcry_md_spec_t _gcry_digest_spec_stribog_512 = { GCRY_MD_STRIBOG512, {0, 0}, "STRIBOG512", NULL, 0, oid_spec_stribog512, 64, stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read_512, NULL, NULL, sizeof (STRIBOG_CONTEXT) }; diff --git a/cipher/tiger.c b/cipher/tiger.c index f8208ac8..ae55359c 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -1,860 +1,860 @@ /* tiger.c - The TIGER hash function * Copyright (C) 1998, 2001, 2002, 2003, 2010 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* See http://www.cs.technion.ac.il/~biham/Reports/Tiger/ */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "hash-common.h" #include "bithelp.h" #include "bufhelp.h" typedef struct { gcry_md_block_ctx_t bctx; u64 a, b, c; int variant; /* 0 = old code, 1 = fixed code, 2 - TIGER2. */ } TIGER_CONTEXT; /********************************* * Okay, okay, this is not the fastest code - improvements are welcome. * */ /* Some test vectors: * "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A * "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 * "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" * 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 * "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" * 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" * 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" * "eedings of Fast Software Encryption 3, Cambridge." * EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" * "eedings of Fast Software Encryption 3, Cambridge, 1996." * 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF" * "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" * 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 */ static u64 sbox1[256] = { U64_C(0x02aab17cf7e90c5e) /* 0 */, U64_C(0xac424b03e243a8ec) /* 1 */, U64_C(0x72cd5be30dd5fcd3) /* 2 */, U64_C(0x6d019b93f6f97f3a) /* 3 */, U64_C(0xcd9978ffd21f9193) /* 4 */, U64_C(0x7573a1c9708029e2) /* 5 */, U64_C(0xb164326b922a83c3) /* 6 */, U64_C(0x46883eee04915870) /* 7 */, U64_C(0xeaace3057103ece6) /* 8 */, U64_C(0xc54169b808a3535c) /* 9 */, U64_C(0x4ce754918ddec47c) /* 10 */, U64_C(0x0aa2f4dfdc0df40c) /* 11 */, U64_C(0x10b76f18a74dbefa) /* 12 */, U64_C(0xc6ccb6235ad1ab6a) /* 13 */, U64_C(0x13726121572fe2ff) /* 14 */, U64_C(0x1a488c6f199d921e) /* 15 */, U64_C(0x4bc9f9f4da0007ca) /* 16 */, U64_C(0x26f5e6f6e85241c7) /* 17 */, U64_C(0x859079dbea5947b6) /* 18 */, U64_C(0x4f1885c5c99e8c92) /* 19 */, U64_C(0xd78e761ea96f864b) /* 20 */, U64_C(0x8e36428c52b5c17d) /* 21 */, U64_C(0x69cf6827373063c1) /* 22 */, U64_C(0xb607c93d9bb4c56e) /* 23 */, U64_C(0x7d820e760e76b5ea) /* 24 */, U64_C(0x645c9cc6f07fdc42) /* 25 */, U64_C(0xbf38a078243342e0) /* 26 */, U64_C(0x5f6b343c9d2e7d04) /* 27 */, U64_C(0xf2c28aeb600b0ec6) /* 28 */, U64_C(0x6c0ed85f7254bcac) /* 29 */, U64_C(0x71592281a4db4fe5) /* 30 */, U64_C(0x1967fa69ce0fed9f) /* 31 */, U64_C(0xfd5293f8b96545db) /* 32 */, U64_C(0xc879e9d7f2a7600b) /* 33 */, U64_C(0x860248920193194e) /* 34 */, U64_C(0xa4f9533b2d9cc0b3) /* 35 */, U64_C(0x9053836c15957613) /* 36 */, U64_C(0xdb6dcf8afc357bf1) /* 37 */, U64_C(0x18beea7a7a370f57) /* 38 */, U64_C(0x037117ca50b99066) /* 39 */, U64_C(0x6ab30a9774424a35) /* 40 */, U64_C(0xf4e92f02e325249b) /* 41 */, U64_C(0x7739db07061ccae1) /* 42 */, U64_C(0xd8f3b49ceca42a05) /* 43 */, U64_C(0xbd56be3f51382f73) /* 44 */, U64_C(0x45faed5843b0bb28) /* 45 */, U64_C(0x1c813d5c11bf1f83) /* 46 */, U64_C(0x8af0e4b6d75fa169) /* 47 */, U64_C(0x33ee18a487ad9999) /* 48 */, U64_C(0x3c26e8eab1c94410) /* 49 */, U64_C(0xb510102bc0a822f9) /* 50 */, U64_C(0x141eef310ce6123b) /* 51 */, U64_C(0xfc65b90059ddb154) /* 52 */, U64_C(0xe0158640c5e0e607) /* 53 */, U64_C(0x884e079826c3a3cf) /* 54 */, U64_C(0x930d0d9523c535fd) /* 55 */, U64_C(0x35638d754e9a2b00) /* 56 */, U64_C(0x4085fccf40469dd5) /* 57 */, U64_C(0xc4b17ad28be23a4c) /* 58 */, U64_C(0xcab2f0fc6a3e6a2e) /* 59 */, U64_C(0x2860971a6b943fcd) /* 60 */, U64_C(0x3dde6ee212e30446) /* 61 */, U64_C(0x6222f32ae01765ae) /* 62 */, U64_C(0x5d550bb5478308fe) /* 63 */, U64_C(0xa9efa98da0eda22a) /* 64 */, U64_C(0xc351a71686c40da7) /* 65 */, U64_C(0x1105586d9c867c84) /* 66 */, U64_C(0xdcffee85fda22853) /* 67 */, U64_C(0xccfbd0262c5eef76) /* 68 */, U64_C(0xbaf294cb8990d201) /* 69 */, U64_C(0xe69464f52afad975) /* 70 */, U64_C(0x94b013afdf133e14) /* 71 */, U64_C(0x06a7d1a32823c958) /* 72 */, U64_C(0x6f95fe5130f61119) /* 73 */, U64_C(0xd92ab34e462c06c0) /* 74 */, U64_C(0xed7bde33887c71d2) /* 75 */, U64_C(0x79746d6e6518393e) /* 76 */, U64_C(0x5ba419385d713329) /* 77 */, U64_C(0x7c1ba6b948a97564) /* 78 */, U64_C(0x31987c197bfdac67) /* 79 */, U64_C(0xde6c23c44b053d02) /* 80 */, U64_C(0x581c49fed002d64d) /* 81 */, U64_C(0xdd474d6338261571) /* 82 */, U64_C(0xaa4546c3e473d062) /* 83 */, U64_C(0x928fce349455f860) /* 84 */, U64_C(0x48161bbacaab94d9) /* 85 */, U64_C(0x63912430770e6f68) /* 86 */, U64_C(0x6ec8a5e602c6641c) /* 87 */, U64_C(0x87282515337ddd2b) /* 88 */, U64_C(0x2cda6b42034b701b) /* 89 */, U64_C(0xb03d37c181cb096d) /* 90 */, U64_C(0xe108438266c71c6f) /* 91 */, U64_C(0x2b3180c7eb51b255) /* 92 */, U64_C(0xdf92b82f96c08bbc) /* 93 */, U64_C(0x5c68c8c0a632f3ba) /* 94 */, U64_C(0x5504cc861c3d0556) /* 95 */, U64_C(0xabbfa4e55fb26b8f) /* 96 */, U64_C(0x41848b0ab3baceb4) /* 97 */, U64_C(0xb334a273aa445d32) /* 98 */, U64_C(0xbca696f0a85ad881) /* 99 */, U64_C(0x24f6ec65b528d56c) /* 100 */, U64_C(0x0ce1512e90f4524a) /* 101 */, U64_C(0x4e9dd79d5506d35a) /* 102 */, U64_C(0x258905fac6ce9779) /* 103 */, U64_C(0x2019295b3e109b33) /* 104 */, U64_C(0xf8a9478b73a054cc) /* 105 */, U64_C(0x2924f2f934417eb0) /* 106 */, U64_C(0x3993357d536d1bc4) /* 107 */, U64_C(0x38a81ac21db6ff8b) /* 108 */, U64_C(0x47c4fbf17d6016bf) /* 109 */, U64_C(0x1e0faadd7667e3f5) /* 110 */, U64_C(0x7abcff62938beb96) /* 111 */, U64_C(0xa78dad948fc179c9) /* 112 */, U64_C(0x8f1f98b72911e50d) /* 113 */, U64_C(0x61e48eae27121a91) /* 114 */, U64_C(0x4d62f7ad31859808) /* 115 */, U64_C(0xeceba345ef5ceaeb) /* 116 */, U64_C(0xf5ceb25ebc9684ce) /* 117 */, U64_C(0xf633e20cb7f76221) /* 118 */, U64_C(0xa32cdf06ab8293e4) /* 119 */, U64_C(0x985a202ca5ee2ca4) /* 120 */, U64_C(0xcf0b8447cc8a8fb1) /* 121 */, U64_C(0x9f765244979859a3) /* 122 */, U64_C(0xa8d516b1a1240017) /* 123 */, U64_C(0x0bd7ba3ebb5dc726) /* 124 */, U64_C(0xe54bca55b86adb39) /* 125 */, U64_C(0x1d7a3afd6c478063) /* 126 */, U64_C(0x519ec608e7669edd) /* 127 */, U64_C(0x0e5715a2d149aa23) /* 128 */, U64_C(0x177d4571848ff194) /* 129 */, U64_C(0xeeb55f3241014c22) /* 130 */, U64_C(0x0f5e5ca13a6e2ec2) /* 131 */, U64_C(0x8029927b75f5c361) /* 132 */, U64_C(0xad139fabc3d6e436) /* 133 */, U64_C(0x0d5df1a94ccf402f) /* 134 */, U64_C(0x3e8bd948bea5dfc8) /* 135 */, U64_C(0xa5a0d357bd3ff77e) /* 136 */, U64_C(0xa2d12e251f74f645) /* 137 */, U64_C(0x66fd9e525e81a082) /* 138 */, U64_C(0x2e0c90ce7f687a49) /* 139 */, U64_C(0xc2e8bcbeba973bc5) /* 140 */, U64_C(0x000001bce509745f) /* 141 */, U64_C(0x423777bbe6dab3d6) /* 142 */, U64_C(0xd1661c7eaef06eb5) /* 143 */, U64_C(0xa1781f354daacfd8) /* 144 */, U64_C(0x2d11284a2b16affc) /* 145 */, U64_C(0xf1fc4f67fa891d1f) /* 146 */, U64_C(0x73ecc25dcb920ada) /* 147 */, U64_C(0xae610c22c2a12651) /* 148 */, U64_C(0x96e0a810d356b78a) /* 149 */, U64_C(0x5a9a381f2fe7870f) /* 150 */, U64_C(0xd5ad62ede94e5530) /* 151 */, U64_C(0xd225e5e8368d1427) /* 152 */, U64_C(0x65977b70c7af4631) /* 153 */, U64_C(0x99f889b2de39d74f) /* 154 */, U64_C(0x233f30bf54e1d143) /* 155 */, U64_C(0x9a9675d3d9a63c97) /* 156 */, U64_C(0x5470554ff334f9a8) /* 157 */, U64_C(0x166acb744a4f5688) /* 158 */, U64_C(0x70c74caab2e4aead) /* 159 */, U64_C(0xf0d091646f294d12) /* 160 */, U64_C(0x57b82a89684031d1) /* 161 */, U64_C(0xefd95a5a61be0b6b) /* 162 */, U64_C(0x2fbd12e969f2f29a) /* 163 */, U64_C(0x9bd37013feff9fe8) /* 164 */, U64_C(0x3f9b0404d6085a06) /* 165 */, U64_C(0x4940c1f3166cfe15) /* 166 */, U64_C(0x09542c4dcdf3defb) /* 167 */, U64_C(0xb4c5218385cd5ce3) /* 168 */, U64_C(0xc935b7dc4462a641) /* 169 */, U64_C(0x3417f8a68ed3b63f) /* 170 */, U64_C(0xb80959295b215b40) /* 171 */, U64_C(0xf99cdaef3b8c8572) /* 172 */, U64_C(0x018c0614f8fcb95d) /* 173 */, U64_C(0x1b14accd1a3acdf3) /* 174 */, U64_C(0x84d471f200bb732d) /* 175 */, U64_C(0xc1a3110e95e8da16) /* 176 */, U64_C(0x430a7220bf1a82b8) /* 177 */, U64_C(0xb77e090d39df210e) /* 178 */, U64_C(0x5ef4bd9f3cd05e9d) /* 179 */, U64_C(0x9d4ff6da7e57a444) /* 180 */, U64_C(0xda1d60e183d4a5f8) /* 181 */, U64_C(0xb287c38417998e47) /* 182 */, U64_C(0xfe3edc121bb31886) /* 183 */, U64_C(0xc7fe3ccc980ccbef) /* 184 */, U64_C(0xe46fb590189bfd03) /* 185 */, U64_C(0x3732fd469a4c57dc) /* 186 */, U64_C(0x7ef700a07cf1ad65) /* 187 */, U64_C(0x59c64468a31d8859) /* 188 */, U64_C(0x762fb0b4d45b61f6) /* 189 */, U64_C(0x155baed099047718) /* 190 */, U64_C(0x68755e4c3d50baa6) /* 191 */, U64_C(0xe9214e7f22d8b4df) /* 192 */, U64_C(0x2addbf532eac95f4) /* 193 */, U64_C(0x32ae3909b4bd0109) /* 194 */, U64_C(0x834df537b08e3450) /* 195 */, U64_C(0xfa209da84220728d) /* 196 */, U64_C(0x9e691d9b9efe23f7) /* 197 */, U64_C(0x0446d288c4ae8d7f) /* 198 */, U64_C(0x7b4cc524e169785b) /* 199 */, U64_C(0x21d87f0135ca1385) /* 200 */, U64_C(0xcebb400f137b8aa5) /* 201 */, U64_C(0x272e2b66580796be) /* 202 */, U64_C(0x3612264125c2b0de) /* 203 */, U64_C(0x057702bdad1efbb2) /* 204 */, U64_C(0xd4babb8eacf84be9) /* 205 */, U64_C(0x91583139641bc67b) /* 206 */, U64_C(0x8bdc2de08036e024) /* 207 */, U64_C(0x603c8156f49f68ed) /* 208 */, U64_C(0xf7d236f7dbef5111) /* 209 */, U64_C(0x9727c4598ad21e80) /* 210 */, U64_C(0xa08a0896670a5fd7) /* 211 */, U64_C(0xcb4a8f4309eba9cb) /* 212 */, U64_C(0x81af564b0f7036a1) /* 213 */, U64_C(0xc0b99aa778199abd) /* 214 */, U64_C(0x959f1ec83fc8e952) /* 215 */, U64_C(0x8c505077794a81b9) /* 216 */, U64_C(0x3acaaf8f056338f0) /* 217 */, U64_C(0x07b43f50627a6778) /* 218 */, U64_C(0x4a44ab49f5eccc77) /* 219 */, U64_C(0x3bc3d6e4b679ee98) /* 220 */, U64_C(0x9cc0d4d1cf14108c) /* 221 */, U64_C(0x4406c00b206bc8a0) /* 222 */, U64_C(0x82a18854c8d72d89) /* 223 */, U64_C(0x67e366b35c3c432c) /* 224 */, U64_C(0xb923dd61102b37f2) /* 225 */, U64_C(0x56ab2779d884271d) /* 226 */, U64_C(0xbe83e1b0ff1525af) /* 227 */, U64_C(0xfb7c65d4217e49a9) /* 228 */, U64_C(0x6bdbe0e76d48e7d4) /* 229 */, U64_C(0x08df828745d9179e) /* 230 */, U64_C(0x22ea6a9add53bd34) /* 231 */, U64_C(0xe36e141c5622200a) /* 232 */, U64_C(0x7f805d1b8cb750ee) /* 233 */, U64_C(0xafe5c7a59f58e837) /* 234 */, U64_C(0xe27f996a4fb1c23c) /* 235 */, U64_C(0xd3867dfb0775f0d0) /* 236 */, U64_C(0xd0e673de6e88891a) /* 237 */, U64_C(0x123aeb9eafb86c25) /* 238 */, U64_C(0x30f1d5d5c145b895) /* 239 */, U64_C(0xbb434a2dee7269e7) /* 240 */, U64_C(0x78cb67ecf931fa38) /* 241 */, U64_C(0xf33b0372323bbf9c) /* 242 */, U64_C(0x52d66336fb279c74) /* 243 */, U64_C(0x505f33ac0afb4eaa) /* 244 */, U64_C(0xe8a5cd99a2cce187) /* 245 */, U64_C(0x534974801e2d30bb) /* 246 */, U64_C(0x8d2d5711d5876d90) /* 247 */, U64_C(0x1f1a412891bc038e) /* 248 */, U64_C(0xd6e2e71d82e56648) /* 249 */, U64_C(0x74036c3a497732b7) /* 250 */, U64_C(0x89b67ed96361f5ab) /* 251 */, U64_C(0xffed95d8f1ea02a2) /* 252 */, U64_C(0xe72b3bd61464d43d) /* 253 */, U64_C(0xa6300f170bdc4820) /* 254 */, U64_C(0xebc18760ed78a77a) /* 255 */ }; static u64 sbox2[256] = { U64_C(0xe6a6be5a05a12138) /* 256 */, U64_C(0xb5a122a5b4f87c98) /* 257 */, U64_C(0x563c6089140b6990) /* 258 */, U64_C(0x4c46cb2e391f5dd5) /* 259 */, U64_C(0xd932addbc9b79434) /* 260 */, U64_C(0x08ea70e42015aff5) /* 261 */, U64_C(0xd765a6673e478cf1) /* 262 */, U64_C(0xc4fb757eab278d99) /* 263 */, U64_C(0xdf11c6862d6e0692) /* 264 */, U64_C(0xddeb84f10d7f3b16) /* 265 */, U64_C(0x6f2ef604a665ea04) /* 266 */, U64_C(0x4a8e0f0ff0e0dfb3) /* 267 */, U64_C(0xa5edeef83dbcba51) /* 268 */, U64_C(0xfc4f0a2a0ea4371e) /* 269 */, U64_C(0xe83e1da85cb38429) /* 270 */, U64_C(0xdc8ff882ba1b1ce2) /* 271 */, U64_C(0xcd45505e8353e80d) /* 272 */, U64_C(0x18d19a00d4db0717) /* 273 */, U64_C(0x34a0cfeda5f38101) /* 274 */, U64_C(0x0be77e518887caf2) /* 275 */, U64_C(0x1e341438b3c45136) /* 276 */, U64_C(0xe05797f49089ccf9) /* 277 */, U64_C(0xffd23f9df2591d14) /* 278 */, U64_C(0x543dda228595c5cd) /* 279 */, U64_C(0x661f81fd99052a33) /* 280 */, U64_C(0x8736e641db0f7b76) /* 281 */, U64_C(0x15227725418e5307) /* 282 */, U64_C(0xe25f7f46162eb2fa) /* 283 */, U64_C(0x48a8b2126c13d9fe) /* 284 */, U64_C(0xafdc541792e76eea) /* 285 */, U64_C(0x03d912bfc6d1898f) /* 286 */, U64_C(0x31b1aafa1b83f51b) /* 287 */, U64_C(0xf1ac2796e42ab7d9) /* 288 */, U64_C(0x40a3a7d7fcd2ebac) /* 289 */, U64_C(0x1056136d0afbbcc5) /* 290 */, U64_C(0x7889e1dd9a6d0c85) /* 291 */, U64_C(0xd33525782a7974aa) /* 292 */, U64_C(0xa7e25d09078ac09b) /* 293 */, U64_C(0xbd4138b3eac6edd0) /* 294 */, U64_C(0x920abfbe71eb9e70) /* 295 */, U64_C(0xa2a5d0f54fc2625c) /* 296 */, U64_C(0xc054e36b0b1290a3) /* 297 */, U64_C(0xf6dd59ff62fe932b) /* 298 */, U64_C(0x3537354511a8ac7d) /* 299 */, U64_C(0xca845e9172fadcd4) /* 300 */, U64_C(0x84f82b60329d20dc) /* 301 */, U64_C(0x79c62ce1cd672f18) /* 302 */, U64_C(0x8b09a2add124642c) /* 303 */, U64_C(0xd0c1e96a19d9e726) /* 304 */, U64_C(0x5a786a9b4ba9500c) /* 305 */, U64_C(0x0e020336634c43f3) /* 306 */, U64_C(0xc17b474aeb66d822) /* 307 */, U64_C(0x6a731ae3ec9baac2) /* 308 */, U64_C(0x8226667ae0840258) /* 309 */, U64_C(0x67d4567691caeca5) /* 310 */, U64_C(0x1d94155c4875adb5) /* 311 */, U64_C(0x6d00fd985b813fdf) /* 312 */, U64_C(0x51286efcb774cd06) /* 313 */, U64_C(0x5e8834471fa744af) /* 314 */, U64_C(0xf72ca0aee761ae2e) /* 315 */, U64_C(0xbe40e4cdaee8e09a) /* 316 */, U64_C(0xe9970bbb5118f665) /* 317 */, U64_C(0x726e4beb33df1964) /* 318 */, U64_C(0x703b000729199762) /* 319 */, U64_C(0x4631d816f5ef30a7) /* 320 */, U64_C(0xb880b5b51504a6be) /* 321 */, U64_C(0x641793c37ed84b6c) /* 322 */, U64_C(0x7b21ed77f6e97d96) /* 323 */, U64_C(0x776306312ef96b73) /* 324 */, U64_C(0xae528948e86ff3f4) /* 325 */, U64_C(0x53dbd7f286a3f8f8) /* 326 */, U64_C(0x16cadce74cfc1063) /* 327 */, U64_C(0x005c19bdfa52c6dd) /* 328 */, U64_C(0x68868f5d64d46ad3) /* 329 */, U64_C(0x3a9d512ccf1e186a) /* 330 */, U64_C(0x367e62c2385660ae) /* 331 */, U64_C(0xe359e7ea77dcb1d7) /* 332 */, U64_C(0x526c0773749abe6e) /* 333 */, U64_C(0x735ae5f9d09f734b) /* 334 */, U64_C(0x493fc7cc8a558ba8) /* 335 */, U64_C(0xb0b9c1533041ab45) /* 336 */, U64_C(0x321958ba470a59bd) /* 337 */, U64_C(0x852db00b5f46c393) /* 338 */, U64_C(0x91209b2bd336b0e5) /* 339 */, U64_C(0x6e604f7d659ef19f) /* 340 */, U64_C(0xb99a8ae2782ccb24) /* 341 */, U64_C(0xccf52ab6c814c4c7) /* 342 */, U64_C(0x4727d9afbe11727b) /* 343 */, U64_C(0x7e950d0c0121b34d) /* 344 */, U64_C(0x756f435670ad471f) /* 345 */, U64_C(0xf5add442615a6849) /* 346 */, U64_C(0x4e87e09980b9957a) /* 347 */, U64_C(0x2acfa1df50aee355) /* 348 */, U64_C(0xd898263afd2fd556) /* 349 */, U64_C(0xc8f4924dd80c8fd6) /* 350 */, U64_C(0xcf99ca3d754a173a) /* 351 */, U64_C(0xfe477bacaf91bf3c) /* 352 */, U64_C(0xed5371f6d690c12d) /* 353 */, U64_C(0x831a5c285e687094) /* 354 */, U64_C(0xc5d3c90a3708a0a4) /* 355 */, U64_C(0x0f7f903717d06580) /* 356 */, U64_C(0x19f9bb13b8fdf27f) /* 357 */, U64_C(0xb1bd6f1b4d502843) /* 358 */, U64_C(0x1c761ba38fff4012) /* 359 */, U64_C(0x0d1530c4e2e21f3b) /* 360 */, U64_C(0x8943ce69a7372c8a) /* 361 */, U64_C(0xe5184e11feb5ce66) /* 362 */, U64_C(0x618bdb80bd736621) /* 363 */, U64_C(0x7d29bad68b574d0b) /* 364 */, U64_C(0x81bb613e25e6fe5b) /* 365 */, U64_C(0x071c9c10bc07913f) /* 366 */, U64_C(0xc7beeb7909ac2d97) /* 367 */, U64_C(0xc3e58d353bc5d757) /* 368 */, U64_C(0xeb017892f38f61e8) /* 369 */, U64_C(0xd4effb9c9b1cc21a) /* 370 */, U64_C(0x99727d26f494f7ab) /* 371 */, U64_C(0xa3e063a2956b3e03) /* 372 */, U64_C(0x9d4a8b9a4aa09c30) /* 373 */, U64_C(0x3f6ab7d500090fb4) /* 374 */, U64_C(0x9cc0f2a057268ac0) /* 375 */, U64_C(0x3dee9d2dedbf42d1) /* 376 */, U64_C(0x330f49c87960a972) /* 377 */, U64_C(0xc6b2720287421b41) /* 378 */, U64_C(0x0ac59ec07c00369c) /* 379 */, U64_C(0xef4eac49cb353425) /* 380 */, U64_C(0xf450244eef0129d8) /* 381 */, U64_C(0x8acc46e5caf4deb6) /* 382 */, U64_C(0x2ffeab63989263f7) /* 383 */, U64_C(0x8f7cb9fe5d7a4578) /* 384 */, U64_C(0x5bd8f7644e634635) /* 385 */, U64_C(0x427a7315bf2dc900) /* 386 */, U64_C(0x17d0c4aa2125261c) /* 387 */, U64_C(0x3992486c93518e50) /* 388 */, U64_C(0xb4cbfee0a2d7d4c3) /* 389 */, U64_C(0x7c75d6202c5ddd8d) /* 390 */, U64_C(0xdbc295d8e35b6c61) /* 391 */, U64_C(0x60b369d302032b19) /* 392 */, U64_C(0xce42685fdce44132) /* 393 */, U64_C(0x06f3ddb9ddf65610) /* 394 */, U64_C(0x8ea4d21db5e148f0) /* 395 */, U64_C(0x20b0fce62fcd496f) /* 396 */, U64_C(0x2c1b912358b0ee31) /* 397 */, U64_C(0xb28317b818f5a308) /* 398 */, U64_C(0xa89c1e189ca6d2cf) /* 399 */, U64_C(0x0c6b18576aaadbc8) /* 400 */, U64_C(0xb65deaa91299fae3) /* 401 */, U64_C(0xfb2b794b7f1027e7) /* 402 */, U64_C(0x04e4317f443b5beb) /* 403 */, U64_C(0x4b852d325939d0a6) /* 404 */, U64_C(0xd5ae6beefb207ffc) /* 405 */, U64_C(0x309682b281c7d374) /* 406 */, U64_C(0xbae309a194c3b475) /* 407 */, U64_C(0x8cc3f97b13b49f05) /* 408 */, U64_C(0x98a9422ff8293967) /* 409 */, U64_C(0x244b16b01076ff7c) /* 410 */, U64_C(0xf8bf571c663d67ee) /* 411 */, U64_C(0x1f0d6758eee30da1) /* 412 */, U64_C(0xc9b611d97adeb9b7) /* 413 */, U64_C(0xb7afd5887b6c57a2) /* 414 */, U64_C(0x6290ae846b984fe1) /* 415 */, U64_C(0x94df4cdeacc1a5fd) /* 416 */, U64_C(0x058a5bd1c5483aff) /* 417 */, U64_C(0x63166cc142ba3c37) /* 418 */, U64_C(0x8db8526eb2f76f40) /* 419 */, U64_C(0xe10880036f0d6d4e) /* 420 */, U64_C(0x9e0523c9971d311d) /* 421 */, U64_C(0x45ec2824cc7cd691) /* 422 */, U64_C(0x575b8359e62382c9) /* 423 */, U64_C(0xfa9e400dc4889995) /* 424 */, U64_C(0xd1823ecb45721568) /* 425 */, U64_C(0xdafd983b8206082f) /* 426 */, U64_C(0xaa7d29082386a8cb) /* 427 */, U64_C(0x269fcd4403b87588) /* 428 */, U64_C(0x1b91f5f728bdd1e0) /* 429 */, U64_C(0xe4669f39040201f6) /* 430 */, U64_C(0x7a1d7c218cf04ade) /* 431 */, U64_C(0x65623c29d79ce5ce) /* 432 */, U64_C(0x2368449096c00bb1) /* 433 */, U64_C(0xab9bf1879da503ba) /* 434 */, U64_C(0xbc23ecb1a458058e) /* 435 */, U64_C(0x9a58df01bb401ecc) /* 436 */, U64_C(0xa070e868a85f143d) /* 437 */, U64_C(0x4ff188307df2239e) /* 438 */, U64_C(0x14d565b41a641183) /* 439 */, U64_C(0xee13337452701602) /* 440 */, U64_C(0x950e3dcf3f285e09) /* 441 */, U64_C(0x59930254b9c80953) /* 442 */, U64_C(0x3bf299408930da6d) /* 443 */, U64_C(0xa955943f53691387) /* 444 */, U64_C(0xa15edecaa9cb8784) /* 445 */, U64_C(0x29142127352be9a0) /* 446 */, U64_C(0x76f0371fff4e7afb) /* 447 */, U64_C(0x0239f450274f2228) /* 448 */, U64_C(0xbb073af01d5e868b) /* 449 */, U64_C(0xbfc80571c10e96c1) /* 450 */, U64_C(0xd267088568222e23) /* 451 */, U64_C(0x9671a3d48e80b5b0) /* 452 */, U64_C(0x55b5d38ae193bb81) /* 453 */, U64_C(0x693ae2d0a18b04b8) /* 454 */, U64_C(0x5c48b4ecadd5335f) /* 455 */, U64_C(0xfd743b194916a1ca) /* 456 */, U64_C(0x2577018134be98c4) /* 457 */, U64_C(0xe77987e83c54a4ad) /* 458 */, U64_C(0x28e11014da33e1b9) /* 459 */, U64_C(0x270cc59e226aa213) /* 460 */, U64_C(0x71495f756d1a5f60) /* 461 */, U64_C(0x9be853fb60afef77) /* 462 */, U64_C(0xadc786a7f7443dbf) /* 463 */, U64_C(0x0904456173b29a82) /* 464 */, U64_C(0x58bc7a66c232bd5e) /* 465 */, U64_C(0xf306558c673ac8b2) /* 466 */, U64_C(0x41f639c6b6c9772a) /* 467 */, U64_C(0x216defe99fda35da) /* 468 */, U64_C(0x11640cc71c7be615) /* 469 */, U64_C(0x93c43694565c5527) /* 470 */, U64_C(0xea038e6246777839) /* 471 */, U64_C(0xf9abf3ce5a3e2469) /* 472 */, U64_C(0x741e768d0fd312d2) /* 473 */, U64_C(0x0144b883ced652c6) /* 474 */, U64_C(0xc20b5a5ba33f8552) /* 475 */, U64_C(0x1ae69633c3435a9d) /* 476 */, U64_C(0x97a28ca4088cfdec) /* 477 */, U64_C(0x8824a43c1e96f420) /* 478 */, U64_C(0x37612fa66eeea746) /* 479 */, U64_C(0x6b4cb165f9cf0e5a) /* 480 */, U64_C(0x43aa1c06a0abfb4a) /* 481 */, U64_C(0x7f4dc26ff162796b) /* 482 */, U64_C(0x6cbacc8e54ed9b0f) /* 483 */, U64_C(0xa6b7ffefd2bb253e) /* 484 */, U64_C(0x2e25bc95b0a29d4f) /* 485 */, U64_C(0x86d6a58bdef1388c) /* 486 */, U64_C(0xded74ac576b6f054) /* 487 */, U64_C(0x8030bdbc2b45805d) /* 488 */, U64_C(0x3c81af70e94d9289) /* 489 */, U64_C(0x3eff6dda9e3100db) /* 490 */, U64_C(0xb38dc39fdfcc8847) /* 491 */, U64_C(0x123885528d17b87e) /* 492 */, U64_C(0xf2da0ed240b1b642) /* 493 */, U64_C(0x44cefadcd54bf9a9) /* 494 */, U64_C(0x1312200e433c7ee6) /* 495 */, U64_C(0x9ffcc84f3a78c748) /* 496 */, U64_C(0xf0cd1f72248576bb) /* 497 */, U64_C(0xec6974053638cfe4) /* 498 */, U64_C(0x2ba7b67c0cec4e4c) /* 499 */, U64_C(0xac2f4df3e5ce32ed) /* 500 */, U64_C(0xcb33d14326ea4c11) /* 501 */, U64_C(0xa4e9044cc77e58bc) /* 502 */, U64_C(0x5f513293d934fcef) /* 503 */, U64_C(0x5dc9645506e55444) /* 504 */, U64_C(0x50de418f317de40a) /* 505 */, U64_C(0x388cb31a69dde259) /* 506 */, U64_C(0x2db4a83455820a86) /* 507 */, U64_C(0x9010a91e84711ae9) /* 508 */, U64_C(0x4df7f0b7b1498371) /* 509 */, U64_C(0xd62a2eabc0977179) /* 510 */, U64_C(0x22fac097aa8d5c0e) /* 511 */ }; static u64 sbox3[256] = { U64_C(0xf49fcc2ff1daf39b) /* 512 */, U64_C(0x487fd5c66ff29281) /* 513 */, U64_C(0xe8a30667fcdca83f) /* 514 */, U64_C(0x2c9b4be3d2fcce63) /* 515 */, U64_C(0xda3ff74b93fbbbc2) /* 516 */, U64_C(0x2fa165d2fe70ba66) /* 517 */, U64_C(0xa103e279970e93d4) /* 518 */, U64_C(0xbecdec77b0e45e71) /* 519 */, U64_C(0xcfb41e723985e497) /* 520 */, U64_C(0xb70aaa025ef75017) /* 521 */, U64_C(0xd42309f03840b8e0) /* 522 */, U64_C(0x8efc1ad035898579) /* 523 */, U64_C(0x96c6920be2b2abc5) /* 524 */, U64_C(0x66af4163375a9172) /* 525 */, U64_C(0x2174abdcca7127fb) /* 526 */, U64_C(0xb33ccea64a72ff41) /* 527 */, U64_C(0xf04a4933083066a5) /* 528 */, U64_C(0x8d970acdd7289af5) /* 529 */, U64_C(0x8f96e8e031c8c25e) /* 530 */, U64_C(0xf3fec02276875d47) /* 531 */, U64_C(0xec7bf310056190dd) /* 532 */, U64_C(0xf5adb0aebb0f1491) /* 533 */, U64_C(0x9b50f8850fd58892) /* 534 */, U64_C(0x4975488358b74de8) /* 535 */, U64_C(0xa3354ff691531c61) /* 536 */, U64_C(0x0702bbe481d2c6ee) /* 537 */, U64_C(0x89fb24057deded98) /* 538 */, U64_C(0xac3075138596e902) /* 539 */, U64_C(0x1d2d3580172772ed) /* 540 */, U64_C(0xeb738fc28e6bc30d) /* 541 */, U64_C(0x5854ef8f63044326) /* 542 */, U64_C(0x9e5c52325add3bbe) /* 543 */, U64_C(0x90aa53cf325c4623) /* 544 */, U64_C(0xc1d24d51349dd067) /* 545 */, U64_C(0x2051cfeea69ea624) /* 546 */, U64_C(0x13220f0a862e7e4f) /* 547 */, U64_C(0xce39399404e04864) /* 548 */, U64_C(0xd9c42ca47086fcb7) /* 549 */, U64_C(0x685ad2238a03e7cc) /* 550 */, U64_C(0x066484b2ab2ff1db) /* 551 */, U64_C(0xfe9d5d70efbf79ec) /* 552 */, U64_C(0x5b13b9dd9c481854) /* 553 */, U64_C(0x15f0d475ed1509ad) /* 554 */, U64_C(0x0bebcd060ec79851) /* 555 */, U64_C(0xd58c6791183ab7f8) /* 556 */, U64_C(0xd1187c5052f3eee4) /* 557 */, U64_C(0xc95d1192e54e82ff) /* 558 */, U64_C(0x86eea14cb9ac6ca2) /* 559 */, U64_C(0x3485beb153677d5d) /* 560 */, U64_C(0xdd191d781f8c492a) /* 561 */, U64_C(0xf60866baa784ebf9) /* 562 */, U64_C(0x518f643ba2d08c74) /* 563 */, U64_C(0x8852e956e1087c22) /* 564 */, U64_C(0xa768cb8dc410ae8d) /* 565 */, U64_C(0x38047726bfec8e1a) /* 566 */, U64_C(0xa67738b4cd3b45aa) /* 567 */, U64_C(0xad16691cec0dde19) /* 568 */, U64_C(0xc6d4319380462e07) /* 569 */, U64_C(0xc5a5876d0ba61938) /* 570 */, U64_C(0x16b9fa1fa58fd840) /* 571 */, U64_C(0x188ab1173ca74f18) /* 572 */, U64_C(0xabda2f98c99c021f) /* 573 */, U64_C(0x3e0580ab134ae816) /* 574 */, U64_C(0x5f3b05b773645abb) /* 575 */, U64_C(0x2501a2be5575f2f6) /* 576 */, U64_C(0x1b2f74004e7e8ba9) /* 577 */, U64_C(0x1cd7580371e8d953) /* 578 */, U64_C(0x7f6ed89562764e30) /* 579 */, U64_C(0xb15926ff596f003d) /* 580 */, U64_C(0x9f65293da8c5d6b9) /* 581 */, U64_C(0x6ecef04dd690f84c) /* 582 */, U64_C(0x4782275fff33af88) /* 583 */, U64_C(0xe41433083f820801) /* 584 */, U64_C(0xfd0dfe409a1af9b5) /* 585 */, U64_C(0x4325a3342cdb396b) /* 586 */, U64_C(0x8ae77e62b301b252) /* 587 */, U64_C(0xc36f9e9f6655615a) /* 588 */, U64_C(0x85455a2d92d32c09) /* 589 */, U64_C(0xf2c7dea949477485) /* 590 */, U64_C(0x63cfb4c133a39eba) /* 591 */, U64_C(0x83b040cc6ebc5462) /* 592 */, U64_C(0x3b9454c8fdb326b0) /* 593 */, U64_C(0x56f56a9e87ffd78c) /* 594 */, U64_C(0x2dc2940d99f42bc6) /* 595 */, U64_C(0x98f7df096b096e2d) /* 596 */, U64_C(0x19a6e01e3ad852bf) /* 597 */, U64_C(0x42a99ccbdbd4b40b) /* 598 */, U64_C(0xa59998af45e9c559) /* 599 */, U64_C(0x366295e807d93186) /* 600 */, U64_C(0x6b48181bfaa1f773) /* 601 */, U64_C(0x1fec57e2157a0a1d) /* 602 */, U64_C(0x4667446af6201ad5) /* 603 */, U64_C(0xe615ebcacfb0f075) /* 604 */, U64_C(0xb8f31f4f68290778) /* 605 */, U64_C(0x22713ed6ce22d11e) /* 606 */, U64_C(0x3057c1a72ec3c93b) /* 607 */, U64_C(0xcb46acc37c3f1f2f) /* 608 */, U64_C(0xdbb893fd02aaf50e) /* 609 */, U64_C(0x331fd92e600b9fcf) /* 610 */, U64_C(0xa498f96148ea3ad6) /* 611 */, U64_C(0xa8d8426e8b6a83ea) /* 612 */, U64_C(0xa089b274b7735cdc) /* 613 */, U64_C(0x87f6b3731e524a11) /* 614 */, U64_C(0x118808e5cbc96749) /* 615 */, U64_C(0x9906e4c7b19bd394) /* 616 */, U64_C(0xafed7f7e9b24a20c) /* 617 */, U64_C(0x6509eadeeb3644a7) /* 618 */, U64_C(0x6c1ef1d3e8ef0ede) /* 619 */, U64_C(0xb9c97d43e9798fb4) /* 620 */, U64_C(0xa2f2d784740c28a3) /* 621 */, U64_C(0x7b8496476197566f) /* 622 */, U64_C(0x7a5be3e6b65f069d) /* 623 */, U64_C(0xf96330ed78be6f10) /* 624 */, U64_C(0xeee60de77a076a15) /* 625 */, U64_C(0x2b4bee4aa08b9bd0) /* 626 */, U64_C(0x6a56a63ec7b8894e) /* 627 */, U64_C(0x02121359ba34fef4) /* 628 */, U64_C(0x4cbf99f8283703fc) /* 629 */, U64_C(0x398071350caf30c8) /* 630 */, U64_C(0xd0a77a89f017687a) /* 631 */, U64_C(0xf1c1a9eb9e423569) /* 632 */, U64_C(0x8c7976282dee8199) /* 633 */, U64_C(0x5d1737a5dd1f7abd) /* 634 */, U64_C(0x4f53433c09a9fa80) /* 635 */, U64_C(0xfa8b0c53df7ca1d9) /* 636 */, U64_C(0x3fd9dcbc886ccb77) /* 637 */, U64_C(0xc040917ca91b4720) /* 638 */, U64_C(0x7dd00142f9d1dcdf) /* 639 */, U64_C(0x8476fc1d4f387b58) /* 640 */, U64_C(0x23f8e7c5f3316503) /* 641 */, U64_C(0x032a2244e7e37339) /* 642 */, U64_C(0x5c87a5d750f5a74b) /* 643 */, U64_C(0x082b4cc43698992e) /* 644 */, U64_C(0xdf917becb858f63c) /* 645 */, U64_C(0x3270b8fc5bf86dda) /* 646 */, U64_C(0x10ae72bb29b5dd76) /* 647 */, U64_C(0x576ac94e7700362b) /* 648 */, U64_C(0x1ad112dac61efb8f) /* 649 */, U64_C(0x691bc30ec5faa427) /* 650 */, U64_C(0xff246311cc327143) /* 651 */, U64_C(0x3142368e30e53206) /* 652 */, U64_C(0x71380e31e02ca396) /* 653 */, U64_C(0x958d5c960aad76f1) /* 654 */, U64_C(0xf8d6f430c16da536) /* 655 */, U64_C(0xc8ffd13f1be7e1d2) /* 656 */, U64_C(0x7578ae66004ddbe1) /* 657 */, U64_C(0x05833f01067be646) /* 658 */, U64_C(0xbb34b5ad3bfe586d) /* 659 */, U64_C(0x095f34c9a12b97f0) /* 660 */, U64_C(0x247ab64525d60ca8) /* 661 */, U64_C(0xdcdbc6f3017477d1) /* 662 */, U64_C(0x4a2e14d4decad24d) /* 663 */, U64_C(0xbdb5e6d9be0a1eeb) /* 664 */, U64_C(0x2a7e70f7794301ab) /* 665 */, U64_C(0xdef42d8a270540fd) /* 666 */, U64_C(0x01078ec0a34c22c1) /* 667 */, U64_C(0xe5de511af4c16387) /* 668 */, U64_C(0x7ebb3a52bd9a330a) /* 669 */, U64_C(0x77697857aa7d6435) /* 670 */, U64_C(0x004e831603ae4c32) /* 671 */, U64_C(0xe7a21020ad78e312) /* 672 */, U64_C(0x9d41a70c6ab420f2) /* 673 */, U64_C(0x28e06c18ea1141e6) /* 674 */, U64_C(0xd2b28cbd984f6b28) /* 675 */, U64_C(0x26b75f6c446e9d83) /* 676 */, U64_C(0xba47568c4d418d7f) /* 677 */, U64_C(0xd80badbfe6183d8e) /* 678 */, U64_C(0x0e206d7f5f166044) /* 679 */, U64_C(0xe258a43911cbca3e) /* 680 */, U64_C(0x723a1746b21dc0bc) /* 681 */, U64_C(0xc7caa854f5d7cdd3) /* 682 */, U64_C(0x7cac32883d261d9c) /* 683 */, U64_C(0x7690c26423ba942c) /* 684 */, U64_C(0x17e55524478042b8) /* 685 */, U64_C(0xe0be477656a2389f) /* 686 */, U64_C(0x4d289b5e67ab2da0) /* 687 */, U64_C(0x44862b9c8fbbfd31) /* 688 */, U64_C(0xb47cc8049d141365) /* 689 */, U64_C(0x822c1b362b91c793) /* 690 */, U64_C(0x4eb14655fb13dfd8) /* 691 */, U64_C(0x1ecbba0714e2a97b) /* 692 */, U64_C(0x6143459d5cde5f14) /* 693 */, U64_C(0x53a8fbf1d5f0ac89) /* 694 */, U64_C(0x97ea04d81c5e5b00) /* 695 */, U64_C(0x622181a8d4fdb3f3) /* 696 */, U64_C(0xe9bcd341572a1208) /* 697 */, U64_C(0x1411258643cce58a) /* 698 */, U64_C(0x9144c5fea4c6e0a4) /* 699 */, U64_C(0x0d33d06565cf620f) /* 700 */, U64_C(0x54a48d489f219ca1) /* 701 */, U64_C(0xc43e5eac6d63c821) /* 702 */, U64_C(0xa9728b3a72770daf) /* 703 */, U64_C(0xd7934e7b20df87ef) /* 704 */, U64_C(0xe35503b61a3e86e5) /* 705 */, U64_C(0xcae321fbc819d504) /* 706 */, U64_C(0x129a50b3ac60bfa6) /* 707 */, U64_C(0xcd5e68ea7e9fb6c3) /* 708 */, U64_C(0xb01c90199483b1c7) /* 709 */, U64_C(0x3de93cd5c295376c) /* 710 */, U64_C(0xaed52edf2ab9ad13) /* 711 */, U64_C(0x2e60f512c0a07884) /* 712 */, U64_C(0xbc3d86a3e36210c9) /* 713 */, U64_C(0x35269d9b163951ce) /* 714 */, U64_C(0x0c7d6e2ad0cdb5fa) /* 715 */, U64_C(0x59e86297d87f5733) /* 716 */, U64_C(0x298ef221898db0e7) /* 717 */, U64_C(0x55000029d1a5aa7e) /* 718 */, U64_C(0x8bc08ae1b5061b45) /* 719 */, U64_C(0xc2c31c2b6c92703a) /* 720 */, U64_C(0x94cc596baf25ef42) /* 721 */, U64_C(0x0a1d73db22540456) /* 722 */, U64_C(0x04b6a0f9d9c4179a) /* 723 */, U64_C(0xeffdafa2ae3d3c60) /* 724 */, U64_C(0xf7c8075bb49496c4) /* 725 */, U64_C(0x9cc5c7141d1cd4e3) /* 726 */, U64_C(0x78bd1638218e5534) /* 727 */, U64_C(0xb2f11568f850246a) /* 728 */, U64_C(0xedfabcfa9502bc29) /* 729 */, U64_C(0x796ce5f2da23051b) /* 730 */, U64_C(0xaae128b0dc93537c) /* 731 */, U64_C(0x3a493da0ee4b29ae) /* 732 */, U64_C(0xb5df6b2c416895d7) /* 733 */, U64_C(0xfcabbd25122d7f37) /* 734 */, U64_C(0x70810b58105dc4b1) /* 735 */, U64_C(0xe10fdd37f7882a90) /* 736 */, U64_C(0x524dcab5518a3f5c) /* 737 */, U64_C(0x3c9e85878451255b) /* 738 */, U64_C(0x4029828119bd34e2) /* 739 */, U64_C(0x74a05b6f5d3ceccb) /* 740 */, U64_C(0xb610021542e13eca) /* 741 */, U64_C(0x0ff979d12f59e2ac) /* 742 */, U64_C(0x6037da27e4f9cc50) /* 743 */, U64_C(0x5e92975a0df1847d) /* 744 */, U64_C(0xd66de190d3e623fe) /* 745 */, U64_C(0x5032d6b87b568048) /* 746 */, U64_C(0x9a36b7ce8235216e) /* 747 */, U64_C(0x80272a7a24f64b4a) /* 748 */, U64_C(0x93efed8b8c6916f7) /* 749 */, U64_C(0x37ddbff44cce1555) /* 750 */, U64_C(0x4b95db5d4b99bd25) /* 751 */, U64_C(0x92d3fda169812fc0) /* 752 */, U64_C(0xfb1a4a9a90660bb6) /* 753 */, U64_C(0x730c196946a4b9b2) /* 754 */, U64_C(0x81e289aa7f49da68) /* 755 */, U64_C(0x64669a0f83b1a05f) /* 756 */, U64_C(0x27b3ff7d9644f48b) /* 757 */, U64_C(0xcc6b615c8db675b3) /* 758 */, U64_C(0x674f20b9bcebbe95) /* 759 */, U64_C(0x6f31238275655982) /* 760 */, U64_C(0x5ae488713e45cf05) /* 761 */, U64_C(0xbf619f9954c21157) /* 762 */, U64_C(0xeabac46040a8eae9) /* 763 */, U64_C(0x454c6fe9f2c0c1cd) /* 764 */, U64_C(0x419cf6496412691c) /* 765 */, U64_C(0xd3dc3bef265b0f70) /* 766 */, U64_C(0x6d0e60f5c3578a9e) /* 767 */ }; static u64 sbox4[256] = { U64_C(0x5b0e608526323c55) /* 768 */, U64_C(0x1a46c1a9fa1b59f5) /* 769 */, U64_C(0xa9e245a17c4c8ffa) /* 770 */, U64_C(0x65ca5159db2955d7) /* 771 */, U64_C(0x05db0a76ce35afc2) /* 772 */, U64_C(0x81eac77ea9113d45) /* 773 */, U64_C(0x528ef88ab6ac0a0d) /* 774 */, U64_C(0xa09ea253597be3ff) /* 775 */, U64_C(0x430ddfb3ac48cd56) /* 776 */, U64_C(0xc4b3a67af45ce46f) /* 777 */, U64_C(0x4ececfd8fbe2d05e) /* 778 */, U64_C(0x3ef56f10b39935f0) /* 779 */, U64_C(0x0b22d6829cd619c6) /* 780 */, U64_C(0x17fd460a74df2069) /* 781 */, U64_C(0x6cf8cc8e8510ed40) /* 782 */, U64_C(0xd6c824bf3a6ecaa7) /* 783 */, U64_C(0x61243d581a817049) /* 784 */, U64_C(0x048bacb6bbc163a2) /* 785 */, U64_C(0xd9a38ac27d44cc32) /* 786 */, U64_C(0x7fddff5baaf410ab) /* 787 */, U64_C(0xad6d495aa804824b) /* 788 */, U64_C(0xe1a6a74f2d8c9f94) /* 789 */, U64_C(0xd4f7851235dee8e3) /* 790 */, U64_C(0xfd4b7f886540d893) /* 791 */, U64_C(0x247c20042aa4bfda) /* 792 */, U64_C(0x096ea1c517d1327c) /* 793 */, U64_C(0xd56966b4361a6685) /* 794 */, U64_C(0x277da5c31221057d) /* 795 */, U64_C(0x94d59893a43acff7) /* 796 */, U64_C(0x64f0c51ccdc02281) /* 797 */, U64_C(0x3d33bcc4ff6189db) /* 798 */, U64_C(0xe005cb184ce66af1) /* 799 */, U64_C(0xff5ccd1d1db99bea) /* 800 */, U64_C(0xb0b854a7fe42980f) /* 801 */, U64_C(0x7bd46a6a718d4b9f) /* 802 */, U64_C(0xd10fa8cc22a5fd8c) /* 803 */, U64_C(0xd31484952be4bd31) /* 804 */, U64_C(0xc7fa975fcb243847) /* 805 */, U64_C(0x4886ed1e5846c407) /* 806 */, U64_C(0x28cddb791eb70b04) /* 807 */, U64_C(0xc2b00be2f573417f) /* 808 */, U64_C(0x5c9590452180f877) /* 809 */, U64_C(0x7a6bddfff370eb00) /* 810 */, U64_C(0xce509e38d6d9d6a4) /* 811 */, U64_C(0xebeb0f00647fa702) /* 812 */, U64_C(0x1dcc06cf76606f06) /* 813 */, U64_C(0xe4d9f28ba286ff0a) /* 814 */, U64_C(0xd85a305dc918c262) /* 815 */, U64_C(0x475b1d8732225f54) /* 816 */, U64_C(0x2d4fb51668ccb5fe) /* 817 */, U64_C(0xa679b9d9d72bba20) /* 818 */, U64_C(0x53841c0d912d43a5) /* 819 */, U64_C(0x3b7eaa48bf12a4e8) /* 820 */, U64_C(0x781e0e47f22f1ddf) /* 821 */, U64_C(0xeff20ce60ab50973) /* 822 */, U64_C(0x20d261d19dffb742) /* 823 */, U64_C(0x16a12b03062a2e39) /* 824 */, U64_C(0x1960eb2239650495) /* 825 */, U64_C(0x251c16fed50eb8b8) /* 826 */, U64_C(0x9ac0c330f826016e) /* 827 */, U64_C(0xed152665953e7671) /* 828 */, U64_C(0x02d63194a6369570) /* 829 */, U64_C(0x5074f08394b1c987) /* 830 */, U64_C(0x70ba598c90b25ce1) /* 831 */, U64_C(0x794a15810b9742f6) /* 832 */, U64_C(0x0d5925e9fcaf8c6c) /* 833 */, U64_C(0x3067716cd868744e) /* 834 */, U64_C(0x910ab077e8d7731b) /* 835 */, U64_C(0x6a61bbdb5ac42f61) /* 836 */, U64_C(0x93513efbf0851567) /* 837 */, U64_C(0xf494724b9e83e9d5) /* 838 */, U64_C(0xe887e1985c09648d) /* 839 */, U64_C(0x34b1d3c675370cfd) /* 840 */, U64_C(0xdc35e433bc0d255d) /* 841 */, U64_C(0xd0aab84234131be0) /* 842 */, U64_C(0x08042a50b48b7eaf) /* 843 */, U64_C(0x9997c4ee44a3ab35) /* 844 */, U64_C(0x829a7b49201799d0) /* 845 */, U64_C(0x263b8307b7c54441) /* 846 */, U64_C(0x752f95f4fd6a6ca6) /* 847 */, U64_C(0x927217402c08c6e5) /* 848 */, U64_C(0x2a8ab754a795d9ee) /* 849 */, U64_C(0xa442f7552f72943d) /* 850 */, U64_C(0x2c31334e19781208) /* 851 */, U64_C(0x4fa98d7ceaee6291) /* 852 */, U64_C(0x55c3862f665db309) /* 853 */, U64_C(0xbd0610175d53b1f3) /* 854 */, U64_C(0x46fe6cb840413f27) /* 855 */, U64_C(0x3fe03792df0cfa59) /* 856 */, U64_C(0xcfe700372eb85e8f) /* 857 */, U64_C(0xa7be29e7adbce118) /* 858 */, U64_C(0xe544ee5cde8431dd) /* 859 */, U64_C(0x8a781b1b41f1873e) /* 860 */, U64_C(0xa5c94c78a0d2f0e7) /* 861 */, U64_C(0x39412e2877b60728) /* 862 */, U64_C(0xa1265ef3afc9a62c) /* 863 */, U64_C(0xbcc2770c6a2506c5) /* 864 */, U64_C(0x3ab66dd5dce1ce12) /* 865 */, U64_C(0xe65499d04a675b37) /* 866 */, U64_C(0x7d8f523481bfd216) /* 867 */, U64_C(0x0f6f64fcec15f389) /* 868 */, U64_C(0x74efbe618b5b13c8) /* 869 */, U64_C(0xacdc82b714273e1d) /* 870 */, U64_C(0xdd40bfe003199d17) /* 871 */, U64_C(0x37e99257e7e061f8) /* 872 */, U64_C(0xfa52626904775aaa) /* 873 */, U64_C(0x8bbbf63a463d56f9) /* 874 */, U64_C(0xf0013f1543a26e64) /* 875 */, U64_C(0xa8307e9f879ec898) /* 876 */, U64_C(0xcc4c27a4150177cc) /* 877 */, U64_C(0x1b432f2cca1d3348) /* 878 */, U64_C(0xde1d1f8f9f6fa013) /* 879 */, U64_C(0x606602a047a7ddd6) /* 880 */, U64_C(0xd237ab64cc1cb2c7) /* 881 */, U64_C(0x9b938e7225fcd1d3) /* 882 */, U64_C(0xec4e03708e0ff476) /* 883 */, U64_C(0xfeb2fbda3d03c12d) /* 884 */, U64_C(0xae0bced2ee43889a) /* 885 */, U64_C(0x22cb8923ebfb4f43) /* 886 */, U64_C(0x69360d013cf7396d) /* 887 */, U64_C(0x855e3602d2d4e022) /* 888 */, U64_C(0x073805bad01f784c) /* 889 */, U64_C(0x33e17a133852f546) /* 890 */, U64_C(0xdf4874058ac7b638) /* 891 */, U64_C(0xba92b29c678aa14a) /* 892 */, U64_C(0x0ce89fc76cfaadcd) /* 893 */, U64_C(0x5f9d4e0908339e34) /* 894 */, U64_C(0xf1afe9291f5923b9) /* 895 */, U64_C(0x6e3480f60f4a265f) /* 896 */, U64_C(0xeebf3a2ab29b841c) /* 897 */, U64_C(0xe21938a88f91b4ad) /* 898 */, U64_C(0x57dfeff845c6d3c3) /* 899 */, U64_C(0x2f006b0bf62caaf2) /* 900 */, U64_C(0x62f479ef6f75ee78) /* 901 */, U64_C(0x11a55ad41c8916a9) /* 902 */, U64_C(0xf229d29084fed453) /* 903 */, U64_C(0x42f1c27b16b000e6) /* 904 */, U64_C(0x2b1f76749823c074) /* 905 */, U64_C(0x4b76eca3c2745360) /* 906 */, U64_C(0x8c98f463b91691bd) /* 907 */, U64_C(0x14bcc93cf1ade66a) /* 908 */, U64_C(0x8885213e6d458397) /* 909 */, U64_C(0x8e177df0274d4711) /* 910 */, U64_C(0xb49b73b5503f2951) /* 911 */, U64_C(0x10168168c3f96b6b) /* 912 */, U64_C(0x0e3d963b63cab0ae) /* 913 */, U64_C(0x8dfc4b5655a1db14) /* 914 */, U64_C(0xf789f1356e14de5c) /* 915 */, U64_C(0x683e68af4e51dac1) /* 916 */, U64_C(0xc9a84f9d8d4b0fd9) /* 917 */, U64_C(0x3691e03f52a0f9d1) /* 918 */, U64_C(0x5ed86e46e1878e80) /* 919 */, U64_C(0x3c711a0e99d07150) /* 920 */, U64_C(0x5a0865b20c4e9310) /* 921 */, U64_C(0x56fbfc1fe4f0682e) /* 922 */, U64_C(0xea8d5de3105edf9b) /* 923 */, U64_C(0x71abfdb12379187a) /* 924 */, U64_C(0x2eb99de1bee77b9c) /* 925 */, U64_C(0x21ecc0ea33cf4523) /* 926 */, U64_C(0x59a4d7521805c7a1) /* 927 */, U64_C(0x3896f5eb56ae7c72) /* 928 */, U64_C(0xaa638f3db18f75dc) /* 929 */, U64_C(0x9f39358dabe9808e) /* 930 */, U64_C(0xb7defa91c00b72ac) /* 931 */, U64_C(0x6b5541fd62492d92) /* 932 */, U64_C(0x6dc6dee8f92e4d5b) /* 933 */, U64_C(0x353f57abc4beea7e) /* 934 */, U64_C(0x735769d6da5690ce) /* 935 */, U64_C(0x0a234aa642391484) /* 936 */, U64_C(0xf6f9508028f80d9d) /* 937 */, U64_C(0xb8e319a27ab3f215) /* 938 */, U64_C(0x31ad9c1151341a4d) /* 939 */, U64_C(0x773c22a57bef5805) /* 940 */, U64_C(0x45c7561a07968633) /* 941 */, U64_C(0xf913da9e249dbe36) /* 942 */, U64_C(0xda652d9b78a64c68) /* 943 */, U64_C(0x4c27a97f3bc334ef) /* 944 */, U64_C(0x76621220e66b17f4) /* 945 */, U64_C(0x967743899acd7d0b) /* 946 */, U64_C(0xf3ee5bcae0ed6782) /* 947 */, U64_C(0x409f753600c879fc) /* 948 */, U64_C(0x06d09a39b5926db6) /* 949 */, U64_C(0x6f83aeb0317ac588) /* 950 */, U64_C(0x01e6ca4a86381f21) /* 951 */, U64_C(0x66ff3462d19f3025) /* 952 */, U64_C(0x72207c24ddfd3bfb) /* 953 */, U64_C(0x4af6b6d3e2ece2eb) /* 954 */, U64_C(0x9c994dbec7ea08de) /* 955 */, U64_C(0x49ace597b09a8bc4) /* 956 */, U64_C(0xb38c4766cf0797ba) /* 957 */, U64_C(0x131b9373c57c2a75) /* 958 */, U64_C(0xb1822cce61931e58) /* 959 */, U64_C(0x9d7555b909ba1c0c) /* 960 */, U64_C(0x127fafdd937d11d2) /* 961 */, U64_C(0x29da3badc66d92e4) /* 962 */, U64_C(0xa2c1d57154c2ecbc) /* 963 */, U64_C(0x58c5134d82f6fe24) /* 964 */, U64_C(0x1c3ae3515b62274f) /* 965 */, U64_C(0xe907c82e01cb8126) /* 966 */, U64_C(0xf8ed091913e37fcb) /* 967 */, U64_C(0x3249d8f9c80046c9) /* 968 */, U64_C(0x80cf9bede388fb63) /* 969 */, U64_C(0x1881539a116cf19e) /* 970 */, U64_C(0x5103f3f76bd52457) /* 971 */, U64_C(0x15b7e6f5ae47f7a8) /* 972 */, U64_C(0xdbd7c6ded47e9ccf) /* 973 */, U64_C(0x44e55c410228bb1a) /* 974 */, U64_C(0xb647d4255edb4e99) /* 975 */, U64_C(0x5d11882bb8aafc30) /* 976 */, U64_C(0xf5098bbb29d3212a) /* 977 */, U64_C(0x8fb5ea14e90296b3) /* 978 */, U64_C(0x677b942157dd025a) /* 979 */, U64_C(0xfb58e7c0a390acb5) /* 980 */, U64_C(0x89d3674c83bd4a01) /* 981 */, U64_C(0x9e2da4df4bf3b93b) /* 982 */, U64_C(0xfcc41e328cab4829) /* 983 */, U64_C(0x03f38c96ba582c52) /* 984 */, U64_C(0xcad1bdbd7fd85db2) /* 985 */, U64_C(0xbbb442c16082ae83) /* 986 */, U64_C(0xb95fe86ba5da9ab0) /* 987 */, U64_C(0xb22e04673771a93f) /* 988 */, U64_C(0x845358c9493152d8) /* 989 */, U64_C(0xbe2a488697b4541e) /* 990 */, U64_C(0x95a2dc2dd38e6966) /* 991 */, U64_C(0xc02c11ac923c852b) /* 992 */, U64_C(0x2388b1990df2a87b) /* 993 */, U64_C(0x7c8008fa1b4f37be) /* 994 */, U64_C(0x1f70d0c84d54e503) /* 995 */, U64_C(0x5490adec7ece57d4) /* 996 */, U64_C(0x002b3c27d9063a3a) /* 997 */, U64_C(0x7eaea3848030a2bf) /* 998 */, U64_C(0xc602326ded2003c0) /* 999 */, U64_C(0x83a7287d69a94086) /* 1000 */, U64_C(0xc57a5fcb30f57a8a) /* 1001 */, U64_C(0xb56844e479ebe779) /* 1002 */, U64_C(0xa373b40f05dcbce9) /* 1003 */, U64_C(0xd71a786e88570ee2) /* 1004 */, U64_C(0x879cbacdbde8f6a0) /* 1005 */, U64_C(0x976ad1bcc164a32f) /* 1006 */, U64_C(0xab21e25e9666d78b) /* 1007 */, U64_C(0x901063aae5e5c33c) /* 1008 */, U64_C(0x9818b34448698d90) /* 1009 */, U64_C(0xe36487ae3e1e8abb) /* 1010 */, U64_C(0xafbdf931893bdcb4) /* 1011 */, U64_C(0x6345a0dc5fbbd519) /* 1012 */, U64_C(0x8628fe269b9465ca) /* 1013 */, U64_C(0x1e5d01603f9c51ec) /* 1014 */, U64_C(0x4de44006a15049b7) /* 1015 */, U64_C(0xbf6c70e5f776cbb1) /* 1016 */, U64_C(0x411218f2ef552bed) /* 1017 */, U64_C(0xcb0c0708705a36a3) /* 1018 */, U64_C(0xe74d14754f986044) /* 1019 */, U64_C(0xcd56d9430ea8280e) /* 1020 */, U64_C(0xc12591d7535f5065) /* 1021 */, U64_C(0xc83223f1720aef96) /* 1022 */, U64_C(0xc3a0396f7363a51f) /* 1023 */ }; static unsigned int transform ( void *ctx, const unsigned char *data, size_t nblks ); static void do_init (void *context, int variant) { TIGER_CONTEXT *hd = context; hd->a = 0x0123456789abcdefLL; hd->b = 0xfedcba9876543210LL; hd->c = 0xf096a5b4c3b2e187LL; hd->bctx.nblocks = 0; hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize_shift = _gcry_ctz(64); hd->bctx.bwrite = transform; hd->variant = variant; } static void tiger_init (void *context, unsigned int flags) { (void)flags; do_init (context, 0); } static void tiger1_init (void *context, unsigned int flags) { (void)flags; do_init (context, 1); } static void tiger2_init (void *context, unsigned int flags) { (void)flags; do_init (context, 2); } #define tiger_round(xa, xb, xc, xx, xmul) { \ xc ^= xx; \ xa -= ( sbox1[ (xc) & 0xff ] ^ sbox2[ ((xc) >> 16) & 0xff ] \ ^ sbox3[ ((xc) >> 32) & 0xff ] ^ sbox4[ ((xc) >> 48) & 0xff ]); \ xb += ( sbox4[ ((xc) >> 8) & 0xff ] ^ sbox3[ ((xc) >> 24) & 0xff ] \ ^ sbox2[ ((xc) >> 40) & 0xff ] ^ sbox1[ ((xc) >> 56) & 0xff ]); \ xb *= xmul; } #define pass(ya, yb, yc, yx, ymul) { \ tiger_round( ya, yb, yc, yx[0], ymul ); \ tiger_round( yb, yc, ya, yx[1], ymul ); \ tiger_round( yc, ya, yb, yx[2], ymul ); \ tiger_round( ya, yb, yc, yx[3], ymul ); \ tiger_round( yb, yc, ya, yx[4], ymul ); \ tiger_round( yc, ya, yb, yx[5], ymul ); \ tiger_round( ya, yb, yc, yx[6], ymul ); \ tiger_round( yb, yc, ya, yx[7], ymul ); } #define key_schedule(x) { \ x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; \ x[1] ^= x[0]; \ x[2] += x[1]; \ x[3] -= x[2] ^ ((~x[1]) << 19 ); \ x[4] ^= x[3]; \ x[5] += x[4]; \ x[6] -= x[5] ^ ((~x[4]) >> 23 ); \ x[7] ^= x[6]; \ x[0] += x[7]; \ x[1] -= x[0] ^ ((~x[7]) << 19 ); \ x[2] ^= x[1]; \ x[3] += x[2]; \ x[4] -= x[3] ^ ((~x[2]) >> 23 ); \ x[5] ^= x[4]; \ x[6] += x[5]; \ x[7] -= x[6] ^ 0x0123456789abcdefLL; } /**************** * Transform the message DATA which consists of 512 bytes (8 words) */ static unsigned int transform_blk ( void *ctx, const unsigned char *data ) { TIGER_CONTEXT *hd = ctx; u64 a,b,c,aa,bb,cc; u64 x[8]; int i; for ( i = 0; i < 8; i++ ) x[i] = buf_get_le64(data + i * 8); /* save */ a = aa = hd->a; b = bb = hd->b; c = cc = hd->c; pass( a, b, c, x, 5); key_schedule( x ); pass( c, a, b, x, 7); key_schedule( x ); pass( b, c, a, x, 9); /* feedforward */ a ^= aa; b -= bb; c += cc; /* store */ hd->a = a; hd->b = b; hd->c = c; return /*burn_stack*/ 21*8+11*sizeof(void*); } static unsigned int transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = transform_blk (c, data); data += 64; } while (--nblks); return burn; } /* The routine terminates the computation */ static void tiger_final( void *context ) { TIGER_CONTEXT *hd = context; u32 t, th, msb, lsb; byte *p; unsigned int burn; byte pad = hd->variant == 2? 0x80 : 0x01; t = hd->bctx.nblocks; if (sizeof t == sizeof hd->bctx.nblocks) th = hd->bctx.nblocks_high; else th = hd->bctx.nblocks >> 32; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->bctx.count < 56 ) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = pad; if (hd->bctx.count < 56) memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 56, lsb); buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf, 1 ); } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = pad; /* pad character */ /* fill pad and next block with zeroes */ memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56); /* append the 64 bit count */ buf_put_le32(hd->bctx.buf + 64 + 56, lsb); buf_put_le32(hd->bctx.buf + 64 + 60, msb); burn = transform( hd, hd->bctx.buf, 2 ); } p = hd->bctx.buf; #define X(a) do { buf_put_be64(p, hd->a); p += 8; } while(0) #define Y(a) do { buf_put_le64(p, hd->a); p += 8; } while(0) if (hd->variant == 0) { X(a); X(b); X(c); } else { Y(a); Y(b); Y(c); } #undef X #undef Y hd->bctx.count = 0; _gcry_burn_stack (burn); } static byte * tiger_read( void *context ) { TIGER_CONTEXT *hd = context; return hd->bctx.buf; } /* This is the old TIGER variant based on the unfixed reference implementation. IT was used in GnupG up to 1.3.2. We don't provide an OID anymore because that would not be correct. */ -gcry_md_spec_t _gcry_digest_spec_tiger = +const gcry_md_spec_t _gcry_digest_spec_tiger = { GCRY_MD_TIGER, {0, 0}, "TIGER192", NULL, 0, NULL, 24, tiger_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, NULL, sizeof (TIGER_CONTEXT) }; /* This is the fixed TIGER implementation. */ -static byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */ +static const byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */ { 0x30, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0c, 0x02, 0x05, 0x00, 0x04, 0x18 }; -static gcry_md_oid_spec_t oid_spec_tiger1[] = +static const gcry_md_oid_spec_t oid_spec_tiger1[] = { /* GNU.digestAlgorithm TIGER */ { "1.3.6.1.4.1.11591.12.2" }, { NULL } }; -gcry_md_spec_t _gcry_digest_spec_tiger1 = +const gcry_md_spec_t _gcry_digest_spec_tiger1 = { GCRY_MD_TIGER1, {0, 0}, "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24, tiger1_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, NULL, sizeof (TIGER_CONTEXT) }; /* This is TIGER2 which usues a changed padding algorithm. */ -gcry_md_spec_t _gcry_digest_spec_tiger2 = +const gcry_md_spec_t _gcry_digest_spec_tiger2 = { GCRY_MD_TIGER2, {0, 0}, "TIGER2", NULL, 0, NULL, 24, tiger2_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, NULL, sizeof (TIGER_CONTEXT) }; diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index f6e5a7db..ecb9a416 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -1,1535 +1,1535 @@ /* whirlpool.c - Whirlpool hashing algorithm * Copyright (C) 2005 Free Software Foundation, Inc. * * 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 . */ /* This is an implementation of the Whirlpool hashing algorithm, which has been developed by Vincent Rijmen and Paulo S. L. M. Barreto; it's homepage is located at: http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html The S-Boxes and the structure of the main transformation function, which implements an optimized version of the algorithm, is taken from the reference implementation available from http://www.larc.usp.br/~pbarreto/whirlpool.zip */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "hash-common.h" /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AMD64_ASM 1 #endif /* Size of a whirlpool block (in bytes). */ #define BLOCK_SIZE 64 /* Number of rounds. */ #define R 10 /* Types. */ typedef u64 whirlpool_block_t[BLOCK_SIZE / 8]; typedef struct { gcry_md_block_ctx_t bctx; whirlpool_block_t hash_state; int use_bugemu; struct { size_t count; unsigned char length[32]; } bugemu; } whirlpool_context_t; /* Macros. */ /* Convert the the buffer BUFFER into a block BLOCK, using I as counter. */ #define buffer_to_block(buffer, block, i) \ for (i = 0; i < 8; i++) \ (block)[i] = buf_get_be64((buffer) + i * 8); /* Convert the block BLOCK into a buffer BUFFER, using I as counter. */ #define block_to_buffer(buffer, block, i) \ for (i = 0; i < 8; i++) \ buf_put_be64((buffer) + i * 8, (block)[i]); /* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */ #define block_copy(block_dst, block_src, i) \ for (i = 0; i < 8; i++) \ block_dst[i] = block_src[i]; /* XOR the block BLOCK_SRC into BLOCK_DST, using I as counter. */ #define block_xor(block_dst, block_src, i) \ for (i = 0; i < 8; i++) \ block_dst[i] ^= block_src[i]; struct whirlpool_tables_s { u64 RC[R]; u64 C[8][256]; }; static const struct whirlpool_tables_s tab = { /* Round constants. */ { U64_C (0x1823c6e887b8014f), U64_C (0x36a6d2f5796f9152), U64_C (0x60bc9b8ea30c7b35), U64_C (0x1de0d7c22e4bfe57), U64_C (0x157737e59ff04ada), U64_C (0x58c9290ab1a06b85), U64_C (0xbd5d10f4cb3e0567), U64_C (0xe427418ba77d95d8), U64_C (0xfbee7c66dd17479e), U64_C (0xca2dbf07ad5a8333), }, /* Main lookup boxes. */ { { U64_C (0x18186018c07830d8), U64_C (0x23238c2305af4626), U64_C (0xc6c63fc67ef991b8), U64_C (0xe8e887e8136fcdfb), U64_C (0x878726874ca113cb), U64_C (0xb8b8dab8a9626d11), U64_C (0x0101040108050209), U64_C (0x4f4f214f426e9e0d), U64_C (0x3636d836adee6c9b), U64_C (0xa6a6a2a6590451ff), U64_C (0xd2d26fd2debdb90c), U64_C (0xf5f5f3f5fb06f70e), U64_C (0x7979f979ef80f296), U64_C (0x6f6fa16f5fcede30), U64_C (0x91917e91fcef3f6d), U64_C (0x52525552aa07a4f8), U64_C (0x60609d6027fdc047), U64_C (0xbcbccabc89766535), U64_C (0x9b9b569baccd2b37), U64_C (0x8e8e028e048c018a), U64_C (0xa3a3b6a371155bd2), U64_C (0x0c0c300c603c186c), U64_C (0x7b7bf17bff8af684), U64_C (0x3535d435b5e16a80), U64_C (0x1d1d741de8693af5), U64_C (0xe0e0a7e05347ddb3), U64_C (0xd7d77bd7f6acb321), U64_C (0xc2c22fc25eed999c), U64_C (0x2e2eb82e6d965c43), U64_C (0x4b4b314b627a9629), U64_C (0xfefedffea321e15d), U64_C (0x575741578216aed5), U64_C (0x15155415a8412abd), U64_C (0x7777c1779fb6eee8), U64_C (0x3737dc37a5eb6e92), U64_C (0xe5e5b3e57b56d79e), U64_C (0x9f9f469f8cd92313), U64_C (0xf0f0e7f0d317fd23), U64_C (0x4a4a354a6a7f9420), U64_C (0xdada4fda9e95a944), U64_C (0x58587d58fa25b0a2), U64_C (0xc9c903c906ca8fcf), U64_C (0x2929a429558d527c), U64_C (0x0a0a280a5022145a), U64_C (0xb1b1feb1e14f7f50), U64_C (0xa0a0baa0691a5dc9), U64_C (0x6b6bb16b7fdad614), U64_C (0x85852e855cab17d9), U64_C (0xbdbdcebd8173673c), U64_C (0x5d5d695dd234ba8f), U64_C (0x1010401080502090), U64_C (0xf4f4f7f4f303f507), U64_C (0xcbcb0bcb16c08bdd), U64_C (0x3e3ef83eedc67cd3), U64_C (0x0505140528110a2d), U64_C (0x676781671fe6ce78), U64_C (0xe4e4b7e47353d597), U64_C (0x27279c2725bb4e02), U64_C (0x4141194132588273), U64_C (0x8b8b168b2c9d0ba7), U64_C (0xa7a7a6a7510153f6), U64_C (0x7d7de97dcf94fab2), U64_C (0x95956e95dcfb3749), U64_C (0xd8d847d88e9fad56), U64_C (0xfbfbcbfb8b30eb70), U64_C (0xeeee9fee2371c1cd), U64_C (0x7c7ced7cc791f8bb), U64_C (0x6666856617e3cc71), U64_C (0xdddd53dda68ea77b), U64_C (0x17175c17b84b2eaf), U64_C (0x4747014702468e45), U64_C (0x9e9e429e84dc211a), U64_C (0xcaca0fca1ec589d4), U64_C (0x2d2db42d75995a58), U64_C (0xbfbfc6bf9179632e), U64_C (0x07071c07381b0e3f), U64_C (0xadad8ead012347ac), U64_C (0x5a5a755aea2fb4b0), U64_C (0x838336836cb51bef), U64_C (0x3333cc3385ff66b6), U64_C (0x636391633ff2c65c), U64_C (0x02020802100a0412), U64_C (0xaaaa92aa39384993), U64_C (0x7171d971afa8e2de), U64_C (0xc8c807c80ecf8dc6), U64_C (0x19196419c87d32d1), U64_C (0x494939497270923b), U64_C (0xd9d943d9869aaf5f), U64_C (0xf2f2eff2c31df931), U64_C (0xe3e3abe34b48dba8), U64_C (0x5b5b715be22ab6b9), U64_C (0x88881a8834920dbc), U64_C (0x9a9a529aa4c8293e), U64_C (0x262698262dbe4c0b), U64_C (0x3232c8328dfa64bf), U64_C (0xb0b0fab0e94a7d59), U64_C (0xe9e983e91b6acff2), U64_C (0x0f0f3c0f78331e77), U64_C (0xd5d573d5e6a6b733), U64_C (0x80803a8074ba1df4), U64_C (0xbebec2be997c6127), U64_C (0xcdcd13cd26de87eb), U64_C (0x3434d034bde46889), U64_C (0x48483d487a759032), U64_C (0xffffdbffab24e354), U64_C (0x7a7af57af78ff48d), U64_C (0x90907a90f4ea3d64), U64_C (0x5f5f615fc23ebe9d), U64_C (0x202080201da0403d), U64_C (0x6868bd6867d5d00f), U64_C (0x1a1a681ad07234ca), U64_C (0xaeae82ae192c41b7), U64_C (0xb4b4eab4c95e757d), U64_C (0x54544d549a19a8ce), U64_C (0x93937693ece53b7f), U64_C (0x222288220daa442f), U64_C (0x64648d6407e9c863), U64_C (0xf1f1e3f1db12ff2a), U64_C (0x7373d173bfa2e6cc), U64_C (0x12124812905a2482), U64_C (0x40401d403a5d807a), U64_C (0x0808200840281048), U64_C (0xc3c32bc356e89b95), U64_C (0xecec97ec337bc5df), U64_C (0xdbdb4bdb9690ab4d), U64_C (0xa1a1bea1611f5fc0), U64_C (0x8d8d0e8d1c830791), U64_C (0x3d3df43df5c97ac8), U64_C (0x97976697ccf1335b), U64_C (0x0000000000000000), U64_C (0xcfcf1bcf36d483f9), U64_C (0x2b2bac2b4587566e), U64_C (0x7676c57697b3ece1), U64_C (0x8282328264b019e6), U64_C (0xd6d67fd6fea9b128), U64_C (0x1b1b6c1bd87736c3), U64_C (0xb5b5eeb5c15b7774), U64_C (0xafaf86af112943be), U64_C (0x6a6ab56a77dfd41d), U64_C (0x50505d50ba0da0ea), U64_C (0x45450945124c8a57), U64_C (0xf3f3ebf3cb18fb38), U64_C (0x3030c0309df060ad), U64_C (0xefef9bef2b74c3c4), U64_C (0x3f3ffc3fe5c37eda), U64_C (0x55554955921caac7), U64_C (0xa2a2b2a2791059db), U64_C (0xeaea8fea0365c9e9), U64_C (0x656589650fecca6a), U64_C (0xbabad2bab9686903), U64_C (0x2f2fbc2f65935e4a), U64_C (0xc0c027c04ee79d8e), U64_C (0xdede5fdebe81a160), U64_C (0x1c1c701ce06c38fc), U64_C (0xfdfdd3fdbb2ee746), U64_C (0x4d4d294d52649a1f), U64_C (0x92927292e4e03976), U64_C (0x7575c9758fbceafa), U64_C (0x06061806301e0c36), U64_C (0x8a8a128a249809ae), U64_C (0xb2b2f2b2f940794b), U64_C (0xe6e6bfe66359d185), U64_C (0x0e0e380e70361c7e), U64_C (0x1f1f7c1ff8633ee7), U64_C (0x6262956237f7c455), U64_C (0xd4d477d4eea3b53a), U64_C (0xa8a89aa829324d81), U64_C (0x96966296c4f43152), U64_C (0xf9f9c3f99b3aef62), U64_C (0xc5c533c566f697a3), U64_C (0x2525942535b14a10), U64_C (0x59597959f220b2ab), U64_C (0x84842a8454ae15d0), U64_C (0x7272d572b7a7e4c5), U64_C (0x3939e439d5dd72ec), U64_C (0x4c4c2d4c5a619816), U64_C (0x5e5e655eca3bbc94), U64_C (0x7878fd78e785f09f), U64_C (0x3838e038ddd870e5), U64_C (0x8c8c0a8c14860598), U64_C (0xd1d163d1c6b2bf17), U64_C (0xa5a5aea5410b57e4), U64_C (0xe2e2afe2434dd9a1), U64_C (0x616199612ff8c24e), U64_C (0xb3b3f6b3f1457b42), U64_C (0x2121842115a54234), U64_C (0x9c9c4a9c94d62508), U64_C (0x1e1e781ef0663cee), U64_C (0x4343114322528661), U64_C (0xc7c73bc776fc93b1), U64_C (0xfcfcd7fcb32be54f), U64_C (0x0404100420140824), U64_C (0x51515951b208a2e3), U64_C (0x99995e99bcc72f25), U64_C (0x6d6da96d4fc4da22), U64_C (0x0d0d340d68391a65), U64_C (0xfafacffa8335e979), U64_C (0xdfdf5bdfb684a369), U64_C (0x7e7ee57ed79bfca9), U64_C (0x242490243db44819), U64_C (0x3b3bec3bc5d776fe), U64_C (0xabab96ab313d4b9a), U64_C (0xcece1fce3ed181f0), U64_C (0x1111441188552299), U64_C (0x8f8f068f0c890383), U64_C (0x4e4e254e4a6b9c04), U64_C (0xb7b7e6b7d1517366), U64_C (0xebeb8beb0b60cbe0), U64_C (0x3c3cf03cfdcc78c1), U64_C (0x81813e817cbf1ffd), U64_C (0x94946a94d4fe3540), U64_C (0xf7f7fbf7eb0cf31c), U64_C (0xb9b9deb9a1676f18), U64_C (0x13134c13985f268b), U64_C (0x2c2cb02c7d9c5851), U64_C (0xd3d36bd3d6b8bb05), U64_C (0xe7e7bbe76b5cd38c), U64_C (0x6e6ea56e57cbdc39), U64_C (0xc4c437c46ef395aa), U64_C (0x03030c03180f061b), U64_C (0x565645568a13acdc), U64_C (0x44440d441a49885e), U64_C (0x7f7fe17fdf9efea0), U64_C (0xa9a99ea921374f88), U64_C (0x2a2aa82a4d825467), U64_C (0xbbbbd6bbb16d6b0a), U64_C (0xc1c123c146e29f87), U64_C (0x53535153a202a6f1), U64_C (0xdcdc57dcae8ba572), U64_C (0x0b0b2c0b58271653), U64_C (0x9d9d4e9d9cd32701), U64_C (0x6c6cad6c47c1d82b), U64_C (0x3131c43195f562a4), U64_C (0x7474cd7487b9e8f3), U64_C (0xf6f6fff6e309f115), U64_C (0x464605460a438c4c), U64_C (0xacac8aac092645a5), U64_C (0x89891e893c970fb5), U64_C (0x14145014a04428b4), U64_C (0xe1e1a3e15b42dfba), U64_C (0x16165816b04e2ca6), U64_C (0x3a3ae83acdd274f7), U64_C (0x6969b9696fd0d206), U64_C (0x09092409482d1241), U64_C (0x7070dd70a7ade0d7), U64_C (0xb6b6e2b6d954716f), U64_C (0xd0d067d0ceb7bd1e), U64_C (0xeded93ed3b7ec7d6), U64_C (0xcccc17cc2edb85e2), U64_C (0x424215422a578468), U64_C (0x98985a98b4c22d2c), U64_C (0xa4a4aaa4490e55ed), U64_C (0x2828a0285d885075), U64_C (0x5c5c6d5cda31b886), U64_C (0xf8f8c7f8933fed6b), U64_C (0x8686228644a411c2), }, { U64_C (0xd818186018c07830), U64_C (0x2623238c2305af46), U64_C (0xb8c6c63fc67ef991), U64_C (0xfbe8e887e8136fcd), U64_C (0xcb878726874ca113), U64_C (0x11b8b8dab8a9626d), U64_C (0x0901010401080502), U64_C (0x0d4f4f214f426e9e), U64_C (0x9b3636d836adee6c), U64_C (0xffa6a6a2a6590451), U64_C (0x0cd2d26fd2debdb9), U64_C (0x0ef5f5f3f5fb06f7), U64_C (0x967979f979ef80f2), U64_C (0x306f6fa16f5fcede), U64_C (0x6d91917e91fcef3f), U64_C (0xf852525552aa07a4), U64_C (0x4760609d6027fdc0), U64_C (0x35bcbccabc897665), U64_C (0x379b9b569baccd2b), U64_C (0x8a8e8e028e048c01), U64_C (0xd2a3a3b6a371155b), U64_C (0x6c0c0c300c603c18), U64_C (0x847b7bf17bff8af6), U64_C (0x803535d435b5e16a), U64_C (0xf51d1d741de8693a), U64_C (0xb3e0e0a7e05347dd), U64_C (0x21d7d77bd7f6acb3), U64_C (0x9cc2c22fc25eed99), U64_C (0x432e2eb82e6d965c), U64_C (0x294b4b314b627a96), U64_C (0x5dfefedffea321e1), U64_C (0xd5575741578216ae), U64_C (0xbd15155415a8412a), U64_C (0xe87777c1779fb6ee), U64_C (0x923737dc37a5eb6e), U64_C (0x9ee5e5b3e57b56d7), U64_C (0x139f9f469f8cd923), U64_C (0x23f0f0e7f0d317fd), U64_C (0x204a4a354a6a7f94), U64_C (0x44dada4fda9e95a9), U64_C (0xa258587d58fa25b0), U64_C (0xcfc9c903c906ca8f), U64_C (0x7c2929a429558d52), U64_C (0x5a0a0a280a502214), U64_C (0x50b1b1feb1e14f7f), U64_C (0xc9a0a0baa0691a5d), U64_C (0x146b6bb16b7fdad6), U64_C (0xd985852e855cab17), U64_C (0x3cbdbdcebd817367), U64_C (0x8f5d5d695dd234ba), U64_C (0x9010104010805020), U64_C (0x07f4f4f7f4f303f5), U64_C (0xddcbcb0bcb16c08b), U64_C (0xd33e3ef83eedc67c), U64_C (0x2d0505140528110a), U64_C (0x78676781671fe6ce), U64_C (0x97e4e4b7e47353d5), U64_C (0x0227279c2725bb4e), U64_C (0x7341411941325882), U64_C (0xa78b8b168b2c9d0b), U64_C (0xf6a7a7a6a7510153), U64_C (0xb27d7de97dcf94fa), U64_C (0x4995956e95dcfb37), U64_C (0x56d8d847d88e9fad), U64_C (0x70fbfbcbfb8b30eb), U64_C (0xcdeeee9fee2371c1), U64_C (0xbb7c7ced7cc791f8), U64_C (0x716666856617e3cc), U64_C (0x7bdddd53dda68ea7), U64_C (0xaf17175c17b84b2e), U64_C (0x454747014702468e), U64_C (0x1a9e9e429e84dc21), U64_C (0xd4caca0fca1ec589), U64_C (0x582d2db42d75995a), U64_C (0x2ebfbfc6bf917963), U64_C (0x3f07071c07381b0e), U64_C (0xacadad8ead012347), U64_C (0xb05a5a755aea2fb4), U64_C (0xef838336836cb51b), U64_C (0xb63333cc3385ff66), U64_C (0x5c636391633ff2c6), U64_C (0x1202020802100a04), U64_C (0x93aaaa92aa393849), U64_C (0xde7171d971afa8e2), U64_C (0xc6c8c807c80ecf8d), U64_C (0xd119196419c87d32), U64_C (0x3b49493949727092), U64_C (0x5fd9d943d9869aaf), U64_C (0x31f2f2eff2c31df9), U64_C (0xa8e3e3abe34b48db), U64_C (0xb95b5b715be22ab6), U64_C (0xbc88881a8834920d), U64_C (0x3e9a9a529aa4c829), U64_C (0x0b262698262dbe4c), U64_C (0xbf3232c8328dfa64), U64_C (0x59b0b0fab0e94a7d), U64_C (0xf2e9e983e91b6acf), U64_C (0x770f0f3c0f78331e), U64_C (0x33d5d573d5e6a6b7), U64_C (0xf480803a8074ba1d), U64_C (0x27bebec2be997c61), U64_C (0xebcdcd13cd26de87), U64_C (0x893434d034bde468), U64_C (0x3248483d487a7590), U64_C (0x54ffffdbffab24e3), U64_C (0x8d7a7af57af78ff4), U64_C (0x6490907a90f4ea3d), U64_C (0x9d5f5f615fc23ebe), U64_C (0x3d202080201da040), U64_C (0x0f6868bd6867d5d0), U64_C (0xca1a1a681ad07234), U64_C (0xb7aeae82ae192c41), U64_C (0x7db4b4eab4c95e75), U64_C (0xce54544d549a19a8), U64_C (0x7f93937693ece53b), U64_C (0x2f222288220daa44), U64_C (0x6364648d6407e9c8), U64_C (0x2af1f1e3f1db12ff), U64_C (0xcc7373d173bfa2e6), U64_C (0x8212124812905a24), U64_C (0x7a40401d403a5d80), U64_C (0x4808082008402810), U64_C (0x95c3c32bc356e89b), U64_C (0xdfecec97ec337bc5), U64_C (0x4ddbdb4bdb9690ab), U64_C (0xc0a1a1bea1611f5f), U64_C (0x918d8d0e8d1c8307), U64_C (0xc83d3df43df5c97a), U64_C (0x5b97976697ccf133), U64_C (0x0000000000000000), U64_C (0xf9cfcf1bcf36d483), U64_C (0x6e2b2bac2b458756), U64_C (0xe17676c57697b3ec), U64_C (0xe68282328264b019), U64_C (0x28d6d67fd6fea9b1), U64_C (0xc31b1b6c1bd87736), U64_C (0x74b5b5eeb5c15b77), U64_C (0xbeafaf86af112943), U64_C (0x1d6a6ab56a77dfd4), U64_C (0xea50505d50ba0da0), U64_C (0x5745450945124c8a), U64_C (0x38f3f3ebf3cb18fb), U64_C (0xad3030c0309df060), U64_C (0xc4efef9bef2b74c3), U64_C (0xda3f3ffc3fe5c37e), U64_C (0xc755554955921caa), U64_C (0xdba2a2b2a2791059), U64_C (0xe9eaea8fea0365c9), U64_C (0x6a656589650fecca), U64_C (0x03babad2bab96869), U64_C (0x4a2f2fbc2f65935e), U64_C (0x8ec0c027c04ee79d), U64_C (0x60dede5fdebe81a1), U64_C (0xfc1c1c701ce06c38), U64_C (0x46fdfdd3fdbb2ee7), U64_C (0x1f4d4d294d52649a), U64_C (0x7692927292e4e039), U64_C (0xfa7575c9758fbcea), U64_C (0x3606061806301e0c), U64_C (0xae8a8a128a249809), U64_C (0x4bb2b2f2b2f94079), U64_C (0x85e6e6bfe66359d1), U64_C (0x7e0e0e380e70361c), U64_C (0xe71f1f7c1ff8633e), U64_C (0x556262956237f7c4), U64_C (0x3ad4d477d4eea3b5), U64_C (0x81a8a89aa829324d), U64_C (0x5296966296c4f431), U64_C (0x62f9f9c3f99b3aef), U64_C (0xa3c5c533c566f697), U64_C (0x102525942535b14a), U64_C (0xab59597959f220b2), U64_C (0xd084842a8454ae15), U64_C (0xc57272d572b7a7e4), U64_C (0xec3939e439d5dd72), U64_C (0x164c4c2d4c5a6198), U64_C (0x945e5e655eca3bbc), U64_C (0x9f7878fd78e785f0), U64_C (0xe53838e038ddd870), U64_C (0x988c8c0a8c148605), U64_C (0x17d1d163d1c6b2bf), U64_C (0xe4a5a5aea5410b57), U64_C (0xa1e2e2afe2434dd9), U64_C (0x4e616199612ff8c2), U64_C (0x42b3b3f6b3f1457b), U64_C (0x342121842115a542), U64_C (0x089c9c4a9c94d625), U64_C (0xee1e1e781ef0663c), U64_C (0x6143431143225286), U64_C (0xb1c7c73bc776fc93), U64_C (0x4ffcfcd7fcb32be5), U64_C (0x2404041004201408), U64_C (0xe351515951b208a2), U64_C (0x2599995e99bcc72f), U64_C (0x226d6da96d4fc4da), U64_C (0x650d0d340d68391a), U64_C (0x79fafacffa8335e9), U64_C (0x69dfdf5bdfb684a3), U64_C (0xa97e7ee57ed79bfc), U64_C (0x19242490243db448), U64_C (0xfe3b3bec3bc5d776), U64_C (0x9aabab96ab313d4b), U64_C (0xf0cece1fce3ed181), U64_C (0x9911114411885522), U64_C (0x838f8f068f0c8903), U64_C (0x044e4e254e4a6b9c), U64_C (0x66b7b7e6b7d15173), U64_C (0xe0ebeb8beb0b60cb), U64_C (0xc13c3cf03cfdcc78), U64_C (0xfd81813e817cbf1f), U64_C (0x4094946a94d4fe35), U64_C (0x1cf7f7fbf7eb0cf3), U64_C (0x18b9b9deb9a1676f), U64_C (0x8b13134c13985f26), U64_C (0x512c2cb02c7d9c58), U64_C (0x05d3d36bd3d6b8bb), U64_C (0x8ce7e7bbe76b5cd3), U64_C (0x396e6ea56e57cbdc), U64_C (0xaac4c437c46ef395), U64_C (0x1b03030c03180f06), U64_C (0xdc565645568a13ac), U64_C (0x5e44440d441a4988), U64_C (0xa07f7fe17fdf9efe), U64_C (0x88a9a99ea921374f), U64_C (0x672a2aa82a4d8254), U64_C (0x0abbbbd6bbb16d6b), U64_C (0x87c1c123c146e29f), U64_C (0xf153535153a202a6), U64_C (0x72dcdc57dcae8ba5), U64_C (0x530b0b2c0b582716), U64_C (0x019d9d4e9d9cd327), U64_C (0x2b6c6cad6c47c1d8), U64_C (0xa43131c43195f562), U64_C (0xf37474cd7487b9e8), U64_C (0x15f6f6fff6e309f1), U64_C (0x4c464605460a438c), U64_C (0xa5acac8aac092645), U64_C (0xb589891e893c970f), U64_C (0xb414145014a04428), U64_C (0xbae1e1a3e15b42df), U64_C (0xa616165816b04e2c), U64_C (0xf73a3ae83acdd274), U64_C (0x066969b9696fd0d2), U64_C (0x4109092409482d12), U64_C (0xd77070dd70a7ade0), U64_C (0x6fb6b6e2b6d95471), U64_C (0x1ed0d067d0ceb7bd), U64_C (0xd6eded93ed3b7ec7), U64_C (0xe2cccc17cc2edb85), U64_C (0x68424215422a5784), U64_C (0x2c98985a98b4c22d), U64_C (0xeda4a4aaa4490e55), U64_C (0x752828a0285d8850), U64_C (0x865c5c6d5cda31b8), U64_C (0x6bf8f8c7f8933fed), U64_C (0xc28686228644a411), }, { U64_C (0x30d818186018c078), U64_C (0x462623238c2305af), U64_C (0x91b8c6c63fc67ef9), U64_C (0xcdfbe8e887e8136f), U64_C (0x13cb878726874ca1), U64_C (0x6d11b8b8dab8a962), U64_C (0x0209010104010805), U64_C (0x9e0d4f4f214f426e), U64_C (0x6c9b3636d836adee), U64_C (0x51ffa6a6a2a65904), U64_C (0xb90cd2d26fd2debd), U64_C (0xf70ef5f5f3f5fb06), U64_C (0xf2967979f979ef80), U64_C (0xde306f6fa16f5fce), U64_C (0x3f6d91917e91fcef), U64_C (0xa4f852525552aa07), U64_C (0xc04760609d6027fd), U64_C (0x6535bcbccabc8976), U64_C (0x2b379b9b569baccd), U64_C (0x018a8e8e028e048c), U64_C (0x5bd2a3a3b6a37115), U64_C (0x186c0c0c300c603c), U64_C (0xf6847b7bf17bff8a), U64_C (0x6a803535d435b5e1), U64_C (0x3af51d1d741de869), U64_C (0xddb3e0e0a7e05347), U64_C (0xb321d7d77bd7f6ac), U64_C (0x999cc2c22fc25eed), U64_C (0x5c432e2eb82e6d96), U64_C (0x96294b4b314b627a), U64_C (0xe15dfefedffea321), U64_C (0xaed5575741578216), U64_C (0x2abd15155415a841), U64_C (0xeee87777c1779fb6), U64_C (0x6e923737dc37a5eb), U64_C (0xd79ee5e5b3e57b56), U64_C (0x23139f9f469f8cd9), U64_C (0xfd23f0f0e7f0d317), U64_C (0x94204a4a354a6a7f), U64_C (0xa944dada4fda9e95), U64_C (0xb0a258587d58fa25), U64_C (0x8fcfc9c903c906ca), U64_C (0x527c2929a429558d), U64_C (0x145a0a0a280a5022), U64_C (0x7f50b1b1feb1e14f), U64_C (0x5dc9a0a0baa0691a), U64_C (0xd6146b6bb16b7fda), U64_C (0x17d985852e855cab), U64_C (0x673cbdbdcebd8173), U64_C (0xba8f5d5d695dd234), U64_C (0x2090101040108050), U64_C (0xf507f4f4f7f4f303), U64_C (0x8bddcbcb0bcb16c0), U64_C (0x7cd33e3ef83eedc6), U64_C (0x0a2d050514052811), U64_C (0xce78676781671fe6), U64_C (0xd597e4e4b7e47353), U64_C (0x4e0227279c2725bb), U64_C (0x8273414119413258), U64_C (0x0ba78b8b168b2c9d), U64_C (0x53f6a7a7a6a75101), U64_C (0xfab27d7de97dcf94), U64_C (0x374995956e95dcfb), U64_C (0xad56d8d847d88e9f), U64_C (0xeb70fbfbcbfb8b30), U64_C (0xc1cdeeee9fee2371), U64_C (0xf8bb7c7ced7cc791), U64_C (0xcc716666856617e3), U64_C (0xa77bdddd53dda68e), U64_C (0x2eaf17175c17b84b), U64_C (0x8e45474701470246), U64_C (0x211a9e9e429e84dc), U64_C (0x89d4caca0fca1ec5), U64_C (0x5a582d2db42d7599), U64_C (0x632ebfbfc6bf9179), U64_C (0x0e3f07071c07381b), U64_C (0x47acadad8ead0123), U64_C (0xb4b05a5a755aea2f), U64_C (0x1bef838336836cb5), U64_C (0x66b63333cc3385ff), U64_C (0xc65c636391633ff2), U64_C (0x041202020802100a), U64_C (0x4993aaaa92aa3938), U64_C (0xe2de7171d971afa8), U64_C (0x8dc6c8c807c80ecf), U64_C (0x32d119196419c87d), U64_C (0x923b494939497270), U64_C (0xaf5fd9d943d9869a), U64_C (0xf931f2f2eff2c31d), U64_C (0xdba8e3e3abe34b48), U64_C (0xb6b95b5b715be22a), U64_C (0x0dbc88881a883492), U64_C (0x293e9a9a529aa4c8), U64_C (0x4c0b262698262dbe), U64_C (0x64bf3232c8328dfa), U64_C (0x7d59b0b0fab0e94a), U64_C (0xcff2e9e983e91b6a), U64_C (0x1e770f0f3c0f7833), U64_C (0xb733d5d573d5e6a6), U64_C (0x1df480803a8074ba), U64_C (0x6127bebec2be997c), U64_C (0x87ebcdcd13cd26de), U64_C (0x68893434d034bde4), U64_C (0x903248483d487a75), U64_C (0xe354ffffdbffab24), U64_C (0xf48d7a7af57af78f), U64_C (0x3d6490907a90f4ea), U64_C (0xbe9d5f5f615fc23e), U64_C (0x403d202080201da0), U64_C (0xd00f6868bd6867d5), U64_C (0x34ca1a1a681ad072), U64_C (0x41b7aeae82ae192c), U64_C (0x757db4b4eab4c95e), U64_C (0xa8ce54544d549a19), U64_C (0x3b7f93937693ece5), U64_C (0x442f222288220daa), U64_C (0xc86364648d6407e9), U64_C (0xff2af1f1e3f1db12), U64_C (0xe6cc7373d173bfa2), U64_C (0x248212124812905a), U64_C (0x807a40401d403a5d), U64_C (0x1048080820084028), U64_C (0x9b95c3c32bc356e8), U64_C (0xc5dfecec97ec337b), U64_C (0xab4ddbdb4bdb9690), U64_C (0x5fc0a1a1bea1611f), U64_C (0x07918d8d0e8d1c83), U64_C (0x7ac83d3df43df5c9), U64_C (0x335b97976697ccf1), U64_C (0x0000000000000000), U64_C (0x83f9cfcf1bcf36d4), U64_C (0x566e2b2bac2b4587), U64_C (0xece17676c57697b3), U64_C (0x19e68282328264b0), U64_C (0xb128d6d67fd6fea9), U64_C (0x36c31b1b6c1bd877), U64_C (0x7774b5b5eeb5c15b), U64_C (0x43beafaf86af1129), U64_C (0xd41d6a6ab56a77df), U64_C (0xa0ea50505d50ba0d), U64_C (0x8a5745450945124c), U64_C (0xfb38f3f3ebf3cb18), U64_C (0x60ad3030c0309df0), U64_C (0xc3c4efef9bef2b74), U64_C (0x7eda3f3ffc3fe5c3), U64_C (0xaac755554955921c), U64_C (0x59dba2a2b2a27910), U64_C (0xc9e9eaea8fea0365), U64_C (0xca6a656589650fec), U64_C (0x6903babad2bab968), U64_C (0x5e4a2f2fbc2f6593), U64_C (0x9d8ec0c027c04ee7), U64_C (0xa160dede5fdebe81), U64_C (0x38fc1c1c701ce06c), U64_C (0xe746fdfdd3fdbb2e), U64_C (0x9a1f4d4d294d5264), U64_C (0x397692927292e4e0), U64_C (0xeafa7575c9758fbc), U64_C (0x0c3606061806301e), U64_C (0x09ae8a8a128a2498), U64_C (0x794bb2b2f2b2f940), U64_C (0xd185e6e6bfe66359), U64_C (0x1c7e0e0e380e7036), U64_C (0x3ee71f1f7c1ff863), U64_C (0xc4556262956237f7), U64_C (0xb53ad4d477d4eea3), U64_C (0x4d81a8a89aa82932), U64_C (0x315296966296c4f4), U64_C (0xef62f9f9c3f99b3a), U64_C (0x97a3c5c533c566f6), U64_C (0x4a102525942535b1), U64_C (0xb2ab59597959f220), U64_C (0x15d084842a8454ae), U64_C (0xe4c57272d572b7a7), U64_C (0x72ec3939e439d5dd), U64_C (0x98164c4c2d4c5a61), U64_C (0xbc945e5e655eca3b), U64_C (0xf09f7878fd78e785), U64_C (0x70e53838e038ddd8), U64_C (0x05988c8c0a8c1486), U64_C (0xbf17d1d163d1c6b2), U64_C (0x57e4a5a5aea5410b), U64_C (0xd9a1e2e2afe2434d), U64_C (0xc24e616199612ff8), U64_C (0x7b42b3b3f6b3f145), U64_C (0x42342121842115a5), U64_C (0x25089c9c4a9c94d6), U64_C (0x3cee1e1e781ef066), U64_C (0x8661434311432252), U64_C (0x93b1c7c73bc776fc), U64_C (0xe54ffcfcd7fcb32b), U64_C (0x0824040410042014), U64_C (0xa2e351515951b208), U64_C (0x2f2599995e99bcc7), U64_C (0xda226d6da96d4fc4), U64_C (0x1a650d0d340d6839), U64_C (0xe979fafacffa8335), U64_C (0xa369dfdf5bdfb684), U64_C (0xfca97e7ee57ed79b), U64_C (0x4819242490243db4), U64_C (0x76fe3b3bec3bc5d7), U64_C (0x4b9aabab96ab313d), U64_C (0x81f0cece1fce3ed1), U64_C (0x2299111144118855), U64_C (0x03838f8f068f0c89), U64_C (0x9c044e4e254e4a6b), U64_C (0x7366b7b7e6b7d151), U64_C (0xcbe0ebeb8beb0b60), U64_C (0x78c13c3cf03cfdcc), U64_C (0x1ffd81813e817cbf), U64_C (0x354094946a94d4fe), U64_C (0xf31cf7f7fbf7eb0c), U64_C (0x6f18b9b9deb9a167), U64_C (0x268b13134c13985f), U64_C (0x58512c2cb02c7d9c), U64_C (0xbb05d3d36bd3d6b8), U64_C (0xd38ce7e7bbe76b5c), U64_C (0xdc396e6ea56e57cb), U64_C (0x95aac4c437c46ef3), U64_C (0x061b03030c03180f), U64_C (0xacdc565645568a13), U64_C (0x885e44440d441a49), U64_C (0xfea07f7fe17fdf9e), U64_C (0x4f88a9a99ea92137), U64_C (0x54672a2aa82a4d82), U64_C (0x6b0abbbbd6bbb16d), U64_C (0x9f87c1c123c146e2), U64_C (0xa6f153535153a202), U64_C (0xa572dcdc57dcae8b), U64_C (0x16530b0b2c0b5827), U64_C (0x27019d9d4e9d9cd3), U64_C (0xd82b6c6cad6c47c1), U64_C (0x62a43131c43195f5), U64_C (0xe8f37474cd7487b9), U64_C (0xf115f6f6fff6e309), U64_C (0x8c4c464605460a43), U64_C (0x45a5acac8aac0926), U64_C (0x0fb589891e893c97), U64_C (0x28b414145014a044), U64_C (0xdfbae1e1a3e15b42), U64_C (0x2ca616165816b04e), U64_C (0x74f73a3ae83acdd2), U64_C (0xd2066969b9696fd0), U64_C (0x124109092409482d), U64_C (0xe0d77070dd70a7ad), U64_C (0x716fb6b6e2b6d954), U64_C (0xbd1ed0d067d0ceb7), U64_C (0xc7d6eded93ed3b7e), U64_C (0x85e2cccc17cc2edb), U64_C (0x8468424215422a57), U64_C (0x2d2c98985a98b4c2), U64_C (0x55eda4a4aaa4490e), U64_C (0x50752828a0285d88), U64_C (0xb8865c5c6d5cda31), U64_C (0xed6bf8f8c7f8933f), U64_C (0x11c28686228644a4), }, { U64_C (0x7830d818186018c0), U64_C (0xaf462623238c2305), U64_C (0xf991b8c6c63fc67e), U64_C (0x6fcdfbe8e887e813), U64_C (0xa113cb878726874c), U64_C (0x626d11b8b8dab8a9), U64_C (0x0502090101040108), U64_C (0x6e9e0d4f4f214f42), U64_C (0xee6c9b3636d836ad), U64_C (0x0451ffa6a6a2a659), U64_C (0xbdb90cd2d26fd2de), U64_C (0x06f70ef5f5f3f5fb), U64_C (0x80f2967979f979ef), U64_C (0xcede306f6fa16f5f), U64_C (0xef3f6d91917e91fc), U64_C (0x07a4f852525552aa), U64_C (0xfdc04760609d6027), U64_C (0x766535bcbccabc89), U64_C (0xcd2b379b9b569bac), U64_C (0x8c018a8e8e028e04), U64_C (0x155bd2a3a3b6a371), U64_C (0x3c186c0c0c300c60), U64_C (0x8af6847b7bf17bff), U64_C (0xe16a803535d435b5), U64_C (0x693af51d1d741de8), U64_C (0x47ddb3e0e0a7e053), U64_C (0xacb321d7d77bd7f6), U64_C (0xed999cc2c22fc25e), U64_C (0x965c432e2eb82e6d), U64_C (0x7a96294b4b314b62), U64_C (0x21e15dfefedffea3), U64_C (0x16aed55757415782), U64_C (0x412abd15155415a8), U64_C (0xb6eee87777c1779f), U64_C (0xeb6e923737dc37a5), U64_C (0x56d79ee5e5b3e57b), U64_C (0xd923139f9f469f8c), U64_C (0x17fd23f0f0e7f0d3), U64_C (0x7f94204a4a354a6a), U64_C (0x95a944dada4fda9e), U64_C (0x25b0a258587d58fa), U64_C (0xca8fcfc9c903c906), U64_C (0x8d527c2929a42955), U64_C (0x22145a0a0a280a50), U64_C (0x4f7f50b1b1feb1e1), U64_C (0x1a5dc9a0a0baa069), U64_C (0xdad6146b6bb16b7f), U64_C (0xab17d985852e855c), U64_C (0x73673cbdbdcebd81), U64_C (0x34ba8f5d5d695dd2), U64_C (0x5020901010401080), U64_C (0x03f507f4f4f7f4f3), U64_C (0xc08bddcbcb0bcb16), U64_C (0xc67cd33e3ef83eed), U64_C (0x110a2d0505140528), U64_C (0xe6ce78676781671f), U64_C (0x53d597e4e4b7e473), U64_C (0xbb4e0227279c2725), U64_C (0x5882734141194132), U64_C (0x9d0ba78b8b168b2c), U64_C (0x0153f6a7a7a6a751), U64_C (0x94fab27d7de97dcf), U64_C (0xfb374995956e95dc), U64_C (0x9fad56d8d847d88e), U64_C (0x30eb70fbfbcbfb8b), U64_C (0x71c1cdeeee9fee23), U64_C (0x91f8bb7c7ced7cc7), U64_C (0xe3cc716666856617), U64_C (0x8ea77bdddd53dda6), U64_C (0x4b2eaf17175c17b8), U64_C (0x468e454747014702), U64_C (0xdc211a9e9e429e84), U64_C (0xc589d4caca0fca1e), U64_C (0x995a582d2db42d75), U64_C (0x79632ebfbfc6bf91), U64_C (0x1b0e3f07071c0738), U64_C (0x2347acadad8ead01), U64_C (0x2fb4b05a5a755aea), U64_C (0xb51bef838336836c), U64_C (0xff66b63333cc3385), U64_C (0xf2c65c636391633f), U64_C (0x0a04120202080210), U64_C (0x384993aaaa92aa39), U64_C (0xa8e2de7171d971af), U64_C (0xcf8dc6c8c807c80e), U64_C (0x7d32d119196419c8), U64_C (0x70923b4949394972), U64_C (0x9aaf5fd9d943d986), U64_C (0x1df931f2f2eff2c3), U64_C (0x48dba8e3e3abe34b), U64_C (0x2ab6b95b5b715be2), U64_C (0x920dbc88881a8834), U64_C (0xc8293e9a9a529aa4), U64_C (0xbe4c0b262698262d), U64_C (0xfa64bf3232c8328d), U64_C (0x4a7d59b0b0fab0e9), U64_C (0x6acff2e9e983e91b), U64_C (0x331e770f0f3c0f78), U64_C (0xa6b733d5d573d5e6), U64_C (0xba1df480803a8074), U64_C (0x7c6127bebec2be99), U64_C (0xde87ebcdcd13cd26), U64_C (0xe468893434d034bd), U64_C (0x75903248483d487a), U64_C (0x24e354ffffdbffab), U64_C (0x8ff48d7a7af57af7), U64_C (0xea3d6490907a90f4), U64_C (0x3ebe9d5f5f615fc2), U64_C (0xa0403d202080201d), U64_C (0xd5d00f6868bd6867), U64_C (0x7234ca1a1a681ad0), U64_C (0x2c41b7aeae82ae19), U64_C (0x5e757db4b4eab4c9), U64_C (0x19a8ce54544d549a), U64_C (0xe53b7f93937693ec), U64_C (0xaa442f222288220d), U64_C (0xe9c86364648d6407), U64_C (0x12ff2af1f1e3f1db), U64_C (0xa2e6cc7373d173bf), U64_C (0x5a24821212481290), U64_C (0x5d807a40401d403a), U64_C (0x2810480808200840), U64_C (0xe89b95c3c32bc356), U64_C (0x7bc5dfecec97ec33), U64_C (0x90ab4ddbdb4bdb96), U64_C (0x1f5fc0a1a1bea161), U64_C (0x8307918d8d0e8d1c), U64_C (0xc97ac83d3df43df5), U64_C (0xf1335b97976697cc), U64_C (0x0000000000000000), U64_C (0xd483f9cfcf1bcf36), U64_C (0x87566e2b2bac2b45), U64_C (0xb3ece17676c57697), U64_C (0xb019e68282328264), U64_C (0xa9b128d6d67fd6fe), U64_C (0x7736c31b1b6c1bd8), U64_C (0x5b7774b5b5eeb5c1), U64_C (0x2943beafaf86af11), U64_C (0xdfd41d6a6ab56a77), U64_C (0x0da0ea50505d50ba), U64_C (0x4c8a574545094512), U64_C (0x18fb38f3f3ebf3cb), U64_C (0xf060ad3030c0309d), U64_C (0x74c3c4efef9bef2b), U64_C (0xc37eda3f3ffc3fe5), U64_C (0x1caac75555495592), U64_C (0x1059dba2a2b2a279), U64_C (0x65c9e9eaea8fea03), U64_C (0xecca6a656589650f), U64_C (0x686903babad2bab9), U64_C (0x935e4a2f2fbc2f65), U64_C (0xe79d8ec0c027c04e), U64_C (0x81a160dede5fdebe), U64_C (0x6c38fc1c1c701ce0), U64_C (0x2ee746fdfdd3fdbb), U64_C (0x649a1f4d4d294d52), U64_C (0xe0397692927292e4), U64_C (0xbceafa7575c9758f), U64_C (0x1e0c360606180630), U64_C (0x9809ae8a8a128a24), U64_C (0x40794bb2b2f2b2f9), U64_C (0x59d185e6e6bfe663), U64_C (0x361c7e0e0e380e70), U64_C (0x633ee71f1f7c1ff8), U64_C (0xf7c4556262956237), U64_C (0xa3b53ad4d477d4ee), U64_C (0x324d81a8a89aa829), U64_C (0xf4315296966296c4), U64_C (0x3aef62f9f9c3f99b), U64_C (0xf697a3c5c533c566), U64_C (0xb14a102525942535), U64_C (0x20b2ab59597959f2), U64_C (0xae15d084842a8454), U64_C (0xa7e4c57272d572b7), U64_C (0xdd72ec3939e439d5), U64_C (0x6198164c4c2d4c5a), U64_C (0x3bbc945e5e655eca), U64_C (0x85f09f7878fd78e7), U64_C (0xd870e53838e038dd), U64_C (0x8605988c8c0a8c14), U64_C (0xb2bf17d1d163d1c6), U64_C (0x0b57e4a5a5aea541), U64_C (0x4dd9a1e2e2afe243), U64_C (0xf8c24e616199612f), U64_C (0x457b42b3b3f6b3f1), U64_C (0xa542342121842115), U64_C (0xd625089c9c4a9c94), U64_C (0x663cee1e1e781ef0), U64_C (0x5286614343114322), U64_C (0xfc93b1c7c73bc776), U64_C (0x2be54ffcfcd7fcb3), U64_C (0x1408240404100420), U64_C (0x08a2e351515951b2), U64_C (0xc72f2599995e99bc), U64_C (0xc4da226d6da96d4f), U64_C (0x391a650d0d340d68), U64_C (0x35e979fafacffa83), U64_C (0x84a369dfdf5bdfb6), U64_C (0x9bfca97e7ee57ed7), U64_C (0xb44819242490243d), U64_C (0xd776fe3b3bec3bc5), U64_C (0x3d4b9aabab96ab31), U64_C (0xd181f0cece1fce3e), U64_C (0x5522991111441188), U64_C (0x8903838f8f068f0c), U64_C (0x6b9c044e4e254e4a), U64_C (0x517366b7b7e6b7d1), U64_C (0x60cbe0ebeb8beb0b), U64_C (0xcc78c13c3cf03cfd), U64_C (0xbf1ffd81813e817c), U64_C (0xfe354094946a94d4), U64_C (0x0cf31cf7f7fbf7eb), U64_C (0x676f18b9b9deb9a1), U64_C (0x5f268b13134c1398), U64_C (0x9c58512c2cb02c7d), U64_C (0xb8bb05d3d36bd3d6), U64_C (0x5cd38ce7e7bbe76b), U64_C (0xcbdc396e6ea56e57), U64_C (0xf395aac4c437c46e), U64_C (0x0f061b03030c0318), U64_C (0x13acdc565645568a), U64_C (0x49885e44440d441a), U64_C (0x9efea07f7fe17fdf), U64_C (0x374f88a9a99ea921), U64_C (0x8254672a2aa82a4d), U64_C (0x6d6b0abbbbd6bbb1), U64_C (0xe29f87c1c123c146), U64_C (0x02a6f153535153a2), U64_C (0x8ba572dcdc57dcae), U64_C (0x2716530b0b2c0b58), U64_C (0xd327019d9d4e9d9c), U64_C (0xc1d82b6c6cad6c47), U64_C (0xf562a43131c43195), U64_C (0xb9e8f37474cd7487), U64_C (0x09f115f6f6fff6e3), U64_C (0x438c4c464605460a), U64_C (0x2645a5acac8aac09), U64_C (0x970fb589891e893c), U64_C (0x4428b414145014a0), U64_C (0x42dfbae1e1a3e15b), U64_C (0x4e2ca616165816b0), U64_C (0xd274f73a3ae83acd), U64_C (0xd0d2066969b9696f), U64_C (0x2d12410909240948), U64_C (0xade0d77070dd70a7), U64_C (0x54716fb6b6e2b6d9), U64_C (0xb7bd1ed0d067d0ce), U64_C (0x7ec7d6eded93ed3b), U64_C (0xdb85e2cccc17cc2e), U64_C (0x578468424215422a), U64_C (0xc22d2c98985a98b4), U64_C (0x0e55eda4a4aaa449), U64_C (0x8850752828a0285d), U64_C (0x31b8865c5c6d5cda), U64_C (0x3fed6bf8f8c7f893), U64_C (0xa411c28686228644), }, { U64_C (0xc07830d818186018), U64_C (0x05af462623238c23), U64_C (0x7ef991b8c6c63fc6), U64_C (0x136fcdfbe8e887e8), U64_C (0x4ca113cb87872687), U64_C (0xa9626d11b8b8dab8), U64_C (0x0805020901010401), U64_C (0x426e9e0d4f4f214f), U64_C (0xadee6c9b3636d836), U64_C (0x590451ffa6a6a2a6), U64_C (0xdebdb90cd2d26fd2), U64_C (0xfb06f70ef5f5f3f5), U64_C (0xef80f2967979f979), U64_C (0x5fcede306f6fa16f), U64_C (0xfcef3f6d91917e91), U64_C (0xaa07a4f852525552), U64_C (0x27fdc04760609d60), U64_C (0x89766535bcbccabc), U64_C (0xaccd2b379b9b569b), U64_C (0x048c018a8e8e028e), U64_C (0x71155bd2a3a3b6a3), U64_C (0x603c186c0c0c300c), U64_C (0xff8af6847b7bf17b), U64_C (0xb5e16a803535d435), U64_C (0xe8693af51d1d741d), U64_C (0x5347ddb3e0e0a7e0), U64_C (0xf6acb321d7d77bd7), U64_C (0x5eed999cc2c22fc2), U64_C (0x6d965c432e2eb82e), U64_C (0x627a96294b4b314b), U64_C (0xa321e15dfefedffe), U64_C (0x8216aed557574157), U64_C (0xa8412abd15155415), U64_C (0x9fb6eee87777c177), U64_C (0xa5eb6e923737dc37), U64_C (0x7b56d79ee5e5b3e5), U64_C (0x8cd923139f9f469f), U64_C (0xd317fd23f0f0e7f0), U64_C (0x6a7f94204a4a354a), U64_C (0x9e95a944dada4fda), U64_C (0xfa25b0a258587d58), U64_C (0x06ca8fcfc9c903c9), U64_C (0x558d527c2929a429), U64_C (0x5022145a0a0a280a), U64_C (0xe14f7f50b1b1feb1), U64_C (0x691a5dc9a0a0baa0), U64_C (0x7fdad6146b6bb16b), U64_C (0x5cab17d985852e85), U64_C (0x8173673cbdbdcebd), U64_C (0xd234ba8f5d5d695d), U64_C (0x8050209010104010), U64_C (0xf303f507f4f4f7f4), U64_C (0x16c08bddcbcb0bcb), U64_C (0xedc67cd33e3ef83e), U64_C (0x28110a2d05051405), U64_C (0x1fe6ce7867678167), U64_C (0x7353d597e4e4b7e4), U64_C (0x25bb4e0227279c27), U64_C (0x3258827341411941), U64_C (0x2c9d0ba78b8b168b), U64_C (0x510153f6a7a7a6a7), U64_C (0xcf94fab27d7de97d), U64_C (0xdcfb374995956e95), U64_C (0x8e9fad56d8d847d8), U64_C (0x8b30eb70fbfbcbfb), U64_C (0x2371c1cdeeee9fee), U64_C (0xc791f8bb7c7ced7c), U64_C (0x17e3cc7166668566), U64_C (0xa68ea77bdddd53dd), U64_C (0xb84b2eaf17175c17), U64_C (0x02468e4547470147), U64_C (0x84dc211a9e9e429e), U64_C (0x1ec589d4caca0fca), U64_C (0x75995a582d2db42d), U64_C (0x9179632ebfbfc6bf), U64_C (0x381b0e3f07071c07), U64_C (0x012347acadad8ead), U64_C (0xea2fb4b05a5a755a), U64_C (0x6cb51bef83833683), U64_C (0x85ff66b63333cc33), U64_C (0x3ff2c65c63639163), U64_C (0x100a041202020802), U64_C (0x39384993aaaa92aa), U64_C (0xafa8e2de7171d971), U64_C (0x0ecf8dc6c8c807c8), U64_C (0xc87d32d119196419), U64_C (0x7270923b49493949), U64_C (0x869aaf5fd9d943d9), U64_C (0xc31df931f2f2eff2), U64_C (0x4b48dba8e3e3abe3), U64_C (0xe22ab6b95b5b715b), U64_C (0x34920dbc88881a88), U64_C (0xa4c8293e9a9a529a), U64_C (0x2dbe4c0b26269826), U64_C (0x8dfa64bf3232c832), U64_C (0xe94a7d59b0b0fab0), U64_C (0x1b6acff2e9e983e9), U64_C (0x78331e770f0f3c0f), U64_C (0xe6a6b733d5d573d5), U64_C (0x74ba1df480803a80), U64_C (0x997c6127bebec2be), U64_C (0x26de87ebcdcd13cd), U64_C (0xbde468893434d034), U64_C (0x7a75903248483d48), U64_C (0xab24e354ffffdbff), U64_C (0xf78ff48d7a7af57a), U64_C (0xf4ea3d6490907a90), U64_C (0xc23ebe9d5f5f615f), U64_C (0x1da0403d20208020), U64_C (0x67d5d00f6868bd68), U64_C (0xd07234ca1a1a681a), U64_C (0x192c41b7aeae82ae), U64_C (0xc95e757db4b4eab4), U64_C (0x9a19a8ce54544d54), U64_C (0xece53b7f93937693), U64_C (0x0daa442f22228822), U64_C (0x07e9c86364648d64), U64_C (0xdb12ff2af1f1e3f1), U64_C (0xbfa2e6cc7373d173), U64_C (0x905a248212124812), U64_C (0x3a5d807a40401d40), U64_C (0x4028104808082008), U64_C (0x56e89b95c3c32bc3), U64_C (0x337bc5dfecec97ec), U64_C (0x9690ab4ddbdb4bdb), U64_C (0x611f5fc0a1a1bea1), U64_C (0x1c8307918d8d0e8d), U64_C (0xf5c97ac83d3df43d), U64_C (0xccf1335b97976697), U64_C (0x0000000000000000), U64_C (0x36d483f9cfcf1bcf), U64_C (0x4587566e2b2bac2b), U64_C (0x97b3ece17676c576), U64_C (0x64b019e682823282), U64_C (0xfea9b128d6d67fd6), U64_C (0xd87736c31b1b6c1b), U64_C (0xc15b7774b5b5eeb5), U64_C (0x112943beafaf86af), U64_C (0x77dfd41d6a6ab56a), U64_C (0xba0da0ea50505d50), U64_C (0x124c8a5745450945), U64_C (0xcb18fb38f3f3ebf3), U64_C (0x9df060ad3030c030), U64_C (0x2b74c3c4efef9bef), U64_C (0xe5c37eda3f3ffc3f), U64_C (0x921caac755554955), U64_C (0x791059dba2a2b2a2), U64_C (0x0365c9e9eaea8fea), U64_C (0x0fecca6a65658965), U64_C (0xb9686903babad2ba), U64_C (0x65935e4a2f2fbc2f), U64_C (0x4ee79d8ec0c027c0), U64_C (0xbe81a160dede5fde), U64_C (0xe06c38fc1c1c701c), U64_C (0xbb2ee746fdfdd3fd), U64_C (0x52649a1f4d4d294d), U64_C (0xe4e0397692927292), U64_C (0x8fbceafa7575c975), U64_C (0x301e0c3606061806), U64_C (0x249809ae8a8a128a), U64_C (0xf940794bb2b2f2b2), U64_C (0x6359d185e6e6bfe6), U64_C (0x70361c7e0e0e380e), U64_C (0xf8633ee71f1f7c1f), U64_C (0x37f7c45562629562), U64_C (0xeea3b53ad4d477d4), U64_C (0x29324d81a8a89aa8), U64_C (0xc4f4315296966296), U64_C (0x9b3aef62f9f9c3f9), U64_C (0x66f697a3c5c533c5), U64_C (0x35b14a1025259425), U64_C (0xf220b2ab59597959), U64_C (0x54ae15d084842a84), U64_C (0xb7a7e4c57272d572), U64_C (0xd5dd72ec3939e439), U64_C (0x5a6198164c4c2d4c), U64_C (0xca3bbc945e5e655e), U64_C (0xe785f09f7878fd78), U64_C (0xddd870e53838e038), U64_C (0x148605988c8c0a8c), U64_C (0xc6b2bf17d1d163d1), U64_C (0x410b57e4a5a5aea5), U64_C (0x434dd9a1e2e2afe2), U64_C (0x2ff8c24e61619961), U64_C (0xf1457b42b3b3f6b3), U64_C (0x15a5423421218421), U64_C (0x94d625089c9c4a9c), U64_C (0xf0663cee1e1e781e), U64_C (0x2252866143431143), U64_C (0x76fc93b1c7c73bc7), U64_C (0xb32be54ffcfcd7fc), U64_C (0x2014082404041004), U64_C (0xb208a2e351515951), U64_C (0xbcc72f2599995e99), U64_C (0x4fc4da226d6da96d), U64_C (0x68391a650d0d340d), U64_C (0x8335e979fafacffa), U64_C (0xb684a369dfdf5bdf), U64_C (0xd79bfca97e7ee57e), U64_C (0x3db4481924249024), U64_C (0xc5d776fe3b3bec3b), U64_C (0x313d4b9aabab96ab), U64_C (0x3ed181f0cece1fce), U64_C (0x8855229911114411), U64_C (0x0c8903838f8f068f), U64_C (0x4a6b9c044e4e254e), U64_C (0xd1517366b7b7e6b7), U64_C (0x0b60cbe0ebeb8beb), U64_C (0xfdcc78c13c3cf03c), U64_C (0x7cbf1ffd81813e81), U64_C (0xd4fe354094946a94), U64_C (0xeb0cf31cf7f7fbf7), U64_C (0xa1676f18b9b9deb9), U64_C (0x985f268b13134c13), U64_C (0x7d9c58512c2cb02c), U64_C (0xd6b8bb05d3d36bd3), U64_C (0x6b5cd38ce7e7bbe7), U64_C (0x57cbdc396e6ea56e), U64_C (0x6ef395aac4c437c4), U64_C (0x180f061b03030c03), U64_C (0x8a13acdc56564556), U64_C (0x1a49885e44440d44), U64_C (0xdf9efea07f7fe17f), U64_C (0x21374f88a9a99ea9), U64_C (0x4d8254672a2aa82a), U64_C (0xb16d6b0abbbbd6bb), U64_C (0x46e29f87c1c123c1), U64_C (0xa202a6f153535153), U64_C (0xae8ba572dcdc57dc), U64_C (0x582716530b0b2c0b), U64_C (0x9cd327019d9d4e9d), U64_C (0x47c1d82b6c6cad6c), U64_C (0x95f562a43131c431), U64_C (0x87b9e8f37474cd74), U64_C (0xe309f115f6f6fff6), U64_C (0x0a438c4c46460546), U64_C (0x092645a5acac8aac), U64_C (0x3c970fb589891e89), U64_C (0xa04428b414145014), U64_C (0x5b42dfbae1e1a3e1), U64_C (0xb04e2ca616165816), U64_C (0xcdd274f73a3ae83a), U64_C (0x6fd0d2066969b969), U64_C (0x482d124109092409), U64_C (0xa7ade0d77070dd70), U64_C (0xd954716fb6b6e2b6), U64_C (0xceb7bd1ed0d067d0), U64_C (0x3b7ec7d6eded93ed), U64_C (0x2edb85e2cccc17cc), U64_C (0x2a57846842421542), U64_C (0xb4c22d2c98985a98), U64_C (0x490e55eda4a4aaa4), U64_C (0x5d8850752828a028), U64_C (0xda31b8865c5c6d5c), U64_C (0x933fed6bf8f8c7f8), U64_C (0x44a411c286862286), }, { U64_C (0x18c07830d8181860), U64_C (0x2305af462623238c), U64_C (0xc67ef991b8c6c63f), U64_C (0xe8136fcdfbe8e887), U64_C (0x874ca113cb878726), U64_C (0xb8a9626d11b8b8da), U64_C (0x0108050209010104), U64_C (0x4f426e9e0d4f4f21), U64_C (0x36adee6c9b3636d8), U64_C (0xa6590451ffa6a6a2), U64_C (0xd2debdb90cd2d26f), U64_C (0xf5fb06f70ef5f5f3), U64_C (0x79ef80f2967979f9), U64_C (0x6f5fcede306f6fa1), U64_C (0x91fcef3f6d91917e), U64_C (0x52aa07a4f8525255), U64_C (0x6027fdc04760609d), U64_C (0xbc89766535bcbcca), U64_C (0x9baccd2b379b9b56), U64_C (0x8e048c018a8e8e02), U64_C (0xa371155bd2a3a3b6), U64_C (0x0c603c186c0c0c30), U64_C (0x7bff8af6847b7bf1), U64_C (0x35b5e16a803535d4), U64_C (0x1de8693af51d1d74), U64_C (0xe05347ddb3e0e0a7), U64_C (0xd7f6acb321d7d77b), U64_C (0xc25eed999cc2c22f), U64_C (0x2e6d965c432e2eb8), U64_C (0x4b627a96294b4b31), U64_C (0xfea321e15dfefedf), U64_C (0x578216aed5575741), U64_C (0x15a8412abd151554), U64_C (0x779fb6eee87777c1), U64_C (0x37a5eb6e923737dc), U64_C (0xe57b56d79ee5e5b3), U64_C (0x9f8cd923139f9f46), U64_C (0xf0d317fd23f0f0e7), U64_C (0x4a6a7f94204a4a35), U64_C (0xda9e95a944dada4f), U64_C (0x58fa25b0a258587d), U64_C (0xc906ca8fcfc9c903), U64_C (0x29558d527c2929a4), U64_C (0x0a5022145a0a0a28), U64_C (0xb1e14f7f50b1b1fe), U64_C (0xa0691a5dc9a0a0ba), U64_C (0x6b7fdad6146b6bb1), U64_C (0x855cab17d985852e), U64_C (0xbd8173673cbdbdce), U64_C (0x5dd234ba8f5d5d69), U64_C (0x1080502090101040), U64_C (0xf4f303f507f4f4f7), U64_C (0xcb16c08bddcbcb0b), U64_C (0x3eedc67cd33e3ef8), U64_C (0x0528110a2d050514), U64_C (0x671fe6ce78676781), U64_C (0xe47353d597e4e4b7), U64_C (0x2725bb4e0227279c), U64_C (0x4132588273414119), U64_C (0x8b2c9d0ba78b8b16), U64_C (0xa7510153f6a7a7a6), U64_C (0x7dcf94fab27d7de9), U64_C (0x95dcfb374995956e), U64_C (0xd88e9fad56d8d847), U64_C (0xfb8b30eb70fbfbcb), U64_C (0xee2371c1cdeeee9f), U64_C (0x7cc791f8bb7c7ced), U64_C (0x6617e3cc71666685), U64_C (0xdda68ea77bdddd53), U64_C (0x17b84b2eaf17175c), U64_C (0x4702468e45474701), U64_C (0x9e84dc211a9e9e42), U64_C (0xca1ec589d4caca0f), U64_C (0x2d75995a582d2db4), U64_C (0xbf9179632ebfbfc6), U64_C (0x07381b0e3f07071c), U64_C (0xad012347acadad8e), U64_C (0x5aea2fb4b05a5a75), U64_C (0x836cb51bef838336), U64_C (0x3385ff66b63333cc), U64_C (0x633ff2c65c636391), U64_C (0x02100a0412020208), U64_C (0xaa39384993aaaa92), U64_C (0x71afa8e2de7171d9), U64_C (0xc80ecf8dc6c8c807), U64_C (0x19c87d32d1191964), U64_C (0x497270923b494939), U64_C (0xd9869aaf5fd9d943), U64_C (0xf2c31df931f2f2ef), U64_C (0xe34b48dba8e3e3ab), U64_C (0x5be22ab6b95b5b71), U64_C (0x8834920dbc88881a), U64_C (0x9aa4c8293e9a9a52), U64_C (0x262dbe4c0b262698), U64_C (0x328dfa64bf3232c8), U64_C (0xb0e94a7d59b0b0fa), U64_C (0xe91b6acff2e9e983), U64_C (0x0f78331e770f0f3c), U64_C (0xd5e6a6b733d5d573), U64_C (0x8074ba1df480803a), U64_C (0xbe997c6127bebec2), U64_C (0xcd26de87ebcdcd13), U64_C (0x34bde468893434d0), U64_C (0x487a75903248483d), U64_C (0xffab24e354ffffdb), U64_C (0x7af78ff48d7a7af5), U64_C (0x90f4ea3d6490907a), U64_C (0x5fc23ebe9d5f5f61), U64_C (0x201da0403d202080), U64_C (0x6867d5d00f6868bd), U64_C (0x1ad07234ca1a1a68), U64_C (0xae192c41b7aeae82), U64_C (0xb4c95e757db4b4ea), U64_C (0x549a19a8ce54544d), U64_C (0x93ece53b7f939376), U64_C (0x220daa442f222288), U64_C (0x6407e9c86364648d), U64_C (0xf1db12ff2af1f1e3), U64_C (0x73bfa2e6cc7373d1), U64_C (0x12905a2482121248), U64_C (0x403a5d807a40401d), U64_C (0x0840281048080820), U64_C (0xc356e89b95c3c32b), U64_C (0xec337bc5dfecec97), U64_C (0xdb9690ab4ddbdb4b), U64_C (0xa1611f5fc0a1a1be), U64_C (0x8d1c8307918d8d0e), U64_C (0x3df5c97ac83d3df4), U64_C (0x97ccf1335b979766), U64_C (0x0000000000000000), U64_C (0xcf36d483f9cfcf1b), U64_C (0x2b4587566e2b2bac), U64_C (0x7697b3ece17676c5), U64_C (0x8264b019e6828232), U64_C (0xd6fea9b128d6d67f), U64_C (0x1bd87736c31b1b6c), U64_C (0xb5c15b7774b5b5ee), U64_C (0xaf112943beafaf86), U64_C (0x6a77dfd41d6a6ab5), U64_C (0x50ba0da0ea50505d), U64_C (0x45124c8a57454509), U64_C (0xf3cb18fb38f3f3eb), U64_C (0x309df060ad3030c0), U64_C (0xef2b74c3c4efef9b), U64_C (0x3fe5c37eda3f3ffc), U64_C (0x55921caac7555549), U64_C (0xa2791059dba2a2b2), U64_C (0xea0365c9e9eaea8f), U64_C (0x650fecca6a656589), U64_C (0xbab9686903babad2), U64_C (0x2f65935e4a2f2fbc), U64_C (0xc04ee79d8ec0c027), U64_C (0xdebe81a160dede5f), U64_C (0x1ce06c38fc1c1c70), U64_C (0xfdbb2ee746fdfdd3), U64_C (0x4d52649a1f4d4d29), U64_C (0x92e4e03976929272), U64_C (0x758fbceafa7575c9), U64_C (0x06301e0c36060618), U64_C (0x8a249809ae8a8a12), U64_C (0xb2f940794bb2b2f2), U64_C (0xe66359d185e6e6bf), U64_C (0x0e70361c7e0e0e38), U64_C (0x1ff8633ee71f1f7c), U64_C (0x6237f7c455626295), U64_C (0xd4eea3b53ad4d477), U64_C (0xa829324d81a8a89a), U64_C (0x96c4f43152969662), U64_C (0xf99b3aef62f9f9c3), U64_C (0xc566f697a3c5c533), U64_C (0x2535b14a10252594), U64_C (0x59f220b2ab595979), U64_C (0x8454ae15d084842a), U64_C (0x72b7a7e4c57272d5), U64_C (0x39d5dd72ec3939e4), U64_C (0x4c5a6198164c4c2d), U64_C (0x5eca3bbc945e5e65), U64_C (0x78e785f09f7878fd), U64_C (0x38ddd870e53838e0), U64_C (0x8c148605988c8c0a), U64_C (0xd1c6b2bf17d1d163), U64_C (0xa5410b57e4a5a5ae), U64_C (0xe2434dd9a1e2e2af), U64_C (0x612ff8c24e616199), U64_C (0xb3f1457b42b3b3f6), U64_C (0x2115a54234212184), U64_C (0x9c94d625089c9c4a), U64_C (0x1ef0663cee1e1e78), U64_C (0x4322528661434311), U64_C (0xc776fc93b1c7c73b), U64_C (0xfcb32be54ffcfcd7), U64_C (0x0420140824040410), U64_C (0x51b208a2e3515159), U64_C (0x99bcc72f2599995e), U64_C (0x6d4fc4da226d6da9), U64_C (0x0d68391a650d0d34), U64_C (0xfa8335e979fafacf), U64_C (0xdfb684a369dfdf5b), U64_C (0x7ed79bfca97e7ee5), U64_C (0x243db44819242490), U64_C (0x3bc5d776fe3b3bec), U64_C (0xab313d4b9aabab96), U64_C (0xce3ed181f0cece1f), U64_C (0x1188552299111144), U64_C (0x8f0c8903838f8f06), U64_C (0x4e4a6b9c044e4e25), U64_C (0xb7d1517366b7b7e6), U64_C (0xeb0b60cbe0ebeb8b), U64_C (0x3cfdcc78c13c3cf0), U64_C (0x817cbf1ffd81813e), U64_C (0x94d4fe354094946a), U64_C (0xf7eb0cf31cf7f7fb), U64_C (0xb9a1676f18b9b9de), U64_C (0x13985f268b13134c), U64_C (0x2c7d9c58512c2cb0), U64_C (0xd3d6b8bb05d3d36b), U64_C (0xe76b5cd38ce7e7bb), U64_C (0x6e57cbdc396e6ea5), U64_C (0xc46ef395aac4c437), U64_C (0x03180f061b03030c), U64_C (0x568a13acdc565645), U64_C (0x441a49885e44440d), U64_C (0x7fdf9efea07f7fe1), U64_C (0xa921374f88a9a99e), U64_C (0x2a4d8254672a2aa8), U64_C (0xbbb16d6b0abbbbd6), U64_C (0xc146e29f87c1c123), U64_C (0x53a202a6f1535351), U64_C (0xdcae8ba572dcdc57), U64_C (0x0b582716530b0b2c), U64_C (0x9d9cd327019d9d4e), U64_C (0x6c47c1d82b6c6cad), U64_C (0x3195f562a43131c4), U64_C (0x7487b9e8f37474cd), U64_C (0xf6e309f115f6f6ff), U64_C (0x460a438c4c464605), U64_C (0xac092645a5acac8a), U64_C (0x893c970fb589891e), U64_C (0x14a04428b4141450), U64_C (0xe15b42dfbae1e1a3), U64_C (0x16b04e2ca6161658), U64_C (0x3acdd274f73a3ae8), U64_C (0x696fd0d2066969b9), U64_C (0x09482d1241090924), U64_C (0x70a7ade0d77070dd), U64_C (0xb6d954716fb6b6e2), U64_C (0xd0ceb7bd1ed0d067), U64_C (0xed3b7ec7d6eded93), U64_C (0xcc2edb85e2cccc17), U64_C (0x422a578468424215), U64_C (0x98b4c22d2c98985a), U64_C (0xa4490e55eda4a4aa), U64_C (0x285d8850752828a0), U64_C (0x5cda31b8865c5c6d), U64_C (0xf8933fed6bf8f8c7), U64_C (0x8644a411c2868622), }, { U64_C (0x6018c07830d81818), U64_C (0x8c2305af46262323), U64_C (0x3fc67ef991b8c6c6), U64_C (0x87e8136fcdfbe8e8), U64_C (0x26874ca113cb8787), U64_C (0xdab8a9626d11b8b8), U64_C (0x0401080502090101), U64_C (0x214f426e9e0d4f4f), U64_C (0xd836adee6c9b3636), U64_C (0xa2a6590451ffa6a6), U64_C (0x6fd2debdb90cd2d2), U64_C (0xf3f5fb06f70ef5f5), U64_C (0xf979ef80f2967979), U64_C (0xa16f5fcede306f6f), U64_C (0x7e91fcef3f6d9191), U64_C (0x5552aa07a4f85252), U64_C (0x9d6027fdc0476060), U64_C (0xcabc89766535bcbc), U64_C (0x569baccd2b379b9b), U64_C (0x028e048c018a8e8e), U64_C (0xb6a371155bd2a3a3), U64_C (0x300c603c186c0c0c), U64_C (0xf17bff8af6847b7b), U64_C (0xd435b5e16a803535), U64_C (0x741de8693af51d1d), U64_C (0xa7e05347ddb3e0e0), U64_C (0x7bd7f6acb321d7d7), U64_C (0x2fc25eed999cc2c2), U64_C (0xb82e6d965c432e2e), U64_C (0x314b627a96294b4b), U64_C (0xdffea321e15dfefe), U64_C (0x41578216aed55757), U64_C (0x5415a8412abd1515), U64_C (0xc1779fb6eee87777), U64_C (0xdc37a5eb6e923737), U64_C (0xb3e57b56d79ee5e5), U64_C (0x469f8cd923139f9f), U64_C (0xe7f0d317fd23f0f0), U64_C (0x354a6a7f94204a4a), U64_C (0x4fda9e95a944dada), U64_C (0x7d58fa25b0a25858), U64_C (0x03c906ca8fcfc9c9), U64_C (0xa429558d527c2929), U64_C (0x280a5022145a0a0a), U64_C (0xfeb1e14f7f50b1b1), U64_C (0xbaa0691a5dc9a0a0), U64_C (0xb16b7fdad6146b6b), U64_C (0x2e855cab17d98585), U64_C (0xcebd8173673cbdbd), U64_C (0x695dd234ba8f5d5d), U64_C (0x4010805020901010), U64_C (0xf7f4f303f507f4f4), U64_C (0x0bcb16c08bddcbcb), U64_C (0xf83eedc67cd33e3e), U64_C (0x140528110a2d0505), U64_C (0x81671fe6ce786767), U64_C (0xb7e47353d597e4e4), U64_C (0x9c2725bb4e022727), U64_C (0x1941325882734141), U64_C (0x168b2c9d0ba78b8b), U64_C (0xa6a7510153f6a7a7), U64_C (0xe97dcf94fab27d7d), U64_C (0x6e95dcfb37499595), U64_C (0x47d88e9fad56d8d8), U64_C (0xcbfb8b30eb70fbfb), U64_C (0x9fee2371c1cdeeee), U64_C (0xed7cc791f8bb7c7c), U64_C (0x856617e3cc716666), U64_C (0x53dda68ea77bdddd), U64_C (0x5c17b84b2eaf1717), U64_C (0x014702468e454747), U64_C (0x429e84dc211a9e9e), U64_C (0x0fca1ec589d4caca), U64_C (0xb42d75995a582d2d), U64_C (0xc6bf9179632ebfbf), U64_C (0x1c07381b0e3f0707), U64_C (0x8ead012347acadad), U64_C (0x755aea2fb4b05a5a), U64_C (0x36836cb51bef8383), U64_C (0xcc3385ff66b63333), U64_C (0x91633ff2c65c6363), U64_C (0x0802100a04120202), U64_C (0x92aa39384993aaaa), U64_C (0xd971afa8e2de7171), U64_C (0x07c80ecf8dc6c8c8), U64_C (0x6419c87d32d11919), U64_C (0x39497270923b4949), U64_C (0x43d9869aaf5fd9d9), U64_C (0xeff2c31df931f2f2), U64_C (0xabe34b48dba8e3e3), U64_C (0x715be22ab6b95b5b), U64_C (0x1a8834920dbc8888), U64_C (0x529aa4c8293e9a9a), U64_C (0x98262dbe4c0b2626), U64_C (0xc8328dfa64bf3232), U64_C (0xfab0e94a7d59b0b0), U64_C (0x83e91b6acff2e9e9), U64_C (0x3c0f78331e770f0f), U64_C (0x73d5e6a6b733d5d5), U64_C (0x3a8074ba1df48080), U64_C (0xc2be997c6127bebe), U64_C (0x13cd26de87ebcdcd), U64_C (0xd034bde468893434), U64_C (0x3d487a7590324848), U64_C (0xdbffab24e354ffff), U64_C (0xf57af78ff48d7a7a), U64_C (0x7a90f4ea3d649090), U64_C (0x615fc23ebe9d5f5f), U64_C (0x80201da0403d2020), U64_C (0xbd6867d5d00f6868), U64_C (0x681ad07234ca1a1a), U64_C (0x82ae192c41b7aeae), U64_C (0xeab4c95e757db4b4), U64_C (0x4d549a19a8ce5454), U64_C (0x7693ece53b7f9393), U64_C (0x88220daa442f2222), U64_C (0x8d6407e9c8636464), U64_C (0xe3f1db12ff2af1f1), U64_C (0xd173bfa2e6cc7373), U64_C (0x4812905a24821212), U64_C (0x1d403a5d807a4040), U64_C (0x2008402810480808), U64_C (0x2bc356e89b95c3c3), U64_C (0x97ec337bc5dfecec), U64_C (0x4bdb9690ab4ddbdb), U64_C (0xbea1611f5fc0a1a1), U64_C (0x0e8d1c8307918d8d), U64_C (0xf43df5c97ac83d3d), U64_C (0x6697ccf1335b9797), U64_C (0x0000000000000000), U64_C (0x1bcf36d483f9cfcf), U64_C (0xac2b4587566e2b2b), U64_C (0xc57697b3ece17676), U64_C (0x328264b019e68282), U64_C (0x7fd6fea9b128d6d6), U64_C (0x6c1bd87736c31b1b), U64_C (0xeeb5c15b7774b5b5), U64_C (0x86af112943beafaf), U64_C (0xb56a77dfd41d6a6a), U64_C (0x5d50ba0da0ea5050), U64_C (0x0945124c8a574545), U64_C (0xebf3cb18fb38f3f3), U64_C (0xc0309df060ad3030), U64_C (0x9bef2b74c3c4efef), U64_C (0xfc3fe5c37eda3f3f), U64_C (0x4955921caac75555), U64_C (0xb2a2791059dba2a2), U64_C (0x8fea0365c9e9eaea), U64_C (0x89650fecca6a6565), U64_C (0xd2bab9686903baba), U64_C (0xbc2f65935e4a2f2f), U64_C (0x27c04ee79d8ec0c0), U64_C (0x5fdebe81a160dede), U64_C (0x701ce06c38fc1c1c), U64_C (0xd3fdbb2ee746fdfd), U64_C (0x294d52649a1f4d4d), U64_C (0x7292e4e039769292), U64_C (0xc9758fbceafa7575), U64_C (0x1806301e0c360606), U64_C (0x128a249809ae8a8a), U64_C (0xf2b2f940794bb2b2), U64_C (0xbfe66359d185e6e6), U64_C (0x380e70361c7e0e0e), U64_C (0x7c1ff8633ee71f1f), U64_C (0x956237f7c4556262), U64_C (0x77d4eea3b53ad4d4), U64_C (0x9aa829324d81a8a8), U64_C (0x6296c4f431529696), U64_C (0xc3f99b3aef62f9f9), U64_C (0x33c566f697a3c5c5), U64_C (0x942535b14a102525), U64_C (0x7959f220b2ab5959), U64_C (0x2a8454ae15d08484), U64_C (0xd572b7a7e4c57272), U64_C (0xe439d5dd72ec3939), U64_C (0x2d4c5a6198164c4c), U64_C (0x655eca3bbc945e5e), U64_C (0xfd78e785f09f7878), U64_C (0xe038ddd870e53838), U64_C (0x0a8c148605988c8c), U64_C (0x63d1c6b2bf17d1d1), U64_C (0xaea5410b57e4a5a5), U64_C (0xafe2434dd9a1e2e2), U64_C (0x99612ff8c24e6161), U64_C (0xf6b3f1457b42b3b3), U64_C (0x842115a542342121), U64_C (0x4a9c94d625089c9c), U64_C (0x781ef0663cee1e1e), U64_C (0x1143225286614343), U64_C (0x3bc776fc93b1c7c7), U64_C (0xd7fcb32be54ffcfc), U64_C (0x1004201408240404), U64_C (0x5951b208a2e35151), U64_C (0x5e99bcc72f259999), U64_C (0xa96d4fc4da226d6d), U64_C (0x340d68391a650d0d), U64_C (0xcffa8335e979fafa), U64_C (0x5bdfb684a369dfdf), U64_C (0xe57ed79bfca97e7e), U64_C (0x90243db448192424), U64_C (0xec3bc5d776fe3b3b), U64_C (0x96ab313d4b9aabab), U64_C (0x1fce3ed181f0cece), U64_C (0x4411885522991111), U64_C (0x068f0c8903838f8f), U64_C (0x254e4a6b9c044e4e), U64_C (0xe6b7d1517366b7b7), U64_C (0x8beb0b60cbe0ebeb), U64_C (0xf03cfdcc78c13c3c), U64_C (0x3e817cbf1ffd8181), U64_C (0x6a94d4fe35409494), U64_C (0xfbf7eb0cf31cf7f7), U64_C (0xdeb9a1676f18b9b9), U64_C (0x4c13985f268b1313), U64_C (0xb02c7d9c58512c2c), U64_C (0x6bd3d6b8bb05d3d3), U64_C (0xbbe76b5cd38ce7e7), U64_C (0xa56e57cbdc396e6e), U64_C (0x37c46ef395aac4c4), U64_C (0x0c03180f061b0303), U64_C (0x45568a13acdc5656), U64_C (0x0d441a49885e4444), U64_C (0xe17fdf9efea07f7f), U64_C (0x9ea921374f88a9a9), U64_C (0xa82a4d8254672a2a), U64_C (0xd6bbb16d6b0abbbb), U64_C (0x23c146e29f87c1c1), U64_C (0x5153a202a6f15353), U64_C (0x57dcae8ba572dcdc), U64_C (0x2c0b582716530b0b), U64_C (0x4e9d9cd327019d9d), U64_C (0xad6c47c1d82b6c6c), U64_C (0xc43195f562a43131), U64_C (0xcd7487b9e8f37474), U64_C (0xfff6e309f115f6f6), U64_C (0x05460a438c4c4646), U64_C (0x8aac092645a5acac), U64_C (0x1e893c970fb58989), U64_C (0x5014a04428b41414), U64_C (0xa3e15b42dfbae1e1), U64_C (0x5816b04e2ca61616), U64_C (0xe83acdd274f73a3a), U64_C (0xb9696fd0d2066969), U64_C (0x2409482d12410909), U64_C (0xdd70a7ade0d77070), U64_C (0xe2b6d954716fb6b6), U64_C (0x67d0ceb7bd1ed0d0), U64_C (0x93ed3b7ec7d6eded), U64_C (0x17cc2edb85e2cccc), U64_C (0x15422a5784684242), U64_C (0x5a98b4c22d2c9898), U64_C (0xaaa4490e55eda4a4), U64_C (0xa0285d8850752828), U64_C (0x6d5cda31b8865c5c), U64_C (0xc7f8933fed6bf8f8), U64_C (0x228644a411c28686), }, { U64_C (0x186018c07830d818), U64_C (0x238c2305af462623), U64_C (0xc63fc67ef991b8c6), U64_C (0xe887e8136fcdfbe8), U64_C (0x8726874ca113cb87), U64_C (0xb8dab8a9626d11b8), U64_C (0x0104010805020901), U64_C (0x4f214f426e9e0d4f), U64_C (0x36d836adee6c9b36), U64_C (0xa6a2a6590451ffa6), U64_C (0xd26fd2debdb90cd2), U64_C (0xf5f3f5fb06f70ef5), U64_C (0x79f979ef80f29679), U64_C (0x6fa16f5fcede306f), U64_C (0x917e91fcef3f6d91), U64_C (0x525552aa07a4f852), U64_C (0x609d6027fdc04760), U64_C (0xbccabc89766535bc), U64_C (0x9b569baccd2b379b), U64_C (0x8e028e048c018a8e), U64_C (0xa3b6a371155bd2a3), U64_C (0x0c300c603c186c0c), U64_C (0x7bf17bff8af6847b), U64_C (0x35d435b5e16a8035), U64_C (0x1d741de8693af51d), U64_C (0xe0a7e05347ddb3e0), U64_C (0xd77bd7f6acb321d7), U64_C (0xc22fc25eed999cc2), U64_C (0x2eb82e6d965c432e), U64_C (0x4b314b627a96294b), U64_C (0xfedffea321e15dfe), U64_C (0x5741578216aed557), U64_C (0x155415a8412abd15), U64_C (0x77c1779fb6eee877), U64_C (0x37dc37a5eb6e9237), U64_C (0xe5b3e57b56d79ee5), U64_C (0x9f469f8cd923139f), U64_C (0xf0e7f0d317fd23f0), U64_C (0x4a354a6a7f94204a), U64_C (0xda4fda9e95a944da), U64_C (0x587d58fa25b0a258), U64_C (0xc903c906ca8fcfc9), U64_C (0x29a429558d527c29), U64_C (0x0a280a5022145a0a), U64_C (0xb1feb1e14f7f50b1), U64_C (0xa0baa0691a5dc9a0), U64_C (0x6bb16b7fdad6146b), U64_C (0x852e855cab17d985), U64_C (0xbdcebd8173673cbd), U64_C (0x5d695dd234ba8f5d), U64_C (0x1040108050209010), U64_C (0xf4f7f4f303f507f4), U64_C (0xcb0bcb16c08bddcb), U64_C (0x3ef83eedc67cd33e), U64_C (0x05140528110a2d05), U64_C (0x6781671fe6ce7867), U64_C (0xe4b7e47353d597e4), U64_C (0x279c2725bb4e0227), U64_C (0x4119413258827341), U64_C (0x8b168b2c9d0ba78b), U64_C (0xa7a6a7510153f6a7), U64_C (0x7de97dcf94fab27d), U64_C (0x956e95dcfb374995), U64_C (0xd847d88e9fad56d8), U64_C (0xfbcbfb8b30eb70fb), U64_C (0xee9fee2371c1cdee), U64_C (0x7ced7cc791f8bb7c), U64_C (0x66856617e3cc7166), U64_C (0xdd53dda68ea77bdd), U64_C (0x175c17b84b2eaf17), U64_C (0x47014702468e4547), U64_C (0x9e429e84dc211a9e), U64_C (0xca0fca1ec589d4ca), U64_C (0x2db42d75995a582d), U64_C (0xbfc6bf9179632ebf), U64_C (0x071c07381b0e3f07), U64_C (0xad8ead012347acad), U64_C (0x5a755aea2fb4b05a), U64_C (0x8336836cb51bef83), U64_C (0x33cc3385ff66b633), U64_C (0x6391633ff2c65c63), U64_C (0x020802100a041202), U64_C (0xaa92aa39384993aa), U64_C (0x71d971afa8e2de71), U64_C (0xc807c80ecf8dc6c8), U64_C (0x196419c87d32d119), U64_C (0x4939497270923b49), U64_C (0xd943d9869aaf5fd9), U64_C (0xf2eff2c31df931f2), U64_C (0xe3abe34b48dba8e3), U64_C (0x5b715be22ab6b95b), U64_C (0x881a8834920dbc88), U64_C (0x9a529aa4c8293e9a), U64_C (0x2698262dbe4c0b26), U64_C (0x32c8328dfa64bf32), U64_C (0xb0fab0e94a7d59b0), U64_C (0xe983e91b6acff2e9), U64_C (0x0f3c0f78331e770f), U64_C (0xd573d5e6a6b733d5), U64_C (0x803a8074ba1df480), U64_C (0xbec2be997c6127be), U64_C (0xcd13cd26de87ebcd), U64_C (0x34d034bde4688934), U64_C (0x483d487a75903248), U64_C (0xffdbffab24e354ff), U64_C (0x7af57af78ff48d7a), U64_C (0x907a90f4ea3d6490), U64_C (0x5f615fc23ebe9d5f), U64_C (0x2080201da0403d20), U64_C (0x68bd6867d5d00f68), U64_C (0x1a681ad07234ca1a), U64_C (0xae82ae192c41b7ae), U64_C (0xb4eab4c95e757db4), U64_C (0x544d549a19a8ce54), U64_C (0x937693ece53b7f93), U64_C (0x2288220daa442f22), U64_C (0x648d6407e9c86364), U64_C (0xf1e3f1db12ff2af1), U64_C (0x73d173bfa2e6cc73), U64_C (0x124812905a248212), U64_C (0x401d403a5d807a40), U64_C (0x0820084028104808), U64_C (0xc32bc356e89b95c3), U64_C (0xec97ec337bc5dfec), U64_C (0xdb4bdb9690ab4ddb), U64_C (0xa1bea1611f5fc0a1), U64_C (0x8d0e8d1c8307918d), U64_C (0x3df43df5c97ac83d), U64_C (0x976697ccf1335b97), U64_C (0x0000000000000000), U64_C (0xcf1bcf36d483f9cf), U64_C (0x2bac2b4587566e2b), U64_C (0x76c57697b3ece176), U64_C (0x82328264b019e682), U64_C (0xd67fd6fea9b128d6), U64_C (0x1b6c1bd87736c31b), U64_C (0xb5eeb5c15b7774b5), U64_C (0xaf86af112943beaf), U64_C (0x6ab56a77dfd41d6a), U64_C (0x505d50ba0da0ea50), U64_C (0x450945124c8a5745), U64_C (0xf3ebf3cb18fb38f3), U64_C (0x30c0309df060ad30), U64_C (0xef9bef2b74c3c4ef), U64_C (0x3ffc3fe5c37eda3f), U64_C (0x554955921caac755), U64_C (0xa2b2a2791059dba2), U64_C (0xea8fea0365c9e9ea), U64_C (0x6589650fecca6a65), U64_C (0xbad2bab9686903ba), U64_C (0x2fbc2f65935e4a2f), U64_C (0xc027c04ee79d8ec0), U64_C (0xde5fdebe81a160de), U64_C (0x1c701ce06c38fc1c), U64_C (0xfdd3fdbb2ee746fd), U64_C (0x4d294d52649a1f4d), U64_C (0x927292e4e0397692), U64_C (0x75c9758fbceafa75), U64_C (0x061806301e0c3606), U64_C (0x8a128a249809ae8a), U64_C (0xb2f2b2f940794bb2), U64_C (0xe6bfe66359d185e6), U64_C (0x0e380e70361c7e0e), U64_C (0x1f7c1ff8633ee71f), U64_C (0x62956237f7c45562), U64_C (0xd477d4eea3b53ad4), U64_C (0xa89aa829324d81a8), U64_C (0x966296c4f4315296), U64_C (0xf9c3f99b3aef62f9), U64_C (0xc533c566f697a3c5), U64_C (0x25942535b14a1025), U64_C (0x597959f220b2ab59), U64_C (0x842a8454ae15d084), U64_C (0x72d572b7a7e4c572), U64_C (0x39e439d5dd72ec39), U64_C (0x4c2d4c5a6198164c), U64_C (0x5e655eca3bbc945e), U64_C (0x78fd78e785f09f78), U64_C (0x38e038ddd870e538), U64_C (0x8c0a8c148605988c), U64_C (0xd163d1c6b2bf17d1), U64_C (0xa5aea5410b57e4a5), U64_C (0xe2afe2434dd9a1e2), U64_C (0x6199612ff8c24e61), U64_C (0xb3f6b3f1457b42b3), U64_C (0x21842115a5423421), U64_C (0x9c4a9c94d625089c), U64_C (0x1e781ef0663cee1e), U64_C (0x4311432252866143), U64_C (0xc73bc776fc93b1c7), U64_C (0xfcd7fcb32be54ffc), U64_C (0x0410042014082404), U64_C (0x515951b208a2e351), U64_C (0x995e99bcc72f2599), U64_C (0x6da96d4fc4da226d), U64_C (0x0d340d68391a650d), U64_C (0xfacffa8335e979fa), U64_C (0xdf5bdfb684a369df), U64_C (0x7ee57ed79bfca97e), U64_C (0x2490243db4481924), U64_C (0x3bec3bc5d776fe3b), U64_C (0xab96ab313d4b9aab), U64_C (0xce1fce3ed181f0ce), U64_C (0x1144118855229911), U64_C (0x8f068f0c8903838f), U64_C (0x4e254e4a6b9c044e), U64_C (0xb7e6b7d1517366b7), U64_C (0xeb8beb0b60cbe0eb), U64_C (0x3cf03cfdcc78c13c), U64_C (0x813e817cbf1ffd81), U64_C (0x946a94d4fe354094), U64_C (0xf7fbf7eb0cf31cf7), U64_C (0xb9deb9a1676f18b9), U64_C (0x134c13985f268b13), U64_C (0x2cb02c7d9c58512c), U64_C (0xd36bd3d6b8bb05d3), U64_C (0xe7bbe76b5cd38ce7), U64_C (0x6ea56e57cbdc396e), U64_C (0xc437c46ef395aac4), U64_C (0x030c03180f061b03), U64_C (0x5645568a13acdc56), U64_C (0x440d441a49885e44), U64_C (0x7fe17fdf9efea07f), U64_C (0xa99ea921374f88a9), U64_C (0x2aa82a4d8254672a), U64_C (0xbbd6bbb16d6b0abb), U64_C (0xc123c146e29f87c1), U64_C (0x535153a202a6f153), U64_C (0xdc57dcae8ba572dc), U64_C (0x0b2c0b582716530b), U64_C (0x9d4e9d9cd327019d), U64_C (0x6cad6c47c1d82b6c), U64_C (0x31c43195f562a431), U64_C (0x74cd7487b9e8f374), U64_C (0xf6fff6e309f115f6), U64_C (0x4605460a438c4c46), U64_C (0xac8aac092645a5ac), U64_C (0x891e893c970fb589), U64_C (0x145014a04428b414), U64_C (0xe1a3e15b42dfbae1), U64_C (0x165816b04e2ca616), U64_C (0x3ae83acdd274f73a), U64_C (0x69b9696fd0d20669), U64_C (0x092409482d124109), U64_C (0x70dd70a7ade0d770), U64_C (0xb6e2b6d954716fb6), U64_C (0xd067d0ceb7bd1ed0), U64_C (0xed93ed3b7ec7d6ed), U64_C (0xcc17cc2edb85e2cc), U64_C (0x4215422a57846842), U64_C (0x985a98b4c22d2c98), U64_C (0xa4aaa4490e55eda4), U64_C (0x28a0285d88507528), U64_C (0x5c6d5cda31b8865c), U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286), } } }; #define C tab.C #define C0 C[0] #define C1 C[1] #define C2 C[2] #define C3 C[3] #define C4 C[4] #define C5 C[5] #define C6 C[6] #define C7 C[7] #define rc tab.RC static unsigned int whirlpool_transform (void *ctx, const unsigned char *data, size_t nblks); static void whirlpool_init (void *ctx, unsigned int flags) { whirlpool_context_t *context = ctx; memset (context, 0, sizeof (*context)); context->bctx.blocksize_shift = _gcry_ctz(BLOCK_SIZE); context->bctx.bwrite = whirlpool_transform; if ((flags & GCRY_MD_FLAG_BUGEMU1)) { memset (&context->bugemu, 0, sizeof context->bugemu); context->use_bugemu = 1; } else context->use_bugemu = 0; } #ifdef USE_AMD64_ASM #ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16) #else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 #endif extern unsigned int _gcry_whirlpool_transform_amd64(u64 *state, const unsigned char *data, size_t nblks, const struct whirlpool_tables_s *tables) ASM_FUNC_ABI; static unsigned int whirlpool_transform (void *ctx, const unsigned char *data, size_t nblks) { whirlpool_context_t *context = ctx; return _gcry_whirlpool_transform_amd64( context->hash_state, data, nblks, &tab) + ASM_EXTRA_STACK; } #else /* USE_AMD64_ASM */ /* * Transform block. */ static unsigned int whirlpool_transform_blk (void *ctx, const unsigned char *data) { whirlpool_context_t *context = ctx; whirlpool_block_t data_block; whirlpool_block_t key; whirlpool_block_t state; whirlpool_block_t block; unsigned int r; unsigned int i; buffer_to_block (data, data_block, i); block_copy (key, context->hash_state, i); block_copy (state, context->hash_state, i); block_xor (state, data_block, i); for (r = 0; r < R; r++) { /* Compute round key K^r. */ block[0] = (C0[(key[0] >> 56) & 0xFF] ^ C1[(key[7] >> 48) & 0xFF] ^ C2[(key[6] >> 40) & 0xFF] ^ C3[(key[5] >> 32) & 0xFF] ^ C4[(key[4] >> 24) & 0xFF] ^ C5[(key[3] >> 16) & 0xFF] ^ C6[(key[2] >> 8) & 0xFF] ^ C7[(key[1] >> 0) & 0xFF] ^ rc[r]); block[1] = (C0[(key[1] >> 56) & 0xFF] ^ C1[(key[0] >> 48) & 0xFF] ^ C2[(key[7] >> 40) & 0xFF] ^ C3[(key[6] >> 32) & 0xFF] ^ C4[(key[5] >> 24) & 0xFF] ^ C5[(key[4] >> 16) & 0xFF] ^ C6[(key[3] >> 8) & 0xFF] ^ C7[(key[2] >> 0) & 0xFF]); block[2] = (C0[(key[2] >> 56) & 0xFF] ^ C1[(key[1] >> 48) & 0xFF] ^ C2[(key[0] >> 40) & 0xFF] ^ C3[(key[7] >> 32) & 0xFF] ^ C4[(key[6] >> 24) & 0xFF] ^ C5[(key[5] >> 16) & 0xFF] ^ C6[(key[4] >> 8) & 0xFF] ^ C7[(key[3] >> 0) & 0xFF]); block[3] = (C0[(key[3] >> 56) & 0xFF] ^ C1[(key[2] >> 48) & 0xFF] ^ C2[(key[1] >> 40) & 0xFF] ^ C3[(key[0] >> 32) & 0xFF] ^ C4[(key[7] >> 24) & 0xFF] ^ C5[(key[6] >> 16) & 0xFF] ^ C6[(key[5] >> 8) & 0xFF] ^ C7[(key[4] >> 0) & 0xFF]); block[4] = (C0[(key[4] >> 56) & 0xFF] ^ C1[(key[3] >> 48) & 0xFF] ^ C2[(key[2] >> 40) & 0xFF] ^ C3[(key[1] >> 32) & 0xFF] ^ C4[(key[0] >> 24) & 0xFF] ^ C5[(key[7] >> 16) & 0xFF] ^ C6[(key[6] >> 8) & 0xFF] ^ C7[(key[5] >> 0) & 0xFF]); block[5] = (C0[(key[5] >> 56) & 0xFF] ^ C1[(key[4] >> 48) & 0xFF] ^ C2[(key[3] >> 40) & 0xFF] ^ C3[(key[2] >> 32) & 0xFF] ^ C4[(key[1] >> 24) & 0xFF] ^ C5[(key[0] >> 16) & 0xFF] ^ C6[(key[7] >> 8) & 0xFF] ^ C7[(key[6] >> 0) & 0xFF]); block[6] = (C0[(key[6] >> 56) & 0xFF] ^ C1[(key[5] >> 48) & 0xFF] ^ C2[(key[4] >> 40) & 0xFF] ^ C3[(key[3] >> 32) & 0xFF] ^ C4[(key[2] >> 24) & 0xFF] ^ C5[(key[1] >> 16) & 0xFF] ^ C6[(key[0] >> 8) & 0xFF] ^ C7[(key[7] >> 0) & 0xFF]); block[7] = (C0[(key[7] >> 56) & 0xFF] ^ C1[(key[6] >> 48) & 0xFF] ^ C2[(key[5] >> 40) & 0xFF] ^ C3[(key[4] >> 32) & 0xFF] ^ C4[(key[3] >> 24) & 0xFF] ^ C5[(key[2] >> 16) & 0xFF] ^ C6[(key[1] >> 8) & 0xFF] ^ C7[(key[0] >> 0) & 0xFF]); block_copy (key, block, i); /* Apply r-th round transformation. */ block[0] = (C0[(state[0] >> 56) & 0xFF] ^ C1[(state[7] >> 48) & 0xFF] ^ C2[(state[6] >> 40) & 0xFF] ^ C3[(state[5] >> 32) & 0xFF] ^ C4[(state[4] >> 24) & 0xFF] ^ C5[(state[3] >> 16) & 0xFF] ^ C6[(state[2] >> 8) & 0xFF] ^ C7[(state[1] >> 0) & 0xFF] ^ key[0]); block[1] = (C0[(state[1] >> 56) & 0xFF] ^ C1[(state[0] >> 48) & 0xFF] ^ C2[(state[7] >> 40) & 0xFF] ^ C3[(state[6] >> 32) & 0xFF] ^ C4[(state[5] >> 24) & 0xFF] ^ C5[(state[4] >> 16) & 0xFF] ^ C6[(state[3] >> 8) & 0xFF] ^ C7[(state[2] >> 0) & 0xFF] ^ key[1]); block[2] = (C0[(state[2] >> 56) & 0xFF] ^ C1[(state[1] >> 48) & 0xFF] ^ C2[(state[0] >> 40) & 0xFF] ^ C3[(state[7] >> 32) & 0xFF] ^ C4[(state[6] >> 24) & 0xFF] ^ C5[(state[5] >> 16) & 0xFF] ^ C6[(state[4] >> 8) & 0xFF] ^ C7[(state[3] >> 0) & 0xFF] ^ key[2]); block[3] = (C0[(state[3] >> 56) & 0xFF] ^ C1[(state[2] >> 48) & 0xFF] ^ C2[(state[1] >> 40) & 0xFF] ^ C3[(state[0] >> 32) & 0xFF] ^ C4[(state[7] >> 24) & 0xFF] ^ C5[(state[6] >> 16) & 0xFF] ^ C6[(state[5] >> 8) & 0xFF] ^ C7[(state[4] >> 0) & 0xFF] ^ key[3]); block[4] = (C0[(state[4] >> 56) & 0xFF] ^ C1[(state[3] >> 48) & 0xFF] ^ C2[(state[2] >> 40) & 0xFF] ^ C3[(state[1] >> 32) & 0xFF] ^ C4[(state[0] >> 24) & 0xFF] ^ C5[(state[7] >> 16) & 0xFF] ^ C6[(state[6] >> 8) & 0xFF] ^ C7[(state[5] >> 0) & 0xFF] ^ key[4]); block[5] = (C0[(state[5] >> 56) & 0xFF] ^ C1[(state[4] >> 48) & 0xFF] ^ C2[(state[3] >> 40) & 0xFF] ^ C3[(state[2] >> 32) & 0xFF] ^ C4[(state[1] >> 24) & 0xFF] ^ C5[(state[0] >> 16) & 0xFF] ^ C6[(state[7] >> 8) & 0xFF] ^ C7[(state[6] >> 0) & 0xFF] ^ key[5]); block[6] = (C0[(state[6] >> 56) & 0xFF] ^ C1[(state[5] >> 48) & 0xFF] ^ C2[(state[4] >> 40) & 0xFF] ^ C3[(state[3] >> 32) & 0xFF] ^ C4[(state[2] >> 24) & 0xFF] ^ C5[(state[1] >> 16) & 0xFF] ^ C6[(state[0] >> 8) & 0xFF] ^ C7[(state[7] >> 0) & 0xFF] ^ key[6]); block[7] = (C0[(state[7] >> 56) & 0xFF] ^ C1[(state[6] >> 48) & 0xFF] ^ C2[(state[5] >> 40) & 0xFF] ^ C3[(state[4] >> 32) & 0xFF] ^ C4[(state[3] >> 24) & 0xFF] ^ C5[(state[2] >> 16) & 0xFF] ^ C6[(state[1] >> 8) & 0xFF] ^ C7[(state[0] >> 0) & 0xFF] ^ key[7]); block_copy (state, block, i); } /* Compression. */ block_xor (context->hash_state, data_block, i); block_xor (context->hash_state, state, i); return /*burn_stack*/ 4 * sizeof(whirlpool_block_t) + 2 * sizeof(int) + 4 * sizeof(void*); } static unsigned int whirlpool_transform ( void *c, const unsigned char *data, size_t nblks ) { unsigned int burn; do { burn = whirlpool_transform_blk (c, data); data += BLOCK_SIZE; } while (--nblks); return burn; } #endif /* !USE_AMD64_ASM */ /* Bug compatibility Whirlpool version. */ static void whirlpool_add_bugemu (whirlpool_context_t *context, const void *buffer_arg, size_t buffer_n) { const unsigned char *buffer = buffer_arg; u64 buffer_size; unsigned int carry; unsigned int i; buffer_size = buffer_n; if (context->bugemu.count == BLOCK_SIZE) { /* Flush the buffer. */ whirlpool_transform (context, context->bctx.buf, 1); context->bugemu.count = 0; } if (! buffer) return; /* Nothing to add. */ if (context->bugemu.count) { while (buffer_n && (context->bugemu.count < BLOCK_SIZE)) { context->bctx.buf[context->bugemu.count++] = *buffer++; buffer_n--; } whirlpool_add_bugemu (context, NULL, 0); if (!buffer_n) return; /* Done. This is the bug we emulate. */ } while (buffer_n >= BLOCK_SIZE) { whirlpool_transform (context, buffer, 1); context->bugemu.count = 0; buffer_n -= BLOCK_SIZE; buffer += BLOCK_SIZE; } while (buffer_n && (context->bugemu.count < BLOCK_SIZE)) { context->bctx.buf[context->bugemu.count++] = *buffer++; buffer_n--; } /* Update bit counter. */ carry = 0; buffer_size <<= 3; for (i = 1; i <= 32; i++) { if (! (buffer_size || carry)) break; carry += context->bugemu.length[32 - i] + (buffer_size & 0xFF); context->bugemu.length[32 - i] = carry; buffer_size >>= 8; carry >>= 8; } gcry_assert (! (buffer_size || carry)); } /* Bug compatibility Whirlpool version. */ static void whirlpool_final_bugemu (void *ctx) { whirlpool_context_t *context = ctx; unsigned int i; /* Flush. */ whirlpool_add_bugemu (context, NULL, 0); /* Pad. */ context->bctx.buf[context->bugemu.count++] = 0x80; if (context->bugemu.count > 32) { /* An extra block is necessary. */ while (context->bugemu.count < 64) context->bctx.buf[context->bugemu.count++] = 0; whirlpool_add_bugemu (context, NULL, 0); } while (context->bugemu.count < 32) context->bctx.buf[context->bugemu.count++] = 0; /* Add length of message. */ memcpy (context->bctx.buf + context->bugemu.count, context->bugemu.length, 32); context->bugemu.count += 32; whirlpool_add_bugemu (context, NULL, 0); block_to_buffer (context->bctx.buf, context->hash_state, i); } static void whirlpool_write (void *ctx, const void *buffer, size_t buffer_n) { whirlpool_context_t *context = ctx; if (context->use_bugemu) { whirlpool_add_bugemu (context, buffer, buffer_n); } else { u64 old_nblocks = context->bctx.nblocks; _gcry_md_block_write (context, buffer, buffer_n); gcry_assert (old_nblocks <= context->bctx.nblocks); } } static void whirlpool_final (void *ctx) { whirlpool_context_t *context = ctx; unsigned int i; u64 t, th, lsb, msb; unsigned char *length; if (context->use_bugemu) { whirlpool_final_bugemu (ctx); return; } t = context->bctx.nblocks; /* if (sizeof t == sizeof context->bctx.nblocks) */ th = context->bctx.nblocks_high; /* else */ /* th = context->bctx.nblocks >> 64; In case we ever use u128 */ /* multiply by 64 to make a byte count */ lsb = t << 6; msb = (th << 6) | (t >> 58); /* add the count */ t = lsb; if ((lsb += context->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 61; /* Flush. */ whirlpool_write (context, NULL, 0); /* Pad. */ context->bctx.buf[context->bctx.count++] = 0x80; if (context->bctx.count > 32) { /* An extra block is necessary. */ if (context->bctx.count < 64) memset (&context->bctx.buf[context->bctx.count], 0, 64 - context->bctx.count); context->bctx.count = 64; whirlpool_write (context, NULL, 0); } if (context->bctx.count < 32) memset (&context->bctx.buf[context->bctx.count], 0, 32 - context->bctx.count); context->bctx.count = 32; /* Add length of message. */ length = context->bctx.buf + context->bctx.count; buf_put_be64(&length[0 * 8], 0); buf_put_be64(&length[1 * 8], 0); buf_put_be64(&length[2 * 8], msb); buf_put_be64(&length[3 * 8], lsb); context->bctx.count += 32; whirlpool_write (context, NULL, 0); block_to_buffer (context->bctx.buf, context->hash_state, i); } static byte * whirlpool_read (void *ctx) { whirlpool_context_t *context = ctx; return context->bctx.buf; } -gcry_md_spec_t _gcry_digest_spec_whirlpool = +const gcry_md_spec_t _gcry_digest_spec_whirlpool = { GCRY_MD_WHIRLPOOL, {0, 0}, "WHIRLPOOL", NULL, 0, NULL, 64, whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, NULL, NULL, sizeof (whirlpool_context_t) }; diff --git a/src/cipher-proto.h b/src/cipher-proto.h index b730fd06..36729165 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -1,276 +1,276 @@ /* cipher-proto.h - Internal declarations * Copyright (C) 2008, 2011 Free Software Foundation, Inc. * * 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 . */ /* This file has been factored out from cipher.h so that it can be used standalone in visibility.c . */ #ifndef G10_CIPHER_PROTO_H #define G10_CIPHER_PROTO_H enum pk_encoding; /* Definition of a function used to report selftest failures. DOMAIN is a string describing the function block: "cipher", "digest", "pubkey or "random", ALGO is the algorithm under test, WHAT is a string describing what has been tested, DESC is a string describing the error. */ typedef void (*selftest_report_func_t)(const char *domain, int algo, const char *what, const char *errdesc); /* Definition of the selftest functions. */ typedef gpg_err_code_t (*selftest_func_t) (int algo, int extended, selftest_report_func_t report); /* * * Public key related definitions. * */ /* Type for the pk_generate function. */ typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms, gcry_sexp_t *r_skey); /* Type for the pk_check_secret_key function. */ typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms); /* Type for the pk_encrypt function. */ typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_decrypt function. */ typedef gcry_err_code_t (*gcry_pk_decrypt_t) (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_sign function. */ typedef gcry_err_code_t (*gcry_pk_sign_t) (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_verify function. */ typedef gcry_err_code_t (*gcry_pk_verify_t) (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_get_nbits function. */ typedef unsigned (*gcry_pk_get_nbits_t) (gcry_sexp_t keyparms); /* The type used to compute the keygrip. */ typedef gpg_err_code_t (*pk_comp_keygrip_t) (gcry_md_hd_t md, gcry_sexp_t keyparm); /* The type used to query an ECC curve name. */ typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits); /* The type used to query ECC curve parameters by name. */ typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); /* Module specification structure for public key algorithms. */ typedef struct gcry_pk_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; int use; const char *name; const char **aliases; const char *elements_pkey; const char *elements_skey; const char *elements_enc; const char *elements_sig; const char *elements_grip; gcry_pk_generate_t generate; gcry_pk_check_secret_key_t check_secret_key; gcry_pk_encrypt_t encrypt; gcry_pk_decrypt_t decrypt; gcry_pk_sign_t sign; gcry_pk_verify_t verify; gcry_pk_get_nbits_t get_nbits; selftest_func_t selftest; pk_comp_keygrip_t comp_keygrip; pk_get_curve_t get_curve; pk_get_curve_param_t get_curve_param; } gcry_pk_spec_t; /* * * Symmetric cipher related definitions. * */ struct cipher_bulk_ops; /* Type for the cipher_setkey function. */ typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c, const unsigned char *key, unsigned keylen, struct cipher_bulk_ops *bulk_ops); /* Type for the cipher_encrypt function. */ typedef unsigned int (*gcry_cipher_encrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf); /* Type for the cipher_decrypt function. */ typedef unsigned int (*gcry_cipher_decrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf); /* Type for the cipher_stencrypt function. */ typedef void (*gcry_cipher_stencrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, size_t n); /* Type for the cipher_stdecrypt function. */ typedef void (*gcry_cipher_stdecrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, size_t n); /* The type used to convey additional information to a cipher. */ typedef gpg_err_code_t (*cipher_set_extra_info_t) (void *c, int what, const void *buffer, size_t buflen); /* The type used to set an IV directly in the algorithm module. */ typedef void (*cipher_setiv_func_t)(void *c, const byte *iv, size_t ivlen); /* A structure to map OIDs to encryption modes. */ typedef struct gcry_cipher_oid_spec { const char *oid; int mode; } gcry_cipher_oid_spec_t; /* Module specification structure for ciphers. */ typedef struct gcry_cipher_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; const char **aliases; - gcry_cipher_oid_spec_t *oids; + const gcry_cipher_oid_spec_t *oids; size_t blocksize; size_t keylen; size_t contextsize; gcry_cipher_setkey_t setkey; gcry_cipher_encrypt_t encrypt; gcry_cipher_decrypt_t decrypt; gcry_cipher_stencrypt_t stencrypt; gcry_cipher_stdecrypt_t stdecrypt; selftest_func_t selftest; cipher_set_extra_info_t set_extra_info; cipher_setiv_func_t setiv; } gcry_cipher_spec_t; /* * * Message digest related definitions. * */ /* Type for the md_init function. */ typedef void (*gcry_md_init_t) (void *c, unsigned int flags); /* Type for the md_write function. */ typedef void (*gcry_md_write_t) (void *c, const void *buf, size_t nbytes); /* Type for the md_final function. */ typedef void (*gcry_md_final_t) (void *c); /* Type for the md_read function. */ typedef unsigned char *(*gcry_md_read_t) (void *c); /* Type for the md_extract function. */ typedef void (*gcry_md_extract_t) (void *c, void *outbuf, size_t nbytes); /* Type for the md_hash_buffers function. */ typedef void (*gcry_md_hash_buffers_t) (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, int iovcnt); typedef struct gcry_md_oid_spec { const char *oidstring; } gcry_md_oid_spec_t; /* Module specification structure for message digests. */ typedef struct gcry_md_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; - unsigned char *asnoid; + const unsigned char *asnoid; int asnlen; - gcry_md_oid_spec_t *oids; + const gcry_md_oid_spec_t *oids; int mdlen; gcry_md_init_t init; gcry_md_write_t write; gcry_md_final_t final; gcry_md_read_t read; gcry_md_extract_t extract; gcry_md_hash_buffers_t hash_buffers; size_t contextsize; /* allocate this amount of context */ selftest_func_t selftest; } gcry_md_spec_t; /* The selftest functions. */ gcry_error_t _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_md_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_mac_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_kdf_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_random_selftest (selftest_report_func_t report); #endif /*G10_CIPHER_PROTO_H*/ diff --git a/src/cipher.h b/src/cipher.h index 2efe00fa..87f8c4d0 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -1,220 +1,220 @@ /* cipher.h * Copyright (C) 1998, 2002, 2003, 2009 Free Software Foundation, Inc. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef G10_CIPHER_H #define G10_CIPHER_H #include "gcrypt-int.h" #define DBG_CIPHER _gcry_get_debug_flag( 1 ) #include "../random/random.h" #define PUBKEY_FLAG_NO_BLINDING (1 << 0) #define PUBKEY_FLAG_RFC6979 (1 << 1) #define PUBKEY_FLAG_FIXEDLEN (1 << 2) #define PUBKEY_FLAG_LEGACYRESULT (1 << 3) #define PUBKEY_FLAG_RAW_FLAG (1 << 4) #define PUBKEY_FLAG_TRANSIENT_KEY (1 << 5) #define PUBKEY_FLAG_USE_X931 (1 << 6) #define PUBKEY_FLAG_USE_FIPS186 (1 << 7) #define PUBKEY_FLAG_USE_FIPS186_2 (1 << 8) #define PUBKEY_FLAG_PARAM (1 << 9) #define PUBKEY_FLAG_COMP (1 << 10) #define PUBKEY_FLAG_NOCOMP (1 << 11) #define PUBKEY_FLAG_EDDSA (1 << 12) #define PUBKEY_FLAG_GOST (1 << 13) #define PUBKEY_FLAG_NO_KEYTEST (1 << 14) #define PUBKEY_FLAG_DJB_TWEAK (1 << 15) #define PUBKEY_FLAG_SM2 (1 << 16) #define PUBKEY_FLAG_PREHASH (1 << 17) enum pk_operation { PUBKEY_OP_ENCRYPT, PUBKEY_OP_DECRYPT, PUBKEY_OP_SIGN, PUBKEY_OP_VERIFY }; enum pk_encoding { PUBKEY_ENC_RAW, PUBKEY_ENC_PKCS1, PUBKEY_ENC_PKCS1_RAW, PUBKEY_ENC_OAEP, PUBKEY_ENC_PSS, PUBKEY_ENC_UNKNOWN }; struct pk_encoding_ctx { enum pk_operation op; unsigned int nbits; enum pk_encoding encoding; int flags; int hash_algo; /* for OAEP */ unsigned char *label; size_t labellen; /* for PSS */ size_t saltlen; int (* verify_cmp) (void *opaque, gcry_mpi_t tmp); void *verify_arg; }; #define CIPHER_INFO_NO_WEAK_KEY 1 #include "cipher-proto.h" /* The internal encryption modes. */ enum gcry_cipher_internal_modes { GCRY_CIPHER_MODE_INTERNAL = 0x10000, GCRY_CIPHER_MODE_CMAC = 0x10000 + 1 /* Cipher-based MAC. */ }; /*-- cipher.c --*/ gcry_err_code_t _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags); /*-- cipher-cmac.c --*/ gcry_err_code_t _gcry_cipher_cmac_authenticate /* */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen); gcry_err_code_t _gcry_cipher_cmac_get_tag /* */ (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen); gcry_err_code_t _gcry_cipher_cmac_check_tag /* */ (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen); gcry_err_code_t _gcry_cipher_cmac_set_subkeys /* */ (gcry_cipher_hd_t c); /*-- sha1.c --*/ void _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length); /*-- blake2.c --*/ gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags, const unsigned char *key, size_t keylen, int algo); /*-- dsa.c --*/ void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data); /*-- elgamal.c --*/ void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb, void *cb_data); /*-- ecc.c --*/ void _gcry_register_pk_ecc_progress (gcry_handler_progress_t cbc, void *cb_data); /*-- primegen.c --*/ void _gcry_register_primegen_progress (gcry_handler_progress_t cb, void *cb_data); /*-- pubkey.c --*/ /* Declarations for the cipher specifications. */ extern gcry_cipher_spec_t _gcry_cipher_spec_blowfish; extern gcry_cipher_spec_t _gcry_cipher_spec_des; extern gcry_cipher_spec_t _gcry_cipher_spec_tripledes; extern gcry_cipher_spec_t _gcry_cipher_spec_arcfour; extern gcry_cipher_spec_t _gcry_cipher_spec_cast5; extern gcry_cipher_spec_t _gcry_cipher_spec_aes; extern gcry_cipher_spec_t _gcry_cipher_spec_aes192; extern gcry_cipher_spec_t _gcry_cipher_spec_aes256; extern gcry_cipher_spec_t _gcry_cipher_spec_twofish; extern gcry_cipher_spec_t _gcry_cipher_spec_twofish128; extern gcry_cipher_spec_t _gcry_cipher_spec_serpent128; extern gcry_cipher_spec_t _gcry_cipher_spec_serpent192; extern gcry_cipher_spec_t _gcry_cipher_spec_serpent256; extern gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40; extern gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_128; extern gcry_cipher_spec_t _gcry_cipher_spec_seed; extern gcry_cipher_spec_t _gcry_cipher_spec_camellia128; extern gcry_cipher_spec_t _gcry_cipher_spec_camellia192; extern gcry_cipher_spec_t _gcry_cipher_spec_camellia256; extern gcry_cipher_spec_t _gcry_cipher_spec_idea; extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20; extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12; extern gcry_cipher_spec_t _gcry_cipher_spec_gost28147; extern gcry_cipher_spec_t _gcry_cipher_spec_gost28147_mesh; extern gcry_cipher_spec_t _gcry_cipher_spec_chacha20; extern gcry_cipher_spec_t _gcry_cipher_spec_sm4; /* Declarations for the digest specifications. */ -extern gcry_md_spec_t _gcry_digest_spec_crc32; -extern gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510; -extern gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440; -extern gcry_md_spec_t _gcry_digest_spec_gost3411_94; -extern gcry_md_spec_t _gcry_digest_spec_gost3411_cp; -extern gcry_md_spec_t _gcry_digest_spec_stribog_256; -extern gcry_md_spec_t _gcry_digest_spec_stribog_512; -extern gcry_md_spec_t _gcry_digest_spec_md2; -extern gcry_md_spec_t _gcry_digest_spec_md4; -extern gcry_md_spec_t _gcry_digest_spec_md5; -extern gcry_md_spec_t _gcry_digest_spec_rmd160; -extern gcry_md_spec_t _gcry_digest_spec_sha1; -extern gcry_md_spec_t _gcry_digest_spec_sha224; -extern gcry_md_spec_t _gcry_digest_spec_sha256; -extern gcry_md_spec_t _gcry_digest_spec_sha384; -extern gcry_md_spec_t _gcry_digest_spec_sha512; -extern gcry_md_spec_t _gcry_digest_spec_sha512_224; -extern gcry_md_spec_t _gcry_digest_spec_sha512_256; -extern gcry_md_spec_t _gcry_digest_spec_sha3_224; -extern gcry_md_spec_t _gcry_digest_spec_sha3_256; -extern gcry_md_spec_t _gcry_digest_spec_sha3_512; -extern gcry_md_spec_t _gcry_digest_spec_sha3_384; -extern gcry_md_spec_t _gcry_digest_spec_shake128; -extern gcry_md_spec_t _gcry_digest_spec_shake256; -extern gcry_md_spec_t _gcry_digest_spec_tiger; -extern gcry_md_spec_t _gcry_digest_spec_tiger1; -extern gcry_md_spec_t _gcry_digest_spec_tiger2; -extern gcry_md_spec_t _gcry_digest_spec_whirlpool; -extern gcry_md_spec_t _gcry_digest_spec_blake2b_512; -extern gcry_md_spec_t _gcry_digest_spec_blake2b_384; -extern gcry_md_spec_t _gcry_digest_spec_blake2b_256; -extern gcry_md_spec_t _gcry_digest_spec_blake2b_160; -extern gcry_md_spec_t _gcry_digest_spec_blake2s_256; -extern gcry_md_spec_t _gcry_digest_spec_blake2s_224; -extern gcry_md_spec_t _gcry_digest_spec_blake2s_160; -extern gcry_md_spec_t _gcry_digest_spec_blake2s_128; -extern gcry_md_spec_t _gcry_digest_spec_sm3; +extern const gcry_md_spec_t _gcry_digest_spec_crc32; +extern const gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510; +extern const gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440; +extern const gcry_md_spec_t _gcry_digest_spec_gost3411_94; +extern const gcry_md_spec_t _gcry_digest_spec_gost3411_cp; +extern const gcry_md_spec_t _gcry_digest_spec_stribog_256; +extern const gcry_md_spec_t _gcry_digest_spec_stribog_512; +extern const gcry_md_spec_t _gcry_digest_spec_md2; +extern const gcry_md_spec_t _gcry_digest_spec_md4; +extern const gcry_md_spec_t _gcry_digest_spec_md5; +extern const gcry_md_spec_t _gcry_digest_spec_rmd160; +extern const gcry_md_spec_t _gcry_digest_spec_sha1; +extern const gcry_md_spec_t _gcry_digest_spec_sha224; +extern const gcry_md_spec_t _gcry_digest_spec_sha256; +extern const gcry_md_spec_t _gcry_digest_spec_sha384; +extern const gcry_md_spec_t _gcry_digest_spec_sha512; +extern const gcry_md_spec_t _gcry_digest_spec_sha512_224; +extern const gcry_md_spec_t _gcry_digest_spec_sha512_256; +extern const gcry_md_spec_t _gcry_digest_spec_sha3_224; +extern const gcry_md_spec_t _gcry_digest_spec_sha3_256; +extern const gcry_md_spec_t _gcry_digest_spec_sha3_512; +extern const gcry_md_spec_t _gcry_digest_spec_sha3_384; +extern const gcry_md_spec_t _gcry_digest_spec_shake128; +extern const gcry_md_spec_t _gcry_digest_spec_shake256; +extern const gcry_md_spec_t _gcry_digest_spec_tiger; +extern const gcry_md_spec_t _gcry_digest_spec_tiger1; +extern const gcry_md_spec_t _gcry_digest_spec_tiger2; +extern const gcry_md_spec_t _gcry_digest_spec_whirlpool; +extern const gcry_md_spec_t _gcry_digest_spec_blake2b_512; +extern const gcry_md_spec_t _gcry_digest_spec_blake2b_384; +extern const gcry_md_spec_t _gcry_digest_spec_blake2b_256; +extern const gcry_md_spec_t _gcry_digest_spec_blake2b_160; +extern const gcry_md_spec_t _gcry_digest_spec_blake2s_256; +extern const gcry_md_spec_t _gcry_digest_spec_blake2s_224; +extern const gcry_md_spec_t _gcry_digest_spec_blake2s_160; +extern const gcry_md_spec_t _gcry_digest_spec_blake2s_128; +extern const gcry_md_spec_t _gcry_digest_spec_sm3; /* Declarations for the pubkey cipher specifications. */ extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; extern gcry_pk_spec_t _gcry_pubkey_spec_elg; extern gcry_pk_spec_t _gcry_pubkey_spec_elg_e; extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; extern gcry_pk_spec_t _gcry_pubkey_spec_ecc; #endif /*G10_CIPHER_H*/