| 40 | } |
| 41 | |
| 42 | static void chacha_block(mi_random_ctx_t* ctx) |
| 43 | { |
| 44 | // scramble into `x` |
| 45 | uint32_t x[16]; |
| 46 | for (size_t i = 0; i < 16; i++) { |
| 47 | x[i] = ctx->input[i]; |
| 48 | } |
| 49 | for (size_t i = 0; i < MI_CHACHA_ROUNDS; i += 2) { |
| 50 | qround(x, 0, 4, 8, 12); |
| 51 | qround(x, 1, 5, 9, 13); |
| 52 | qround(x, 2, 6, 10, 14); |
| 53 | qround(x, 3, 7, 11, 15); |
| 54 | qround(x, 0, 5, 10, 15); |
| 55 | qround(x, 1, 6, 11, 12); |
| 56 | qround(x, 2, 7, 8, 13); |
| 57 | qround(x, 3, 4, 9, 14); |
| 58 | } |
| 59 | |
| 60 | // add scrambled data to the initial state |
| 61 | for (size_t i = 0; i < 16; i++) { |
| 62 | ctx->output[i] = x[i] + ctx->input[i]; |
| 63 | } |
| 64 | ctx->output_available = 16; |
| 65 | |
| 66 | // increment the counter for the next round |
| 67 | ctx->input[12] += 1; |
| 68 | if (ctx->input[12] == 0) { |
| 69 | ctx->input[13] += 1; |
| 70 | if (ctx->input[13] == 0) { // and keep increasing into the nonce |
| 71 | ctx->input[14] += 1; |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | static uint32_t chacha_next32(mi_random_ctx_t* ctx) { |
| 77 | if (ctx->output_available <= 0) { |
no test coverage detected