ftu/blst/sha256.h
2022-09-09 02:47:49 -04:00

141 lines
3.8 KiB
C

/*
* Copyright Supranational LLC
* Licensed under the Apache License, Version 2.0, see LICENSE for details.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __BLS12_381_ASM_SHA256_H__
#define __BLS12_381_ASM_SHA256_H__
#include "vect.h"
#if (defined(__x86_64__) || defined(__x86_64) || defined(_M_X64)) && \
defined(__SHA__) /* -msha */ && !defined(__BLST_PORTABLE__)
# define sha256_block_data_order blst_sha256_block_data_order_shaext
#elif defined(__aarch64__) && \
defined(__ARM_FEATURE_CRYPTO) && !defined(__BLST_PORTABLE__)
# define sha256_block_data_order blst_sha256_block_armv8
#else
# define sha256_block_data_order blst_sha256_block_data_order
#endif
#define sha256_hcopy blst_sha256_hcopy
#define sha256_bcopy blst_sha256_bcopy
#define sha256_emit blst_sha256_emit
void sha256_block_data_order(unsigned int *h, const void *inp, size_t blocks);
void sha256_hcopy(unsigned int dst[8], const unsigned int src[8]);
void sha256_bcopy(void *dst, const void *src, size_t len);
/*
* If SHA256_CTX conflicts with something, just redefine it to alternative
* custom name prior including this header.
*/
typedef struct {
unsigned int h[8];
unsigned long long N;
unsigned char buf[64];
size_t off;
} SHA256_CTX;
static void sha256_init_h(unsigned int h[8])
{
h[0] = 0x6a09e667U;
h[1] = 0xbb67ae85U;
h[2] = 0x3c6ef372U;
h[3] = 0xa54ff53aU;
h[4] = 0x510e527fU;
h[5] = 0x9b05688cU;
h[6] = 0x1f83d9abU;
h[7] = 0x5be0cd19U;
}
static void sha256_init(SHA256_CTX *ctx)
{
sha256_init_h(ctx->h);
ctx->N = 0;
vec_zero(ctx->buf, sizeof(ctx->buf));
ctx->off = 0;
}
static void sha256_update(SHA256_CTX *ctx, const void *_inp, size_t len)
{
size_t n;
const unsigned char *inp = _inp;
ctx->N += len;
if ((len != 0) & ((n = ctx->off) != 0)) {
size_t rem = sizeof(ctx->buf) - n;
if (rem > len) {
sha256_bcopy(ctx->buf + n, inp, len);
ctx->off += len;
return;
} else {
sha256_bcopy(ctx->buf + n, inp, rem);
inp += rem;
len -= rem;
sha256_block_data_order(ctx->h, ctx->buf, 1);
vec_zero(ctx->buf, sizeof(ctx->buf));
ctx->off = 0;
}
}
n = len / sizeof(ctx->buf);
if (n > 0) {
sha256_block_data_order(ctx->h, inp, n);
n *= sizeof(ctx->buf);
inp += n;
len -= n;
}
if (len)
sha256_bcopy(ctx->buf, inp, ctx->off = len);
}
#define __TOBE32(ptr, val) ((ptr)[0] = (unsigned char)((val)>>24), \
(ptr)[1] = (unsigned char)((val)>>16), \
(ptr)[2] = (unsigned char)((val)>>8), \
(ptr)[3] = (unsigned char)(val))
#if 1
void sha256_emit(unsigned char md[32], const unsigned int h[8]);
#else
static void sha256_emit(unsigned char md[32], const unsigned int h[8])
{
unsigned int h_i;
h_i = h[0]; __TOBE32(md + 0, h_i);
h_i = h[1]; __TOBE32(md + 4, h_i);
h_i = h[2]; __TOBE32(md + 8, h_i);
h_i = h[3]; __TOBE32(md + 12, h_i);
h_i = h[4]; __TOBE32(md + 16, h_i);
h_i = h[5]; __TOBE32(md + 20, h_i);
h_i = h[6]; __TOBE32(md + 24, h_i);
h_i = h[7]; __TOBE32(md + 28, h_i);
}
#endif
static void sha256_final(unsigned char md[32], SHA256_CTX *ctx)
{
unsigned long long bits = ctx->N * 8;
size_t n = ctx->off;
unsigned char *tail;
ctx->buf[n++] = 0x80;
if (n > (sizeof(ctx->buf) - 8)) {
sha256_block_data_order(ctx->h, ctx->buf, 1);
vec_zero(ctx->buf, sizeof(ctx->buf));
}
tail = ctx->buf + sizeof(ctx->buf) - 8;
__TOBE32(tail, (unsigned int)(bits >> 32));
__TOBE32(tail + 4, (unsigned int)bits);
sha256_block_data_order(ctx->h, ctx->buf, 1);
sha256_emit(md, ctx->h);
}
#undef __TOBE32
#endif