add support for BLAKE2b and BLAKE2s hash sums

benchmark results:
********* Start testing of tst_qcryptographichash *********
Config: Using QTest library 4.12.0, Katie 4.12.0
PASS  : tst_qcryptographichash::initTestCase()
RESULT   : tst_qcryptographichash::append():"10 (Md5)":
     0.00275 msecs per iteration (total: 551, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"100 (Md5)":
     0.000625 msecs per iteration (total: 125, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"250 (Md5)":
     0.000570 msecs per iteration (total: 114, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"500 (Md5)":
     0.000550 msecs per iteration (total: 110, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"10 (Sha1)":
     0.00327 msecs per iteration (total: 655, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"100 (Sha1)":
     0.00106 msecs per iteration (total: 212, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"250 (Sha1)":
     0.00131 msecs per iteration (total: 262, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"500 (Sha1)":
     0.00133 msecs per iteration (total: 267, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"10 (Sha256)":
     0.00467 msecs per iteration (total: 934, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"100 (Sha256)":
     0.000895 msecs per iteration (total: 179, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"250 (Sha256)":
     0.000850 msecs per iteration (total: 170, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"500 (Sha256)":
     0.000825 msecs per iteration (total: 165, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"10 (Sha512)":
     0.00361 msecs per iteration (total: 723, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"100 (Sha512)":
     0.00105 msecs per iteration (total: 211, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"250 (Sha512)":
     0.000995 msecs per iteration (total: 199, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"500 (Sha512)":
     0.000980 msecs per iteration (total: 196, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"10 (BLAKE2b)":
     0.00278 msecs per iteration (total: 557, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"100 (BLAKE2b)":
     0.000740 msecs per iteration (total: 148, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"250 (BLAKE2b)":
     0.000690 msecs per iteration (total: 138, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"500 (BLAKE2b)":
     0.000650 msecs per iteration (total: 130, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"10 (BLAKE2s)":
     0.00335 msecs per iteration (total: 670, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"100 (BLAKE2s)":
     0.000645 msecs per iteration (total: 129, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"250 (BLAKE2s)":
     0.000600 msecs per iteration (total: 120, iterations: 200000)
RESULT   : tst_qcryptographichash::append():"500 (BLAKE2s)":
     0.000580 msecs per iteration (total: 116, iterations: 200000)
PASS  : tst_qcryptographichash::append()
RESULT   : tst_qcryptographichash::append_once():"Md5":
     0.00154 msecs per iteration (total: 308, iterations: 200000)
RESULT   : tst_qcryptographichash::append_once():"Sha1":
     0.00211 msecs per iteration (total: 422, iterations: 200000)
RESULT   : tst_qcryptographichash::append_once():"Sha256":
     0.00415 msecs per iteration (total: 831, iterations: 200000)
RESULT   : tst_qcryptographichash::append_once():"Sha512":
     0.00314 msecs per iteration (total: 629, iterations: 200000)
RESULT   : tst_qcryptographichash::append_once():"BLAKE2b":
     0.00164 msecs per iteration (total: 328, iterations: 200000)
RESULT   : tst_qcryptographichash::append_once():"BLAKE2s":
     0.00217 msecs per iteration (total: 435, iterations: 200000)
PASS  : tst_qcryptographichash::append_once()
RESULT   : tst_qcryptographichash::statichash():"Md5":
     0.00148 msecs per iteration (total: 297, iterations: 200000)
RESULT   : tst_qcryptographichash::statichash():"Sha1":
     0.00206 msecs per iteration (total: 412, iterations: 200000)
RESULT   : tst_qcryptographichash::statichash():"Sha256":
     0.00409 msecs per iteration (total: 818, iterations: 200000)
RESULT   : tst_qcryptographichash::statichash():"Sha512":
     0.00307 msecs per iteration (total: 614, iterations: 200000)
RESULT   : tst_qcryptographichash::statichash():"BLAKE2b":
     0.00157 msecs per iteration (total: 314, iterations: 200000)
RESULT   : tst_qcryptographichash::statichash():"BLAKE2s":
     0.00211 msecs per iteration (total: 422, iterations: 200000)
PASS  : tst_qcryptographichash::statichash()
RESULT   : tst_qcryptographichash::algorithms():"Md5":
     0.00148 msecs per iteration (total: 297, iterations: 200000)
RESULT   : tst_qcryptographichash::algorithms():"Sha1":
     0.00206 msecs per iteration (total: 412, iterations: 200000)
RESULT   : tst_qcryptographichash::algorithms():"Sha256":
     0.00409 msecs per iteration (total: 819, iterations: 200000)
RESULT   : tst_qcryptographichash::algorithms():"Sha512":
     0.00307 msecs per iteration (total: 614, iterations: 200000)
RESULT   : tst_qcryptographichash::algorithms():"BLAKE2b":
     0.00157 msecs per iteration (total: 314, iterations: 200000)
RESULT   : tst_qcryptographichash::algorithms():"BLAKE2s":
     0.00212 msecs per iteration (total: 424, iterations: 200000)
PASS  : tst_qcryptographichash::algorithms()
PASS  : tst_qcryptographichash::cleanupTestCase()
Totals: 6 passed, 0 failed, 0 skipped
********* Finished testing of tst_qcryptographichash *********

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-03-11 06:22:41 +02:00
parent bfee83b9ab
commit 75589486a3
10 changed files with 766 additions and 2 deletions

1
README
View file

@ -59,6 +59,7 @@ There are several things you should be aware before considering Katie:
- support for AArch64 architecture
- support for locale aliases
- support for generating SHA-256 and SHA-512 hash sums (SHA-2)
- support for generating BLAKE2b and BLAKE2s hash sums
- verification section for plugins build with Clang
- qCompress() and qUncompress() use libdeflate which is much faster
- stack backtrace on assert, crash or warning via execinfo

294
src/3rdparty/digest/blake2b.c vendored Normal file
View file

@ -0,0 +1,294 @@
/*-
* Copyright (c) 2015 Taylor R. Campbell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "blake2b.h"
void *(*volatile blake2b_explicit_memset_impl)(void *, int, size_t) = &memset;
static void *
blake2b_explicit_memset(void *buf, int c, size_t n)
{
return (*blake2b_explicit_memset_impl)(buf, c, n);
}
static inline uint64_t
rotr64(uint64_t x, unsigned c)
{
return ((x >> c) | (x << (64 - c)));
}
static inline uint64_t
le64dec(const void *buf)
{
const uint8_t *p = buf;
return (((uint64_t)p[0]) |
((uint64_t)p[1] << 8) |
((uint64_t)p[2] << 16) |
((uint64_t)p[3] << 24) |
((uint64_t)p[4] << 32) |
((uint64_t)p[5] << 40) |
((uint64_t)p[6] << 48) |
((uint64_t)p[7] << 56));
}
static inline void
le64enc(void *buf, uint64_t v)
{
uint8_t *p = buf;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v;
}
#define BLAKE2B_G(VA, VB, VC, VD, X, Y) do \
{ \
(VA) = (VA) + (VB) + (X); \
(VD) = rotr64((VD) ^ (VA), 32); \
(VC) = (VC) + (VD); \
(VB) = rotr64((VB) ^ (VC), 24); \
(VA) = (VA) + (VB) + (Y); \
(VD) = rotr64((VD) ^ (VA), 16); \
(VC) = (VC) + (VD); \
(VB) = rotr64((VB) ^ (VC), 63); \
} while (0)
static const uint64_t blake2b_iv[8] = {
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL,
};
static const uint8_t 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 },
};
static void
blake2b_compress(uint64_t h[8], uint64_t c, uint64_t last,
const uint8_t in[128])
{
uint64_t v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15;
uint64_t m[16];
unsigned i;
/* Load the variables: first 8 from state, next 8 from IV. */
v0 = h[0];
v1 = h[1];
v2 = h[2];
v3 = h[3];
v4 = h[4];
v5 = h[5];
v6 = h[6];
v7 = h[7];
v8 = blake2b_iv[0];
v9 = blake2b_iv[1];
v10 = blake2b_iv[2];
v11 = blake2b_iv[3];
v12 = blake2b_iv[4];
v13 = blake2b_iv[5];
v14 = blake2b_iv[6];
v15 = blake2b_iv[7];
/* Incorporate the block counter and whether this is last. */
v12 ^= c;
v14 ^= last;
/* Load the message block. */
for (i = 0; i < 16; i++)
m[i] = le64dec(in + 8*i);
/* Transform the variables. */
for (i = 0; i < 12; i++) {
const uint8_t *sigma = blake2b_sigma[i];
BLAKE2B_G(v0, v4, v8, v12, m[sigma[ 0]], m[sigma[ 1]]);
BLAKE2B_G(v1, v5, v9, v13, m[sigma[ 2]], m[sigma[ 3]]);
BLAKE2B_G(v2, v6, v10, v14, m[sigma[ 4]], m[sigma[ 5]]);
BLAKE2B_G(v3, v7, v11, v15, m[sigma[ 6]], m[sigma[ 7]]);
BLAKE2B_G(v0, v5, v10, v15, m[sigma[ 8]], m[sigma[ 9]]);
BLAKE2B_G(v1, v6, v11, v12, m[sigma[10]], m[sigma[11]]);
BLAKE2B_G(v2, v7, v8, v13, m[sigma[12]], m[sigma[13]]);
BLAKE2B_G(v3, v4, v9, v14, m[sigma[14]], m[sigma[15]]);
}
/* Update the state. */
h[0] ^= v0 ^ v8;
h[1] ^= v1 ^ v9;
h[2] ^= v2 ^ v10;
h[3] ^= v3 ^ v11;
h[4] ^= v4 ^ v12;
h[5] ^= v5 ^ v13;
h[6] ^= v6 ^ v14;
h[7] ^= v7 ^ v15;
(void)blake2b_explicit_memset(m, 0, sizeof m);
}
void
blake2b_init(struct blake2b *B, size_t dlen, const void *key, size_t keylen)
{
uint64_t param0;
unsigned i;
assert(0 < dlen);
assert(dlen <= 64);
assert(keylen <= 64);
/* Record the digest length. */
B->dlen = dlen;
/* Initialize the buffer. */
B->nb = 0;
/* Initialize the state. */
B->c = 0;
for (i = 0; i < 8; i++)
B->h[i] = blake2b_iv[i];
/*
* Set the parameters. We support only variable digest and key
* lengths: no tree hashing, no salt, no personalization.
*/
param0 = 0;
param0 |= (uint64_t)dlen << 0;
param0 |= (uint64_t)keylen << 8;
param0 |= (uint64_t)1 << 16; /* tree fanout = 1 */
param0 |= (uint64_t)1 << 24; /* tree depth = 1 */
B->h[0] ^= param0;
/* If there's a key, compress it as the first message block. */
if (keylen) {
static const uint8_t zero_block[128];
blake2b_update(B, key, keylen);
blake2b_update(B, zero_block, 128 - keylen);
}
}
void
blake2b_update(struct blake2b *B, const void *buf, size_t len)
{
const uint8_t *p = buf;
size_t n = len;
/* Check the current state of the buffer. */
if (n <= 128u - B->nb) {
/* Can at most exactly fill the buffer. */
(void)memcpy(&B->b[B->nb], p, n);
B->nb += n;
return;
} else if (0 < B->nb) {
/* Can fill the buffer and go on. */
(void)memcpy(&B->b[B->nb], p, 128 - B->nb);
B->c += 128;
blake2b_compress(B->h, B->c, 0, B->b);
p += 128 - B->nb;
n -= 128 - B->nb;
}
/* At a block boundary. Compress straight from the input. */
while (128 < n) {
B->c += 128;
blake2b_compress(B->h, B->c, 0, p);
p += 128;
n -= 128;
}
/*
* Put whatever's left in the buffer. We may fill the buffer,
* but we can't compress in that case until we know whether we
* are compressing the last block or not.
*/
(void)memcpy(B->b, p, n);
B->nb = n;
}
void
blake2b_final(struct blake2b *B, void *digest)
{
uint8_t *d = digest;
unsigned dlen = B->dlen;
unsigned i;
/* Pad with zeros, and do the last compression. */
B->c += B->nb;
for (i = B->nb; i < 128; i++)
B->b[i] = 0;
blake2b_compress(B->h, B->c, ~(uint64_t)0, B->b);
/* Reveal the first dlen/8 words of the state. */
for (i = 0; i < dlen/8; i++)
le64enc(d + 8*i, B->h[i]);
d += 8*i;
dlen -= 8*i;
/* If the caller wants a partial word, reveal that too. */
if (dlen) {
uint64_t hi = B->h[i];
do {
*d++ = hi;
hi >>= 8;
} while (--dlen);
}
/* Erase the state. */
(void)blake2b_explicit_memset(B, 0, sizeof B);
}
void
blake2b(void *digest, size_t dlen, const void *key, size_t keylen,
const void *in, size_t inlen)
{
struct blake2b ctx;
blake2b_init(&ctx, dlen, key, keylen);
blake2b_update(&ctx, in, inlen);
blake2b_final(&ctx, digest);
}

56
src/3rdparty/digest/blake2b.h vendored Normal file
View file

@ -0,0 +1,56 @@
/*-
* Copyright (c) 2015 Taylor R. Campbell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef BLAKE2B_H
#define BLAKE2B_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct blake2b {
uint8_t b[128]; /* 128-byte buffer */
uint64_t h[8]; /* 64-byte state */
uint64_t c; /* 64-bit input byte counter */
uint8_t nb; /* number of bytes in buffer */
uint8_t dlen; /* digest length */
};
#define BLAKE2B_MAX_DIGEST 64
#define BLAKE2B_MAX_KEY 64
void blake2b_init(struct blake2b *, size_t, const void *, size_t);
void blake2b_update(struct blake2b *, const void *, size_t);
void blake2b_final(struct blake2b *, void *);
void blake2b(void *, size_t, const void *, size_t, const void *, size_t);
#ifdef __cplusplus
}
#endif
#endif /* BLAKE2B_H */

283
src/3rdparty/digest/blake2s.c vendored Normal file
View file

@ -0,0 +1,283 @@
/*-
* Copyright (c) 2015 Taylor R. Campbell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "blake2s.h"
void *(*volatile blake2s_explicit_memset_impl)(void *, int, size_t) = &memset;
static void *
blake2s_explicit_memset(void *buf, int c, size_t n)
{
return (*blake2s_explicit_memset_impl)(buf, c, n);
}
static inline uint32_t
rotr32(uint32_t x, unsigned c)
{
return ((x >> c) | (x << (32 - c)));
}
static inline uint32_t
le32dec(const void *buf)
{
const uint8_t *p = buf;
return (((uint32_t)p[0]) |
((uint32_t)p[1] << 8) |
((uint32_t)p[2] << 16) |
((uint32_t)p[3] << 24));
}
static inline void
le32enc(void *buf, uint32_t v)
{
uint8_t *p = buf;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v; v >>= 8;
*p++ = v;
}
#define BLAKE2S_G(VA, VB, VC, VD, X, Y) do \
{ \
(VA) = (VA) + (VB) + (X); \
(VD) = rotr32((VD) ^ (VA), 16); \
(VC) = (VC) + (VD); \
(VB) = rotr32((VB) ^ (VC), 12); \
(VA) = (VA) + (VB) + (Y); \
(VD) = rotr32((VD) ^ (VA), 8); \
(VC) = (VC) + (VD); \
(VB) = rotr32((VB) ^ (VC), 7); \
} while (0)
static const uint32_t blake2s_iv[8] = {
0x6a09e667U, 0xbb67ae85U, 0x3c6ef372U, 0xa54ff53aU,
0x510e527fU, 0x9b05688cU, 0x1f83d9abU, 0x5be0cd19U,
};
static const uint8_t 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 },
};
static void
blake2s_compress(uint32_t h[8], uint64_t c, uint32_t last,
const uint8_t in[64])
{
uint32_t v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15;
uint32_t m[16];
unsigned i;
/* Load the variables: first 8 from state, next 8 from IV. */
v0 = h[0];
v1 = h[1];
v2 = h[2];
v3 = h[3];
v4 = h[4];
v5 = h[5];
v6 = h[6];
v7 = h[7];
v8 = blake2s_iv[0];
v9 = blake2s_iv[1];
v10 = blake2s_iv[2];
v11 = blake2s_iv[3];
v12 = blake2s_iv[4];
v13 = blake2s_iv[5];
v14 = blake2s_iv[6];
v15 = blake2s_iv[7];
/* Incorporate the block counter and whether this is last. */
v12 ^= c & 0xffffffffU;
v13 ^= c >> 32;
v14 ^= last;
/* Load the message block. */
for (i = 0; i < 16; i++)
m[i] = le32dec(in + 4*i);
/* Transform the variables. */
for (i = 0; i < 10; i++) {
const uint8_t *sigma = blake2s_sigma[i];
BLAKE2S_G(v0, v4, v8, v12, m[sigma[ 0]], m[sigma[ 1]]);
BLAKE2S_G(v1, v5, v9, v13, m[sigma[ 2]], m[sigma[ 3]]);
BLAKE2S_G(v2, v6, v10, v14, m[sigma[ 4]], m[sigma[ 5]]);
BLAKE2S_G(v3, v7, v11, v15, m[sigma[ 6]], m[sigma[ 7]]);
BLAKE2S_G(v0, v5, v10, v15, m[sigma[ 8]], m[sigma[ 9]]);
BLAKE2S_G(v1, v6, v11, v12, m[sigma[10]], m[sigma[11]]);
BLAKE2S_G(v2, v7, v8, v13, m[sigma[12]], m[sigma[13]]);
BLAKE2S_G(v3, v4, v9, v14, m[sigma[14]], m[sigma[15]]);
}
/* Update the state. */
h[0] ^= v0 ^ v8;
h[1] ^= v1 ^ v9;
h[2] ^= v2 ^ v10;
h[3] ^= v3 ^ v11;
h[4] ^= v4 ^ v12;
h[5] ^= v5 ^ v13;
h[6] ^= v6 ^ v14;
h[7] ^= v7 ^ v15;
(void)blake2s_explicit_memset(m, 0, sizeof m);
}
void
blake2s_init(struct blake2s *B, size_t dlen, const void *key, size_t keylen)
{
uint32_t param0;
unsigned i;
assert(0 < dlen);
assert(dlen <= 32);
assert(keylen <= 32);
/* Record the digest length. */
B->dlen = dlen;
/* Initialize the buffer. */
B->nb = 0;
/* Initialize the state. */
B->c = 0;
for (i = 0; i < 8; i++)
B->h[i] = blake2s_iv[i];
/*
* Set the parameters. We support only variable digest and key
* lengths: no tree hashing, no salt, no personalization.
*/
param0 = 0;
param0 |= (uint32_t)dlen << 0;
param0 |= (uint32_t)keylen << 8;
param0 |= (uint32_t)1 << 16; /* tree fanout = 1 */
param0 |= (uint32_t)1 << 24; /* tree depth = 1 */
B->h[0] ^= param0;
/* If there's a key, compress it as the first message block. */
if (keylen) {
static const uint8_t zero_block[64];
blake2s_update(B, key, keylen);
blake2s_update(B, zero_block, 64 - keylen);
}
}
void
blake2s_update(struct blake2s *B, const void *buf, size_t len)
{
const uint8_t *p = buf;
size_t n = len;
/* Check the current state of the buffer. */
if (n <= 64u - B->nb) {
/* Can at most exactly fill the buffer. */
(void)memcpy(&B->b[B->nb], p, n);
B->nb += n;
return;
} else if (0 < B->nb) {
/* Can fill the buffer and go on. */
(void)memcpy(&B->b[B->nb], p, 64 - B->nb);
B->c += 64;
blake2s_compress(B->h, B->c, 0, B->b);
p += 64 - B->nb;
n -= 64 - B->nb;
}
/* At a block boundary. Compress straight from the input. */
while (64 < n) {
B->c += 64;
blake2s_compress(B->h, B->c, 0, p);
p += 64;
n -= 64;
}
/*
* Put whatever's left in the buffer. We may fill the buffer,
* but we can't compress in that case until we know whether we
* are compressing the last block or not.
*/
(void)memcpy(B->b, p, n);
B->nb = n;
}
void
blake2s_final(struct blake2s *B, void *digest)
{
uint8_t *d = digest;
unsigned dlen = B->dlen;
unsigned i;
/* Pad with zeros, and do the last compression. */
B->c += B->nb;
for (i = B->nb; i < 64; i++)
B->b[i] = 0;
blake2s_compress(B->h, B->c, ~(uint32_t)0, B->b);
/* Reveal the first dlen/4 words of the state. */
for (i = 0; i < dlen/4; i++)
le32enc(d + 4*i, B->h[i]);
d += 4*i;
dlen -= 4*i;
/* If the caller wants a partial word, reveal that too. */
if (dlen) {
uint32_t hi = B->h[i];
do {
*d++ = hi;
hi >>= 8;
} while (--dlen);
}
/* Erase the state. */
(void)blake2s_explicit_memset(B, 0, sizeof B);
}
void
blake2s(void *digest, size_t dlen, const void *key, size_t keylen,
const void *in, size_t inlen)
{
struct blake2s ctx;
blake2s_init(&ctx, dlen, key, keylen);
blake2s_update(&ctx, in, inlen);
blake2s_final(&ctx, digest);
}

57
src/3rdparty/digest/blake2s.h vendored Normal file
View file

@ -0,0 +1,57 @@
/*-
* Copyright (c) 2015 Taylor R. Campbell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef BLAKE2S_H
#define BLAKE2S_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct blake2s {
uint8_t b[64]; /* 64-byte buffer */
uint32_t h[8]; /* 32-byte state */
uint64_t c; /* 64-bit input byte counter */
uint8_t nb; /* number of bytes in buffer */
uint8_t dlen; /* digest length */
};
#define BLAKE2S_MAX_DIGEST 32
#define BLAKE2S_MAX_KEY 32
void blake2s_init(struct blake2s *, size_t, const void *, size_t);
void blake2s_update(struct blake2s *, const void *, size_t);
void blake2s_final(struct blake2s *, void *);
void blake2s(void *, size_t, const void *, size_t, const void *, size_t);
#ifdef __cplusplus
}
#endif
#endif /* BLAKE2S_H */

View file

@ -64,6 +64,8 @@ set(NETWORK_SOURCES
${CMAKE_SOURCE_DIR}/src/3rdparty/digest/md5c.c
${CMAKE_SOURCE_DIR}/src/3rdparty/digest/sha1.c
${CMAKE_SOURCE_DIR}/src/3rdparty/digest/sha2.c
${CMAKE_SOURCE_DIR}/src/3rdparty/digest/blake2b.c
${CMAKE_SOURCE_DIR}/src/3rdparty/digest/blake2s.c
)
katie_generate_misc("${NETWORK_HEADERS}" QtNetwork)

View file

@ -27,6 +27,8 @@
#include "md5.h"
#include "sha1.h"
#include "sha2.h"
#include "blake2b.h"
#include "blake2s.h"
QT_BEGIN_NAMESPACE
@ -39,6 +41,8 @@ public:
SHA1_CTX sha1Context;
SHA256_CTX sha256Context;
SHA512_CTX sha512Context;
struct blake2b blake2bContext;
struct blake2s blake2sContext;
bool rehash;
const QCryptographicHash::Algorithm method;
};
@ -74,6 +78,8 @@ QCryptographicHashPrivate::QCryptographicHashPrivate(const QCryptographicHash::A
\value Sha1 Generate an SHA-1 hash sum
\value Sha256 Generate an SHA-256 hash sum (SHA-2). Introduced in Katie 4.9
\value Sha512 Generate an SHA-512 hash sum (SHA-2). Introduced in Katie 4.9
\value BLAKE2b Generate an BLAKE2b hash sum. Introduced in Katie 4.12
\value BLAKE2s Generate an BLAKE2s hash sum. Introduced in Katie 4.12
*/
/*!
@ -117,6 +123,14 @@ void QCryptographicHash::reset()
SHA512_Init(&d->sha512Context);
break;
}
case QCryptographicHash::BLAKE2b: {
blake2b_init(&d->blake2bContext, BLAKE2B_MAX_DIGEST, NULL, 0);
break;
}
case QCryptographicHash::BLAKE2s: {
blake2s_init(&d->blake2sContext, BLAKE2S_MAX_DIGEST, NULL, 0);
break;
}
}
}
@ -143,6 +157,14 @@ void QCryptographicHash::addData(const char *data, int length)
SHA512_Update(&d->sha512Context, reinterpret_cast<const uchar*>(data), length);
break;
}
case QCryptographicHash::BLAKE2b: {
blake2b_update(&d->blake2bContext, reinterpret_cast<const uchar*>(data), length);
break;
}
case QCryptographicHash::BLAKE2s: {
blake2s_update(&d->blake2sContext, reinterpret_cast<const uchar*>(data), length);
break;
}
}
}
@ -206,6 +228,18 @@ QByteArray QCryptographicHash::result() const
SHA512_Final(result, &copy);
return QByteArray(reinterpret_cast<char *>(result), SHA512_DIGEST_LENGTH);
}
case QCryptographicHash::BLAKE2b: {
QSTACKARRAY(char, result, BLAKE2B_MAX_DIGEST);
struct blake2b copy = d->blake2bContext;
blake2b_final(&copy, result);
return QByteArray(result, BLAKE2B_MAX_DIGEST);
}
case QCryptographicHash::BLAKE2s: {
QSTACKARRAY(char, result, BLAKE2S_MAX_DIGEST);
struct blake2s copy = d->blake2sContext;
blake2s_final(&copy, result);
return QByteArray(result, BLAKE2S_MAX_DIGEST);
}
}
return QByteArray();
@ -249,6 +283,22 @@ QByteArray QCryptographicHash::hash(const QByteArray &data, QCryptographicHash::
SHA512_Final(result, &sha512Context);
return QByteArray(reinterpret_cast<char *>(result), SHA512_DIGEST_LENGTH);
}
case QCryptographicHash::BLAKE2b: {
QSTACKARRAY(char, result, BLAKE2B_MAX_DIGEST);
struct blake2b blake2bContext;
blake2b_init(&blake2bContext, BLAKE2B_MAX_DIGEST, NULL, 0);
blake2b_update(&blake2bContext, reinterpret_cast<const uchar*>(data.constData()), data.length());
blake2b_final(&blake2bContext, result);
return QByteArray(result, BLAKE2B_MAX_DIGEST);
}
case QCryptographicHash::BLAKE2s: {
QSTACKARRAY(char, result, BLAKE2S_MAX_DIGEST);
struct blake2s blake2sContext;
blake2s_init(&blake2sContext, BLAKE2S_MAX_DIGEST, NULL, 0);
blake2s_update(&blake2sContext, reinterpret_cast<const uchar*>(data.constData()), data.length());
blake2s_final(&blake2sContext, result);
return QByteArray(result, BLAKE2S_MAX_DIGEST);
}
}
return QByteArray();

View file

@ -38,7 +38,9 @@ public:
Md5,
Sha1,
Sha256,
Sha512
Sha512,
BLAKE2b,
BLAKE2s
};
explicit QCryptographicHash(Algorithm method);

View file

@ -21,6 +21,7 @@
#include <QtTest/QtTest>
#include <QCryptographicHash>
#include <QDebug>
class tst_QCryptographicHash : public QObject
{
@ -84,6 +85,14 @@ void tst_QCryptographicHash::intermediary_result_data()
<< QByteArray("abc") << QByteArray("abc")
<< QByteArray::fromHex("DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F")
<< QByteArray::fromHex("F3C41E7B63EE869596FC28BAD64120612C520F65928AB4D126C72C6998B551B8FF1CEDDFED4373E6717554DC89D1EEE6F0AB22FD3675E561ABA9AE26A3EEC53B");
QTest::newRow("BLAKE2b") << int(QCryptographicHash::BLAKE2b)
<< QByteArray("abc") << QByteArray("abc")
<< QByteArray::fromHex("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")
<< QByteArray::fromHex("60b5c037082a21e1b92bc3484d8bbe015a56574bdf3517796dd9a32095bec69af06104d0391076e9329d150b0ec925af7c482faf4d66127f38b6a65bec4d695b");
QTest::newRow("BLAKE2s") << int(QCryptographicHash::BLAKE2s)
<< QByteArray("abc") << QByteArray("abc")
<< QByteArray::fromHex("508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982")
<< QByteArray::fromHex("3605affd00f95791174cf1f50f90c40aa094dfc5e80898f014729b23eabe6415");
}
void tst_QCryptographicHash::intermediary_result()
@ -97,6 +106,7 @@ void tst_QCryptographicHash::intermediary_result()
QFETCH(QByteArray, hash_first);
QByteArray result = hash.result();
// qDebug() result.toHex();
QCOMPARE(result, hash_first);
// don't reset
@ -105,6 +115,7 @@ void tst_QCryptographicHash::intermediary_result()
hash.addData(second);
result = hash.result();
// qDebug() << result.toHex();
QCOMPARE(result, hash_firstsecond);
hash.reset();

View file

@ -43,6 +43,12 @@ static QString algorithmToString(const QCryptographicHash::Algorithm algorithm)
case QCryptographicHash::Sha512: {
return QString::fromLatin1("Sha512");
}
case QCryptographicHash::BLAKE2b: {
return QString::fromLatin1("BLAKE2b");
}
case QCryptographicHash::BLAKE2s: {
return QString::fromLatin1("BLAKE2s");
}
}
Q_ASSERT(false);
return QString();
@ -66,7 +72,7 @@ void tst_qcryptographichash::append_data()
{
QTest::addColumn<int>("size");
QTest::addColumn<QCryptographicHash::Algorithm>("algorithm");
for (int i = QCryptographicHash::Md5; i < QCryptographicHash::Sha512; i++) {
for (int i = QCryptographicHash::Md5; i < (QCryptographicHash::BLAKE2s + 1); i++) {
const QCryptographicHash::Algorithm algorithm = static_cast<QCryptographicHash::Algorithm>(i);
QTest::newRow(QString::fromLatin1("10 (%1)").arg(algorithmToString(algorithm)).toAscii()) << int(10) << algorithm;
QTest::newRow(QString::fromLatin1("100 (%1)").arg(algorithmToString(algorithm)).toAscii()) << int(100) << algorithm;
@ -105,6 +111,8 @@ void tst_qcryptographichash::append_once_data()
QTest::newRow("Sha1") << QCryptographicHash::Sha1;
QTest::newRow("Sha256") << QCryptographicHash::Sha256;
QTest::newRow("Sha512") << QCryptographicHash::Sha512;
QTest::newRow("BLAKE2b") << QCryptographicHash::BLAKE2b;
QTest::newRow("BLAKE2s") << QCryptographicHash::BLAKE2s;
}
void tst_qcryptographichash::append_once()