ctx->input[word] |= (u64)input << (byte << 3);
}
-void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx, size_t hash_size,
- const u8 *key, size_t key_size)
+// Defaults are no key, 64 byte hash
+crypto_blake2b_config crypto_blake2b_defaults = { 0, 0, 64 };
+
+void crypto_blake2b_init(crypto_blake2b_ctx *ctx, crypto_blake2b_config config)
{
// initial hash
COPY(ctx->hash, iv, 8);
- ctx->hash[0] ^= 0x01010000 ^ (key_size << 8) ^ hash_size;
+ ctx->hash[0] ^= 0x01010000 ^ (config.key_size << 8) ^ config.hash_size;
- ctx->input_offset[0] = 0; // beginning of the input, no offset
- ctx->input_offset[1] = 0; // beginning of the input, no offset
- ctx->hash_size = hash_size; // remember the hash size we want
+ ctx->input_offset[0] = 0; // beginning of the input, no offset
+ ctx->input_offset[1] = 0; // beginning of the input, no offset
+ ctx->hash_size = config.hash_size;
ctx->input_idx = 0;
// if there is a key, the first block is that key (padded with zeroes)
- if (key_size > 0) {
+ if (config.key_size > 0) {
u8 key_block[128] = {0};
- COPY(key_block, key, key_size);
+ COPY(key_block, config.key, config.key_size);
// same as calling crypto_blake2b_update(ctx, key_block , 128)
load64_le_buf(ctx->input, key_block, 16);
ctx->input_idx = 128;
}
}
-void crypto_blake2b_init(crypto_blake2b_ctx *ctx)
-{
- crypto_blake2b_general_init(ctx, 64, 0, 0);
-}
-
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
const u8 *message, size_t message_size)
{
WIPE_CTX(ctx);
}
-void crypto_blake2b_general(u8 *hash , size_t hash_size,
- const u8 *key , size_t key_size,
- const u8 *message, size_t message_size)
+void crypto_blake2b(u8 *hash, crypto_blake2b_config config,
+ const u8 *message, size_t message_size)
{
crypto_blake2b_ctx ctx;
- crypto_blake2b_general_init(&ctx, hash_size, key, key_size);
+ crypto_blake2b_init (&ctx, config);
crypto_blake2b_update(&ctx, message, message_size);
- crypto_blake2b_final(&ctx, hash);
-}
-
-void crypto_blake2b(u8 hash[64], const u8 *message, size_t message_size)
-{
- crypto_blake2b_general(hash, 64, 0, 0, message, message_size);
+ crypto_blake2b_final (&ctx, hash);
}
//////////////
static void extended_hash(u8 *digest, u32 digest_size,
const u8 *input , u32 input_size)
{
+ crypto_blake2b_config config = { 0, 0, MIN(digest_size, 64) };
crypto_blake2b_ctx ctx;
- crypto_blake2b_general_init(&ctx, MIN(digest_size, 64), 0, 0);
- blake_update_32 (&ctx, digest_size);
- crypto_blake2b_update (&ctx, input, input_size);
- crypto_blake2b_final (&ctx, digest);
+ crypto_blake2b_init (&ctx, config);
+ blake_update_32 (&ctx, digest_size);
+ crypto_blake2b_update(&ctx, input, input_size);
+ crypto_blake2b_final (&ctx, digest);
if (digest_size > 64) {
// the conversion to u64 avoids integer overflow on
u32 out = 32;
while (i < r) {
// Input and output overlap. This is intentional
- crypto_blake2b(digest + out, digest + in, 64);
+ crypto_blake2b(digest + out, crypto_blake2b_defaults,
+ digest + in, 64);
i += 1;
in += 32;
out += 32;
}
- crypto_blake2b_general(digest + out, digest_size - (32 * r),
- 0, 0, // no key
- digest + in , 64);
+ config.hash_size = digest_size - (32 * r);
+ crypto_blake2b(digest + out, config, digest + in , 64);
}
}
{
u8 initial_hash[72]; // 64 bytes plus 2 words for future hashes
crypto_blake2b_ctx ctx;
- crypto_blake2b_init (&ctx);
+ crypto_blake2b_init (&ctx, crypto_blake2b_defaults);
blake_update_32 (&ctx, config.nb_lanes ); // p: number of "threads"
blake_update_32 (&ctx, hash_size);
blake_update_32 (&ctx, config.nb_blocks);
WIPE_CTX(&P);
}
+// Input:
+// - seed.
+// Outputs:
+// - secret_key[ 0..31] = seed
+// - secret_key[32..63] = [trim(hash(seed)[0..31])]B
+// - public_key = [trim(hash(seed)[0..31])]B
+// - seed = zeroes
+//
+// Writes happen in the following order:
+// 1. seed
+// 2. secret_key[0..31]
+// 3. public_key
+// 4. secret_key[32..63]
+//
+// The point of it all is to be robust to overly clever users who
+// overlap input arguments:
+// - We don' care if the seed is overwritten.
+// - Everything still works when public_key == secret_key + 32.
void crypto_eddsa_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
{
u8 a[64];
- COPY(a, seed, 32); // a[ 0..31] = seed
+ COPY(a, seed, 32);
crypto_wipe(seed, 32);
- COPY(secret_key, a, 32); // secret key = seed
- crypto_blake2b(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
+ COPY(secret_key, a, 32);
+ crypto_blake2b(a, crypto_blake2b_defaults, a, 32);
+ crypto_eddsa_trim_scalar(a, a);
+ crypto_eddsa_scalarbase(public_key, a);
+ COPY(secret_key + 32, public_key, 32);
WIPE_BUFFER(a);
}
{
u8 hash[64];
crypto_blake2b_ctx ctx;
- crypto_blake2b_init (&ctx);
+ crypto_blake2b_init (&ctx, crypto_blake2b_defaults);
crypto_blake2b_update(&ctx, a, a_size);
crypto_blake2b_update(&ctx, b, b_size);
crypto_blake2b_update(&ctx, c, c_size);
u8 h[32]; // publically verifiable hash of the message (not wiped)
u8 R[32]; // first half of the signature (allows overlapping inputs)
- crypto_blake2b(a, secret_key, 32);
+ crypto_blake2b(a, crypto_blake2b_defaults, secret_key, 32);
crypto_eddsa_trim_scalar(a, a);
hash_reduce(r, a + 32, 32, message, message_size, 0, 0);
crypto_eddsa_scalarbase(R, r);
// General purpose hash (BLAKE2b)
// ------------------------------
+typedef struct {
+ const uint8_t *key;
+ size_t key_size;
+ size_t hash_size;
+} crypto_blake2b_config;
+
+extern crypto_blake2b_config crypto_blake2b_defaults;
+
// Direct interface
-void crypto_blake2b(uint8_t hash[64],
+void crypto_blake2b(uint8_t *hash, crypto_blake2b_config config,
const uint8_t *message, size_t message_size);
-void crypto_blake2b_general(uint8_t *hash , size_t hash_size,
- const uint8_t *key , size_t key_size, // optional
- const uint8_t *message, size_t message_size);
-
// Incremental interface
typedef struct {
// Do not rely on the size or contents of this type,
size_t hash_size;
} crypto_blake2b_ctx;
-void crypto_blake2b_init (crypto_blake2b_ctx *ctx);
+void crypto_blake2b_init(crypto_blake2b_ctx *ctx, crypto_blake2b_config config);
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
const uint8_t *message, size_t message_size);
-void crypto_blake2b_final (crypto_blake2b_ctx *ctx, uint8_t *hash);
-
-void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx, size_t hash_size,
- const uint8_t *key, size_t key_size);
+void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
// Password key derivation (Argon2)
vector msg = next_input(reader);
vector key = next_input(reader);
vector out = next_output(reader);
- crypto_blake2b_general(out.buf, out.size,
- key.buf, key.size,
- msg.buf, msg.size);
+ crypto_blake2b_config config = { key.buf, key.size, out.size, };
+ crypto_blake2b(out.buf, config, msg.buf, msg.size);
}
static void test_blake2b()
// Authenticate bit by bit
crypto_blake2b_ctx ctx;
- crypto_blake2b_init(&ctx);
+ crypto_blake2b_init(&ctx, crypto_blake2b_defaults);
crypto_blake2b_update(&ctx, input , i);
crypto_blake2b_update(&ctx, input + i, INPUT_SIZE - i);
crypto_blake2b_final(&ctx, hash_chunk);
// Authenticate all at once
- crypto_blake2b(hash_whole, input, INPUT_SIZE);
+ crypto_blake2b(hash_whole, crypto_blake2b_defaults, input, INPUT_SIZE);
// Compare the results (must be the same)
ASSERT_EQUAL(hash_chunk, hash_whole, 64);
FOR (i, 0, BLAKE2B_BLOCK_SIZE + 64) {
u8 hash [64];
RANDOM_INPUT(input, INPUT_SIZE);
- crypto_blake2b(hash , input + 64, BLAKE2B_BLOCK_SIZE);
- crypto_blake2b(input+i, input + 64, BLAKE2B_BLOCK_SIZE);
+ crypto_blake2b_config config = crypto_blake2b_defaults;
+ crypto_blake2b(hash , config, input + 64, BLAKE2B_BLOCK_SIZE);
+ crypto_blake2b(input+i, config, input + 64, BLAKE2B_BLOCK_SIZE);
ASSERT_EQUAL(hash, input + i, 64);
}
}
{
printf("\tX25519 <-> EdDSA\n");
FOR (i, 0, 32) {
+ crypto_blake2b_config config = crypto_blake2b_defaults;
RANDOM_INPUT(e_seed, 32);
- u8 secret [64];
+ u8 secret [64];
u8 e_public1[32]; crypto_eddsa_key_pair(secret, e_public1, e_seed);
- u8 x_private[64]; crypto_blake2b (x_private, secret, 32);
+ u8 x_private[64]; crypto_blake2b(x_private, config, secret, 32);
u8 x_public1[32]; crypto_eddsa_to_x25519 (x_public1, e_public1);
u8 x_public2[32]; crypto_x25519_public_key(x_public2, x_private);
ASSERT_EQUAL(x_public1, x_public2, 32);