mirror of
https://github.com/luxfi/pqclean.git
synced 2026-11-03 09:57:54 +00:00
188 lines
6.6 KiB
C
188 lines
6.6 KiB
C
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "sha256avx.h"
|
|
#include "sha256x8.h"
|
|
#include "sha2_offsets.h"
|
|
#include "utils.h"
|
|
|
|
// Performs sha256x8 on an initialized (and perhaps seeded) state.
|
|
static void _sha256x8(
|
|
sha256x8ctx *ctx,
|
|
unsigned char *out0,
|
|
unsigned char *out1,
|
|
unsigned char *out2,
|
|
unsigned char *out3,
|
|
unsigned char *out4,
|
|
unsigned char *out5,
|
|
unsigned char *out6,
|
|
unsigned char *out7,
|
|
const unsigned char *in0,
|
|
const unsigned char *in1,
|
|
const unsigned char *in2,
|
|
const unsigned char *in3,
|
|
const unsigned char *in4,
|
|
const unsigned char *in5,
|
|
const unsigned char *in6,
|
|
const unsigned char *in7, unsigned long long inlen) {
|
|
unsigned long long i = 0;
|
|
while (inlen - i >= 64) {
|
|
sha256_transform8x(ctx,
|
|
in0 + i,
|
|
in1 + i,
|
|
in2 + i,
|
|
in3 + i,
|
|
in4 + i,
|
|
in5 + i,
|
|
in6 + i,
|
|
in7 + i
|
|
);
|
|
i += 64;
|
|
ctx->msglen += 512;
|
|
}
|
|
|
|
size_t bytes_to_copy = (size_t)(inlen - i);
|
|
memcpy(&ctx->msgblocks[64 * 0], in0 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 1], in1 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 2], in2 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 3], in3 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 4], in4 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 5], in5 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 6], in6 + i, bytes_to_copy);
|
|
memcpy(&ctx->msgblocks[64 * 7], in7 + i, bytes_to_copy);
|
|
ctx->datalen = (unsigned int)bytes_to_copy;
|
|
|
|
sha256_final8x(ctx, out0, out1, out2, out3, out4, out5, out6, out7);
|
|
}
|
|
|
|
void sha256x8_seeded(
|
|
unsigned char *out0,
|
|
unsigned char *out1,
|
|
unsigned char *out2,
|
|
unsigned char *out3,
|
|
unsigned char *out4,
|
|
unsigned char *out5,
|
|
unsigned char *out6,
|
|
unsigned char *out7,
|
|
const sha256x8ctx *seed,
|
|
const unsigned char *in0,
|
|
const unsigned char *in1,
|
|
const unsigned char *in2,
|
|
const unsigned char *in3,
|
|
const unsigned char *in4,
|
|
const unsigned char *in5,
|
|
const unsigned char *in6,
|
|
const unsigned char *in7, unsigned long long inlen) {
|
|
|
|
sha256x8ctx ctx;
|
|
sha256_ctx_clone8x(&ctx, seed);
|
|
|
|
_sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7,
|
|
in0, in1, in2, in3, in4, in5, in6, in7, inlen);
|
|
}
|
|
|
|
/* This provides a wrapper around the internals of 8x parallel SHA256 */
|
|
void sha256x8(unsigned char *out0,
|
|
unsigned char *out1,
|
|
unsigned char *out2,
|
|
unsigned char *out3,
|
|
unsigned char *out4,
|
|
unsigned char *out5,
|
|
unsigned char *out6,
|
|
unsigned char *out7,
|
|
const unsigned char *in0,
|
|
const unsigned char *in1,
|
|
const unsigned char *in2,
|
|
const unsigned char *in3,
|
|
const unsigned char *in4,
|
|
const unsigned char *in5,
|
|
const unsigned char *in6,
|
|
const unsigned char *in7, unsigned long long inlen) {
|
|
sha256x8ctx ctx;
|
|
sha256_init8x(&ctx);
|
|
|
|
_sha256x8(&ctx, out0, out1, out2, out3, out4, out5, out6, out7,
|
|
in0, in1, in2, in3, in4, in5, in6, in7, inlen);
|
|
}
|
|
|
|
/**
|
|
* Note that inlen should be sufficiently small that it still allows for
|
|
* an array to be allocated on the stack. Typically 'in' is merely a seed.
|
|
* Outputs outlen number of bytes
|
|
*/
|
|
void mgf1x8(unsigned char *outx8, unsigned long outlen,
|
|
const unsigned char *in0,
|
|
const unsigned char *in1,
|
|
const unsigned char *in2,
|
|
const unsigned char *in3,
|
|
const unsigned char *in4,
|
|
const unsigned char *in5,
|
|
const unsigned char *in6,
|
|
const unsigned char *in7,
|
|
unsigned long inlen) {
|
|
PQCLEAN_VLA(unsigned char, inbufx8, 8 * (inlen + 4));
|
|
unsigned char outbufx8[8 * SPX_SHA256_OUTPUT_BYTES];
|
|
uint32_t i;
|
|
unsigned int j;
|
|
|
|
memcpy(inbufx8 + (0 * (inlen + 4)), in0, inlen);
|
|
memcpy(inbufx8 + (1 * (inlen + 4)), in1, inlen);
|
|
memcpy(inbufx8 + (2 * (inlen + 4)), in2, inlen);
|
|
memcpy(inbufx8 + (3 * (inlen + 4)), in3, inlen);
|
|
memcpy(inbufx8 + (4 * (inlen + 4)), in4, inlen);
|
|
memcpy(inbufx8 + (5 * (inlen + 4)), in5, inlen);
|
|
memcpy(inbufx8 + (6 * (inlen + 4)), in6, inlen);
|
|
memcpy(inbufx8 + (7 * (inlen + 4)), in7, inlen);
|
|
|
|
/* While we can fit in at least another full block of SHA256 output.. */
|
|
for (i = 0; (i + 1) * SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
|
|
for (j = 0; j < 8; j++) {
|
|
u32_to_bytes(inbufx8 + inlen + (j * (inlen + 4)), i);
|
|
}
|
|
|
|
sha256x8(outx8 + (0 * outlen),
|
|
outx8 + (1 * outlen),
|
|
outx8 + (2 * outlen),
|
|
outx8 + (3 * outlen),
|
|
outx8 + (4 * outlen),
|
|
outx8 + (5 * outlen),
|
|
outx8 + (6 * outlen),
|
|
outx8 + (7 * outlen),
|
|
inbufx8 + (0 * (inlen + 4)),
|
|
inbufx8 + (1 * (inlen + 4)),
|
|
inbufx8 + (2 * (inlen + 4)),
|
|
inbufx8 + (3 * (inlen + 4)),
|
|
inbufx8 + (4 * (inlen + 4)),
|
|
inbufx8 + (5 * (inlen + 4)),
|
|
inbufx8 + (6 * (inlen + 4)),
|
|
inbufx8 + (7 * (inlen + 4)), inlen + 4);
|
|
outx8 += SPX_SHA256_OUTPUT_BYTES;
|
|
}
|
|
/* Until we cannot anymore, and we fill the remainder. */
|
|
for (j = 0; j < 8; j++) {
|
|
u32_to_bytes(inbufx8 + inlen + (j * (inlen + 4)), i);
|
|
}
|
|
sha256x8(outbufx8 + (0 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (1 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (2 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (3 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (4 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (5 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (6 * SPX_SHA256_OUTPUT_BYTES),
|
|
outbufx8 + (7 * SPX_SHA256_OUTPUT_BYTES),
|
|
inbufx8 + (0 * (inlen + 4)),
|
|
inbufx8 + (1 * (inlen + 4)),
|
|
inbufx8 + (2 * (inlen + 4)),
|
|
inbufx8 + (3 * (inlen + 4)),
|
|
inbufx8 + (4 * (inlen + 4)),
|
|
inbufx8 + (5 * (inlen + 4)),
|
|
inbufx8 + (6 * (inlen + 4)),
|
|
inbufx8 + (7 * (inlen + 4)), inlen + 4);
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
memcpy(outx8 + (j * outlen),
|
|
outbufx8 + (j * SPX_SHA256_OUTPUT_BYTES),
|
|
outlen - (i * SPX_SHA256_OUTPUT_BYTES));
|
|
}
|
|
}
|