m += CHACHA_BLOCK_SIZE;
}
}
+
+void
+chacha_crypt32(struct chacha_ctx *ctx,
+ size_t length,
+ uint8_t *c,
+ const uint8_t *m)
+{
+ if (!length)
+ return;
+
+ for (;;)
+ {
+ uint32_t x[_CHACHA_STATE_LENGTH];
+
+ _chacha_core (x, ctx->state, CHACHA_ROUNDS);
+
+ ++ctx->state[12];
+
+ /* stopping at 2^70 length per nonce is user's responsibility */
+
+ if (length <= CHACHA_BLOCK_SIZE)
+ {
+ memxor3 (c, m, x, length);
+ return;
+ }
+ memxor3 (c, m, x, CHACHA_BLOCK_SIZE);
+
+ length -= CHACHA_BLOCK_SIZE;
+ c += CHACHA_BLOCK_SIZE;
+ m += CHACHA_BLOCK_SIZE;
+ }
+}
assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
poly1305_pad (ctx);
- chacha_crypt (&ctx->chacha, length, dst, src);
+ chacha_crypt32 (&ctx->chacha, length, dst, src);
poly1305_update (ctx, length, dst);
ctx->data_size += length;
}
poly1305_pad (ctx);
poly1305_update (ctx, length, src);
- chacha_crypt (&ctx->chacha, length, dst, src);
+ chacha_crypt32 (&ctx->chacha, length, dst, src);
ctx->data_size += length;
}
ctx->state[12] = LE_READ_UINT32(counter + 0);
ctx->state[13] = LE_READ_UINT32(counter + 4);
}
+
+void
+chacha_set_counter32(struct chacha_ctx *ctx, const uint8_t *counter)
+{
+ ctx->state[12] = LE_READ_UINT32(counter + 0);
+}
#define chacha_set_nonce nettle_chacha_set_nonce
#define chacha_set_nonce96 nettle_chacha_set_nonce96
#define chacha_set_counter nettle_chacha_set_counter
+#define chacha_set_counter32 nettle_chacha_set_counter32
#define chacha_crypt nettle_chacha_crypt
+#define chacha_crypt32 nettle_chacha_crypt32
/* Currently, only 256-bit keys are supported. */
#define CHACHA_KEY_SIZE 32
#define CHACHA_NONCE_SIZE 8
#define CHACHA_NONCE96_SIZE 12
#define CHACHA_COUNTER_SIZE 8
+#define CHACHA_COUNTER32_SIZE 4
#define _CHACHA_STATE_LENGTH 16
void
chacha_set_counter(struct chacha_ctx *ctx, const uint8_t *counter);
+void
+chacha_set_counter32(struct chacha_ctx *ctx, const uint8_t *counter);
+
void
chacha_crypt(struct chacha_ctx *ctx, size_t length,
uint8_t *dst, const uint8_t *src);
+void
+chacha_crypt32(struct chacha_ctx *ctx, size_t length,
+ uint8_t *dst, const uint8_t *src);
+
#ifdef __cplusplus
}
#endif
@code{CHACHA_BLOCK_SIZE}.
@end deftypefun
+@subsubsection 32-bit counter variant
+
+While the original paper uses 64-bit counter value, the variant defined
+in @cite{RFC 8439} uses 32-bit counter value. This variant is
+particularly useful for @pxref{ChaCha-Poly1305} AEAD construction, which
+supports 12-octet nonces.
+
+@defvr Constant CHACHA_NONCE96_SIZE
+Size of the nonce, 12.
+@end defvr
+
+@defvr Constant CHACHA_COUNTER32_SIZE
+Size of the counter, 4.
+@end defvr
+
+@deftypefun void chacha_set_nonce96 (struct chacha_ctx *@var{ctx}, const uint8_t *@var{nonce})
+Sets the nonce. This is similar to the above @code{chacha_set_nonce},
+but the input is always of size @code{CHACHA_NONCE96_SIZE}, 12 octets.
+@end deftypefun
+
+@deftypefun void chacha_set_counter32 (struct chacha_ctx *@var{ctx}, const uint8_t *@var{counter})
+Sets the block counter. This is similar to the above @code{chacha_set_counter},
+but the input is always of size @code{CHACHA_COUNTER32_SIZE}, 4 octets.
+@end deftypefun
+
+@deftypefun void chacha_crypt32 (struct chacha_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
+Encrypts or decrypts the data of a message, using ChaCha. This is similar to the
+above @code{chacha_crypt}, but it assumes the internal counter value is 32-bit
+long and the nonce is 96-bit long.
+@end deftypefun
+
@subsection DES
@cindex DES
DES is the old Data Encryption Standard, specified by NIST. It uses a
die ("Bad nonce size %u.\n", (unsigned) nonce->length);
if (counter)
- chacha_set_counter(&ctx, counter->data);
+ {
+ if (counter->length == CHACHA_COUNTER_SIZE)
+ {
+ ASSERT (nonce->length == CHACHA_NONCE_SIZE);
+ chacha_set_counter(&ctx, counter->data);
+ }
+ else if (counter->length == CHACHA_COUNTER32_SIZE)
+ {
+ ASSERT (nonce->length == CHACHA_NONCE96_SIZE);
+ chacha_set_counter32(&ctx, counter->data);
+ }
+ }
- chacha_crypt (&ctx, length, data, data);
+ if (nonce->length == CHACHA_NONCE_SIZE)
+ chacha_crypt (&ctx, length, data, data);
+ else
+ chacha_crypt32 (&ctx, length, data, data);
ASSERT (data[-1] == 17);
ASSERT (data[length] == 17);
"b5129cd1de164eb9 cbd083e8a2503c4e"),
20);
- /* This is identical to the 96-bit nonce test, but it manually sets
- the counter value */
+ /* This is identical to the above 96-bit nonce test, but it manually
+ sets the 32-bit counter value */
+ test_chacha_with_counter(SHEX("0001020304050607 08090a0b0c0d0e0f"
+ "1011121314151617 18191a1b1c1d1e1f"),
+ SHEX("000000090000004a 00000000"),
+ SHEX("10f1e7e4d13b5915 500fdd1fa32071c4"
+ "c7d1f4c733c06803 0422aa9ac3d46c4e"
+ "d2826446079faa09 14c2d705d98b02a2"
+ "b5129cd1de164eb9 cbd083e8a2503c4e"),
+ 20,
+ SHEX("01000000"));
+
+ /* This is identical to the above 96-bit nonce test, but it manually
+ sets the 64-bit counter value */
test_chacha_with_counter(SHEX("0001020304050607 08090a0b0c0d0e0f"
"1011121314151617 18191a1b1c1d1e1f"),
SHEX("0000004a00000000"),