linux/crypto/blake2b_generic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0-only OR Apache-2.0)
   2/*
   3 * Generic implementation of the BLAKE2b digest algorithm.  Based on the BLAKE2b
   4 * reference implementation, but it has been heavily modified for use in the
   5 * kernel.  The reference implementation was:
   6 *
   7 *      Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under
   8 *      the terms of the CC0, the OpenSSL Licence, or the Apache Public License
   9 *      2.0, at your option.  The terms of these licenses can be found at:
  10 *
  11 *      - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
  12 *      - OpenSSL license   : https://www.openssl.org/source/license.html
  13 *      - Apache 2.0        : https://www.apache.org/licenses/LICENSE-2.0
  14 *
  15 * More information about BLAKE2 can be found at https://blake2.net.
  16 */
  17
  18#include <asm/unaligned.h>
  19#include <linux/module.h>
  20#include <linux/kernel.h>
  21#include <linux/bitops.h>
  22#include <crypto/internal/blake2b.h>
  23#include <crypto/internal/hash.h>
  24
  25static const u8 blake2b_sigma[12][16] = {
  26        {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },
  27        { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 },
  28        { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 },
  29        {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 },
  30        {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 },
  31        {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 },
  32        { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 },
  33        { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 },
  34        {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 },
  35        { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0 },
  36        {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },
  37        { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
  38};
  39
  40static void blake2b_increment_counter(struct blake2b_state *S, const u64 inc)
  41{
  42        S->t[0] += inc;
  43        S->t[1] += (S->t[0] < inc);
  44}
  45
  46#define G(r,i,a,b,c,d)                                  \
  47        do {                                            \
  48                a = a + b + m[blake2b_sigma[r][2*i+0]]; \
  49                d = ror64(d ^ a, 32);                   \
  50                c = c + d;                              \
  51                b = ror64(b ^ c, 24);                   \
  52                a = a + b + m[blake2b_sigma[r][2*i+1]]; \
  53                d = ror64(d ^ a, 16);                   \
  54                c = c + d;                              \
  55                b = ror64(b ^ c, 63);                   \
  56        } while (0)
  57
  58#define ROUND(r)                                \
  59        do {                                    \
  60                G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
  61                G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
  62                G(r,2,v[ 2],v[ 6],v[10],v[14]); \
  63                G(r,3,v[ 3],v[ 7],v[11],v[15]); \
  64                G(r,4,v[ 0],v[ 5],v[10],v[15]); \
  65                G(r,5,v[ 1],v[ 6],v[11],v[12]); \
  66                G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
  67                G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
  68        } while (0)
  69
  70static void blake2b_compress_one_generic(struct blake2b_state *S,
  71                                         const u8 block[BLAKE2B_BLOCK_SIZE])
  72{
  73        u64 m[16];
  74        u64 v[16];
  75        size_t i;
  76
  77        for (i = 0; i < 16; ++i)
  78                m[i] = get_unaligned_le64(block + i * sizeof(m[i]));
  79
  80        for (i = 0; i < 8; ++i)
  81                v[i] = S->h[i];
  82
  83        v[ 8] = BLAKE2B_IV0;
  84        v[ 9] = BLAKE2B_IV1;
  85        v[10] = BLAKE2B_IV2;
  86        v[11] = BLAKE2B_IV3;
  87        v[12] = BLAKE2B_IV4 ^ S->t[0];
  88        v[13] = BLAKE2B_IV5 ^ S->t[1];
  89        v[14] = BLAKE2B_IV6 ^ S->f[0];
  90        v[15] = BLAKE2B_IV7 ^ S->f[1];
  91
  92        ROUND(0);
  93        ROUND(1);
  94        ROUND(2);
  95        ROUND(3);
  96        ROUND(4);
  97        ROUND(5);
  98        ROUND(6);
  99        ROUND(7);
 100        ROUND(8);
 101        ROUND(9);
 102        ROUND(10);
 103        ROUND(11);
 104#ifdef CONFIG_CC_IS_CLANG
 105#pragma nounroll /* https://bugs.llvm.org/show_bug.cgi?id=45803 */
 106#endif
 107        for (i = 0; i < 8; ++i)
 108                S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
 109}
 110
 111#undef G
 112#undef ROUND
 113
 114void blake2b_compress_generic(struct blake2b_state *state,
 115                              const u8 *block, size_t nblocks, u32 inc)
 116{
 117        do {
 118                blake2b_increment_counter(state, inc);
 119                blake2b_compress_one_generic(state, block);
 120                block += BLAKE2B_BLOCK_SIZE;
 121        } while (--nblocks);
 122}
 123EXPORT_SYMBOL(blake2b_compress_generic);
 124
 125static int crypto_blake2b_update_generic(struct shash_desc *desc,
 126                                         const u8 *in, unsigned int inlen)
 127{
 128        return crypto_blake2b_update(desc, in, inlen, blake2b_compress_generic);
 129}
 130
 131static int crypto_blake2b_final_generic(struct shash_desc *desc, u8 *out)
 132{
 133        return crypto_blake2b_final(desc, out, blake2b_compress_generic);
 134}
 135
 136#define BLAKE2B_ALG(name, driver_name, digest_size)                     \
 137        {                                                               \
 138                .base.cra_name          = name,                         \
 139                .base.cra_driver_name   = driver_name,                  \
 140                .base.cra_priority      = 100,                          \
 141                .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,      \
 142                .base.cra_blocksize     = BLAKE2B_BLOCK_SIZE,           \
 143                .base.cra_ctxsize       = sizeof(struct blake2b_tfm_ctx), \
 144                .base.cra_module        = THIS_MODULE,                  \
 145                .digestsize             = digest_size,                  \
 146                .setkey                 = crypto_blake2b_setkey,        \
 147                .init                   = crypto_blake2b_init,          \
 148                .update                 = crypto_blake2b_update_generic, \
 149                .final                  = crypto_blake2b_final_generic, \
 150                .descsize               = sizeof(struct blake2b_state), \
 151        }
 152
 153static struct shash_alg blake2b_algs[] = {
 154        BLAKE2B_ALG("blake2b-160", "blake2b-160-generic",
 155                    BLAKE2B_160_HASH_SIZE),
 156        BLAKE2B_ALG("blake2b-256", "blake2b-256-generic",
 157                    BLAKE2B_256_HASH_SIZE),
 158        BLAKE2B_ALG("blake2b-384", "blake2b-384-generic",
 159                    BLAKE2B_384_HASH_SIZE),
 160        BLAKE2B_ALG("blake2b-512", "blake2b-512-generic",
 161                    BLAKE2B_512_HASH_SIZE),
 162};
 163
 164static int __init blake2b_mod_init(void)
 165{
 166        return crypto_register_shashes(blake2b_algs, ARRAY_SIZE(blake2b_algs));
 167}
 168
 169static void __exit blake2b_mod_fini(void)
 170{
 171        crypto_unregister_shashes(blake2b_algs, ARRAY_SIZE(blake2b_algs));
 172}
 173
 174subsys_initcall(blake2b_mod_init);
 175module_exit(blake2b_mod_fini);
 176
 177MODULE_AUTHOR("David Sterba <kdave@kernel.org>");
 178MODULE_DESCRIPTION("BLAKE2b generic implementation");
 179MODULE_LICENSE("GPL");
 180MODULE_ALIAS_CRYPTO("blake2b-160");
 181MODULE_ALIAS_CRYPTO("blake2b-160-generic");
 182MODULE_ALIAS_CRYPTO("blake2b-256");
 183MODULE_ALIAS_CRYPTO("blake2b-256-generic");
 184MODULE_ALIAS_CRYPTO("blake2b-384");
 185MODULE_ALIAS_CRYPTO("blake2b-384-generic");
 186MODULE_ALIAS_CRYPTO("blake2b-512");
 187MODULE_ALIAS_CRYPTO("blake2b-512-generic");
 188
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.