commit d9955ba697a3ef0d5d248c633705a7fb953d70f0
parent deb315bc225a227e18d4dc19da17f8c36c01fa65
Author: Michael Savage <mikejsavage@gmail.com>
Date: Wed, 25 Oct 2017 20:04:27 +0300
Monocypher 1.0.1
Diffstat:
2 files changed, 446 insertions(+), 276 deletions(-)
diff --git a/libs/monocypher/monocypher.cc b/libs/monocypher/monocypher.cc
@@ -22,13 +22,19 @@
#define HASH_FINAL COMBINE2(HASH, _final)
#define FOR(i, start, end) for (size_t (i) = (start); (i) < (end); (i)++)
-#define sv static void
-typedef uint8_t u8;
+typedef uint8_t u8;
typedef uint32_t u32;
-typedef int32_t i32;
-typedef int64_t i64;
+typedef int32_t i32;
+typedef int64_t i64;
typedef uint64_t u64;
+static u32 load24_le(const u8 s[3])
+{
+ return (u32)s[0]
+ | ((u32)s[1] << 8)
+ | ((u32)s[2] << 16);
+}
+
static u32 load32_le(const u8 s[4])
{
return (u32)s[0]
@@ -49,24 +55,24 @@ static u64 load64_le(const u8 s[8])
| ((u64)s[7] << 56);
}
-sv store32_le(u8 output[4], u32 input)
+static void store32_le(u8 out[4], u32 in)
{
- output[0] = input & 0xff;
- output[1] = (input >> 8) & 0xff;
- output[2] = (input >> 16) & 0xff;
- output[3] = (input >> 24) & 0xff;
+ out[0] = in & 0xff;
+ out[1] = (in >> 8) & 0xff;
+ out[2] = (in >> 16) & 0xff;
+ out[3] = (in >> 24) & 0xff;
}
-sv store64_le(u8 output[8], u64 input)
+static void store64_le(u8 out[8], u64 in)
{
- output[0] = input & 0xff;
- output[1] = (input >> 8) & 0xff;
- output[2] = (input >> 16) & 0xff;
- output[3] = (input >> 24) & 0xff;
- output[4] = (input >> 32) & 0xff;
- output[5] = (input >> 40) & 0xff;
- output[6] = (input >> 48) & 0xff;
- output[7] = (input >> 56) & 0xff;
+ out[0] = in & 0xff;
+ out[1] = (in >> 8) & 0xff;
+ out[2] = (in >> 16) & 0xff;
+ out[3] = (in >> 24) & 0xff;
+ out[4] = (in >> 32) & 0xff;
+ out[5] = (in >> 40) & 0xff;
+ out[6] = (in >> 48) & 0xff;
+ out[7] = (in >> 56) & 0xff;
}
static u64 rotr64(u64 x, u64 n) { return (x >> n) ^ (x << (64 - n)); }
@@ -75,14 +81,18 @@ static u32 rotl32(u32 x, u32 n) { return (x << n) ^ (x >> (32 - n)); }
int crypto_memcmp(const u8 *p1, const u8 *p2, size_t n)
{
unsigned diff = 0;
- FOR (i, 0, n) { diff |= (p1[i] ^ p2[i]); }
+ FOR (i, 0, n) {
+ diff |= (p1[i] ^ p2[i]);
+ }
return (1 & ((diff - 1) >> 8)) - 1;
}
int crypto_zerocmp(const u8 *p, size_t n)
{
unsigned diff = 0;
- FOR (i, 0, n) { diff |= p[i]; }
+ FOR (i, 0, n) {
+ diff |= p[i];
+ }
return (1 & ((diff - 1) >> 8)) - 1;
}
@@ -95,7 +105,7 @@ int crypto_zerocmp(const u8 *p, size_t n)
a += b; d ^= a; d = rotl32(d, 8); \
c += d; b ^= c; b = rotl32(b, 7)
-sv chacha20_rounds(u32 out[16], const u32 in[16])
+static void chacha20_rounds(u32 out[16], const u32 in[16])
{
// The temporary variables make Chacha20 10% faster.
u32 t0 = in[ 0]; u32 t1 = in[ 1]; u32 t2 = in[ 2]; u32 t3 = in[ 3];
@@ -119,7 +129,7 @@ sv chacha20_rounds(u32 out[16], const u32 in[16])
out[12] = t12; out[13] = t13; out[14] = t14; out[15] = t15;
}
-sv chacha20_init_key(crypto_chacha_ctx *ctx, const u8 key[32])
+static void chacha20_init_key(crypto_chacha_ctx *ctx, const u8 key[32])
{
// constant
ctx->input[0] = load32_le((u8*)"expa");
@@ -132,6 +142,30 @@ sv chacha20_init_key(crypto_chacha_ctx *ctx, const u8 key[32])
}
}
+static u8 chacha20_pool_byte(crypto_chacha_ctx *ctx)
+{
+ u32 pool_word = ctx->pool[ctx->pool_idx / 4];
+ u8 pool_byte = pool_word >> (8*(ctx->pool_idx % 4));
+ ctx->pool_idx++;
+ return pool_byte;
+}
+
+// Fill the pool if needed, update the counters
+static void chacha20_refill_pool(crypto_chacha_ctx *ctx)
+{
+ if (ctx->pool_idx == 64) {
+ chacha20_rounds(ctx->pool, ctx->input);
+ FOR (j, 0, 16) {
+ ctx->pool[j] += ctx->input[j];
+ }
+ ctx->pool_idx = 0;
+ ctx->input[12]++;
+ if (ctx->input[12] == 0) {
+ ctx->input[13]++;
+ }
+ }
+}
+
void crypto_chacha20_H(u8 out[32], const u8 key[32], const u8 in[16])
{
crypto_chacha_ctx ctx;
@@ -152,8 +186,8 @@ void crypto_chacha20_init(crypto_chacha_ctx *ctx,
const u8 key[32],
const u8 nonce[8])
{
- chacha20_init_key(ctx, key ); // key
- crypto_chacha20_set_ctr(ctx, 0); // counter
+ chacha20_init_key (ctx, key); // key
+ crypto_chacha20_set_ctr(ctx, 0 ); // counter
ctx->input[14] = load32_le(nonce + 0); // nonce
ctx->input[15] = load32_le(nonce + 4); // nonce
}
@@ -169,35 +203,53 @@ void crypto_chacha20_x_init(crypto_chacha_ctx *ctx,
void crypto_chacha20_set_ctr(crypto_chacha_ctx *ctx, u64 ctr)
{
- ctx->input[12] = ctr & 0xffffffff;
- ctx->input[13] = ctr >> 32;
- ctx->pool_index = 64; // The random pool (re)starts empty
+ ctx->input[12] = ctr & 0xffffffff;
+ ctx->input[13] = ctr >> 32;
+ ctx->pool_idx = 64; // The random pool (re)starts empty
}
void crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
u8 *cipher_text,
const u8 *plain_text,
- size_t message_size)
-{
- FOR (i, 0, message_size) {
- // refill the pool if empty
- if (ctx->pool_index == 64) {
- // fill the pool
- u32 buffer[16];
- chacha20_rounds(buffer, ctx->input);
- FOR (j, 0, 16) {
- store32_le(ctx->random_pool + j*4, buffer[j] + ctx->input[j]);
- }
- // update the counters
- ctx->pool_index = 0;
- ctx->input[12]++;
- if (ctx->input[12] == 0) { ctx->input[13]++; }
+ size_t text_size)
+{
+ // Align ourselves with 4 byte words
+ while (ctx->pool_idx % 4 != 0 && text_size > 0) {
+ u8 stream = chacha20_pool_byte(ctx);
+ u8 plain = 0;
+ if (plain_text != 0) {
+ plain = *plain_text;
+ plain_text++;
}
- // use the pool for encryption (or random stream)
- cipher_text[i] =
- (plain_text == 0 ? 0 : plain_text[i]) // ignore null plaintext
- ^ ctx->random_pool[ctx->pool_index];
- ctx->pool_index++;
+ *cipher_text = stream ^ plain;
+ text_size--;
+ cipher_text++;
+ }
+ // Main processing by 4 byte chunks
+ size_t nb_words = text_size / 4;
+ size_t remainder = text_size % 4;
+ FOR (i, 0, nb_words) {
+ chacha20_refill_pool(ctx);
+ u32 txt = 0;
+ if (plain_text) {
+ txt = load32_le(plain_text);
+ plain_text += 4;
+ }
+ store32_le(cipher_text, ctx->pool[ctx->pool_idx / 4] ^ txt);
+ cipher_text += 4;
+ ctx->pool_idx += 4;
+ }
+ // Remaining input, byte by byte
+ FOR (i, 0, remainder) {
+ chacha20_refill_pool(ctx);
+ u8 stream = chacha20_pool_byte(ctx);
+ u8 plain = 0;
+ if (plain_text != 0) {
+ plain = *plain_text;
+ plain_text++;
+ }
+ *cipher_text = stream ^ plain;
+ cipher_text++;
}
}
@@ -219,7 +271,7 @@ void crypto_chacha20_stream(crypto_chacha_ctx *ctx,
// ctx->r <= 0ffffffc_0ffffffc_0ffffffc_0fffffff
// Postcondition:
// ctx->h <= 4_87ffffe4_8fffffe2_97ffffe0_9ffffffa
-sv poly_block(crypto_poly1305_ctx *ctx)
+static void poly_block(crypto_poly1305_ctx *ctx)
{
// s = h + c, without carry propagation
const u64 s0 = ctx->h[0] + (u64)ctx->c[0]; // s0 <= 1_fffffffe
@@ -234,9 +286,9 @@ sv poly_block(crypto_poly1305_ctx *ctx)
const u32 r2 = ctx->r[2]; // r2 <= 0ffffffc
const u32 r3 = ctx->r[3]; // r3 <= 0ffffffc
const u32 rr0 = (r0 >> 2) * 5; // rr0 <= 13fffffb // lose 2 bits...
- const u32 rr1 = (r1 >> 2) + r1; // rr1 <= 13fffffb // * 5 trick
- const u32 rr2 = (r2 >> 2) + r2; // rr2 <= 13fffffb // * 5 trick
- const u32 rr3 = (r3 >> 2) + r3; // rr3 <= 13fffffb // * 5 trick
+ const u32 rr1 = (r1 >> 2) + r1; // rr1 <= 13fffffb // rr1 == (r1 >> 2) * 5
+ const u32 rr2 = (r2 >> 2) + r2; // rr2 <= 13fffffb // rr1 == (r2 >> 2) * 5
+ const u32 rr3 = (r3 >> 2) + r3; // rr3 <= 13fffffb // rr1 == (r3 >> 2) * 5
// (h + c) * r, without carry propagation
const u64 x0 = s0*r0 + s1*rr3 + s2*rr2 + s3*rr1 + s4*rr0;//<=97ffffe007fffff8
@@ -262,47 +314,82 @@ sv poly_block(crypto_poly1305_ctx *ctx)
}
// (re-)initializes the input counter and input buffer
-sv poly_clear_c(crypto_poly1305_ctx *ctx)
+static void poly_clear_c(crypto_poly1305_ctx *ctx)
+{
+ FOR (i, 0, 4) {
+ ctx->c[i] = 0;
+ }
+ ctx->c_idx = 0;
+}
+
+static void poly_end_block(crypto_poly1305_ctx *ctx)
+{
+ if (ctx->c_idx == 16) {
+ poly_block(ctx);
+ poly_clear_c(ctx);
+ }
+}
+
+static void poly_take_input(crypto_poly1305_ctx *ctx, u8 input)
{
- FOR (i, 0, 4) { ctx->c[i] = 0; }
- ctx->c_index = 0;
+ size_t word = ctx->c_idx / 4;
+ size_t byte = ctx->c_idx % 4;
+ ctx->c[word] |= (u32)input << (byte * 8);
+ ctx->c_idx++;
}
void crypto_poly1305_init(crypto_poly1305_ctx *ctx, const u8 key[32])
{
- // constant init
- FOR (i, 0, 5) { ctx->h [i] = 0; } // initial hash: zero
- ctx->c [4] = 1; // add 2^130 to every input block
- ctx->pad[4] = 0; // poly_add() compatibility
+ // Initial hash is zero
+ FOR (i, 0, 5) {
+ ctx->h [i] = 0;
+ }
+ // add 2^130 to every input block
+ ctx->c [4] = 1;
poly_clear_c(ctx);
// load r and pad (r has some of its bits cleared)
- /**/ ctx->r [0] = load32_le(key ) & 0x0fffffff;
- FOR (i, 1, 4) { ctx->r [i] = load32_le(key + i*4) & 0x0ffffffc; }
- FOR (i, 0, 4) { ctx->pad[i] = load32_le(key + i*4 + 16); }
+ FOR (i, 0, 1) { ctx->r [0] = load32_le(key ) & 0x0fffffff; }
+ FOR (i, 1, 4) { ctx->r [i] = load32_le(key + i*4 ) & 0x0ffffffc; }
+ FOR (i, 0, 4) { ctx->pad[i] = load32_le(key + i*4 + 16); }
}
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
- const u8 *msg, size_t msg_size)
+ const u8 *message, size_t message_size)
{
- FOR (i, 0, msg_size) {
- if (ctx->c_index == 16) {
- poly_block(ctx);
- poly_clear_c(ctx);
- }
- // feed the input buffer
- ctx->c[ctx->c_index / 4] |= (u32)msg[i] << ((ctx->c_index % 4) * 8);
- ctx->c_index++;
+ // Align ourselves with 4 byte words
+ while (ctx->c_idx % 4 != 0 && message_size > 0) {
+ poly_take_input(ctx, *message);
+ message++;
+ message_size--;
+ }
+
+ // Process the input 4 bytes at a time
+ size_t nb_words = message_size / 4;
+ size_t remainder = message_size % 4;
+ FOR (i, 0, nb_words) {
+ poly_end_block(ctx);
+ ctx->c[ctx->c_idx / 4] = load32_le(message);
+ message += 4;
+ ctx->c_idx += 4;
+ }
+
+ // Input the remaining bytes
+ if (remainder != 0) {
+ poly_end_block(ctx);
+ }
+ FOR (i, 0, remainder) {
+ poly_take_input(ctx, message[i]);
}
}
void crypto_poly1305_final(crypto_poly1305_ctx *ctx, u8 mac[16])
{
// Process the last block (if any)
- if (ctx->c_index != 0) {
+ if (ctx->c_idx != 0) {
// move the final 1 according to remaining input length
// (We may add less than 2^130 to the last input block)
ctx->c[4] = 0;
- ctx->c[ctx->c_index / 4] |= (u32)1 << ((ctx->c_index % 4) * 8);
+ poly_take_input(ctx, 1);
// one last hash update
poly_block(ctx);
}
@@ -325,12 +412,12 @@ void crypto_poly1305_final(crypto_poly1305_ctx *ctx, u8 mac[16])
u += (i64)(ctx->h[3]) + ctx->pad[3]; store32_le(mac + 12, u);
}
-void crypto_poly1305_auth(u8 mac[16], const u8 *msg,
- size_t msg_size, const u8 key[32])
+void crypto_poly1305_auth(u8 mac[16], const u8 *message,
+ size_t message_size, const u8 key[32])
{
crypto_poly1305_ctx ctx;
crypto_poly1305_init (&ctx, key);
- crypto_poly1305_update(&ctx, msg, msg_size);
+ crypto_poly1305_update(&ctx, message, message_size);
crypto_poly1305_final (&ctx, mac);
}
@@ -345,22 +432,25 @@ static const u64 iv[8] = {
};
// increment the input offset
-sv incr(crypto_blake2b_ctx *ctx)
+static void blake2b_incr(crypto_blake2b_ctx *ctx)
{
u64 *x = ctx->input_offset;
- size_t y = ctx->buffer_idx;
- x[0] += y; // increment low word
- if (x[0] < y) { x[1]++; } // carry overflow to high word
+ size_t y = ctx->input_idx;
+ x[0] += y;
+ if (x[0] < y) {
+ x[1]++;
+ }
}
-// pad the buffer with zeroes
-sv pad(crypto_blake2b_ctx *ctx)
+static void blake2b_set_input(crypto_blake2b_ctx *ctx, u8 input)
{
- FOR (i, ctx->buffer_idx, 128) { ctx->buffer[i] = 0; }
- ctx->buffer_idx = 128; // mark the buffer as filled
+ size_t word = ctx->input_idx / 8;
+ size_t byte = ctx->input_idx % 8;
+ ctx->input[word] |= (u64)input << (byte * 8);
+ ctx->input_idx++;
}
-sv compress(crypto_blake2b_ctx *ctx, int is_last_block)
+static void blake2b_compress(crypto_blake2b_ctx *ctx, int is_last_block)
{
static const u8 sigma[12][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
@@ -377,10 +467,6 @@ sv compress(crypto_blake2b_ctx *ctx, int is_last_block)
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
};
- // load input buffer
- u64 input[16];
- FOR(i, 0, 16) { input[i] = load64_le(ctx->buffer + i*8); }
-
// init work vector
u64 v[16];
FOR (i, 0, 8) {
@@ -389,9 +475,12 @@ sv compress(crypto_blake2b_ctx *ctx, int is_last_block)
}
v[12] ^= ctx->input_offset[0];
v[13] ^= ctx->input_offset[1];
- if (is_last_block) { v[14] = ~v[14]; }
+ if (is_last_block) {
+ v[14] = ~v[14];
+ }
// mangle work vector
+ uint64_t *input = ctx->input;
FOR (i, 0, 12) {
#define BLAKE2_G(v, a, b, c, d, x, y) \
v[a] += v[b] + x; v[d] = rotr64(v[d] ^ v[a], 32); \
@@ -409,27 +498,47 @@ sv compress(crypto_blake2b_ctx *ctx, int is_last_block)
BLAKE2_G(v, 3, 4, 9, 14, input[sigma[i][14]], input[sigma[i][15]]);
}
// update hash
- FOR (i, 0, 8) { ctx->hash[i] ^= v[i] ^ v[i+8]; }
- // mark buffer as empty
- ctx->buffer_idx = 0;
+ FOR (i, 0, 8) {
+ ctx->hash[i] ^= v[i] ^ v[i+8];
+ }
+}
+
+static void blake2b_reset_input(crypto_blake2b_ctx *ctx)
+{
+ FOR(i, 0, 16) {
+ ctx->input[i] = 0;
+ }
+ ctx->input_idx = 0;
+}
+
+static void blake2b_end_block(crypto_blake2b_ctx *ctx)
+{
+ if (ctx->input_idx == 128) { // If buffer is full,
+ blake2b_incr(ctx); // update the input offset
+ blake2b_compress(ctx, 0); // and compress the (not last) block
+ blake2b_reset_input(ctx);
+ }
}
-void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx, size_t out_size,
+void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx, size_t hash_size,
const u8 *key, size_t key_size)
{
// initial hash
- FOR (i, 0, 8) { ctx->hash[i] = iv[i]; }
- ctx->hash[0] ^= 0x01010000 ^ (key_size << 8) ^ out_size;
+ FOR (i, 0, 8) {
+ ctx->hash[i] = iv[i];
+ }
+ ctx->hash[0] ^= 0x01010000 ^ (key_size << 8) ^ hash_size;
ctx->input_offset[0] = 0; // begining of the input, no offset
ctx->input_offset[1] = 0; // begining of the input, no offset
- ctx->buffer_idx = 0; // buffer is empty
- ctx->hash_size = out_size; // remember the hash size we want
+ ctx->input_idx = 0; // buffer is empty
+ ctx->hash_size = hash_size; // remember the hash size we want
+ blake2b_reset_input(ctx); // clear the input buffer
// if there is a key, the first block is that key
if (key_size > 0) {
crypto_blake2b_update(ctx, key, key_size);
- pad(ctx);
+ ctx->input_idx = 128;
}
}
@@ -438,41 +547,61 @@ 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 *in, size_t in_size)
+void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
+ const u8 *message, size_t message_size)
{
- FOR (i, 0, in_size) {
- if (ctx->buffer_idx == 128) { // If buffer is full,
- incr(ctx); // update the input offset
- compress(ctx, 0); // compress the (not last) block
- }
- ctx->buffer[ctx->buffer_idx] = in[i];
- ctx->buffer_idx++;
+ // Align ourselves with 8 byte words
+ while (ctx->input_idx % 8 != 0 && message_size > 0) {
+ blake2b_set_input(ctx, *message);
+ message++;
+ message_size--;
+ }
+
+ // Process the input 8 bytes at a time
+ size_t nb_words = message_size / 8;
+ size_t remainder = message_size % 8;
+ FOR (i, 0, nb_words) {
+ blake2b_end_block(ctx);
+ ctx->input[ctx->input_idx / 8] = load64_le(message);
+ message += 8;
+ ctx->input_idx += 8;
+ }
+
+ // Load the remainder
+ if (remainder != 0) {
+ blake2b_end_block(ctx);
+ }
+ FOR (i, 0, remainder) {
+ blake2b_set_input(ctx, message[i]);
}
}
-void crypto_blake2b_final(crypto_blake2b_ctx *ctx, u8 *out)
+void crypto_blake2b_final(crypto_blake2b_ctx *ctx, u8 *hash)
{
- incr(ctx); // update the input offset (the last block may not be full)
- pad(ctx); // pad the last block with zeroes
- compress(ctx, 1); // compress the last block
- FOR (i, 0, ctx->hash_size) {
- out[i] = (ctx->hash[i / 8] >> (8 * (i & 7))) & 0xff;
+ blake2b_incr(ctx); // update the input offset
+ blake2b_compress(ctx, 1); // compress the last block
+ size_t nb_words = ctx->hash_size / 8;
+ FOR (i, 0, nb_words) {
+ store64_le(hash + i*8, ctx->hash[i]);
+ }
+ FOR (i, nb_words * 8, ctx->hash_size) {
+ hash[i] = (ctx->hash[i / 8] >> (8 * (i % 8))) & 0xff;
}
}
-void crypto_blake2b_general(u8 *out, size_t out_size,
- const u8 *key, size_t key_size,
- const u8 *in, size_t in_size)
+void crypto_blake2b_general(u8 *hash , size_t hash_size,
+ const u8 *key , size_t key_size,
+ const u8 *message, size_t message_size)
{
crypto_blake2b_ctx ctx;
- crypto_blake2b_general_init(&ctx, out_size, key, key_size);
- crypto_blake2b_update(&ctx, in, in_size);
- crypto_blake2b_final(&ctx, out);
+ crypto_blake2b_general_init(&ctx, hash_size, key, key_size);
+ crypto_blake2b_update(&ctx, message, message_size);
+ crypto_blake2b_final(&ctx, hash);
}
-void crypto_blake2b(u8 out[64], const u8 *in, size_t in_size)
+void crypto_blake2b(u8 hash[64], const u8 *message, size_t message_size)
{
- crypto_blake2b_general(out, 64, 0, 0, in, in_size);
+ crypto_blake2b_general(hash, 64, 0, 0, message, message_size);
}
@@ -481,38 +610,43 @@ void crypto_blake2b(u8 out[64], const u8 *in, size_t in_size)
////////////////
// references to R, Z, Q etc. come from the spec
-typedef struct { u64 a[128]; } block; // 1024 octets
+// Argon2 operates on 1024 byte blocks.
+typedef struct { u64 a[128]; } block;
static u32 min(u32 a, u32 b) { return a <= b ? a : b; }
// updates a blake2 hash with a 32 bit word, little endian.
-sv blake_update_32(crypto_blake2b_ctx *ctx, u32 input)
+static void blake_update_32(crypto_blake2b_ctx *ctx, u32 input)
{
u8 buf[4];
store32_le(buf, input);
crypto_blake2b_update(ctx, buf, 4);
}
-sv load_block(block *b, const u8 bytes[1024])
+static void load_block(block *b, const u8 bytes[1024])
{
- FOR (i, 0, 128) { b->a[i] = load64_le(bytes + i*8); }
+ FOR (i, 0, 128) {
+ b->a[i] = load64_le(bytes + i*8);
+ }
}
-sv store_block(u8 bytes[1024], const block *b)
+static void store_block(u8 bytes[1024], const block *b)
{
- FOR (i, 0, 128) { store64_le(bytes + i*8, b->a[i]); }
+ FOR (i, 0, 128) {
+ store64_le(bytes + i*8, b->a[i]);
+ }
}
-// type of copy_block() and xor_block()
-typedef void (*copy_fun) (block*, const block*);
-sv copy_block(block *o, const block *in) { FOR (i, 0, 128) o->a[i] = in->a[i]; }
-sv xor_block(block *o, const block *in) { FOR (i, 0, 128) o->a[i] ^= in->a[i]; }
+static void copy_block(block *o,const block*in){FOR(i,0,128) o->a[i] = in->a[i];}
+static void xor_block(block *o,const block*in){FOR(i,0,128) o->a[i]^= in->a[i];}
// Hash with a virtually unlimited digest size.
// Doesn't extract more entropy than the base hash function.
// Mainly used for filling a whole kilobyte block with pseudo-random bytes.
-sv extended_hash(u8 *digest, u32 digest_size,
- const u8 *input , u32 input_size)
+// (One could use a stream cipher with a seed hash as the key, but
+// this would introduce another dependency —and point of failure.)
+static void extended_hash(u8 *digest, u32 digest_size,
+ const u8 *input , u32 input_size)
{
crypto_blake2b_ctx ctx;
crypto_blake2b_general_init(&ctx, min(digest_size, 64), 0, 0);
@@ -554,7 +688,7 @@ sv extended_hash(u8 *digest, u32 digest_size,
G(v2, v7, v8, v13); G(v3, v4, v9, v14)
// Core of the compression function G. Computes Z from R in place.
-sv g_rounds(block *work_block)
+static void g_rounds(block *work_block)
{
// column rounds (work_block = Q)
for (int i = 0; i < 128; i += 16) {
@@ -581,31 +715,31 @@ sv g_rounds(block *work_block)
}
// The compression function G (copy version for the first pass)
-sv g_copy(block *result, const block *x, const block *y)
+static void g_copy(block *result, const block *x, const block *y)
{
block tmp;
- copy_block(&tmp, x); // tmp = X
- xor_block (&tmp, y); // tmp = X ^ Y = R
- copy_block(result, &tmp);// result = R
- g_rounds(&tmp); // tmp = Z
- xor_block(result, &tmp); // result = R ^ Z
+ copy_block(&tmp , x ); // tmp = X
+ xor_block (&tmp , y ); // tmp = X ^ Y = R
+ copy_block(result, &tmp); // result = R (only difference with g_xor)
+ g_rounds (&tmp); // tmp = Z
+ xor_block (result, &tmp); // result = R ^ Z
}
// The compression function G (xor version for subsequent passes)
-sv g_xor(block *result, const block *x, const block *y)
+static void g_xor(block *result, const block *x, const block *y)
{
block tmp;
- copy_block(&tmp, x); // tmp = X
- xor_block (&tmp, y); // tmp = X ^ Y = R
- xor_block(result, &tmp); // result = R ^ old
- g_rounds(&tmp); // tmp = Z
- xor_block(result, &tmp); // result = R ^ old ^ Z
+ copy_block(&tmp , x ); // tmp = X
+ xor_block (&tmp , y ); // tmp = X ^ Y = R
+ xor_block (result, &tmp); // result = R ^ old (only difference with g_copy)
+ g_rounds (&tmp); // tmp = Z
+ xor_block (result, &tmp); // result = R ^ old ^ Z
}
// unary version of the compression function.
// The missing argument is implied zero.
// Does the transformation in place.
-sv unary_g(block *work_block)
+static void unary_g(block *work_block)
{
// work_block == R
block tmp;
@@ -614,14 +748,25 @@ sv unary_g(block *work_block)
xor_block(work_block, &tmp); // work_block = Z ^ R
}
+// Argon2i uses a kind of stream cipher to determine which reference
+// block it will take to synthesise the next block. This context hold
+// that stream's state. (It's very similar to Chacha20. The block b
+// is anologous to Chacha's own pool)
typedef struct {
block b;
- u32 pass_number; u32 slice_number;
- u32 nb_blocks; u32 nb_iterations;
- u32 ctr; u32 offset;
+ u32 pass_number;
+ u32 slice_number;
+ u32 nb_blocks;
+ u32 nb_iterations;
+ u32 ctr;
+ u32 offset;
} gidx_ctx;
-sv gidx_refresh(gidx_ctx *ctx)
+// The block in the context will determine array indices. To avoid
+// timing attacks, it only depends on public information. No looking
+// at a previous block to seed the next. This makes offline attacks
+// easier, but timing attacks are the bigger threat in many settings.
+static void gidx_refresh(gidx_ctx *ctx)
{
// seed the begining of the block...
ctx->b.a[0] = ctx->pass_number;
@@ -639,9 +784,9 @@ sv gidx_refresh(gidx_ctx *ctx)
unary_g(&(ctx->b));
}
-sv gidx_init(gidx_ctx *ctx,
- u32 pass_number, u32 slice_number,
- u32 nb_blocks, u32 nb_iterations)
+static void gidx_init(gidx_ctx *ctx,
+ u32 pass_number, u32 slice_number,
+ u32 nb_blocks, u32 nb_iterations)
{
ctx->pass_number = pass_number;
ctx->slice_number = slice_number;
@@ -650,7 +795,7 @@ sv gidx_init(gidx_ctx *ctx,
ctx->ctr = 0;
// Offset from the begining of the segment. For the first slice
- // of the firs pass, we start at the *third* block, so the offset
+ // of the first pass, we start at the *third* block, so the offset
// starts at 2, not 0.
if (pass_number != 0 || slice_number != 0) {
ctx->offset = 0;
@@ -698,7 +843,7 @@ static u32 gidx_next(gidx_ctx *ctx)
}
// Main algorithm
-void crypto_argon2i(u8 *tag, u32 tag_size,
+void crypto_argon2i(u8 *hash, u32 hash_size,
void *work_area, u32 nb_blocks, u32 nb_iterations,
const u8 *password, u32 password_size,
const u8 *salt, u32 salt_size,
@@ -712,7 +857,7 @@ void crypto_argon2i(u8 *tag, u32 tag_size,
crypto_blake2b_init(&ctx);
blake_update_32 (&ctx, 1 ); // p: number of threads
- blake_update_32 (&ctx, tag_size );
+ blake_update_32 (&ctx, hash_size );
blake_update_32 (&ctx, nb_blocks );
blake_update_32 (&ctx, nb_iterations);
blake_update_32 (&ctx, 0x13 ); // v: version number
@@ -750,7 +895,7 @@ void crypto_argon2i(u8 *tag, u32 tag_size,
// fill (then re-fill) the rest of the blocks
FOR (pass_number, 0, nb_iterations) {
- int first_pass = pass_number == 0;
+ int first_pass = pass_number == 0;
FOR (segment, 0, 4) {
gidx_ctx ctx;
@@ -775,29 +920,29 @@ void crypto_argon2i(u8 *tag, u32 tag_size,
}
}
}
- // hash the very last block with H' into the output tag
+ // hash the very last block with H' into the output hash
u8 final_block[1024];
store_block(final_block, blocks + (nb_blocks - 1));
- extended_hash(tag, tag_size, final_block, 1024);
+ extended_hash(hash, hash_size, final_block, 1024);
}
////////////////////////////////////
/// Arithmetic modulo 2^255 - 19 ///
////////////////////////////////////
// Taken from Supercop's ref10 implementation.
-// A bit bigger than TweetNaCl, about 8 times faster.
+// A bit bigger than TweetNaCl, over 4 times faster.
// field element
typedef i32 fe[10];
-sv fe_0 (fe h) { FOR (i, 0, 10) h[i] = 0; }
-sv fe_1 (fe h) { h[0] = 1; FOR (i, 1, 10) h[i] = 0; }
-sv fe_neg (fe h, const fe f) { FOR (i, 0, 10) h[i] = -f[i]; }
-sv fe_add (fe h, const fe f, const fe g) { FOR (i, 0, 10) h[i] = f[i] + g[i]; }
-sv fe_sub (fe h, const fe f, const fe g) { FOR (i, 0, 10) h[i] = f[i] - g[i]; }
-sv fe_copy(fe h, const fe f ) { FOR (i, 0, 10) h[i] = f[i]; }
+static void fe_0 (fe h) { FOR(i,0,10) h[i] = 0; }
+static void fe_1 (fe h) { h[0] = 1; FOR(i,1,10) h[i] = 0; }
+static void fe_neg (fe h,const fe f) {FOR(i,0,10) h[i] = -f[i]; }
+static void fe_add (fe h,const fe f,const fe g){FOR(i,0,10) h[i] = f[i] + g[i];}
+static void fe_sub (fe h,const fe f,const fe g){FOR(i,0,10) h[i] = f[i] - g[i];}
+static void fe_copy(fe h,const fe f) {FOR(i,0,10) h[i] = f[i]; }
-sv fe_cswap(fe f, fe g, int b)
+static void fe_cswap(fe f, fe g, int b)
{
FOR (i, 0, 10) {
i32 x = (f[i] ^ g[i]) & -b;
@@ -806,14 +951,7 @@ sv fe_cswap(fe f, fe g, int b)
}
}
-static u32 load24_le(const u8 s[3])
-{
- return (u32)s[0]
- | ((u32)s[1] << 8)
- | ((u32)s[2] << 16);
-}
-
-sv fe_carry(fe h, i64 t[10])
+static void fe_carry(fe h, i64 t[10])
{
i64 c0, c1, c2, c3, c4, c5, c6, c7, c8, c9;
c9 = (t[9] + (i64) (1<<24)) >> 25; t[0] += c9 * 19; t[9] -= c9 * (1 << 25);
@@ -829,7 +967,7 @@ sv fe_carry(fe h, i64 t[10])
FOR (i, 0, 10) { h[i] = t[i]; }
}
-sv fe_frombytes(fe h, const u8 s[32])
+static void fe_frombytes(fe h, const u8 s[32])
{
i64 t[10]; // intermediate result (may overflow 32 bits)
t[0] = load32_le(s);
@@ -845,16 +983,18 @@ sv fe_frombytes(fe h, const u8 s[32])
fe_carry(h, t);
}
-sv fe_mul_small(fe h, const fe f, i32 g)
+static void fe_mul_small(fe h, const fe f, i32 g)
{
i64 t[10];
- FOR(i, 0, 10) { t[i] = f[i] * (i64) g; }
+ FOR(i, 0, 10) {
+ t[i] = f[i] * (i64) g;
+ }
fe_carry(h, t);
}
-sv fe_mul121666(fe h, const fe f) { fe_mul_small(h, f, 121666); }
-sv fe_mul973324(fe h, const fe f) { fe_mul_small(h, f, 973324); }
+static void fe_mul121666(fe h, const fe f) { fe_mul_small(h, f, 121666); }
+static void fe_mul973324(fe h, const fe f) { fe_mul_small(h, f, 973324); }
-sv fe_mul(fe h, const fe f, const fe g)
+static void fe_mul(fe h, const fe f, const fe g)
{
// Everything is unrolled and put in temporary variables.
// We could roll the loop, but that would make curve25519 twice as slow.
@@ -909,7 +1049,7 @@ sv fe_mul(fe h, const fe f, const fe g)
}
// we could use fe_mul() for this, but this is significantly faster
-sv fe_sq(fe h, const fe f)
+static void fe_sq(fe h, const fe f)
{
i32 f0 = f[0]; i32 f1 = f[1]; i32 f2 = f[2]; i32 f3 = f[3]; i32 f4 = f[4];
i32 f5 = f[5]; i32 f6 = f[6]; i32 f7 = f[7]; i32 f8 = f[8]; i32 f9 = f[9];
@@ -943,7 +1083,7 @@ sv fe_sq(fe h, const fe f)
}
// This could be simplified, but it would be slower
-sv fe_invert(fe out, const fe z)
+static void fe_invert(fe out, const fe z)
{
fe t0, t1, t2, t3;
fe_sq(t0, z );
@@ -980,11 +1120,12 @@ void fe_pow22523(fe out, const fe z)
fe_sq(t0, t0); FOR (i, 1, 2) fe_sq(t0, t0); fe_mul(out, t0, z);
}
-sv fe_tobytes(u8 s[32], const fe h)
+static void fe_tobytes(u8 s[32], const fe h)
{
i32 t[10];
- FOR (i, 0, 10) { t[i] = h[i]; }
-
+ FOR (i, 0, 10) {
+ t[i] = h[i];
+ }
i32 q = (19 * t[9] + (((i32) 1) << 24)) >> 25;
FOR (i, 0, 5) {
q += t[2*i ]; q >>= 26;
@@ -1032,14 +1173,15 @@ static int fe_isnonzero(const fe f)
/// X-25519 /// Taken from Supercop's ref10 implementation.
///////////////
-sv trim_scalar(u8 s[32])
+static void trim_scalar(u8 s[32])
{
s[ 0] &= 248;
s[31] &= 127;
s[31] |= 64;
}
-sv x25519_ladder(const fe x1, fe x2, fe z2, fe x3, fe z3, const u8 scalar[32])
+static void x25519_ladder(const fe x1, fe x2, fe z2, fe x3, fe z3,
+ const u8 scalar[32])
{
// Montgomery ladder
// In projective coordinates, to avoid divisons: x = X / Z
@@ -1066,6 +1208,7 @@ sv x25519_ladder(const fe x1, fe x2, fe z2, fe x3, fe z3, const u8 scalar[32])
fe_add(t0, t0, z3); fe_mul(z3, x1, z2); fe_mul(z2, t1, t0);
}
// last swap is necessary to compensate for the xor trick
+ // Note: after this swap, P3 == P2 + P1.
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
}
@@ -1075,14 +1218,18 @@ int crypto_x25519(u8 shared_secret [32],
const u8 their_public_key[32])
{
// computes the scalar product
- fe x1, x2, z2, x3, z3;
+ fe x1;
fe_frombytes(x1, their_public_key);
// restrict the possible scalar values
- u8 e[32]; FOR (i, 0, 32) { e[i] = your_secret_key[i]; }
+ u8 e[32];
+ FOR (i, 0, 32) {
+ e[i] = your_secret_key[i];
+ }
trim_scalar(e);
// computes the actual scalar product (the result is in x2 and z2)
+ fe x2, z2, x3, z3;
x25519_ladder(x1, x2, z2, x3, z3, e);
// normalises the coordinates: x == X / Z
@@ -1107,11 +1254,11 @@ void crypto_x25519_public_key(u8 public_key[32],
///////////////
// Point in a twisted Edwards curve,
-// in extended projective coordinates
+// in extended projective coordinates.
// x = X/Z, y = Y/Z, T = XY/Z
typedef struct { fe X; fe Y; fe Z; fe T; } ge;
-sv ge_from_xy(ge *p, const fe x, const fe y)
+static void ge_from_xy(ge *p, const fe x, const fe y)
{
FOR (i, 0, 10) {
p->X[i] = x[i];
@@ -1121,7 +1268,7 @@ sv ge_from_xy(ge *p, const fe x, const fe y)
fe_mul(p->T, x, y);
}
-sv ge_tobytes(u8 s[32], const ge *h)
+static void ge_tobytes(u8 s[32], const ge *h)
{
fe recip, x, y;
fe_invert(recip, h->Z);
@@ -1135,12 +1282,12 @@ sv ge_tobytes(u8 s[32], const ge *h)
static int ge_frombytes_neg(ge *h, const u8 s[32])
{
static const fe d = {
- -10913610,13857413,-15372611,6949391,114729,
- -8787816,-6275908,-3247719,-18696448,-12055116
+ -10913610, 13857413, -15372611, 6949391, 114729,
+ -8787816, -6275908, -3247719, -18696448, -12055116
} ;
static const fe sqrtm1 = {
- -32595792,-7943725,9377950,3500415,12389472,
- -272473,-25146209,-2005654,326686,11406482
+ -32595792, -7943725, 9377950, 3500415, 12389472,
+ -272473, -25146209, -2005654, 326686, 11406482
} ;
fe u, v, v3, vxx, check;
fe_frombytes(h->Y, s);
@@ -1176,14 +1323,12 @@ static int ge_frombytes_neg(ge *h, const u8 s[32])
return 0;
}
-// for point additon
-static const fe D2 = { // - 2 * 121665 / 121666
- 0x2b2f159, 0x1a6e509, 0x22add7a, 0x0d4141d, 0x0038052,
- 0x0f3d130, 0x3407977, 0x19ce331, 0x1c56dff, 0x0901b67
-};
-
-sv ge_add(ge *s, const ge *p, const ge *q)
+static void ge_add(ge *s, const ge *p, const ge *q)
{
+ static const fe D2 = { // - 2 * 121665 / 121666
+ 0x2b2f159, 0x1a6e509, 0x22add7a, 0x0d4141d, 0x0038052,
+ 0x0f3d130, 0x3407977, 0x19ce331, 0x1c56dff, 0x0901b67
+ };
fe a, b, c, d, e, f, g, h;
// A = (Y1-X1) * (Y2-X2)
// B = (Y1+X1) * (Y2+X2)
@@ -1201,7 +1346,11 @@ sv ge_add(ge *s, const ge *p, const ge *q)
fe_mul(s->T, e, h); // T3 = E * H
}
-sv ge_scalarmult(ge *p, const ge *q, const u8 scalar[32])
+// Performing the scalar multiplication directly in Twisted Edwards
+// space woud be simpler, but also slower. So we do it in Montgomery
+// space instead. The sign of the Y coordinate however gets lost in
+// translation, so we use a dirty trick to recover it.
+static void ge_scalarmult(ge *p, const ge *q, const u8 scalar[32])
{
// sqrt(-486664)
static const fe K = { 54885894, 25242303, 55597453, 9067496, 51808079,
@@ -1218,7 +1367,9 @@ sv ge_scalarmult(ge *p, const ge *q, const u8 scalar[32])
// montgomery scalarmult
x25519_ladder(x1, x2, z2, x3, z3, scalar);
- // recover the y1 coordinate (Katsuyuki Okeya & Kouichi Sakurai, 2001)
+ // Recover the y coordinate (Katsuyuki Okeya & Kouichi Sakurai, 2001)
+ // Note the shameless reuse of x1: (x1, y1, z1) will correspond to
+ // what was originally (x2, z2).
fe_mul(t1, x1, z2); // t1 = x1 * z2
fe_add(t2, x2, t1); // t2 = x2 + t1
fe_sub(t3, x2, t1); // t3 = x2 − t1
@@ -1249,7 +1400,7 @@ sv ge_scalarmult(ge *p, const ge *q, const u8 scalar[32])
fe_mul(p->T, x1, t1);
}
-sv ge_scalarmult_base(ge *p, const u8 scalar[32])
+static void ge_scalarmult_base(ge *p, const u8 scalar[32])
{
// Calls the general ge_scalarmult() with the base point.
// Other implementations use a precomputed table, but it
@@ -1265,7 +1416,7 @@ sv ge_scalarmult_base(ge *p, const u8 scalar[32])
ge_scalarmult(p, &base_point, scalar);
}
-sv modL(u8 *r, i64 x[64])
+static void modL(u8 *r, i64 x[64])
{
static const u64 L[32] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
@@ -1287,23 +1438,28 @@ sv modL(u8 *r, i64 x[64])
carry = x[i] >> 8;
x[i] &= 255;
}
- FOR(i, 0, 32) { x[i] -= carry * L[i]; }
+ FOR(i, 0, 32) {
+ x[i] -= carry * L[i];
+ }
FOR(i, 0, 32) {
x[i+1] += x[i] >> 8;
r[i ] = x[i] & 255;
}
}
-sv reduce(u8 r[64])
+static void reduce(u8 r[64])
{
i64 x[64];
- FOR(i, 0, 64) x[i] = (u64) r[i];
- FOR(i, 0, 64) r[i] = 0;
+ FOR(i, 0, 64) {
+ x[i] = (u64) r[i];
+ r[i] = 0;
+ }
modL(r, x);
}
// hashes R || A || M, reduces it modulo L
-sv hash_ram(u8 k[64], const u8 R[32], const u8 A[32], const u8 *M, size_t M_size)
+static void hash_ram(u8 k[64], const u8 R[32], const u8 A[32],
+ const u8 *M, size_t M_size)
{
HASH_CTX ctx;
HASH_INIT (&ctx);
@@ -1362,9 +1518,9 @@ void crypto_sign(u8 signature[64],
hash_ram(h_ram, signature, pk, message, message_size);
i64 s[64]; // s = r + h_ram * a
- FOR(i, 0, 32) s[i] = (u64) r[i];
- FOR(i, 32, 64) s[i] = 0;
- FOR(i, 0, 32) {
+ FOR(i, 0, 32) { s[i] = (u64) r[i]; }
+ FOR(i, 32, 64) { s[i] = 0; }
+ FOR(i, 0, 32) {
FOR(j, 0, 32) {
s[i+j] += h_ram[i] * (u64) a[j];
}
@@ -1378,11 +1534,13 @@ int crypto_check(const u8 signature[64],
{
ge A, p, sB, diff;
u8 h_ram[64], R_check[32];
- if (ge_frombytes_neg(&A, public_key)) { return -1; } // -A
+ if (ge_frombytes_neg(&A, public_key)) { // -A
+ return -1;
+ }
hash_ram(h_ram, signature, public_key, message, message_size);
- ge_scalarmult(&p, &A, h_ram); // p = -A*h_ram
+ ge_scalarmult(&p, &A, h_ram); // p = -A*h_ram
ge_scalarmult_base(&sB, signature + 32);
- ge_add(&diff, &p, &sB); // diff = s - A*h_ram
+ ge_add(&diff, &p, &sB); // diff = s - A*h_ram
ge_tobytes(R_check, &diff);
return crypto_memcmp(signature, R_check, 32); // R == s - A*h_ram ? OK : fail
}
@@ -1404,9 +1562,9 @@ int crypto_key_exchange(u8 shared_key[32],
////////////////////////////////
/// Authenticated encryption ///
////////////////////////////////
-sv authenticate2(u8 mac[16] , const u8 auth_key[32],
- const u8 *t1, size_t size1,
- const u8 *t2, size_t size2)
+static void authenticate2(u8 mac[16] , const u8 auth_key[32],
+ const u8 *t1, size_t size1,
+ const u8 *t2, size_t size2)
{
crypto_poly1305_ctx a_ctx;
crypto_poly1305_init (&a_ctx, auth_key);
@@ -1416,52 +1574,54 @@ sv authenticate2(u8 mac[16] , const u8 auth_key[32],
}
void crypto_aead_lock(u8 mac[16],
- u8 *ciphertext,
+ u8 *cipher_text,
const u8 key[32],
const u8 nonce[24],
- const u8 *ad , size_t ad_size,
- const u8 *plaintext, size_t text_size)
+ const u8 *ad , size_t ad_size,
+ const u8 *plain_text, size_t text_size)
{ // encrypt then mac
u8 auth_key[32];
crypto_chacha_ctx e_ctx;
crypto_chacha20_x_init (&e_ctx, key, nonce);
crypto_chacha20_stream (&e_ctx, auth_key, 32);
- crypto_chacha20_encrypt(&e_ctx, ciphertext, plaintext, text_size);
- authenticate2(mac, auth_key, ad, ad_size, ciphertext, text_size);
+ crypto_chacha20_encrypt(&e_ctx, cipher_text, plain_text, text_size);
+ authenticate2(mac, auth_key, ad, ad_size, cipher_text, text_size);
}
-int crypto_aead_unlock(u8 *plaintext,
+int crypto_aead_unlock(u8 *plain_text,
const u8 key[32],
const u8 nonce[24],
const u8 mac[16],
- const u8 *ad , size_t ad_size,
- const u8 *ciphertext, size_t text_size)
+ const u8 *ad , size_t ad_size,
+ const u8 *cipher_text, size_t text_size)
{
u8 auth_key[32], real_mac[16];
crypto_chacha_ctx e_ctx;
crypto_chacha20_x_init(&e_ctx, key, nonce);
crypto_chacha20_stream(&e_ctx, auth_key, 32);
- authenticate2(real_mac, auth_key, ad, ad_size, ciphertext, text_size);
- if (crypto_memcmp(real_mac, mac, 16)) { return -1; } // reject forgeries
- crypto_chacha20_encrypt(&e_ctx, plaintext, ciphertext, text_size);
+ authenticate2(real_mac, auth_key, ad, ad_size, cipher_text, text_size);
+ if (crypto_memcmp(real_mac, mac, 16)) {
+ return -1; // reject forgeries
+ }
+ crypto_chacha20_encrypt(&e_ctx, plain_text, cipher_text, text_size);
return 0;
}
void crypto_lock(u8 mac[16],
- u8 *ciphertext,
+ u8 *cipher_text,
const u8 key[32],
const u8 nonce[24],
- const u8 *plaintext, size_t text_size)
+ const u8 *plain_text, size_t text_size)
{
- crypto_aead_lock(mac, ciphertext, key, nonce, 0, 0, plaintext, text_size);
+ crypto_aead_lock(mac, cipher_text, key, nonce, 0, 0, plain_text, text_size);
}
-int crypto_unlock(u8 *plaintext,
+int crypto_unlock(u8 *plain_text,
const u8 key[32],
const u8 nonce[24],
const u8 mac[16],
- const u8 *ciphertext, size_t text_size)
+ const u8 *cipher_text, size_t text_size)
{
- return crypto_aead_unlock(plaintext, key, nonce, mac, 0, 0,
- ciphertext, text_size);
+ return crypto_aead_unlock(plain_text, key, nonce, mac, 0, 0,
+ cipher_text, text_size);
}
diff --git a/libs/monocypher/monocypher.h b/libs/monocypher/monocypher.h
@@ -15,10 +15,13 @@ int crypto_zerocmp(const uint8_t *p, size_t n);
////////////////
/// Chacha20 ///
////////////////
+
+// Chacha context. Do not rely on its contents or its size,
+// they may change without notice.
typedef struct {
- uint32_t input[16]; // current input, unencrypted
- uint8_t random_pool[64]; // last input, encrypted
- uint8_t pool_index; // pointer to random_pool
+ uint32_t input[16]; // current input, unencrypted
+ uint32_t pool [16]; // last input, encrypted
+ size_t pool_idx; // pointer to random_pool
} crypto_chacha_ctx;
void crypto_chacha20_H(uint8_t out[32],
@@ -38,7 +41,7 @@ void crypto_chacha20_set_ctr(crypto_chacha_ctx *ctx, uint64_t ctr);
void crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
uint8_t *cipher_text,
const uint8_t *plain_text,
- size_t message_size);
+ size_t text_size);
void crypto_chacha20_stream(crypto_chacha_ctx *ctx,
uint8_t *stream, size_t size);
@@ -46,62 +49,69 @@ void crypto_chacha20_stream(crypto_chacha_ctx *ctx,
/////////////////
/// Poly 1305 ///
/////////////////
+
+// Poly 1305 context. Do not rely on its contents or its size, they
+// may change without notice.
typedef struct {
- uint32_t r[4];
- uint32_t h[5];
- uint32_t c[5];
- uint32_t pad[5];
- size_t c_index;
+ uint32_t r[4]; // constant multiplier (from the secret key)
+ uint32_t h[5]; // accumulated hash
+ uint32_t c[5]; // chunk of the message
+ uint32_t pad[4]; // random number added at the end (from the secret key)
+ size_t c_idx; // How many bytes are there in the chunk.
} crypto_poly1305_ctx;
void crypto_poly1305_init(crypto_poly1305_ctx *ctx, const uint8_t key[32]);
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
- const uint8_t *msg, size_t msg_size);
+ const uint8_t *message, size_t message_size);
void crypto_poly1305_final(crypto_poly1305_ctx *ctx, uint8_t mac[16]);
void crypto_poly1305_auth(uint8_t mac[16],
- const uint8_t *msg, size_t msg_size,
+ const uint8_t *message, size_t message_size,
const uint8_t key[32]);
////////////////
/// Blake2 b ///
////////////////
+
+// Blake2b context. Do not rely on its contents or its size, they
+// may change without notice.
typedef struct {
uint64_t hash[8];
uint64_t input_offset[2];
- uint8_t buffer[128];
- size_t buffer_idx;
+ uint64_t input[16];
+ size_t input_idx;
size_t hash_size;
} crypto_blake2b_ctx;
-void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx, size_t out_size,
+void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx, size_t hash_size,
const uint8_t *key, size_t key_size);
void crypto_blake2b_init(crypto_blake2b_ctx *ctx);
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
- const uint8_t *in, size_t in_size);
+ const uint8_t *message, size_t message_size);
-void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *out);
+void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
-void crypto_blake2b_general(uint8_t *out, size_t out_size, // digest
- const uint8_t *key, size_t key_size, // optional
- const uint8_t *in , size_t in_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);
-void crypto_blake2b(uint8_t out[64], const uint8_t *in, size_t in_size);
+void crypto_blake2b(uint8_t hash[64],
+ const uint8_t *message, size_t message_size);
////////////////
/// Argon2 i ///
////////////////
-void crypto_argon2i(uint8_t *tag, uint32_t tag_size, // >= 4
+void crypto_argon2i(uint8_t *hash, uint32_t hash_size, // >= 4
void *work_area, uint32_t nb_blocks, // >= 8
- uint32_t nb_iterations,
+ uint32_t nb_iterations, // >= 1
const uint8_t *password, uint32_t password_size,
const uint8_t *salt, uint32_t salt_size, // >= 8
- const uint8_t *key, uint32_t key_size,
- const uint8_t *ad, uint32_t ad_size);
+ const uint8_t *key, uint32_t key_size, // optional
+ const uint8_t *ad, uint32_t ad_size); // optional
///////////////
/// X-25519 ///
@@ -120,12 +130,12 @@ void crypto_x25519_public_key(uint8_t public_key[32],
void crypto_sign_public_key(uint8_t public_key[32],
const uint8_t secret_key[32]);
-void crypto_sign(uint8_t signature[64],
+void crypto_sign(uint8_t signature [64],
const uint8_t secret_key[32],
const uint8_t public_key[32], // optional, may be 0
const uint8_t *message, size_t message_size);
-int crypto_check(const uint8_t signature[64],
+int crypto_check(const uint8_t signature [64],
const uint8_t public_key[32],
const uint8_t *message, size_t message_size);
@@ -140,29 +150,29 @@ int crypto_key_exchange(uint8_t shared_key [32],
/// Authenticated encryption ///
////////////////////////////////
void crypto_aead_lock(uint8_t mac[16],
- uint8_t *ciphertext,
+ uint8_t *cipher_text,
const uint8_t key[32],
const uint8_t nonce[24],
- const uint8_t *ad , size_t ad_size,
- const uint8_t *plaintext, size_t text_size);
+ const uint8_t *ad , size_t ad_size,
+ const uint8_t *plain_text, size_t text_size);
-int crypto_aead_unlock(uint8_t *plaintext,
+int crypto_aead_unlock(uint8_t *plain_text,
const uint8_t key[32],
const uint8_t nonce[24],
const uint8_t mac[16],
- const uint8_t *ad , size_t ad_size,
- const uint8_t *ciphertext, size_t text_size);
+ const uint8_t *ad , size_t ad_size,
+ const uint8_t *cipher_text, size_t text_size);
void crypto_lock(uint8_t mac[16],
- uint8_t *ciphertext,
+ uint8_t *cipher_text,
const uint8_t key[32],
const uint8_t nonce[24],
- const uint8_t *plaintext, size_t text_size);
+ const uint8_t *plain_text, size_t text_size);
-int crypto_unlock(uint8_t *plaintext,
+int crypto_unlock(uint8_t *plain_text,
const uint8_t key[32],
const uint8_t nonce[24],
const uint8_t mac[16],
- const uint8_t *ciphertext, size_t text_size);
+ const uint8_t *cipher_text, size_t text_size);
#endif // MONOCYPHER_H