]> git.codecow.com Git - Monocypher.git/commitdiff
extracted hchacha20
authorLoup Vaillant <loup@loup-vaillant.fr>
Mon, 16 Jan 2017 21:27:18 +0000 (22:27 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Mon, 16 Jan 2017 21:27:18 +0000 (22:27 +0100)
chacha20.c
chacha20.h

index b57868504779f9a0d11701d0f7421a4671420d4f..023f11430dea90e24a3f68ef270cde685bbd444a 100644 (file)
@@ -1,9 +1,5 @@
 #include "chacha20.h"
 
-/////////////////
-/// Utilities ///
-/////////////////
-
 static uint32_t
 load32_le(const uint8_t s[4])
 {
@@ -25,10 +21,6 @@ store32_le(uint8_t output[4], uint32_t input)
     output[3] = (input >> 24) & 0xff;
 }
 
-////////////
-/// Core ///
-////////////
-
 static void
 chacha20_rounds(uint32_t out[16], const uint32_t in[16])
 {
@@ -54,46 +46,50 @@ chacha20_rounds(uint32_t out[16], const uint32_t in[16])
     }
 }
 
-//////////////////////////////
-/// Context initialization ///
-//////////////////////////////
 static void
-init_constant(crypto_chacha_ctx *ctx)
+chacha20_init_key(crypto_chacha_ctx *ctx, const uint8_t key[32])
 {
+    // constant
     ctx->input[0]   = load32_le((uint8_t*)"expa");
     ctx->input[1]   = load32_le((uint8_t*)"nd 3");
     ctx->input[2]   = load32_le((uint8_t*)"2-by");
     ctx->input[3]   = load32_le((uint8_t*)"te k");
-    ctx->pool_index = 64; // the random pool starts empty
-}
-
-static void
-init_key(crypto_chacha_ctx *ctx, const uint8_t key[32])
-{
+    // key
     for (int i = 0; i < 8; i++)
         ctx->input[i + 4] = load32_le(key + i*4);
+    // pool index (the random pool starts empty)
+    ctx->pool_index = 64;
 }
 
-static void
-init_nonce(crypto_chacha_ctx *ctx, const uint8_t nonce[8])
+void
+crypto_chacha20_H(uint8_t       out[32],
+                  const uint8_t key[32],
+                  const uint8_t in [16])
 {
-    ctx->input[12] = 0; // counter
-    ctx->input[13] = 0; // counter
-    ctx->input[14] = load32_le(nonce + 0);
-    ctx->input[15] = load32_le(nonce + 4);
+    crypto_chacha_ctx ctx;
+    chacha20_init_key(&ctx, key);
+    for (int i = 0; i < 4; i++)
+        ctx.input[i + 12] = load32_le(in + i*4);
+
+    uint32_t buffer[16];
+    chacha20_rounds(buffer, ctx.input);
+    // prevents reversal of the rounds by revealing only half of the buffer.
+    for (int i = 0; i < 4; i++) {
+        store32_le(out      + i*4, buffer[i     ]); // constant
+        store32_le(out + 16 + i*4, buffer[i + 12]); // counter and nonce
+    }
 }
 
-///////////////////
-/// Exposed API ///
-///////////////////
 void
 crypto_chacha20_init(crypto_chacha_ctx *ctx,
                      const uint8_t      key[32],
                      const uint8_t      nonce[8])
 {
-    init_constant(ctx       );
-    init_key     (ctx, key  );
-    init_nonce   (ctx, nonce);
+    chacha20_init_key(ctx, key  );         // key
+    ctx->input[12] = 0;                    // counter
+    ctx->input[13] = 0;                    // counter
+    ctx->input[14] = load32_le(nonce + 0); // nonce
+    ctx->input[15] = load32_le(nonce + 4); // nonce
 }
 
 void
@@ -101,33 +97,18 @@ crypto_chacha20_Xinit(crypto_chacha_ctx *ctx,
                       const uint8_t      key[32],
                       const uint8_t      nonce[24])
 {
-    crypto_chacha_ctx init_ctx;
-    init_constant (&init_ctx     );
-    init_key      (&init_ctx, key);
-    // init big nonce (first 16 bytes)
-    for (int i = 0; i < 4; i++)
-        init_ctx.input[i + 12] = load32_le(nonce +  i*4);
-
-    // chacha20 rounds (reversible if we reveal all the buffer)
-    uint32_t buffer[16];
-    chacha20_rounds(buffer, init_ctx.input);
-
-    init_constant(ctx);
-    // init key
-    for (int i = 0; i < 4; i++) {
-        ctx->input[i + 4] = buffer[i     ]; // constant
-        ctx->input[i + 8] = buffer[i + 12]; // counter and nonce
-    }
-    init_nonce(ctx, nonce + 16); // init big nonce (last 8 bytes)
+    uint8_t derived_key[32];
+    crypto_chacha20_H(derived_key, key, nonce);
+    crypto_chacha20_init(ctx, derived_key, nonce + 16);
 }
 
 void
 crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
                         const uint8_t     *plain_text,
                         uint8_t           *cipher_text,
-                        size_t             msg_length)
+                        size_t             message_size)
 {
-    for (size_t i = 0; i < msg_length; i++) {
+    for (size_t i = 0; i < message_size; i++) {
         // refill the pool if empty
         if (ctx->pool_index == 64) {
             // fill the pool
@@ -152,7 +133,7 @@ crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
 void
 crypto_chacha20_random(crypto_chacha_ctx *ctx,
                        uint8_t           *cipher_text,
-                       size_t             msg_length)
+                       size_t             message_size)
 {
-    crypto_chacha20_encrypt(ctx, 0, cipher_text, msg_length);
+    crypto_chacha20_encrypt(ctx, 0, cipher_text, message_size);
 }
index 56e42f3b1f9cb9d12dc3ebd09a837b5f49df3f23..9f63614e2351683ff6c461075d162c09fdab9251 100644 (file)
@@ -7,7 +7,7 @@
 // This is a chacha20 context.
 // To use safely, just follow these guidelines:
 // - Always initialize your context with one of the crypto_init_* functions below
-// - Dont't modify it, except through the crypto_*_chacha20 below.
+// - Dont't modify it, except through the crypto_chacha20_* below.
 // - Never duplicate it.
 typedef struct crypto_chacha_ctx {
     uint32_t input[16];       // current input, unencrypted
@@ -15,6 +15,14 @@ typedef struct crypto_chacha_ctx {
     uint8_t  pool_index;      // pointer to random_pool
 } crypto_chacha_ctx;
 
+// HChacha20.  *Kind* of a cryptographic hash, based on the chacha20 rounds.
+// Used for XChacha20, and the key derivation of the X25519 shared secret.
+// Don't use it unless you really know what you're doing.
+void
+crypto_chacha20_H(uint8_t       out[32],
+                  const uint8_t key[32],
+                  const uint8_t in [16]);
+
 // Initializes a chacha context.
 //
 // WARNING: DON'T USE THE SAME NONCE AND KEY TWICE
@@ -36,7 +44,7 @@ crypto_chacha20_init(crypto_chacha_ctx *ctx,
                      const uint8_t      key[32],
                      const uint8_t      nonce[8]);
 
-// Initializes a chacha context, with an even bigger nonce (192 bits),
+// Initializes a chacha context, with a big nonce (192 bits),
 // more than enough to be selected at random.
 //
 // The price you pay for that is a slower initialization.  The security
@@ -48,27 +56,34 @@ crypto_chacha20_Xinit(crypto_chacha_ctx *ctx,
 
 // Encrypts the plain_text by XORing it with a pseudo-random
 // stream of numbers, seeded by the provided chacha20 context.
-// It can safely be chained thus:
+// Decryption uses the exact same method.
+//
+// Once the context is initialized, encryptions can safely be chained thus:
 //
-//    crypto_encrypt_chacha20(ctx, plaint_0, cipher_0, length_0);
-//    crypto_encrypt_chacha20(ctx, plaint_1, cipher_1, length_1);
-//    crypto_encrypt_chacha20(ctx, plaint_2, cipher_2, length_2);
+//    crypto_encrypt_chacha20(ctx, plain_0, cipher_0, length_0);
+//    crypto_encrypt_chacha20(ctx, plain_1, cipher_1, length_1);
+//    crypto_encrypt_chacha20(ctx, plain_2, cipher_2, length_2);
+//
+// plain_text and cipher_text may point to the same location, for in-place
+// encryption.
 //
 // plain_text is allowed to be null (0), in which case it will be
 // interpreted as an all zero input.  The cipher_text will then
 // contain the raw chacha20 stream.  Useful as a random number
 // generator.
+//
+// WARNING: ENCRYPTION ALONE IS NOT SECURE.  YOU NEED AUTHENTICATION AS WELL.
+// Use the provided authenticated encryption constructions.
 void
 crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
                         const uint8_t     *plain_text,
                         uint8_t           *cipher_text,
-                        size_t             msg_length);
+                        size_t             message_size);
 
-// convenience function.
-// equivalent to encrypt_chacha20(ctx, 0, cipher_text, msg_length)
+// convenience function.  Same as chacha20_encrypt() with a null plain_text.
 void
 crypto_chacha20_random(crypto_chacha_ctx *ctx,
                        uint8_t           *cipher_text,
-                       size_t             msg_length);
+                       size_t             message_size);
 
 #endif // CHACHA20_H