static inline u_int64_t getblock64(const u_int64_t *p, int i) { const u_int8_t *bytes = (const u_int8_t *)(void *)(uintptr_t)(p + i); u_int64_t value; if (ALIGNED64(p)) { value = p[i]; } else { #if BYTE_ORDER == BIG_ENDIAN value = (((u_int64_t)bytes[0]) << 56) | (((u_int64_t)bytes[1]) << 48) | (((u_int64_t)bytes[2]) << 40) | (((u_int64_t)bytes[3]) << 32) | (((u_int64_t)bytes[4]) << 24) | (((u_int64_t)bytes[5]) << 16) | (((u_int64_t)bytes[6]) << 8) | ((u_int64_t)bytes[7]); #else /* LITTLE_ENDIAN */ value = (((u_int64_t)bytes[7]) << 56) | (((u_int64_t)bytes[6]) << 48) | (((u_int64_t)bytes[5]) << 40) | (((u_int64_t)bytes[4]) << 32) | (((u_int64_t)bytes[3]) << 24) | (((u_int64_t)bytes[2]) << 16) | (((u_int64_t)bytes[1]) << 8) | ((u_int64_t)bytes[0]); #endif /* LITTLE_ENDIAN */ } return (value); }
void cryptonite_chacha_generate(uint8_t *dst, cryptonite_chacha_context *ctx, uint32_t bytes) { cryptonite_chacha_state *st; block out; 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] = 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; dst += to_copy; bytes -= to_copy; } if (bytes == 0) return; st = &ctx->st; if (ALIGNED64(dst)) { /* xor new 64-bytes chunks and store the left over if any */ for (; bytes >= 64; bytes -= 64, dst += 64) { /* generate new chunk and update state */ chacha_core(ctx->nb_rounds, (block *) dst, st); st->d[12] += 1; if (st->d[12] == 0) st->d[13] += 1; } } else { /* xor new 64-bytes chunks and store the left over if any */ for (; bytes >= 64; bytes -= 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] = 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] = 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]; } }