int foundation_rngV1_generate(uint8_t newkey[CHACHA_KEY_SIZE], uint8_t *dst, uint8_t key[CHACHA_KEY_SIZE], FsCountOf bytes) { const int rounds = 20; uint8_t nonce[CHACHA_NONCE_SIZE] = { 0 }; uint8_t buf[CHACHA_OUTPUT_SIZE]; /* for partial buffer */ if (!bytes) return 0; for (; bytes >= CHACHA_OUTPUT_SIZE; bytes -= CHACHA_OUTPUT_SIZE, dst += CHACHA_OUTPUT_SIZE) { chacha_core(rounds, dst, key, nonce); if (++nonce[0] == 0) nonce[1]++; } assert(bytes < CHACHA_OUTPUT_SIZE); chacha_core(rounds, buf, key, nonce); int remaining = CHACHA_OUTPUT_SIZE - bytes; if (remaining >= CHACHA_KEY_SIZE) { memcpy(dst, buf, bytes); memcpy(newkey, buf + bytes, CHACHA_KEY_SIZE); } else { memcpy(dst, buf, bytes); if (++nonce[0] == 0) nonce[1]++; chacha_core(rounds, buf, key, nonce); memcpy(newkey, buf, CHACHA_KEY_SIZE); } memset(buf, 0, CHACHA_OUTPUT_SIZE); return 0; }
void cryptonite_chacha_combine(uint8_t *dst, cryptonite_chacha_context *ctx, const uint8_t *src, uint32_t bytes) { block out; cryptonite_chacha_state *st; int i; if (!bytes) return; /* xor the previous buffer first (if any) */ if (ctx->prev_len > 0) { int to_copy = (ctx->prev_len < bytes) ? ctx->prev_len : bytes; for (i = 0; i < to_copy; i++) dst[i] = src[i] ^ ctx->prev[ctx->prev_ofs+i]; memset(ctx->prev + ctx->prev_ofs, 0, to_copy); ctx->prev_len -= to_copy; ctx->prev_ofs += to_copy; src += to_copy; dst += to_copy; bytes -= to_copy; } if (bytes == 0) return; st = &ctx->st; /* xor new 64-bytes chunks and store the left over if any */ for (; bytes >= 64; bytes -= 64, src += 64, dst += 64) { /* generate new chunk and update state */ chacha_core(ctx->nb_rounds, &out, st); st->d[12] += 1; if (st->d[12] == 0) st->d[13] += 1; for (i = 0; i < 64; ++i) dst[i] = src[i] ^ out.b[i]; } if (bytes > 0) { /* generate new chunk and update state */ chacha_core(ctx->nb_rounds, &out, st); st->d[12] += 1; if (st->d[12] == 0) st->d[13] += 1; /* xor as much as needed */ for (i = 0; i < bytes; i++) dst[i] = src[i] ^ out.b[i]; /* copy the left over in the buffer */ ctx->prev_len = 64 - bytes; ctx->prev_ofs = i; for (; i < 64; i++) { ctx->prev[i] = out.b[i]; } } }
void cryptonite_chacha_random(uint32_t rounds, uint8_t *dst, cryptonite_chacha_state *st, uint32_t bytes) { block out; if (!bytes) return; for (; bytes >= 16; bytes -= 16, dst += 16) { chacha_core(rounds, &out, st); memcpy(dst, out.b + 40, 16); cryptonite_chacha_init_core(st, 32, out.b, 8, out.b + 32); } if (bytes) { chacha_core(rounds, &out, st); memcpy(dst, out.b + 40, bytes); cryptonite_chacha_init_core(st, 32, out.b, 8, out.b + 32); } }