#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#ifdef WOLFSSL_RISCV_ASM
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
#if FIPS_VERSION3_LT(6,0,0) && defined(HAVE_FIPS)
#undef HAVE_FIPS
#else
#if defined(HAVE_FIPS) && FIPS_VERSION3_GE(6,0,0)
#define FIPS_NO_WRAPPERS
#endif
#endif
#include <wolfssl/wolfcrypt/sha256.h>
#if FIPS_VERSION3_GE(6,0,0)
const unsigned int wolfCrypt_FIPS_sha256_ro_sanity[2] =
{ 0x1a2b3c4d, 0x00000014 };
int wolfCrypt_FIPS_SHA256_sanity(void)
{
return 0;
}
#endif
#include <wolfssl/wolfcrypt/port/riscv/riscv-64-asm.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
static const FLASH_QUALIFIER ALIGN32 word32 K[64] = {
0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
};
static void InitSha256(wc_Sha256* sha256)
{
#ifndef WOLFSSL_RISCV_VECTOR_CRYPTO_ASM
sha256->digest[0] = 0x6A09E667L;
sha256->digest[1] = 0xBB67AE85L;
sha256->digest[2] = 0x3C6EF372L;
sha256->digest[3] = 0xA54FF53AL;
sha256->digest[4] = 0x510E527FL;
sha256->digest[5] = 0x9B05688CL;
sha256->digest[6] = 0x1F83D9ABL;
sha256->digest[7] = 0x5BE0CD19L;
#else
sha256->digest[0] = 0x9B05688CL;
sha256->digest[1] = 0x510E527FL;
sha256->digest[2] = 0xBB67AE85L;
sha256->digest[3] = 0x6A09E667L;
sha256->digest[4] = 0x5BE0CD19L;
sha256->digest[5] = 0x1F83D9ABL;
sha256->digest[6] = 0xA54FF53AL;
sha256->digest[7] = 0x3C6EF372L;
#endif
sha256->buffLen = 0;
sha256->loLen = 0;
sha256->hiLen = 0;
#ifdef WOLFSSL_HASH_FLAGS
sha256->flags = 0;
#endif
}
static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len)
{
word32 tmp = sha256->loLen;
if ((sha256->loLen += len) < tmp)
sha256->hiLen++;
}
#ifndef WOLFSSL_RISCV_BASE_BIT_MANIPULATION
#define LOAD_WORD_REV(r, o, p, t0, t1, t2) \
"lbu " #t0 ", " #o "(" #p ")\n\t" \
"lbu " #t1 ", " #o "+1(" #p ")\n\t" \
"lbu " #t2 ", " #o "+2(" #p ")\n\t" \
"lbu " #r ", " #o "+3(" #p ")\n\t" \
"slli " #t0 ", " #t0 ", 24\n\t" \
"slli " #t1 ", " #t1 ", 16\n\t" \
"slli " #t2 ", " #t2 ", 8\n\t" \
"or " #r ", " #r ", " #t0 "\n\t" \
"or " #r ", " #r ", " #t1 "\n\t" \
"or " #r ", " #r ", " #t2 "\n\t"
#define LOAD_DWORD_REV(r, o, p, t0, t1, t2, t3) \
"lbu " #t0 ", " #o "(" #p ")\n\t" \
"lbu " #t1 ", " #o "+1(" #p ")\n\t" \
"lbu " #t2 ", " #o "+2(" #p ")\n\t" \
"lbu " #r ", " #o "+3(" #p ")\n\t" \
"slli " #t0 ", " #t0 ", 24\n\t" \
"slli " #t1 ", " #t1 ", 16\n\t" \
"slli " #t2 ", " #t2 ", 8\n\t" \
"or " #r ", " #r ", " #t0 "\n\t" \
"or " #r ", " #r ", " #t1 "\n\t" \
"or " #r ", " #r ", " #t2 "\n\t" \
"lbu " #t0 ", " #o "+4(" #p ")\n\t" \
"lbu " #t1 ", " #o "+5(" #p ")\n\t" \
"lbu " #t2 ", " #o "+6(" #p ")\n\t" \
"lbu " #t3 ", " #o "+7(" #p ")\n\t" \
"slli " #t0 ", " #t0 ", 56\n\t" \
"slli " #t1 ", " #t1 ", 48\n\t" \
"slli " #t2 ", " #t2 ", 40\n\t" \
"slli " #t3 ", " #t3 ", 32\n\t" \
"or " #r ", " #r ", " #t0 "\n\t" \
"or " #r ", " #r ", " #t1 "\n\t" \
"or " #r ", " #r ", " #t2 "\n\t" \
"or " #r ", " #r ", " #t3 "\n\t"
#define PACK_BB(rd, rs1, rs2, rrd, rrs1, rrs2) \
"slli " #rd ", " #rs1 ", 32\n\t" \
"slli " #rs2 ", " #rs2 ", 32\n\t" \
"srli " #rd ", " #rs1 ", 32\n\t" \
"or " #rd ", " #rd ", " #rs2 "\n\t"
#else
#define PACK_BB(rd, rs1, rs2, rrd, rrs1, rrs2) \
PACK(rrd, rrs1, rrs2)
#endif
#ifndef WOLFSSL_RISCV_VECTOR_CRYPTO_ASM
#ifdef WOLFSSL_RISCV_SCALAR_CRYPTO_ASM
#define SHA256SUM0(rd, rs1) \
ASM_WORD((0b000100000000 << 20) | (0b001 << 12) | 0b0010011 | \
(rs1 << 15) | (rd << 7))
#define SHA256SUM1(rd, rs1) \
ASM_WORD((0b000100000001 << 20) | (0b001 << 12) | 0b0010011 | \
(rs1 << 15) | (rd << 7))
#define SHA256SIG0(rd, rs1) \
ASM_WORD((0b000100000010 << 20) | (0b001 << 12) | 0b0010011 | \
(rs1 << 15) | (rd << 7))
#define SHA256SIG1(rd, rs1) \
ASM_WORD((0b000100000011 << 20) | (0b001 << 12) | 0b0010011 | \
(rs1 << 15) | (rd << 7))
#define RND(a, b, c, d, e, f, g, h, w, k) \
\
"mv a4, " #e "\n\t" \
"mv a5, " #a "\n\t" \
\
SHA256SUM1(REG_A4, REG_A4) \
\
SHA256SUM0(REG_A5, REG_A5) \
\
\
\
"xor t6, " #f ", " #g "\n\t" \
\
"xor t4, " #a ", " #b "\n\t" \
\
"xor t5, " #b ", " #c "\n\t" \
\
"and t6, t6, " #e "\n\t" \
\
"addw " #h ", " #h ", a4\n\t" \
\
"and t5, t5, t4\n\t" \
\
"xor t6, t6, " #g "\n\t" \
\
"addw t4, " #k ", " #w "\n\t" \
\
"xor t5, t5, " #b "\n\t" \
\
"addw " #h ", " #h ", t6\n\t" \
\
"addw " #h ", " #h ", t4\n\t" \
\
"addw t5, a5, t5\n\t" \
\
"addw " #d ", " #d ", " #h "\n\t" \
\
"addw " #h ", " #h ", t5\n\t"
#define W_UPDATE_2(w0, w1, w4, w5, w7, reg_w0, reg_w1, reg_w7) \
\
"srli t4, " #w0 ", 32\n\t" \
\
"srli t6, " #w4 ", 32\n\t" \
\
SHA256SIG0(REG_A4, REG_T4) \
\
SHA256SIG1(REG_A5, reg_w7) \
\
"addw a5, a5, t6\n\t" \
\
"addw " #w0 ", " #w0 ", a4\n\t" \
\
"srli t5, " #w7 ", 32\n\t" \
\
"addw " #w0 ", a5, " #w0 "\n\t" \
\
\
\
SHA256SIG0(REG_A6, reg_w1) \
\
SHA256SIG1(REG_A7, REG_T5) \
\
"addw a7, a7, " #w5 "\n\t" \
\
"addw t5, a6, t4\n\t" \
\
"addw a7, a7, t5\n\t" \
\
PACK_BB(w0, w0, a7, reg_w0, reg_w0, REG_A7)
#else
#define SHA256SIG1(rd, rs1) \
"slliw t6, " #rs1 ", 15\n\t" \
"srliw t5, " #rs1 ", 17\n\t" \
"slliw t4, " #rs1 ", 13\n\t" \
"srliw " #rd ", " #rs1 ", 19\n\t" \
"or t6, t6, t5\n\t" \
"srliw t5, " #rs1 ", 10\n\t" \
"xor " #rd ", "#rd ", t4\n\t" \
"xor t6, t6, t5\n\t" \
"xor " #rd ", " #rd ", t6\n\t" \
#define RND(a, b, c, d, e, f, g, h, w, k) \
\
"slliw t5, " #e ", 26\n\t" \
"srliw t4, " #e ", 6\n\t" \
"slliw t6, " #e ", 21\n\t" \
"srliw a4, " #e ", 11\n\t" \
"slliw a5, " #e ", 7\n\t" \
"or t4, t4, t5\n\t" \
"xor a4, a4, t6\n\t" \
"srliw t5, " #e ", 25\n\t" \
"xor t4, t4, a5\n\t" \
"xor a4, a4, t5\n\t" \
\
"slliw t5, " #a ", 30\n\t" \
"xor a4, a4, t4\n\t" \
"srliw t4, " #a ", 2\n\t" \
"slliw t6, " #a ", 19\n\t" \
\
"addw " #h ", " #h ", a4\n\t" \
"srliw a5, " #a ", 13\n\t" \
"slliw a4, " #a ", 10\n\t" \
"or t4, t4, t5\n\t" \
"xor a5, a5, t6\n\t" \
"srliw t6, " #a ", 22\n\t" \
"xor t4, t4, a4\n\t" \
"xor a5, a5, t6\n\t" \
\
\
\
"xor t6, " #f ", " #g "\n\t" \
\
"xor t5, " #a ", " #b "\n\t" \
\
"xor a4, " #b ", " #c "\n\t" \
"xor a5, a5, t4\n\t" \
\
"and t6, t6, " #e "\n\t" \
\
"and t5, t5, a4\n\t" \
\
"xor t6, t6, " #g "\n\t" \
\
"addw a4, " #k ", " #w "\n\t" \
\
"addw " #h ", " #h ", t6\n\t" \
\
"xor t5, t5, " #b "\n\t" \
\
"addw " #h ", " #h ", a4\n\t" \
\
"addw t5, a5, t5\n\t" \
\
"addw " #d ", " #d ", " #h "\n\t" \
\
"addw " #h ", " #h ", t5\n\t"
#define W_UPDATE_2(w0, w1, w4, w5, w7, reg_w0, reg_w1, reg_w7) \
\
"srli a7, " #w0 ", 32\n\t" \
\
"srli a6, " #w4 ", 32\n\t" \
\
"slliw t4, a7, 25\n\t" \
"srliw t5, a7, 7\n\t" \
"slliw t6, a7, 14\n\t" \
"srliw a4, a7, 18\n\t" \
"or t4, t4, t5\n\t" \
"srliw t5, a7, 3\n\t" \
"xor a4, a4, t6\n\t" \
"xor t4, t4, t5\n\t" \
\
"slliw t6, " #w7 ", 15\n\t" \
"srliw t5, " #w7 ", 17\n\t" \
"xor a4, a4, t4\n\t" \
"slliw t4, " #w7 ", 13\n\t" \
"srliw a5, " #w7 ", 19\n\t" \
"or t6, t6, t5\n\t" \
"srliw t5, " #w7 ", 10\n\t" \
"xor a5, a5, t4\n\t" \
"xor t6, t6, t5\n\t" \
"xor a5, a5, t6\n\t" \
\
"addw " #w0 ", " #w0 ", a4\n\t" \
\
"addw a5, a5, a6\n\t" \
\
"addw " #w0 ", a5, " #w0 "\n\t" \
\
\
\
"srli a4, " #w7 ", 32\n\t" \
\
"slliw t4, " #w1 ", 25\n\t" \
"srliw t5, " #w1 ", 7\n\t" \
"slliw t6, " #w1 ", 14\n\t" \
"srliw a6, " #w1 ", 18\n\t" \
"or t4, t4, t5\n\t" \
"srliw t5, " #w1 ", 3\n\t" \
"xor a6, a6, t6\n\t" \
"xor t4, t4, t5\n\t" \
\
"slliw t6, a4, 15\n\t" \
"srliw t5, a4, 17\n\t" \
"xor a6, a6, t4\n\t" \
"slliw t4, a4, 13\n\t" \
"srliw a5, a4, 19\n\t" \
"or t6, t6, t5\n\t" \
"srliw t5, a4, 10\n\t" \
"xor a5, a5, t4\n\t" \
"xor t6, t6, t5\n\t" \
"xor a5, a5, t6\n\t" \
\
"addw t5, a6, a7\n\t" \
\
"addw a5, a5, " #w5 "\n\t" \
\
"addw a5, a5, t5\n\t" \
\
PACK_BB(w0, w0, a5, reg_w0, reg_w0, REG_A5)
#endif
#define RND2(a, b, c, d, e, f, g, h, w, o) \
\
"ld a6, " #o "(%[k])\n\t" \
RND(a, b, c, d, e, f, g, h, w, a6) \
\
"srli a6, a6, 32\n\t" \
\
"srli a7, " #w ", 32\n\t" \
RND(h, a, b, c, d, e, f, g, a7, a6)
#define RND16() \
RND2(t0, t1, t2, t3, s8, s9, s10, s11, s0, 0) \
W_UPDATE_2(s0, s1, s4, s5, s7, REG_S0, REG_S1, REG_S7) \
RND2(s10, s11, t0, t1, t2, t3, s8, s9, s1, 8) \
W_UPDATE_2(s1, s2, s5, s6, s0, REG_S1, REG_S2, REG_S0) \
RND2(s8, s9, s10, s11, t0, t1, t2, t3, s2, 16) \
W_UPDATE_2(s2, s3, s6, s7, s1, REG_S2, REG_S3, REG_S1) \
RND2(t2, t3, s8, s9, s10, s11, t0, t1, s3, 24) \
W_UPDATE_2(s3, s4, s7, s0, s2, REG_S3, REG_S4, REG_S2) \
RND2(t0, t1, t2, t3, s8, s9, s10, s11, s4, 32) \
W_UPDATE_2(s4, s5, s0, s1, s3, REG_S4, REG_S5, REG_S3) \
RND2(s10, s11, t0, t1, t2, t3, s8, s9, s5, 40) \
W_UPDATE_2(s5, s6, s1, s2, s4, REG_S5, REG_S6, REG_S4) \
RND2(s8, s9, s10, s11, t0, t1, t2, t3, s6, 48) \
W_UPDATE_2(s6, s7, s2, s3, s5, REG_S6, REG_S7, REG_S5) \
RND2(t2, t3, s8, s9, s10, s11, t0, t1, s7, 56) \
W_UPDATE_2(s7, s0, s3, s4, s6, REG_S7, REG_S0, REG_S6)
#define RND16_LAST() \
RND2(t0, t1, t2, t3, s8, s9, s10, s11, s0, 0) \
RND2(s10, s11, t0, t1, t2, t3, s8, s9, s1, 8) \
RND2(s8, s9, s10, s11, t0, t1, t2, t3, s2, 16) \
RND2(t2, t3, s8, s9, s10, s11, t0, t1, s3, 24) \
RND2(t0, t1, t2, t3, s8, s9, s10, s11, s4, 32) \
RND2(s10, s11, t0, t1, t2, t3, s8, s9, s5, 40) \
RND2(s8, s9, s10, s11, t0, t1, t2, t3, s6, 48) \
RND2(t2, t3, s8, s9, s10, s11, t0, t1, s7, 56)
static WC_OMIT_FRAME_POINTER WC_INLINE void Sha256Transform(wc_Sha256* sha256,
const byte* data, word32 blocks)
{
word32* k = (word32*)K;
__asm__ __volatile__ (
"ld t0, 0(%[digest])\n\t"
"ld t2, 8(%[digest])\n\t"
"ld s8, 16(%[digest])\n\t"
"ld s10, 24(%[digest])\n\t"
"srli t1, t0, 32\n\t"
"srli t3, t2, 32\n\t"
"srli s9, s8, 32\n\t"
"srli s11, s10, 32\n\t"
"slli %[blocks], %[blocks], 2\n\t"
"\n1:\n\t"
#ifndef WOLFSSL_RISCV_BASE_BIT_MANIPULATION
LOAD_DWORD_REV(s0, 0, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s1, 8, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s2, 16, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s3, 24, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s4, 32, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s5, 40, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s6, 48, %[data], a4, a5, a6, a7)
LOAD_DWORD_REV(s7, 56, %[data], a4, a5, a6, a7)
#else
"lwu a4, 0(%[data])\n\t"
"lwu s0, 4(%[data])\n\t"
"lwu a5, 8(%[data])\n\t"
"lwu s1, 12(%[data])\n\t"
"lwu a6, 16(%[data])\n\t"
"lwu s2, 20(%[data])\n\t"
"lwu a7, 24(%[data])\n\t"
"lwu s3, 28(%[data])\n\t"
PACK_BB(s0, s0, a4, REG_S0, REG_S0, REG_A4)
PACK_BB(s1, s1, a5, REG_S1, REG_S1, REG_A5)
PACK_BB(s2, s2, a6, REG_S2, REG_S2, REG_A6)
PACK_BB(s3, s3, a7, REG_S3, REG_S3, REG_A7)
REV8(REG_S0, REG_S0)
REV8(REG_S1, REG_S1)
REV8(REG_S2, REG_S2)
REV8(REG_S3, REG_S3)
"lwu a4, 32(%[data])\n\t"
"lwu s4, 36(%[data])\n\t"
"lwu a5, 40(%[data])\n\t"
"lwu s5, 44(%[data])\n\t"
"lwu a6, 48(%[data])\n\t"
"lwu s6, 52(%[data])\n\t"
"lwu a7, 56(%[data])\n\t"
"lwu s7, 60(%[data])\n\t"
PACK_BB(s4, s4, a4, REG_S4, REG_S4, REG_A4)
PACK_BB(s5, s5, a5, REG_S5, REG_S5, REG_A5)
PACK_BB(s6, s6, a6, REG_S6, REG_S6, REG_A6)
PACK_BB(s7, s7, a7, REG_S7, REG_S7, REG_A7)
REV8(REG_S4, REG_S4)
REV8(REG_S5, REG_S5)
REV8(REG_S6, REG_S6)
REV8(REG_S7, REG_S7)
#endif
"addi %[blocks], %[blocks], -1\n\t"
"\n2:\n\t"
RND16()
"addi %[blocks], %[blocks], -1\n\t"
"add %[k], %[k], 64\n\t"
"andi a4, %[blocks], 3\n\t"
"bnez a4, 2b \n\t"
RND16_LAST()
"addi %[k], %[k], -192\n\t"
"# Add working vars back into digest state.\n\t"
"ld a4, 0(%[digest])\n\t"
"ld a5, 8(%[digest])\n\t"
"ld a6, 16(%[digest])\n\t"
"ld a7, 24(%[digest])\n\t"
"addw t0, t0, a4\n\t"
"addw t2, t2, a5\n\t"
"addw s8, s8, a6\n\t"
"addw s10, s10, a7\n\t"
"srli a4, a4, 32\n\t"
"srli a5, a5, 32\n\t"
"srli a6, a6, 32\n\t"
"srli a7, a7, 32\n\t"
"addw t1, t1, a4\n\t"
"addw t3, t3, a5\n\t"
"addw s9, s9, a6\n\t"
"addw s11, s11, a7\n\t"
"sw t0, 0(%[digest])\n\t"
"sw t1, 4(%[digest])\n\t"
"sw t2, 8(%[digest])\n\t"
"sw t3, 12(%[digest])\n\t"
"sw s8, 16(%[digest])\n\t"
"sw s9, 20(%[digest])\n\t"
"sw s10, 24(%[digest])\n\t"
"sw s11, 28(%[digest])\n\t"
"add %[data], %[data], 64\n\t"
"bnez %[blocks], 1b \n\t"
: [blocks] "+r" (blocks), [data] "+r" (data), [k] "+r" (k)
: [digest] "r" (sha256->digest)
: "cc", "memory", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
"a4", "a5", "a6", "a7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10",
"s11"
);
}
#else
#define VSHA2CL_VV(vd, vs1, vs2) \
ASM_WORD((0b101111 << 26) | (0b1 << 25) | \
(0b010 << 12) | (0b1110111 << 0) | \
(vd << 7) | (vs1 << 15) | (vs2 << 20))
#define VSHA2CH_VV(vd, vs1, vs2) \
ASM_WORD((0b101110 << 26) | (0b1 << 25) | \
(0b010 << 12) | (0b1110111 << 0) | \
(vd << 7) | (vs1 << 15) | (vs2 << 20))
#define VSHA2MS_VV(vd, vs1, vs2) \
ASM_WORD((0b101101 << 26) | (0b1 << 25) | \
(0b010 << 12) | (0b1110111 << 0) | \
(vd << 7) | (vs1 << 15) | (vs2 << 20))
#define RND4(w0, w1, w2, w3, k) \
\
VADD_VV(REG_V7, w0, k) \
VMV_X_S(REG_T1, w1) \
VSHA2CL_VV(REG_V5, REG_V7, REG_V4) \
VMV_V_V(REG_V6, w2) \
VSHA2CH_VV(REG_V4, REG_V7, REG_V5) \
\
VMV_S_X(REG_V6, REG_T1) \
VSHA2MS_VV(w0, w3, REG_V6)
#define RND4_LAST(w, k) \
\
VADD_VV(REG_V7, w, k) \
VSHA2CL_VV(REG_V5, REG_V7, REG_V4) \
VSHA2CH_VV(REG_V4, REG_V7, REG_V5)
#define RND16(k) \
RND4(REG_V0, REG_V1, REG_V2, REG_V3, (k + 0)) \
RND4(REG_V1, REG_V2, REG_V3, REG_V0, (k + 1)) \
RND4(REG_V2, REG_V3, REG_V0, REG_V1, (k + 2)) \
RND4(REG_V3, REG_V0, REG_V1, REG_V2, (k + 3))
#define RND16_LAST(k) \
RND4_LAST(REG_V0, (k + 0)) \
RND4_LAST(REG_V1, (k + 1)) \
RND4_LAST(REG_V2, (k + 2)) \
RND4_LAST(REG_V3, (k + 3))
static void Sha256Transform(wc_Sha256* sha256, const byte* data,
word32 blocks)
{
word32* k = (word32*)K;
__asm__ __volatile__ (
VSETIVLI(REG_ZERO, 4, 1, 1, 0b010, 0b000)
"mv t0, %[digest]\n\t"
VL2RE32_V(REG_V4, REG_T0)
"mv t0, %[k]\n\t"
VL8RE32_V(REG_V8, REG_T0)
"addi t0, %[k], 128\n\t"
VL8RE32_V(REG_V16, REG_T0)
"\n1:\n\t"
VMV_V_V(REG_V30, REG_V4)
VMV_V_V(REG_V31, REG_V5)
"mv t0, %[data]\n\t"
VL4RE32_V(REG_V0, REG_T0)
VREV8(REG_V0, REG_V0)
VREV8(REG_V1, REG_V1)
VREV8(REG_V2, REG_V2)
VREV8(REG_V3, REG_V3)
RND16(REG_V8)
RND16(REG_V12)
RND16(REG_V16)
RND16_LAST(REG_V20)
VADD_VV(REG_V4, REG_V4, REG_V30)
VADD_VV(REG_V5, REG_V5, REG_V31)
"addi %[blocks], %[blocks], -1\n\t"
"add %[data], %[data], 64\n\t"
"bnez %[blocks], 1b \n\t"
"mv t0, %[digest]\n\t"
VS2R_V(REG_V4, REG_T0)
: [blocks] "+r" (blocks), [data] "+r" (data), [k] "+r" (k)
: [digest] "r" (sha256->digest)
: "cc", "memory", "t0", "t1"
);
}
#endif
static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data,
word32 len)
{
word32 add;
word32 blocks;
if (len > 0) {
AddLength(sha256, len);
if (sha256->buffLen > 0) {
add = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen);
XMEMCPY((byte*)(sha256->buffer) + sha256->buffLen, data, add);
sha256->buffLen += add;
data += add;
len -= add;
if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) {
Sha256Transform(sha256, (byte*)sha256->buffer, 1);
sha256->buffLen = 0;
}
}
blocks = len / WC_SHA256_BLOCK_SIZE;
if (blocks > 0) {
Sha256Transform(sha256, data, blocks);
data += blocks * WC_SHA256_BLOCK_SIZE;
len -= blocks * WC_SHA256_BLOCK_SIZE;
}
if (len > 0) {
XMEMCPY(sha256->buffer, data, len);
sha256->buffLen = len;
}
}
(void)add;
(void)blocks;
return 0;
}
static WC_INLINE void Sha256Final(wc_Sha256* sha256, byte* hash)
{
byte* local;
local = (byte*)sha256->buffer;
local[sha256->buffLen++] = 0x80;
if (sha256->buffLen > WC_SHA256_PAD_SIZE) {
XMEMSET(&local[sha256->buffLen], 0,
WC_SHA256_BLOCK_SIZE - sha256->buffLen);
Sha256Transform(sha256, (byte*)sha256->buffer, 1);
sha256->buffLen = 0;
}
XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen);
sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) +
(sha256->hiLen << 3);
sha256->loLen = sha256->loLen << 3;
XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
sizeof(word32));
__asm__ __volatile__ (
#if defined(WOLFSSL_RISCV_BASE_BIT_MANIPULATION)
"ld t1, 56(%[buff])\n\t"
REV8(REG_T1, REG_T1)
"srli t0, t1, 32\n\t"
"sw t0, 56(%[buff])\n\t"
"sw t1, 60(%[buff])\n\t"
#else
LOAD_WORD_REV(t0, 56, %[buff], t2, t3, t4)
LOAD_WORD_REV(t1, 60, %[buff], t2, t3, t4)
"sw t0, 56(%[buff])\n\t"
"sw t1, 60(%[buff])\n\t"
#endif
:
: [buff] "r" (sha256->buffer)
: "cc", "memory", "t0", "t1", "t2", "t3", "t4"
);
Sha256Transform(sha256, (byte*)sha256->buffer, 1);
__asm__ __volatile__ (
#if defined(WOLFSSL_RISCV_VECTOR_CRYPTO_ASM)
VSETIVLI(REG_ZERO, 4, 1, 1, 0b010, 0b000)
"mv t0, %[digest]\n\t"
VL2RE32_V(REG_V8, REG_T0)
VREV8(REG_V8, REG_V8)
VREV8(REG_V9, REG_V9)
VSLIDEDOWN_VI(REG_V0, REG_V8, 3)
VSLIDEDOWN_VI(REG_V2, REG_V8, 2)
VSLIDEDOWN_VI(REG_V1, REG_V8, 1)
VSLIDEDOWN_VI(REG_V3, REG_V9, 3)
VSLIDEDOWN_VI(REG_V4, REG_V9, 2)
VSLIDEDOWN_VI(REG_V5, REG_V9, 1)
VSLIDEUP_VI(REG_V0, REG_V2, 1)
VSLIDEUP_VI(REG_V0, REG_V3, 2)
VSLIDEUP_VI(REG_V0, REG_V4, 3)
VSLIDEUP_VI(REG_V1, REG_V8, 1)
VSLIDEUP_VI(REG_V1, REG_V5, 2)
VSLIDEUP_VI(REG_V1, REG_V9, 3)
"mv t0, %[hash]\n\t"
VS2R_V(REG_V0, REG_T0)
#elif defined(WOLFSSL_RISCV_VECTOR_BASE_BIT_MANIPULATION)
VSETIVLI(REG_ZERO, 4, 1, 1, 0b010, 0b000)
"mv t0, %[digest]\n\t"
VL2RE32_V(REG_V0, REG_T0)
VREV8(REG_V0, REG_V0)
VREV8(REG_V1, REG_V1)
"mv t0, %[hash]\n\t"
VS2R_V(REG_V0, REG_T0)
#elif defined(WOLFSSL_RISCV_BASE_BIT_MANIPULATION)
"ld t1, 0(%[digest])\n\t"
"ld t3, 8(%[digest])\n\t"
"ld a5, 16(%[digest])\n\t"
"ld a7, 24(%[digest])\n\t"
REV8(REG_T1, REG_T1)
REV8(REG_T3, REG_T3)
REV8(REG_A5, REG_A5)
REV8(REG_A7, REG_A7)
"srli t0, t1, 32\n\t"
"srli t2, t3, 32\n\t"
"srli a4, a5, 32\n\t"
"srli a6, a7, 32\n\t"
"sw t0, 0(%[hash])\n\t"
"sw t1, 4(%[hash])\n\t"
"sw t2, 8(%[hash])\n\t"
"sw t3, 12(%[hash])\n\t"
"sw a4, 16(%[hash])\n\t"
"sw a5, 20(%[hash])\n\t"
"sw a6, 24(%[hash])\n\t"
"sw a7, 28(%[hash])\n\t"
#else
LOAD_WORD_REV(t0, 0, %[digest], t2, t3, t4)
LOAD_WORD_REV(t1, 4, %[digest], t2, t3, t4)
LOAD_WORD_REV(a4, 8, %[digest], t2, t3, t4)
LOAD_WORD_REV(a5, 12, %[digest], t2, t3, t4)
"sw t0, 0(%[hash])\n\t"
"sw t1, 4(%[hash])\n\t"
"sw a4, 8(%[hash])\n\t"
"sw a5, 12(%[hash])\n\t"
LOAD_WORD_REV(t0, 16, %[digest], t2, t3, t4)
LOAD_WORD_REV(t1, 20, %[digest], t2, t3, t4)
LOAD_WORD_REV(a4, 24, %[digest], t2, t3, t4)
LOAD_WORD_REV(a5, 28, %[digest], t2, t3, t4)
"sw t0, 16(%[hash])\n\t"
"sw t1, 20(%[hash])\n\t"
"sw a4, 24(%[hash])\n\t"
"sw a5, 28(%[hash])\n\t"
#endif
:
: [digest] "r" (sha256->digest), [hash] "r" (hash)
: "cc", "memory", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
"a4", "a5", "a6", "a7"
);
}
#ifndef NO_SHA256
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
int ret = 0;
if (sha256 == NULL) {
ret = BAD_FUNC_ARG;
}
else {
sha256->heap = heap;
#ifdef WOLF_CRYPTO_CB
sha256->devId = devId;
#endif
(void)devId;
InitSha256(sha256);
}
return ret;
}
int wc_InitSha256(wc_Sha256* sha256)
{
return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
}
void wc_Sha256Free(wc_Sha256* sha256)
{
(void)sha256;
}
int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
{
int ret;
if ((sha256 == NULL) || ((data == NULL) && (len != 0))) {
ret = BAD_FUNC_ARG;
}
else {
ret = Sha256Update(sha256, data, len);
}
return ret;
}
int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
{
int ret = 0;
if ((sha256 == NULL) || (hash == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
#ifndef WOLFSSL_RISCV_VECTOR_CRYPTO_ASM
ByteReverseWords((word32*)digest, (word32*)sha256->digest,
WC_SHA256_DIGEST_SIZE);
#else
digest[0] = ByteReverseWord32(sha256->digest[3]);
digest[1] = ByteReverseWord32(sha256->digest[2]);
digest[2] = ByteReverseWord32(sha256->digest[7]);
digest[3] = ByteReverseWord32(sha256->digest[6]);
digest[4] = ByteReverseWord32(sha256->digest[1]);
digest[5] = ByteReverseWord32(sha256->digest[0]);
digest[6] = ByteReverseWord32(sha256->digest[5]);
digest[7] = ByteReverseWord32(sha256->digest[4]);
#endif
XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE);
}
return ret;
}
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
{
int ret = 0;
if ((sha256 == NULL) || (hash == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
Sha256Final(sha256, hash);
InitSha256(sha256);
}
return ret;
}
int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
{
int ret;
if ((sha256 == NULL) || (hash == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
wc_Sha256 tmpSha256;
XMEMSET(&tmpSha256, 0, sizeof(tmpSha256));
ret = wc_Sha256Copy(sha256, &tmpSha256);
if (ret == 0) {
Sha256Final(&tmpSha256, hash);
}
}
return ret;
}
#ifdef WOLFSSL_HASH_FLAGS
int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags)
{
if (sha256 != NULL) {
sha256->flags = flags;
}
return 0;
}
int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags)
{
if ((sha256 != NULL) && (flags != NULL)) {
*flags = sha256->flags;
}
return 0;
}
#endif
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
int ret = 0;
if ((src == NULL) || (dst == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
XMEMCPY(dst, src, sizeof(wc_Sha256));
}
return ret;
}
#ifdef OPENSSL_EXTRA
int wc_Sha256Transform(wc_Sha256* sha256, const unsigned char* data)
{
int ret = 0;
if ((sha256 == NULL) || (data == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords(sha256->buffer, (word32*)data, WC_SHA256_BLOCK_SIZE);
#else
XMEMCPY(sha256->buffer, data, WC_SHA256_BLOCK_SIZE);
#endif
Sha256Transform(sha256, (byte*)sha256->buffer, 1);
}
return ret;
}
#endif
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH)
int wc_Sha256HashBlock(wc_Sha256* sha256, const unsigned char* data,
unsigned char* hash)
{
int ret = 0;
if ((sha256 == NULL) || (data == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
Sha256Transform(sha256, data, 1);
if (hash != NULL) {
#ifdef LITTLE_ENDIAN_ORDER
word32* hash32 = (word32*)hash;
word32* digest = (word32*)sha256->digest;
hash32[0] = ByteReverseWord32(digest[0]);
hash32[1] = ByteReverseWord32(digest[1]);
hash32[2] = ByteReverseWord32(digest[2]);
hash32[3] = ByteReverseWord32(digest[3]);
hash32[4] = ByteReverseWord32(digest[4]);
hash32[5] = ByteReverseWord32(digest[5]);
hash32[6] = ByteReverseWord32(digest[6]);
hash32[7] = ByteReverseWord32(digest[7]);
#else
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
#endif
#ifndef WOLFSSL_RISCV_VECTOR_CRYPTO_ASM
sha256->digest[0] = 0x6A09E667L;
sha256->digest[1] = 0xBB67AE85L;
sha256->digest[2] = 0x3C6EF372L;
sha256->digest[3] = 0xA54FF53AL;
sha256->digest[4] = 0x510E527FL;
sha256->digest[5] = 0x9B05688CL;
sha256->digest[6] = 0x1F83D9ABL;
sha256->digest[7] = 0x5BE0CD19L;
#else
sha256->digest[0] = 0x9B05688CL;
sha256->digest[1] = 0x510E527FL;
sha256->digest[2] = 0xBB67AE85L;
sha256->digest[3] = 0x6A09E667L;
sha256->digest[4] = 0x5BE0CD19L;
sha256->digest[5] = 0x1F83D9ABL;
sha256->digest[6] = 0xA54FF53AL;
sha256->digest[7] = 0x3C6EF372L;
#endif
}
}
return ret;
}
#endif
#endif
#ifdef WOLFSSL_SHA224
static void InitSha224(wc_Sha224* sha224)
{
#ifndef WOLFSSL_RISCV_VECTOR_CRYPTO_ASM
sha224->digest[0] = 0xc1059ed8;
sha224->digest[1] = 0x367cd507;
sha224->digest[2] = 0x3070dd17;
sha224->digest[3] = 0xf70e5939;
sha224->digest[4] = 0xffc00b31;
sha224->digest[5] = 0x68581511;
sha224->digest[6] = 0x64f98fa7;
sha224->digest[7] = 0xbefa4fa4;
#else
sha224->digest[0] = 0x68581511;
sha224->digest[1] = 0xffc00b31;
sha224->digest[2] = 0x367cd507;
sha224->digest[3] = 0xc1059ed8;
sha224->digest[4] = 0xbefa4fa4;
sha224->digest[5] = 0x64f98fa7;
sha224->digest[6] = 0xf70e5939;
sha224->digest[7] = 0x3070dd17;
#endif
sha224->buffLen = 0;
sha224->loLen = 0;
sha224->hiLen = 0;
#ifdef WOLFSSL_HASH_FLAGS
sha224->flags = 0;
#endif
}
int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
{
int ret = 0;
if (sha224 == NULL) {
ret = BAD_FUNC_ARG;
}
else {
sha224->heap = heap;
(void)devId;
InitSha224(sha224);
}
return ret;
}
int wc_InitSha224(wc_Sha224* sha224)
{
return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID);
}
int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
{
int ret;
if ((sha224 == NULL) || ((data == NULL) && (len > 0))) {
ret = BAD_FUNC_ARG;
}
else {
ret = Sha256Update((wc_Sha256 *)sha224, data, len);
}
return ret;
}
int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
{
int ret = 0;
if ((sha224 == NULL) || (hash == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
word32 hashTmp[WC_SHA256_DIGEST_SIZE/sizeof(word32)];
Sha256Final((wc_Sha256*)sha224, (byte*)hashTmp);
XMEMCPY(hash, hashTmp, WC_SHA224_DIGEST_SIZE);
InitSha224(sha224);
}
return ret;
}
void wc_Sha224Free(wc_Sha224* sha224)
{
(void)sha224;
}
int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash)
{
int ret;
if ((sha224 == NULL) || (hash == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
wc_Sha224 tmpSha224;
XMEMSET(&tmpSha224, 0, sizeof(tmpSha224));
ret = wc_Sha224Copy(sha224, &tmpSha224);
if (ret == 0) {
ret = wc_Sha224Final(&tmpSha224, hash);
}
}
return ret;
}
#ifdef WOLFSSL_HASH_FLAGS
int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags)
{
if (sha224 != NULL) {
sha224->flags = flags;
}
return 0;
}
int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags)
{
if ((sha224 != NULL) && (flags != NULL)) {
*flags = sha224->flags;
}
return 0;
}
#endif
int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst)
{
int ret = 0;
if ((src == NULL) || (dst == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
XMEMCPY(dst, src, sizeof(wc_Sha224));
}
return ret;
}
#endif
#endif
#endif