Merge branch 'master' into jgrpp
# Conflicts: # src/3rdparty/monocypher/CHANGELOG.md # src/3rdparty/monocypher/CMakeLists.txt # src/3rdparty/monocypher/README.md # src/3rdparty/monocypher/monocypher.h # src/core/random_func.cpp # src/misc.cpp
This commit is contained in:
@@ -524,6 +524,7 @@ if(WIN32)
|
|||||||
usp10
|
usp10
|
||||||
psapi
|
psapi
|
||||||
winhttp
|
winhttp
|
||||||
|
bcrypt
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -587,6 +587,9 @@ See `src/3rdparty/catch2/LICENSE.txt` for the complete license text.
|
|||||||
The icu scriptrun implementation in `src/3rdparty/icu` is licensed under the Unicode license.
|
The icu scriptrun implementation in `src/3rdparty/icu` is licensed under the Unicode license.
|
||||||
See `src/3rdparty/icu/LICENSE` for the complete license text.
|
See `src/3rdparty/icu/LICENSE` for the complete license text.
|
||||||
|
|
||||||
|
The monocypher implementation in `src/3rdparty/monocypher` is licensed under the 2-clause BSD and CC-0 license.
|
||||||
|
See src/3rdparty/monocypher/LICENSE.md` for the complete license text.
|
||||||
|
|
||||||
## 4.0 Credits
|
## 4.0 Credits
|
||||||
|
|
||||||
See [CREDITS.md](./CREDITS.md)
|
See [CREDITS.md](./CREDITS.md)
|
||||||
|
2
src/3rdparty/CMakeLists.txt
vendored
2
src/3rdparty/CMakeLists.txt
vendored
@@ -2,11 +2,11 @@ add_subdirectory(catch2)
|
|||||||
add_subdirectory(fmt)
|
add_subdirectory(fmt)
|
||||||
add_subdirectory(icu)
|
add_subdirectory(icu)
|
||||||
add_subdirectory(md5)
|
add_subdirectory(md5)
|
||||||
|
add_subdirectory(monocypher)
|
||||||
add_subdirectory(squirrel)
|
add_subdirectory(squirrel)
|
||||||
add_subdirectory(nlohmann)
|
add_subdirectory(nlohmann)
|
||||||
add_subdirectory(opengl)
|
add_subdirectory(opengl)
|
||||||
add_subdirectory(cpp-btree)
|
add_subdirectory(cpp-btree)
|
||||||
add_subdirectory(monocypher)
|
|
||||||
add_subdirectory(randombytes)
|
add_subdirectory(randombytes)
|
||||||
add_subdirectory(robin_hood)
|
add_subdirectory(robin_hood)
|
||||||
|
|
||||||
|
10
src/3rdparty/monocypher/CHANGELOG.md
vendored
10
src/3rdparty/monocypher/CHANGELOG.md
vendored
@@ -1,3 +1,13 @@
|
|||||||
|
4.0.2
|
||||||
|
-----
|
||||||
|
2023/08/24
|
||||||
|
|
||||||
|
- Fixed multiple-lanes Argon2.
|
||||||
|
- Improved Poly1305 performance.
|
||||||
|
- Improved Argon2 performance.
|
||||||
|
- Makefiles no longer override standard environment variables.
|
||||||
|
|
||||||
|
|
||||||
4.0.1
|
4.0.1
|
||||||
-----
|
-----
|
||||||
2023/03/06
|
2023/03/06
|
||||||
|
4
src/3rdparty/monocypher/CMakeLists.txt
vendored
4
src/3rdparty/monocypher/CMakeLists.txt
vendored
@@ -1,4 +1,6 @@
|
|||||||
add_files(
|
add_files(
|
||||||
|
monocypher-ed25519.cpp
|
||||||
|
monocypher-ed25519.h
|
||||||
|
monocypher.cpp
|
||||||
monocypher.h
|
monocypher.h
|
||||||
monocypher.c
|
|
||||||
)
|
)
|
||||||
|
500
src/3rdparty/monocypher/monocypher-ed25519.cpp
vendored
Normal file
500
src/3rdparty/monocypher/monocypher-ed25519.cpp
vendored
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
// Monocypher version 4.0.2
|
||||||
|
//
|
||||||
|
// This file is dual-licensed. Choose whichever licence you want from
|
||||||
|
// the two licences listed below.
|
||||||
|
//
|
||||||
|
// The first licence is a regular 2-clause BSD licence. The second licence
|
||||||
|
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
||||||
|
// to the public domain. The BSD licence serves as a fallback option.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017-2019, Loup Vaillant
|
||||||
|
// 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||||
|
// HOLDER 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.
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Written in 2017-2019 by Loup Vaillant
|
||||||
|
//
|
||||||
|
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||||
|
// and related neighboring rights to this software to the public domain
|
||||||
|
// worldwide. This software is distributed without any warranty.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the CC0 Public Domain Dedication along
|
||||||
|
// with this software. If not, see
|
||||||
|
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||||
|
|
||||||
|
#include "monocypher-ed25519.h"
|
||||||
|
|
||||||
|
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||||
|
namespace MONOCYPHER_CPP_NAMESPACE {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
/// Utilities ///
|
||||||
|
/////////////////
|
||||||
|
#define FOR(i, min, max) for (size_t i = min; i < max; i++)
|
||||||
|
#define COPY(dst, src, size) FOR(_i_, 0, size) (dst)[_i_] = (src)[_i_]
|
||||||
|
#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
|
||||||
|
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
|
||||||
|
#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
|
||||||
|
#define MC_MIN(a, b) ((a) <= (b) ? (a) : (b))
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
|
||||||
|
// Returns the smallest positive integer y such that
|
||||||
|
// (x + y) % pow_2 == 0
|
||||||
|
// Basically, it's how many bytes we need to add to "align" x.
|
||||||
|
// Only works when pow_2 is a power of 2.
|
||||||
|
// Note: we use ~x+1 instead of -x to avoid compiler warnings
|
||||||
|
static size_t align(size_t x, size_t pow_2)
|
||||||
|
{
|
||||||
|
return (~x + 1) & (pow_2 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 load64_be(const u8 s[8])
|
||||||
|
{
|
||||||
|
return((u64)s[0] << 56)
|
||||||
|
| ((u64)s[1] << 48)
|
||||||
|
| ((u64)s[2] << 40)
|
||||||
|
| ((u64)s[3] << 32)
|
||||||
|
| ((u64)s[4] << 24)
|
||||||
|
| ((u64)s[5] << 16)
|
||||||
|
| ((u64)s[6] << 8)
|
||||||
|
| (u64)s[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void store64_be(u8 out[8], u64 in)
|
||||||
|
{
|
||||||
|
out[0] = (in >> 56) & 0xff;
|
||||||
|
out[1] = (in >> 48) & 0xff;
|
||||||
|
out[2] = (in >> 40) & 0xff;
|
||||||
|
out[3] = (in >> 32) & 0xff;
|
||||||
|
out[4] = (in >> 24) & 0xff;
|
||||||
|
out[5] = (in >> 16) & 0xff;
|
||||||
|
out[6] = (in >> 8) & 0xff;
|
||||||
|
out[7] = in & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load64_be_buf (u64 *dst, const u8 *src, size_t size) {
|
||||||
|
FOR(i, 0, size) { dst[i] = load64_be(src + i*8); }
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
/// SHA 512 ///
|
||||||
|
///////////////
|
||||||
|
static u64 rot(u64 x, int c ) { return (x >> c) | (x << (64 - c)); }
|
||||||
|
static u64 ch (u64 x, u64 y, u64 z) { return (x & y) ^ (~x & z); }
|
||||||
|
static u64 maj(u64 x, u64 y, u64 z) { return (x & y) ^ ( x & z) ^ (y & z); }
|
||||||
|
static u64 big_sigma0(u64 x) { return rot(x, 28) ^ rot(x, 34) ^ rot(x, 39); }
|
||||||
|
static u64 big_sigma1(u64 x) { return rot(x, 14) ^ rot(x, 18) ^ rot(x, 41); }
|
||||||
|
static u64 lit_sigma0(u64 x) { return rot(x, 1) ^ rot(x, 8) ^ (x >> 7); }
|
||||||
|
static u64 lit_sigma1(u64 x) { return rot(x, 19) ^ rot(x, 61) ^ (x >> 6); }
|
||||||
|
|
||||||
|
static const u64 K[80] = {
|
||||||
|
0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
|
||||||
|
0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
|
||||||
|
0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
|
||||||
|
0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
|
||||||
|
0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
|
||||||
|
0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
|
||||||
|
0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
|
||||||
|
0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
|
||||||
|
0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
|
||||||
|
0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
|
||||||
|
0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
|
||||||
|
0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
|
||||||
|
0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
|
||||||
|
0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
|
||||||
|
0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
|
||||||
|
0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
|
||||||
|
0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
|
||||||
|
0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
|
||||||
|
0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
|
||||||
|
0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817
|
||||||
|
};
|
||||||
|
|
||||||
|
static void sha512_compress(crypto_sha512_ctx *ctx)
|
||||||
|
{
|
||||||
|
u64 a = ctx->hash[0]; u64 b = ctx->hash[1];
|
||||||
|
u64 c = ctx->hash[2]; u64 d = ctx->hash[3];
|
||||||
|
u64 e = ctx->hash[4]; u64 f = ctx->hash[5];
|
||||||
|
u64 g = ctx->hash[6]; u64 h = ctx->hash[7];
|
||||||
|
|
||||||
|
FOR (j, 0, 16) {
|
||||||
|
u64 in = K[j] + ctx->input[j];
|
||||||
|
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
|
||||||
|
u64 t2 = big_sigma0(a) + maj(a, b, c);
|
||||||
|
h = g; g = f; f = e; e = d + t1;
|
||||||
|
d = c; c = b; b = a; a = t1 + t2;
|
||||||
|
}
|
||||||
|
size_t i16 = 0;
|
||||||
|
FOR(i, 1, 5) {
|
||||||
|
i16 += 16;
|
||||||
|
FOR (j, 0, 16) {
|
||||||
|
ctx->input[j] += lit_sigma1(ctx->input[(j- 2) & 15]);
|
||||||
|
ctx->input[j] += lit_sigma0(ctx->input[(j-15) & 15]);
|
||||||
|
ctx->input[j] += ctx->input[(j- 7) & 15];
|
||||||
|
u64 in = K[i16 + j] + ctx->input[j];
|
||||||
|
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
|
||||||
|
u64 t2 = big_sigma0(a) + maj(a, b, c);
|
||||||
|
h = g; g = f; f = e; e = d + t1;
|
||||||
|
d = c; c = b; b = a; a = t1 + t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->hash[0] += a; ctx->hash[1] += b;
|
||||||
|
ctx->hash[2] += c; ctx->hash[3] += d;
|
||||||
|
ctx->hash[4] += e; ctx->hash[5] += f;
|
||||||
|
ctx->hash[6] += g; ctx->hash[7] += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write 1 input byte
|
||||||
|
static void sha512_set_input(crypto_sha512_ctx *ctx, u8 input)
|
||||||
|
{
|
||||||
|
size_t word = ctx->input_idx >> 3;
|
||||||
|
size_t byte = ctx->input_idx & 7;
|
||||||
|
ctx->input[word] |= (u64)input << (8 * (7 - byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment a 128-bit "word".
|
||||||
|
static void sha512_incr(u64 x[2], u64 y)
|
||||||
|
{
|
||||||
|
x[1] += y;
|
||||||
|
if (x[1] < y) {
|
||||||
|
x[0]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_init(crypto_sha512_ctx *ctx)
|
||||||
|
{
|
||||||
|
ctx->hash[0] = 0x6a09e667f3bcc908;
|
||||||
|
ctx->hash[1] = 0xbb67ae8584caa73b;
|
||||||
|
ctx->hash[2] = 0x3c6ef372fe94f82b;
|
||||||
|
ctx->hash[3] = 0xa54ff53a5f1d36f1;
|
||||||
|
ctx->hash[4] = 0x510e527fade682d1;
|
||||||
|
ctx->hash[5] = 0x9b05688c2b3e6c1f;
|
||||||
|
ctx->hash[6] = 0x1f83d9abfb41bd6b;
|
||||||
|
ctx->hash[7] = 0x5be0cd19137e2179;
|
||||||
|
ctx->input_size[0] = 0;
|
||||||
|
ctx->input_size[1] = 0;
|
||||||
|
ctx->input_idx = 0;
|
||||||
|
ZERO(ctx->input, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_update(crypto_sha512_ctx *ctx,
|
||||||
|
const u8 *message, size_t message_size)
|
||||||
|
{
|
||||||
|
// Avoid undefined NULL pointer increments with empty messages
|
||||||
|
if (message_size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align ourselves with word boundaries
|
||||||
|
if ((ctx->input_idx & 7) != 0) {
|
||||||
|
size_t nb_bytes = MC_MIN(align(ctx->input_idx, 8), message_size);
|
||||||
|
FOR (i, 0, nb_bytes) {
|
||||||
|
sha512_set_input(ctx, message[i]);
|
||||||
|
ctx->input_idx++;
|
||||||
|
}
|
||||||
|
message += nb_bytes;
|
||||||
|
message_size -= nb_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align ourselves with block boundaries
|
||||||
|
if ((ctx->input_idx & 127) != 0) {
|
||||||
|
size_t nb_words = MC_MIN(align(ctx->input_idx, 128), message_size) >> 3;
|
||||||
|
load64_be_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
|
||||||
|
ctx->input_idx += nb_words << 3;
|
||||||
|
message += nb_words << 3;
|
||||||
|
message_size -= nb_words << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress block if needed
|
||||||
|
if (ctx->input_idx == 128) {
|
||||||
|
sha512_incr(ctx->input_size, 1024); // size is in bits
|
||||||
|
sha512_compress(ctx);
|
||||||
|
ctx->input_idx = 0;
|
||||||
|
ZERO(ctx->input, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the message block by block
|
||||||
|
FOR (i, 0, message_size >> 7) { // number of blocks
|
||||||
|
load64_be_buf(ctx->input, message, 16);
|
||||||
|
sha512_incr(ctx->input_size, 1024); // size is in bits
|
||||||
|
sha512_compress(ctx);
|
||||||
|
ctx->input_idx = 0;
|
||||||
|
ZERO(ctx->input, 16);
|
||||||
|
message += 128;
|
||||||
|
}
|
||||||
|
message_size &= 127;
|
||||||
|
|
||||||
|
if (message_size != 0) {
|
||||||
|
// Remaining words
|
||||||
|
size_t nb_words = message_size >> 3;
|
||||||
|
load64_be_buf(ctx->input, message, nb_words);
|
||||||
|
ctx->input_idx += nb_words << 3;
|
||||||
|
message += nb_words << 3;
|
||||||
|
message_size -= nb_words << 3;
|
||||||
|
|
||||||
|
// Remaining bytes
|
||||||
|
FOR (i, 0, message_size) {
|
||||||
|
sha512_set_input(ctx, message[i]);
|
||||||
|
ctx->input_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_final(crypto_sha512_ctx *ctx, u8 hash[64])
|
||||||
|
{
|
||||||
|
// Add padding bit
|
||||||
|
if (ctx->input_idx == 0) {
|
||||||
|
ZERO(ctx->input, 16);
|
||||||
|
}
|
||||||
|
sha512_set_input(ctx, 128);
|
||||||
|
|
||||||
|
// Update size
|
||||||
|
sha512_incr(ctx->input_size, ctx->input_idx * 8);
|
||||||
|
|
||||||
|
// Compress penultimate block (if any)
|
||||||
|
if (ctx->input_idx > 111) {
|
||||||
|
sha512_compress(ctx);
|
||||||
|
ZERO(ctx->input, 14);
|
||||||
|
}
|
||||||
|
// Compress last block
|
||||||
|
ctx->input[14] = ctx->input_size[0];
|
||||||
|
ctx->input[15] = ctx->input_size[1];
|
||||||
|
sha512_compress(ctx);
|
||||||
|
|
||||||
|
// Copy hash to output (big endian)
|
||||||
|
FOR (i, 0, 8) {
|
||||||
|
store64_be(hash + i*8, ctx->hash[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WIPE_CTX(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512(u8 hash[64], const u8 *message, size_t message_size)
|
||||||
|
{
|
||||||
|
crypto_sha512_ctx ctx;
|
||||||
|
crypto_sha512_init (&ctx);
|
||||||
|
crypto_sha512_update(&ctx, message, message_size);
|
||||||
|
crypto_sha512_final (&ctx, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
/// HMAC SHA 512 ///
|
||||||
|
////////////////////
|
||||||
|
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
|
||||||
|
const u8 *key, size_t key_size)
|
||||||
|
{
|
||||||
|
// hash key if it is too long
|
||||||
|
if (key_size > 128) {
|
||||||
|
crypto_sha512(ctx->key, key, key_size);
|
||||||
|
key = ctx->key;
|
||||||
|
key_size = 64;
|
||||||
|
}
|
||||||
|
// Compute inner key: padded key XOR 0x36
|
||||||
|
FOR (i, 0, key_size) { ctx->key[i] = key[i] ^ 0x36; }
|
||||||
|
FOR (i, key_size, 128) { ctx->key[i] = 0x36; }
|
||||||
|
// Start computing inner hash
|
||||||
|
crypto_sha512_init (&ctx->ctx);
|
||||||
|
crypto_sha512_update(&ctx->ctx, ctx->key, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
|
||||||
|
const u8 *message, size_t message_size)
|
||||||
|
{
|
||||||
|
crypto_sha512_update(&ctx->ctx, message, message_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, u8 hmac[64])
|
||||||
|
{
|
||||||
|
// Finish computing inner hash
|
||||||
|
crypto_sha512_final(&ctx->ctx, hmac);
|
||||||
|
// Compute outer key: padded key XOR 0x5c
|
||||||
|
FOR (i, 0, 128) {
|
||||||
|
ctx->key[i] ^= 0x36 ^ 0x5c;
|
||||||
|
}
|
||||||
|
// Compute outer hash
|
||||||
|
crypto_sha512_init (&ctx->ctx);
|
||||||
|
crypto_sha512_update(&ctx->ctx, ctx->key , 128);
|
||||||
|
crypto_sha512_update(&ctx->ctx, hmac, 64);
|
||||||
|
crypto_sha512_final (&ctx->ctx, hmac); // outer hash
|
||||||
|
WIPE_CTX(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_hmac(u8 hmac[64], const u8 *key, size_t key_size,
|
||||||
|
const u8 *message, size_t message_size)
|
||||||
|
{
|
||||||
|
crypto_sha512_hmac_ctx ctx;
|
||||||
|
crypto_sha512_hmac_init (&ctx, key, key_size);
|
||||||
|
crypto_sha512_hmac_update(&ctx, message, message_size);
|
||||||
|
crypto_sha512_hmac_final (&ctx, hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
/// HKDF SHA 512 ///
|
||||||
|
////////////////////
|
||||||
|
void crypto_sha512_hkdf_expand(u8 *okm, size_t okm_size,
|
||||||
|
const u8 *prk, size_t prk_size,
|
||||||
|
const u8 *info, size_t info_size)
|
||||||
|
{
|
||||||
|
int not_first = 0;
|
||||||
|
u8 ctr = 1;
|
||||||
|
u8 blk[64];
|
||||||
|
|
||||||
|
while (okm_size > 0) {
|
||||||
|
size_t out_size = MC_MIN(okm_size, sizeof(blk));
|
||||||
|
|
||||||
|
crypto_sha512_hmac_ctx ctx;
|
||||||
|
crypto_sha512_hmac_init(&ctx, prk , prk_size);
|
||||||
|
if (not_first) {
|
||||||
|
// For some reason HKDF uses some kind of CBC mode.
|
||||||
|
// For some reason CTR mode alone wasn't enough.
|
||||||
|
// Like what, they didn't trust HMAC in 2010? Really??
|
||||||
|
crypto_sha512_hmac_update(&ctx, blk , sizeof(blk));
|
||||||
|
}
|
||||||
|
crypto_sha512_hmac_update(&ctx, info, info_size);
|
||||||
|
crypto_sha512_hmac_update(&ctx, &ctr, 1);
|
||||||
|
crypto_sha512_hmac_final(&ctx, blk);
|
||||||
|
|
||||||
|
COPY(okm, blk, out_size);
|
||||||
|
|
||||||
|
not_first = 1;
|
||||||
|
okm += out_size;
|
||||||
|
okm_size -= out_size;
|
||||||
|
ctr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_sha512_hkdf(u8 *okm , size_t okm_size,
|
||||||
|
const u8 *ikm , size_t ikm_size,
|
||||||
|
const u8 *salt, size_t salt_size,
|
||||||
|
const u8 *info, size_t info_size)
|
||||||
|
{
|
||||||
|
// Extract
|
||||||
|
u8 prk[64];
|
||||||
|
crypto_sha512_hmac(prk, salt, salt_size, ikm, ikm_size);
|
||||||
|
|
||||||
|
// Expand
|
||||||
|
crypto_sha512_hkdf_expand(okm, okm_size, prk, sizeof(prk), info, info_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
/// Ed25519 ///
|
||||||
|
///////////////
|
||||||
|
void crypto_ed25519_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
|
||||||
|
{
|
||||||
|
u8 a[64];
|
||||||
|
COPY(a, seed, 32); // a[ 0..31] = seed
|
||||||
|
crypto_wipe(seed, 32);
|
||||||
|
COPY(secret_key, a, 32); // secret key = seed
|
||||||
|
crypto_sha512(a, a, 32); // a[ 0..31] = scalar
|
||||||
|
crypto_eddsa_trim_scalar(a, a); // a[ 0..31] = trimmed scalar
|
||||||
|
crypto_eddsa_scalarbase(public_key, a); // public key = [trimmed scalar]B
|
||||||
|
COPY(secret_key + 32, public_key, 32); // secret key includes public half
|
||||||
|
WIPE_BUFFER(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hash_reduce(u8 h[32],
|
||||||
|
const u8 *a, size_t a_size,
|
||||||
|
const u8 *b, size_t b_size,
|
||||||
|
const u8 *c, size_t c_size,
|
||||||
|
const u8 *d, size_t d_size)
|
||||||
|
{
|
||||||
|
u8 hash[64];
|
||||||
|
crypto_sha512_ctx ctx;
|
||||||
|
crypto_sha512_init (&ctx);
|
||||||
|
crypto_sha512_update(&ctx, a, a_size);
|
||||||
|
crypto_sha512_update(&ctx, b, b_size);
|
||||||
|
crypto_sha512_update(&ctx, c, c_size);
|
||||||
|
crypto_sha512_update(&ctx, d, d_size);
|
||||||
|
crypto_sha512_final (&ctx, hash);
|
||||||
|
crypto_eddsa_reduce(h, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ed25519_dom_sign(u8 signature [64], const u8 secret_key[32],
|
||||||
|
const u8 *dom, size_t dom_size,
|
||||||
|
const u8 *message, size_t message_size)
|
||||||
|
{
|
||||||
|
u8 a[64]; // secret scalar and prefix
|
||||||
|
u8 r[32]; // secret deterministic "random" nonce
|
||||||
|
u8 h[32]; // publically verifiable hash of the message (not wiped)
|
||||||
|
u8 R[32]; // first half of the signature (allows overlapping inputs)
|
||||||
|
const u8 *pk = secret_key + 32;
|
||||||
|
|
||||||
|
crypto_sha512(a, secret_key, 32);
|
||||||
|
crypto_eddsa_trim_scalar(a, a);
|
||||||
|
hash_reduce(r, dom, dom_size, a + 32, 32, message, message_size, 0, 0);
|
||||||
|
crypto_eddsa_scalarbase(R, r);
|
||||||
|
hash_reduce(h, dom, dom_size, R, 32, pk, 32, message, message_size);
|
||||||
|
COPY(signature, R, 32);
|
||||||
|
crypto_eddsa_mul_add(signature + 32, h, a, r);
|
||||||
|
|
||||||
|
WIPE_BUFFER(a);
|
||||||
|
WIPE_BUFFER(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_ed25519_sign(u8 signature [64], const u8 secret_key[64],
|
||||||
|
const u8 *message, size_t message_size)
|
||||||
|
{
|
||||||
|
ed25519_dom_sign(signature, secret_key, 0, 0, message, message_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_ed25519_check(const u8 signature[64], const u8 public_key[32],
|
||||||
|
const u8 *msg, size_t msg_size)
|
||||||
|
{
|
||||||
|
u8 h_ram[32];
|
||||||
|
hash_reduce(h_ram, signature, 32, public_key, 32, msg, msg_size, 0, 0);
|
||||||
|
return crypto_eddsa_check_equation(signature, public_key, h_ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u8 domain[34] = "SigEd25519 no Ed25519 collisions\1";
|
||||||
|
|
||||||
|
void crypto_ed25519_ph_sign(uint8_t signature[64], const uint8_t secret_key[64],
|
||||||
|
const uint8_t message_hash[64])
|
||||||
|
{
|
||||||
|
ed25519_dom_sign(signature, secret_key, domain, sizeof(domain),
|
||||||
|
message_hash, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_ed25519_ph_check(const uint8_t sig[64], const uint8_t pk[32],
|
||||||
|
const uint8_t msg_hash[64])
|
||||||
|
{
|
||||||
|
u8 h_ram[32];
|
||||||
|
hash_reduce(h_ram, domain, sizeof(domain), sig, 32, pk, 32, msg_hash, 64);
|
||||||
|
return crypto_eddsa_check_equation(sig, pk, h_ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||||
|
}
|
||||||
|
#endif
|
140
src/3rdparty/monocypher/monocypher-ed25519.h
vendored
Normal file
140
src/3rdparty/monocypher/monocypher-ed25519.h
vendored
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// Monocypher version 4.0.2
|
||||||
|
//
|
||||||
|
// This file is dual-licensed. Choose whichever licence you want from
|
||||||
|
// the two licences listed below.
|
||||||
|
//
|
||||||
|
// The first licence is a regular 2-clause BSD licence. The second licence
|
||||||
|
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
||||||
|
// to the public domain. The BSD licence serves as a fallback option.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017-2019, Loup Vaillant
|
||||||
|
// 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||||
|
// HOLDER 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.
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Written in 2017-2019 by Loup Vaillant
|
||||||
|
//
|
||||||
|
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||||
|
// and related neighboring rights to this software to the public domain
|
||||||
|
// worldwide. This software is distributed without any warranty.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the CC0 Public Domain Dedication along
|
||||||
|
// with this software. If not, see
|
||||||
|
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||||
|
|
||||||
|
#ifndef ED25519_H
|
||||||
|
#define ED25519_H
|
||||||
|
|
||||||
|
#include "monocypher.h"
|
||||||
|
|
||||||
|
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||||
|
namespace MONOCYPHER_CPP_NAMESPACE {
|
||||||
|
#elif defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
/// Type definitions ///
|
||||||
|
////////////////////////
|
||||||
|
|
||||||
|
// Do not rely on the size or content on any of those types,
|
||||||
|
// they may change without notice.
|
||||||
|
typedef struct {
|
||||||
|
uint64_t hash[8];
|
||||||
|
uint64_t input[16];
|
||||||
|
uint64_t input_size[2];
|
||||||
|
size_t input_idx;
|
||||||
|
} crypto_sha512_ctx;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t key[128];
|
||||||
|
crypto_sha512_ctx ctx;
|
||||||
|
} crypto_sha512_hmac_ctx;
|
||||||
|
|
||||||
|
|
||||||
|
// SHA 512
|
||||||
|
// -------
|
||||||
|
void crypto_sha512_init (crypto_sha512_ctx *ctx);
|
||||||
|
void crypto_sha512_update(crypto_sha512_ctx *ctx,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
void crypto_sha512_final (crypto_sha512_ctx *ctx, uint8_t hash[64]);
|
||||||
|
void crypto_sha512(uint8_t hash[64],
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
|
||||||
|
// SHA 512 HMAC
|
||||||
|
// ------------
|
||||||
|
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
|
||||||
|
const uint8_t *key, size_t key_size);
|
||||||
|
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, uint8_t hmac[64]);
|
||||||
|
void crypto_sha512_hmac(uint8_t hmac[64],
|
||||||
|
const uint8_t *key , size_t key_size,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
|
||||||
|
// SHA 512 HKDF
|
||||||
|
// ------------
|
||||||
|
void crypto_sha512_hkdf_expand(uint8_t *okm, size_t okm_size,
|
||||||
|
const uint8_t *prk, size_t prk_size,
|
||||||
|
const uint8_t *info, size_t info_size);
|
||||||
|
void crypto_sha512_hkdf(uint8_t *okm , size_t okm_size,
|
||||||
|
const uint8_t *ikm , size_t ikm_size,
|
||||||
|
const uint8_t *salt, size_t salt_size,
|
||||||
|
const uint8_t *info, size_t info_size);
|
||||||
|
|
||||||
|
// Ed25519
|
||||||
|
// -------
|
||||||
|
// Signatures (EdDSA with curve25519 + SHA-512)
|
||||||
|
// --------------------------------------------
|
||||||
|
void crypto_ed25519_key_pair(uint8_t secret_key[64],
|
||||||
|
uint8_t public_key[32],
|
||||||
|
uint8_t seed[32]);
|
||||||
|
void crypto_ed25519_sign(uint8_t signature [64],
|
||||||
|
const uint8_t secret_key[64],
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
int crypto_ed25519_check(const uint8_t signature [64],
|
||||||
|
const uint8_t public_key[32],
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
|
||||||
|
// Pre-hash variants
|
||||||
|
void crypto_ed25519_ph_sign(uint8_t signature [64],
|
||||||
|
const uint8_t secret_key [64],
|
||||||
|
const uint8_t message_hash[64]);
|
||||||
|
int crypto_ed25519_ph_check(const uint8_t signature [64],
|
||||||
|
const uint8_t public_key [32],
|
||||||
|
const uint8_t message_hash[64]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ED25519_H
|
@@ -1,4 +1,4 @@
|
|||||||
// Monocypher version 4.0.1
|
// Monocypher version 4.0.2
|
||||||
//
|
//
|
||||||
// This file is dual-licensed. Choose whichever licence you want from
|
// This file is dual-licensed. Choose whichever licence you want from
|
||||||
// the two licences listed below.
|
// the two licences listed below.
|
||||||
@@ -66,8 +66,8 @@ namespace MONOCYPHER_CPP_NAMESPACE {
|
|||||||
#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
|
#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
|
||||||
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
|
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
|
||||||
#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
|
#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
|
||||||
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
|
#define MC_MIN(a, b) ((a) <= (b) ? (a) : (b))
|
||||||
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
|
#define MC_MAX(a, b) ((a) >= (b) ? (a) : (b))
|
||||||
|
|
||||||
typedef int8_t i8;
|
typedef int8_t i8;
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
@@ -81,10 +81,10 @@ static const u8 zero[128] = {0};
|
|||||||
|
|
||||||
// returns the smallest positive integer y such that
|
// returns the smallest positive integer y such that
|
||||||
// (x + y) % pow_2 == 0
|
// (x + y) % pow_2 == 0
|
||||||
// Basically, it's how many bytes we need to add to "align" x.
|
// Basically, y is the "gap" missing to align x.
|
||||||
// Only works when pow_2 is a power of 2.
|
// Only works when pow_2 is a power of 2.
|
||||||
// Note: we use ~x+1 instead of -x to avoid compiler warnings
|
// Note: we use ~x+1 instead of -x to avoid compiler warnings
|
||||||
static size_t align(size_t x, size_t pow_2)
|
static size_t gap(size_t x, size_t pow_2)
|
||||||
{
|
{
|
||||||
return (~x + 1) & (pow_2 - 1);
|
return (~x + 1) & (pow_2 - 1);
|
||||||
}
|
}
|
||||||
@@ -307,55 +307,39 @@ u64 crypto_chacha20_x(u8 *cipher_text, const u8 *plain_text,
|
|||||||
// end <= 1
|
// end <= 1
|
||||||
// Postcondition:
|
// Postcondition:
|
||||||
// ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
|
// ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
|
||||||
static void poly_block(crypto_poly1305_ctx *ctx, const u8 in[16], unsigned end)
|
static void poly_blocks(crypto_poly1305_ctx *ctx, const u8 *in,
|
||||||
|
size_t nb_blocks, unsigned end)
|
||||||
{
|
{
|
||||||
u32 s[4];
|
|
||||||
load32_le_buf(s, in, 4);
|
|
||||||
|
|
||||||
//- PROOF Poly1305
|
|
||||||
//-
|
|
||||||
//- # Inputs & preconditions
|
|
||||||
//- ctx->h[0] = u32()
|
|
||||||
//- ctx->h[1] = u32()
|
|
||||||
//- ctx->h[2] = u32()
|
|
||||||
//- ctx->h[3] = u32()
|
|
||||||
//- ctx->h[4] = u32(limit = 4)
|
|
||||||
//-
|
|
||||||
//- ctx->r[0] = u32(limit = 0x0fffffff)
|
|
||||||
//- ctx->r[1] = u32(limit = 0x0ffffffc)
|
|
||||||
//- ctx->r[2] = u32(limit = 0x0ffffffc)
|
|
||||||
//- ctx->r[3] = u32(limit = 0x0ffffffc)
|
|
||||||
//-
|
|
||||||
//- s[0] = u32()
|
|
||||||
//- s[1] = u32()
|
|
||||||
//- s[2] = u32()
|
|
||||||
//- s[3] = u32()
|
|
||||||
//-
|
|
||||||
//- end = unsigned(limit = 1)
|
|
||||||
|
|
||||||
// s = h + c, without carry propagation
|
|
||||||
const u64 s0 = ctx->h[0] + (u64)s[0]; // s0 <= 1_fffffffe
|
|
||||||
const u64 s1 = ctx->h[1] + (u64)s[1]; // s1 <= 1_fffffffe
|
|
||||||
const u64 s2 = ctx->h[2] + (u64)s[2]; // s2 <= 1_fffffffe
|
|
||||||
const u64 s3 = ctx->h[3] + (u64)s[3]; // s3 <= 1_fffffffe
|
|
||||||
const u32 s4 = ctx->h[4] + end; // s4 <= 5
|
|
||||||
|
|
||||||
// Local all the things!
|
// Local all the things!
|
||||||
const u32 r0 = ctx->r[0]; // r0 <= 0fffffff
|
const u32 r0 = ctx->r[0];
|
||||||
const u32 r1 = ctx->r[1]; // r1 <= 0ffffffc
|
const u32 r1 = ctx->r[1];
|
||||||
const u32 r2 = ctx->r[2]; // r2 <= 0ffffffc
|
const u32 r2 = ctx->r[2];
|
||||||
const u32 r3 = ctx->r[3]; // r3 <= 0ffffffc
|
const u32 r3 = ctx->r[3];
|
||||||
const u32 rr0 = (r0 >> 2) * 5; // rr0 <= 13fffffb // lose 2 bits...
|
const u32 rr0 = (r0 >> 2) * 5; // lose 2 bits...
|
||||||
const u32 rr1 = (r1 >> 2) + r1; // rr1 <= 13fffffb // rr1 == (r1 >> 2) * 5
|
const u32 rr1 = (r1 >> 2) + r1; // rr1 == (r1 >> 2) * 5
|
||||||
const u32 rr2 = (r2 >> 2) + r2; // rr2 <= 13fffffb // rr1 == (r2 >> 2) * 5
|
const u32 rr2 = (r2 >> 2) + r2; // rr1 == (r2 >> 2) * 5
|
||||||
const u32 rr3 = (r3 >> 2) + r3; // rr3 <= 13fffffb // rr1 == (r3 >> 2) * 5
|
const u32 rr3 = (r3 >> 2) + r3; // rr1 == (r3 >> 2) * 5
|
||||||
|
const u32 rr4 = r0 & 3; // ...recover 2 bits
|
||||||
|
u32 h0 = ctx->h[0];
|
||||||
|
u32 h1 = ctx->h[1];
|
||||||
|
u32 h2 = ctx->h[2];
|
||||||
|
u32 h3 = ctx->h[3];
|
||||||
|
u32 h4 = ctx->h[4];
|
||||||
|
|
||||||
|
FOR (i, 0, nb_blocks) {
|
||||||
|
// h + c, without carry propagation
|
||||||
|
const u64 s0 = (u64)h0 + load32_le(in); in += 4;
|
||||||
|
const u64 s1 = (u64)h1 + load32_le(in); in += 4;
|
||||||
|
const u64 s2 = (u64)h2 + load32_le(in); in += 4;
|
||||||
|
const u64 s3 = (u64)h3 + load32_le(in); in += 4;
|
||||||
|
const u32 s4 = h4 + end;
|
||||||
|
|
||||||
// (h + c) * r, without carry propagation
|
// (h + c) * r, without carry propagation
|
||||||
const u64 x0 = s0*r0+ s1*rr3+ s2*rr2+ s3*rr1+ s4*rr0; // <= 97ffffe007fffff8
|
const u64 x0 = s0*r0+ s1*rr3+ s2*rr2+ s3*rr1+ s4*rr0;
|
||||||
const u64 x1 = s0*r1+ s1*r0 + s2*rr3+ s3*rr2+ s4*rr1; // <= 8fffffe20ffffff6
|
const u64 x1 = s0*r1+ s1*r0 + s2*rr3+ s3*rr2+ s4*rr1;
|
||||||
const u64 x2 = s0*r2+ s1*r1 + s2*r0 + s3*rr3+ s4*rr2; // <= 87ffffe417fffff4
|
const u64 x2 = s0*r2+ s1*r1 + s2*r0 + s3*rr3+ s4*rr2;
|
||||||
const u64 x3 = s0*r3+ s1*r2 + s2*r1 + s3*r0 + s4*rr3; // <= 7fffffe61ffffff2
|
const u64 x3 = s0*r3+ s1*r2 + s2*r1 + s3*r0 + s4*rr3;
|
||||||
const u32 x4 = s4 * (r0 & 3); // ...recover 2 bits // <= f
|
const u32 x4 = s4*rr4;
|
||||||
|
|
||||||
// partial reduction modulo 2^130 - 5
|
// partial reduction modulo 2^130 - 5
|
||||||
const u32 u5 = x4 + (x3 >> 32); // u5 <= 7ffffff5
|
const u32 u5 = x4 + (x3 >> 32); // u5 <= 7ffffff5
|
||||||
@@ -363,18 +347,20 @@ static void poly_block(crypto_poly1305_ctx *ctx, const u8 in[16], unsigned end)
|
|||||||
const u64 u1 = (u0 >> 32) + (x1 & 0xffffffff) + (x0 >> 32);
|
const u64 u1 = (u0 >> 32) + (x1 & 0xffffffff) + (x0 >> 32);
|
||||||
const u64 u2 = (u1 >> 32) + (x2 & 0xffffffff) + (x1 >> 32);
|
const u64 u2 = (u1 >> 32) + (x2 & 0xffffffff) + (x1 >> 32);
|
||||||
const u64 u3 = (u2 >> 32) + (x3 & 0xffffffff) + (x2 >> 32);
|
const u64 u3 = (u2 >> 32) + (x3 & 0xffffffff) + (x2 >> 32);
|
||||||
const u64 u4 = (u3 >> 32) + (u5 & 3);
|
const u32 u4 = (u3 >> 32) + (u5 & 3); // u4 <= 4
|
||||||
|
|
||||||
// Update the hash
|
// Update the hash
|
||||||
ctx->h[0] = u0 & 0xffffffff; // u0 <= 1_9ffffff0
|
h0 = u0 & 0xffffffff;
|
||||||
ctx->h[1] = u1 & 0xffffffff; // u1 <= 1_97ffffe0
|
h1 = u1 & 0xffffffff;
|
||||||
ctx->h[2] = u2 & 0xffffffff; // u2 <= 1_8fffffe2
|
h2 = u2 & 0xffffffff;
|
||||||
ctx->h[3] = u3 & 0xffffffff; // u3 <= 1_87ffffe4
|
h3 = u3 & 0xffffffff;
|
||||||
ctx->h[4] = u4 & 0xffffffff; // u4 <= 4
|
h4 = u4;
|
||||||
|
}
|
||||||
//- # postconditions
|
ctx->h[0] = h0;
|
||||||
//- ASSERT(ctx->h[4].limit() <= 4)
|
ctx->h[1] = h1;
|
||||||
//- CQFD Poly1305
|
ctx->h[2] = h2;
|
||||||
|
ctx->h[3] = h3;
|
||||||
|
ctx->h[4] = h4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_poly1305_init(crypto_poly1305_ctx *ctx, const u8 key[32])
|
void crypto_poly1305_init(crypto_poly1305_ctx *ctx, const u8 key[32])
|
||||||
@@ -391,8 +377,13 @@ void crypto_poly1305_init(crypto_poly1305_ctx *ctx, const u8 key[32])
|
|||||||
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
|
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
|
||||||
const u8 *message, size_t message_size)
|
const u8 *message, size_t message_size)
|
||||||
{
|
{
|
||||||
|
// Avoid undefined NULL pointer increments with empty messages
|
||||||
|
if (message_size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Align ourselves with block boundaries
|
// Align ourselves with block boundaries
|
||||||
size_t aligned = MIN(align(ctx->c_idx, 16), message_size);
|
size_t aligned = MC_MIN(gap(ctx->c_idx, 16), message_size);
|
||||||
FOR (i, 0, aligned) {
|
FOR (i, 0, aligned) {
|
||||||
ctx->c[ctx->c_idx] = *message;
|
ctx->c[ctx->c_idx] = *message;
|
||||||
ctx->c_idx++;
|
ctx->c_idx++;
|
||||||
@@ -402,16 +393,14 @@ void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
|
|||||||
|
|
||||||
// If block is complete, process it
|
// If block is complete, process it
|
||||||
if (ctx->c_idx == 16) {
|
if (ctx->c_idx == 16) {
|
||||||
poly_block(ctx, ctx->c, 1);
|
poly_blocks(ctx, ctx->c, 1, 1);
|
||||||
ctx->c_idx = 0;
|
ctx->c_idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the message block by block
|
// Process the message block by block
|
||||||
size_t nb_blocks = message_size >> 4;
|
size_t nb_blocks = message_size >> 4;
|
||||||
FOR (i, 0, nb_blocks) {
|
poly_blocks(ctx, message, nb_blocks, 1);
|
||||||
poly_block(ctx, message, 1);
|
message += nb_blocks << 4;
|
||||||
message += 16;
|
|
||||||
}
|
|
||||||
message_size &= 15;
|
message_size &= 15;
|
||||||
|
|
||||||
// remaining bytes (we never complete a block here)
|
// remaining bytes (we never complete a block here)
|
||||||
@@ -429,7 +418,7 @@ void crypto_poly1305_final(crypto_poly1305_ctx *ctx, u8 mac[16])
|
|||||||
if (ctx->c_idx != 0) {
|
if (ctx->c_idx != 0) {
|
||||||
ZERO(ctx->c + ctx->c_idx, 16 - ctx->c_idx);
|
ZERO(ctx->c + ctx->c_idx, 16 - ctx->c_idx);
|
||||||
ctx->c[ctx->c_idx] = 1;
|
ctx->c[ctx->c_idx] = 1;
|
||||||
poly_block(ctx, ctx->c, 0);
|
poly_blocks(ctx, ctx->c, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we should subtract 2^130-5 by performing the
|
// check if we should subtract 2^130-5 by performing the
|
||||||
@@ -576,7 +565,7 @@ void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
|
|||||||
|
|
||||||
// Align with word boundaries
|
// Align with word boundaries
|
||||||
if ((ctx->input_idx & 7) != 0) {
|
if ((ctx->input_idx & 7) != 0) {
|
||||||
size_t nb_bytes = MIN(align(ctx->input_idx, 8), message_size);
|
size_t nb_bytes = MC_MIN(gap(ctx->input_idx, 8), message_size);
|
||||||
size_t word = ctx->input_idx >> 3;
|
size_t word = ctx->input_idx >> 3;
|
||||||
size_t byte = ctx->input_idx & 7;
|
size_t byte = ctx->input_idx & 7;
|
||||||
FOR (i, 0, nb_bytes) {
|
FOR (i, 0, nb_bytes) {
|
||||||
@@ -589,7 +578,7 @@ void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
|
|||||||
|
|
||||||
// Align with block boundaries (faster than byte by byte)
|
// Align with block boundaries (faster than byte by byte)
|
||||||
if ((ctx->input_idx & 127) != 0) {
|
if ((ctx->input_idx & 127) != 0) {
|
||||||
size_t nb_words = MIN(align(ctx->input_idx, 128), message_size) >> 3;
|
size_t nb_words = MC_MIN(gap(ctx->input_idx, 128), message_size) >> 3;
|
||||||
load64_le_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
|
load64_le_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
|
||||||
ctx->input_idx += nb_words << 3;
|
ctx->input_idx += nb_words << 3;
|
||||||
message += nb_words << 3;
|
message += nb_words << 3;
|
||||||
@@ -637,7 +626,7 @@ void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
|
|||||||
void crypto_blake2b_final(crypto_blake2b_ctx *ctx, u8 *hash)
|
void crypto_blake2b_final(crypto_blake2b_ctx *ctx, u8 *hash)
|
||||||
{
|
{
|
||||||
blake2b_compress(ctx, 1); // compress the last block
|
blake2b_compress(ctx, 1); // compress the last block
|
||||||
size_t hash_size = MIN(ctx->hash_size, 64);
|
size_t hash_size = MC_MIN(ctx->hash_size, 64);
|
||||||
size_t nb_words = hash_size >> 3;
|
size_t nb_words = hash_size >> 3;
|
||||||
store64_le_buf(hash, ctx->hash, nb_words);
|
store64_le_buf(hash, ctx->hash, nb_words);
|
||||||
FOR (i, nb_words << 3, hash_size) {
|
FOR (i, nb_words << 3, hash_size) {
|
||||||
@@ -698,7 +687,7 @@ static void extended_hash(u8 *digest, u32 digest_size,
|
|||||||
const u8 *input , u32 input_size)
|
const u8 *input , u32 input_size)
|
||||||
{
|
{
|
||||||
crypto_blake2b_ctx ctx;
|
crypto_blake2b_ctx ctx;
|
||||||
crypto_blake2b_init (&ctx, MIN(digest_size, 64));
|
crypto_blake2b_init (&ctx, MC_MIN(digest_size, 64));
|
||||||
blake_update_32 (&ctx, digest_size);
|
blake_update_32 (&ctx, digest_size);
|
||||||
crypto_blake2b_update(&ctx, input, input_size);
|
crypto_blake2b_update(&ctx, input, input_size);
|
||||||
crypto_blake2b_final (&ctx, digest);
|
crypto_blake2b_final (&ctx, digest);
|
||||||
@@ -721,12 +710,12 @@ static void extended_hash(u8 *digest, u32 digest_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LSB(x) ((x) & 0xffffffff)
|
#define LSB(x) ((u64)(u32)x)
|
||||||
#define G(a, b, c, d) \
|
#define G(a, b, c, d) \
|
||||||
a += b + 2 * LSB(a) * LSB(b); d ^= a; d = rotr64(d, 32); \
|
a += b + ((LSB(a) * LSB(b)) << 1); d ^= a; d = rotr64(d, 32); \
|
||||||
c += d + 2 * LSB(c) * LSB(d); b ^= c; b = rotr64(b, 24); \
|
c += d + ((LSB(c) * LSB(d)) << 1); b ^= c; b = rotr64(b, 24); \
|
||||||
a += b + 2 * LSB(a) * LSB(b); d ^= a; d = rotr64(d, 16); \
|
a += b + ((LSB(a) * LSB(b)) << 1); d ^= a; d = rotr64(d, 16); \
|
||||||
c += d + 2 * LSB(c) * LSB(d); b ^= c; b = rotr64(b, 63)
|
c += d + ((LSB(c) * LSB(d)) << 1); b ^= c; b = rotr64(b, 63)
|
||||||
#define ROUND(v0, v1, v2, v3, v4, v5, v6, v7, \
|
#define ROUND(v0, v1, v2, v3, v4, v5, v6, v7, \
|
||||||
v8, v9, v10, v11, v12, v13, v14, v15) \
|
v8, v9, v10, v11, v12, v13, v14, v15) \
|
||||||
G(v0, v4, v8, v12); G(v1, v5, v9, v13); \
|
G(v0, v4, v8, v12); G(v1, v5, v9, v13); \
|
||||||
@@ -874,16 +863,22 @@ void crypto_argon2(u8 *hash, u32 hash_size, void *work_area,
|
|||||||
u32 next_slice = ((slice + 1) % 4) * segment_size;
|
u32 next_slice = ((slice + 1) % 4) * segment_size;
|
||||||
u32 window_start = pass == 0 ? 0 : next_slice;
|
u32 window_start = pass == 0 ? 0 : next_slice;
|
||||||
u32 nb_segments = pass == 0 ? slice : 3;
|
u32 nb_segments = pass == 0 ? slice : 3;
|
||||||
u32 window_size = nb_segments * segment_size + block - 1;
|
u64 lane =
|
||||||
|
pass == 0 && slice == 0
|
||||||
|
? segment
|
||||||
|
: (index_seed >> 32) % config.nb_lanes;
|
||||||
|
u32 window_size =
|
||||||
|
nb_segments * segment_size +
|
||||||
|
(lane == segment ? block-1 :
|
||||||
|
block == 0 ? (u32)-1 : 0);
|
||||||
|
|
||||||
// Find reference block
|
// Find reference block
|
||||||
u64 j1 = index_seed & 0xffffffff; // block selector
|
u64 j1 = index_seed & 0xffffffff; // block selector
|
||||||
u64 j2 = index_seed >> 32; // lane selector
|
|
||||||
u64 x = (j1 * j1) >> 32;
|
u64 x = (j1 * j1) >> 32;
|
||||||
u64 y = (window_size * x) >> 32;
|
u64 y = (window_size * x) >> 32;
|
||||||
u64 z = (window_size - 1) - y;
|
u64 z = (window_size - 1) - y;
|
||||||
u64 ref = (window_start + z) % lane_size;
|
u64 ref = (window_start + z) % lane_size;
|
||||||
u32 index = (j2%config.nb_lanes)*lane_size + (u32)ref;
|
u32 index = lane * lane_size + (u32)ref;
|
||||||
blk *reference = blocks + index;
|
blk *reference = blocks + index;
|
||||||
|
|
||||||
// Shuffle the previous & reference block
|
// Shuffle the previous & reference block
|
||||||
@@ -1420,14 +1415,14 @@ static int invsqrt(fe isr, const fe x)
|
|||||||
fe_sq(t1,t0); fe_sq(t1, t1); fe_mul(t1, x, t1);
|
fe_sq(t1,t0); fe_sq(t1, t1); fe_mul(t1, x, t1);
|
||||||
fe_mul(t0, t0, t1);
|
fe_mul(t0, t0, t1);
|
||||||
fe_sq(t0, t0); fe_mul(t0, t1, t0);
|
fe_sq(t0, t0); fe_mul(t0, t1, t0);
|
||||||
fe_sq(t1, t0); FOR (i, 1, 5) fe_sq(t1, t1); fe_mul(t0, t1, t0);
|
fe_sq(t1, t0); FOR (i, 1, 5) { fe_sq(t1, t1); } fe_mul(t0, t1, t0);
|
||||||
fe_sq(t1, t0); FOR (i, 1, 10) fe_sq(t1, t1); fe_mul(t1, t1, t0);
|
fe_sq(t1, t0); FOR (i, 1, 10) { fe_sq(t1, t1); } fe_mul(t1, t1, t0);
|
||||||
fe_sq(t2, t1); FOR (i, 1, 20) fe_sq(t2, t2); fe_mul(t1, t2, t1);
|
fe_sq(t2, t1); FOR (i, 1, 20) { fe_sq(t2, t2); } fe_mul(t1, t2, t1);
|
||||||
fe_sq(t1, t1); FOR (i, 1, 10) fe_sq(t1, t1); fe_mul(t0, t1, t0);
|
fe_sq(t1, t1); FOR (i, 1, 10) { fe_sq(t1, t1); } fe_mul(t0, t1, t0);
|
||||||
fe_sq(t1, t0); FOR (i, 1, 50) fe_sq(t1, t1); fe_mul(t1, t1, t0);
|
fe_sq(t1, t0); FOR (i, 1, 50) { fe_sq(t1, t1); } fe_mul(t1, t1, t0);
|
||||||
fe_sq(t2, t1); FOR (i, 1, 100) fe_sq(t2, t2); fe_mul(t1, t2, t1);
|
fe_sq(t2, t1); FOR (i, 1, 100) { fe_sq(t2, t2); } fe_mul(t1, t2, t1);
|
||||||
fe_sq(t1, t1); FOR (i, 1, 50) fe_sq(t1, t1); fe_mul(t0, t1, t0);
|
fe_sq(t1, t1); FOR (i, 1, 50) { fe_sq(t1, t1); } fe_mul(t0, t1, t0);
|
||||||
fe_sq(t0, t0); FOR (i, 1, 2) fe_sq(t0, t0); fe_mul(t0, t0, x);
|
fe_sq(t0, t0); FOR (i, 1, 2) { fe_sq(t0, t0); } fe_mul(t0, t0, x);
|
||||||
|
|
||||||
// quartic = x^((p-1)/4)
|
// quartic = x^((p-1)/4)
|
||||||
i32 *quartic = t1;
|
i32 *quartic = t1;
|
||||||
@@ -1947,7 +1942,7 @@ static int slide_step(slide_ctx *ctx, int width, int i, const u8 scalar[32])
|
|||||||
ctx->next_check--;
|
ctx->next_check--;
|
||||||
} else {
|
} else {
|
||||||
// compute digit of next window
|
// compute digit of next window
|
||||||
int w = MIN(width, i + 1);
|
int w = MC_MIN(width, i + 1);
|
||||||
int v = -(scalar_bit(scalar, i) << (w-1));
|
int v = -(scalar_bit(scalar, i) << (w-1));
|
||||||
FOR_T (int, j, 0, w-1) {
|
FOR_T (int, j, 0, w-1) {
|
||||||
v += scalar_bit(scalar, i-(w-1)+j) << j;
|
v += scalar_bit(scalar, i-(w-1)+j) << j;
|
||||||
@@ -2006,7 +2001,7 @@ int crypto_eddsa_check_equation(const u8 signature[64], const u8 public_key[32],
|
|||||||
// Merged double and add ladder, fused with sliding
|
// Merged double and add ladder, fused with sliding
|
||||||
slide_ctx h_slide; slide_init(&h_slide, h);
|
slide_ctx h_slide; slide_init(&h_slide, h);
|
||||||
slide_ctx s_slide; slide_init(&s_slide, s);
|
slide_ctx s_slide; slide_init(&s_slide, s);
|
||||||
int i = MAX(h_slide.next_check, s_slide.next_check);
|
int i = MC_MAX(h_slide.next_check, s_slide.next_check);
|
||||||
ge *sum = &minus_A; // reuse minus_A for the sum
|
ge *sum = &minus_A; // reuse minus_A for the sum
|
||||||
ge_zero(sum);
|
ge_zero(sum);
|
||||||
while (i >= 0) {
|
while (i >= 0) {
|
||||||
@@ -2870,9 +2865,9 @@ static void lock_auth(u8 mac[16], const u8 auth_key[32],
|
|||||||
crypto_poly1305_ctx poly_ctx; // auto wiped...
|
crypto_poly1305_ctx poly_ctx; // auto wiped...
|
||||||
crypto_poly1305_init (&poly_ctx, auth_key);
|
crypto_poly1305_init (&poly_ctx, auth_key);
|
||||||
crypto_poly1305_update(&poly_ctx, ad , ad_size);
|
crypto_poly1305_update(&poly_ctx, ad , ad_size);
|
||||||
crypto_poly1305_update(&poly_ctx, zero , align(ad_size, 16));
|
crypto_poly1305_update(&poly_ctx, zero , gap(ad_size, 16));
|
||||||
crypto_poly1305_update(&poly_ctx, cipher_text, text_size);
|
crypto_poly1305_update(&poly_ctx, cipher_text, text_size);
|
||||||
crypto_poly1305_update(&poly_ctx, zero , align(text_size, 16));
|
crypto_poly1305_update(&poly_ctx, zero , gap(text_size, 16));
|
||||||
crypto_poly1305_update(&poly_ctx, sizes , 16);
|
crypto_poly1305_update(&poly_ctx, sizes , 16);
|
||||||
crypto_poly1305_final (&poly_ctx, mac); // ...here
|
crypto_poly1305_final (&poly_ctx, mac); // ...here
|
||||||
}
|
}
|
2
src/3rdparty/monocypher/monocypher.h
vendored
2
src/3rdparty/monocypher/monocypher.h
vendored
@@ -1,4 +1,4 @@
|
|||||||
// Monocypher version 4.0.1
|
// Monocypher version 4.0.2
|
||||||
//
|
//
|
||||||
// This file is dual-licensed. Choose whichever licence you want from
|
// This file is dual-licensed. Choose whichever licence you want from
|
||||||
// the two licences listed below.
|
// the two licences listed below.
|
||||||
|
@@ -10,6 +10,8 @@
|
|||||||
#include "../stdafx.h"
|
#include "../stdafx.h"
|
||||||
#include "random_func.hpp"
|
#include "random_func.hpp"
|
||||||
#include "bitmath_func.hpp"
|
#include "bitmath_func.hpp"
|
||||||
|
#include "../debug.h"
|
||||||
|
#include <atomic>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
||||||
#ifdef RANDOM_DEBUG
|
#ifdef RANDOM_DEBUG
|
||||||
@@ -21,6 +23,17 @@
|
|||||||
#include "../date_func.h"
|
#include "../date_func.h"
|
||||||
#endif /* RANDOM_DEBUG */
|
#endif /* RANDOM_DEBUG */
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
# include <bcrypt.h>
|
||||||
|
#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||||
|
// No includes required.
|
||||||
|
#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
|
||||||
|
# include <sys/random.h>
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
# include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
Randomizer _random, _interactive_random;
|
Randomizer _random, _interactive_random;
|
||||||
@@ -84,3 +97,53 @@ uint32_t DoRandomRange(uint32_t limit, int line, const char *file)
|
|||||||
return ((uint64_t)DoRandom(line, file) * (uint64_t)limit) >> 32;
|
return ((uint64_t)DoRandom(line, file) * (uint64_t)limit) >> 32;
|
||||||
}
|
}
|
||||||
#endif /* RANDOM_DEBUG */
|
#endif /* RANDOM_DEBUG */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the given buffer with random bytes.
|
||||||
|
*
|
||||||
|
* This function will attempt to use a cryptographically-strong random
|
||||||
|
* generator, but will fall back to a weaker random generator if none is
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* In the end, the buffer will always be filled with some form of random
|
||||||
|
* bytes when this function returns.
|
||||||
|
*
|
||||||
|
* @param buf The buffer to fill with random bytes.
|
||||||
|
*/
|
||||||
|
void RandomBytesWithFallback(std::span<uint8_t> buf)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
auto res = BCryptGenRandom(nullptr, static_cast<PUCHAR>(buf.data()), static_cast<ULONG>(buf.size()), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
|
||||||
|
if (res >= 0) return;
|
||||||
|
#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||||
|
arc4random_buf(buf.data(), buf.size());
|
||||||
|
return;
|
||||||
|
#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
|
||||||
|
auto res = getrandom(buf.data(), buf.size(), 0);
|
||||||
|
if (res > 0 && static_cast<size_t>(res) == buf.size()) return;
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
auto res = EM_ASM_INT({
|
||||||
|
var buf = $0;
|
||||||
|
var bytes = $1;
|
||||||
|
|
||||||
|
var crypto = window.crypto;
|
||||||
|
if (crypto === undefined || crypto.getRandomValues === undefined) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto.getRandomValues(Module.HEAPU8.subarray(buf, buf + bytes));
|
||||||
|
return 1;
|
||||||
|
}, buf.data(), buf.size());
|
||||||
|
if (res > 0) return;
|
||||||
|
#else
|
||||||
|
# warning "No cryptographically-strong random generator available; using a fallback instead"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static std::atomic<bool> warned_once = false;
|
||||||
|
bool have_warned = warned_once.exchange(true);
|
||||||
|
DEBUG(misc, have_warned ? 1 : 0, "Cryptographically-strong random generator unavailable; using fallback");
|
||||||
|
|
||||||
|
for (uint i = 0; i < buf.size(); i++) {
|
||||||
|
buf[i] = static_cast<uint8_t>(InteractiveRandom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -177,4 +177,6 @@ inline bool Chance16R(const uint a, const uint b, uint32_t &r)
|
|||||||
}
|
}
|
||||||
#endif /* RANDOM_DEBUG */
|
#endif /* RANDOM_DEBUG */
|
||||||
|
|
||||||
|
void RandomBytesWithFallback(std::span<uint8_t> buf);
|
||||||
|
|
||||||
#endif /* RANDOM_FUNC_HPP */
|
#endif /* RANDOM_FUNC_HPP */
|
||||||
|
25
src/misc.cpp
25
src/misc.cpp
@@ -42,6 +42,7 @@
|
|||||||
#include "event_logs.h"
|
#include "event_logs.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
#include "plans_func.h"
|
#include "plans_func.h"
|
||||||
|
#include "core/format.hpp"
|
||||||
#include "3rdparty/monocypher/monocypher.h"
|
#include "3rdparty/monocypher/monocypher.h"
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
@@ -75,23 +76,27 @@ void InitializeOldNames();
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a unique ID.
|
* Generate a unique ID.
|
||||||
|
*
|
||||||
|
* It isn't as much of an unique ID but more a hashed digest of a random
|
||||||
|
* string and a time. It is very likely to be unique, but it does not follow
|
||||||
|
* any UUID standard.
|
||||||
*/
|
*/
|
||||||
std::string GenerateUid(std::string_view subject)
|
std::string GenerateUid(std::string_view subject)
|
||||||
{
|
{
|
||||||
extern void NetworkRandomBytesWithFallback(void *buf, size_t n);
|
std::array<uint8_t, 32> random_bytes;
|
||||||
|
RandomBytesWithFallback(random_bytes);
|
||||||
|
|
||||||
uint8_t random_bytes[32];
|
auto current_time = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||||
NetworkRandomBytesWithFallback(random_bytes, lengthof(random_bytes));
|
std::string coding_string = fmt::format("{}{}", current_time, subject);
|
||||||
|
|
||||||
uint8_t digest[16];
|
|
||||||
|
|
||||||
|
std::array<uint8_t, 16> digest;
|
||||||
crypto_blake2b_ctx ctx;
|
crypto_blake2b_ctx ctx;
|
||||||
crypto_blake2b_init (&ctx, lengthof(digest));
|
crypto_blake2b_init(&ctx, digest.size());
|
||||||
crypto_blake2b_update(&ctx, random_bytes, lengthof(random_bytes));
|
crypto_blake2b_update(&ctx, random_bytes.data(), random_bytes.size());
|
||||||
crypto_blake2b_update(&ctx, (const byte *)subject.data(), subject.size());
|
crypto_blake2b_update(&ctx, reinterpret_cast<const uint8_t *>(coding_string.data()), coding_string.size());
|
||||||
crypto_blake2b_final (&ctx, digest);
|
crypto_blake2b_final(&ctx, digest.data());
|
||||||
|
|
||||||
return FormatArrayAsHex({digest, lengthof(digest)});
|
return FormatArrayAsHex(digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user