aboutsummaryrefslogtreecommitdiff
path: root/src/cc20rng/cc20_prng.c
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordberg.se>2019-12-18 23:36:25 +0100
committerLinus Nordberg <linus@nordberg.se>2019-12-18 23:36:25 +0100
commite47310c3d5ef6fc10e60562d2d88da0927bc1fce (patch)
treee5120a2cbfb18deeca95c6670dfd3216745d4d8c /src/cc20rng/cc20_prng.c
parentbef34ab8ac602d36d86b4a3f3013b89e3e2e5402 (diff)
WIP Revamp ChaCha20 seedingln/cc20rng-revamp
- chacha20_prng_block() uses counter in the state struct - chacha20_setup() replaces chacha20_prng_reseed() and fills the whole state struct, fixing a bug where only half of the key was being set; as a result of 'counter' being set, a state struct filled with entropy from the TRNG makes reseeding occur after a random number of rounds instead of after a fixed 2^32-1 rounds - decrementing of the block counter is done in chacha20_prng_block() - chacha output is copied to buf _after_ the interrupt driven transmission of buf to UART has finished, to stop the race between reading and refilling of buf
Diffstat (limited to 'src/cc20rng/cc20_prng.c')
-rw-r--r--src/cc20rng/cc20_prng.c124
1 files changed, 64 insertions, 60 deletions
diff --git a/src/cc20rng/cc20_prng.c b/src/cc20rng/cc20_prng.c
index 50739bd..36c06a4 100644
--- a/src/cc20rng/cc20_prng.c
+++ b/src/cc20rng/cc20_prng.c
@@ -41,16 +41,16 @@
#define CHACHA20_CONSTANT3 0x6b206574
#ifdef CHACHA20_PRNG_DEBUG
-void _dump(struct cc20_state *cc, char *str);
+static void _dump(struct cc20_state *cc, char *str);
#endif
-inline uint32_t rotl32(uint32_t x, uint32_t n)
+static inline uint32_t rotl32(uint32_t x, uint32_t n)
{
return (x << n) | (x >> (32 - n));
}
-inline void _qr(struct cc20_state *cc, uint32_t a, uint32_t b, uint32_t c,
- uint32_t d)
+static inline void _qr(struct cc20_state *cc, uint32_t a, uint32_t b,
+ uint32_t c, uint32_t d)
{
cc->i[a] += cc->i[b];
cc->i[d] ^= cc->i[a];
@@ -69,44 +69,40 @@ inline void _qr(struct cc20_state *cc, uint32_t a, uint32_t b, uint32_t c,
cc->i[b] = rotl32(cc->i[b], 7);
}
-void chacha20_prng_reseed(struct cc20_state *cc, uint32_t *entropy)
+static void chacha20_setup(struct cc20_state *state,
+ const struct cc20_state *src)
{
- uint32_t i = 256 / 8 / 4;
- while (i--) {
- cc->i[i] = entropy[i];
- }
+ state->s.constant[0] = CHACHA20_CONSTANT0;
+ state->s.constant[1] = CHACHA20_CONSTANT1;
+ state->s.constant[2] = CHACHA20_CONSTANT2;
+ state->s.constant[3] = CHACHA20_CONSTANT3;
+
+ for (int i = 4; i < CHACHA20_BLOCK_SIZE_WORDS; i++)
+ state->i[i] = src->i[i];
}
-void chacha20_prng_block(struct cc20_state *cc, uint32_t block_counter,
- struct cc20_state *out)
+void chacha20_prng_block(struct cc20_state *cc, uint8_t *out)
{
uint32_t i;
+ struct cc20_state *ws = (struct cc20_state *)out;
- out->i[0] = CHACHA20_CONSTANT0;
- out->i[1] = CHACHA20_CONSTANT1;
- out->i[2] = CHACHA20_CONSTANT2;
- out->i[3] = CHACHA20_CONSTANT3;
-
- cc->i[12] = block_counter;
-
- for (i = 4; i < CHACHA20_NUM_WORDS; i++) {
- out->i[i] = cc->i[i];
- }
+ chacha20_setup(ws, cc);
for (i = 10; i; i--) {
- _qr(out, 0, 4, 8, 12);
- _qr(out, 1, 5, 9, 13);
- _qr(out, 2, 6, 10, 14);
- _qr(out, 3, 7, 11, 15);
- _qr(out, 0, 5, 10, 15);
- _qr(out, 1, 6, 11, 12);
- _qr(out, 2, 7, 8, 13);
- _qr(out, 3, 4, 9, 14);
+ _qr(ws, 0, 4, 8, 12);
+ _qr(ws, 1, 5, 9, 13);
+ _qr(ws, 2, 6, 10, 14);
+ _qr(ws, 3, 7, 11, 15);
+ _qr(ws, 0, 5, 10, 15);
+ _qr(ws, 1, 6, 11, 12);
+ _qr(ws, 2, 7, 8, 13);
+ _qr(ws, 3, 4, 9, 14);
}
- for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
- out->i[i] += cc->i[i];
- }
+ for (i = 0; i < CHACHA20_BLOCK_SIZE_WORDS; i++)
+ ws->i[i] += cc->i[i];
+
+ cc->s.counter--;
}
int chacha20_prng_self_test1()
@@ -115,16 +111,18 @@ int chacha20_prng_self_test1()
* https://tools.ietf.org/html/rfc7539#section-2.3.2
*/
struct cc20_state test = {
- {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
- 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
- 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
- 0x00000001, 0x09000000, 0x4a000000, 0x00000000,
+ .i = {
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
+ 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
+ 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
+ 0x00000001, 0x09000000, 0x4a000000, 0x00000000,
}};
struct cc20_state expected = {
- {0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3,
- 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3,
- 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9,
- 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2,
+ .i = {
+ 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3,
+ 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3,
+ 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9,
+ 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2,
}};
uint32_t i;
struct cc20_state out;
@@ -133,12 +131,13 @@ int chacha20_prng_self_test1()
_dump(&test, "Test vector from RFC7539, section 2.3.2. Input:");
#endif
- chacha20_prng_block(&test, 1, &out);
+ test.s.counter = 1; /* nop */
+ chacha20_prng_block(&test, (uint8_t *)&out);
#ifdef CHACHA20_PRNG_DEBUG
_dump(&out, "Test vector from RFC7539, section 2.3.2. Output:");
#endif
- for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+ for (i = 0; i < CHACHA20_BLOCK_SIZE_WORDS; i++) {
if (out.i[i] != expected.i[i])
return 0;
}
@@ -152,22 +151,25 @@ int chacha20_prng_self_test2()
* https://tools.ietf.org/html/rfc7539#section-2.4.2
*/
struct cc20_state test = {
- {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
- 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
- 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
- 0x00000001, 0x00000000, 0x4a000000, 0x00000000,
+ .i = {
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
+ 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
+ 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
+ 0x00000001, 0x00000000, 0x4a000000, 0x00000000,
}};
struct cc20_state expected1 = {
- {0xf3514f22, 0xe1d91b40, 0x6f27de2f, 0xed1d63b8,
- 0x821f138c, 0xe2062c3d, 0xecca4f7e, 0x78cff39e,
- 0xa30a3b8a, 0x920a6072, 0xcd7479b5, 0x34932bed,
- 0x40ba4c79, 0xcd343ec6, 0x4c2c21ea, 0xb7417df0,
+ .i = {
+ 0xf3514f22, 0xe1d91b40, 0x6f27de2f, 0xed1d63b8,
+ 0x821f138c, 0xe2062c3d, 0xecca4f7e, 0x78cff39e,
+ 0xa30a3b8a, 0x920a6072, 0xcd7479b5, 0x34932bed,
+ 0x40ba4c79, 0xcd343ec6, 0x4c2c21ea, 0xb7417df0,
}};
struct cc20_state expected2 = {
- {0x9f74a669, 0x410f633f, 0x28feca22, 0x7ec44dec,
- 0x6d34d426, 0x738cb970, 0x3ac5e9f3, 0x45590cc4,
- 0xda6e8b39, 0x892c831a, 0xcdea67c1, 0x2b7e1d90,
- 0x037463f3, 0xa11a2073, 0xe8bcfb88, 0xedc49139,
+ .i = {
+ 0x9f74a669, 0x410f633f, 0x28feca22, 0x7ec44dec,
+ 0x6d34d426, 0x738cb970, 0x3ac5e9f3, 0x45590cc4,
+ 0xda6e8b39, 0x892c831a, 0xcdea67c1, 0x2b7e1d90,
+ 0x037463f3, 0xa11a2073, 0xe8bcfb88, 0xedc49139,
}};
struct cc20_state out;
uint32_t i;
@@ -176,20 +178,22 @@ int chacha20_prng_self_test2()
_dump(&test, "Test vector from RFC7539, section 2.4.2. Input:");
#endif
- chacha20_prng_block(&test, 1, &out);
+ test.s.counter = 1; /* nop */
+ chacha20_prng_block(&test, (uint8_t *)&out);
#ifdef CHACHA20_PRNG_DEBUG
_dump(&out, "First block");
#endif
- for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+ for (i = 0; i < CHACHA20_BLOCK_SIZE_WORDS; i++) {
if (out.i[i] != expected1.i[i])
return 0;
}
- chacha20_prng_block(&test, 2, &out);
+ test.s.counter = 2;
+ chacha20_prng_block(&test, (uint8_t *)&out);
#ifdef CHACHA20_PRNG_DEBUG
_dump(&out, "Second block");
#endif
- for (i = 0; i < CHACHA20_NUM_WORDS; i++) {
+ for (i = 0; i < CHACHA20_BLOCK_SIZE_WORDS; i++) {
if (out.i[i] != expected2.i[i])
return 0;
}
@@ -213,8 +217,8 @@ void _dump(struct cc20_state *cc, char *str)
}
#endif
-/* Test vector from RFC, used as simple power-on self-test of ability to compute
- * a block correctly.
+/* Test vector from RFC7539, used as simple power-on self-test of
+ * ability to compute a block correctly.
*/
int chacha20_prng_self_test()
{