Skip to content

Commit

Permalink
Merge pull request wolfSSL#7928 from dgarske/riscv_fixes
Browse files Browse the repository at this point in the history
Fixes for building on RISC-V
  • Loading branch information
SparkiDev authored Sep 3, 2024
2 parents 4d837e7 + b7a6c6c commit ec6c705
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 124 deletions.
5 changes: 2 additions & 3 deletions src/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -992,14 +992,13 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/blake2s.c
endif

if BUILD_CHACHA
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/chacha.c
if BUILD_ARMASM_NEON
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-chacha.c
else
if BUILD_RISCV_ASM
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/riscv/riscv-64-chacha.c
else
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/chacha.c
endif !BUILD_RISCV_ASM
endif BUILD_RISCV_ASM
if !BUILD_X86_ASM
if BUILD_INTELASM
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/chacha_asm.S
Expand Down
238 changes: 122 additions & 116 deletions wolfcrypt/src/chacha.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,56 @@ Public domain.

#include <wolfssl/wolfcrypt/settings.h>

#ifdef HAVE_CHACHA
#include <wolfssl/wolfcrypt/chacha.h>
#include <wolfssl/wolfcrypt/error-crypt.h>

#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif

#ifdef BIG_ENDIAN_ORDER
#define LITTLE32(x) ByteReverseWord32(x)
#else
#define LITTLE32(x) (x)
#endif

/* Number of rounds */
#define ROUNDS 20

#define U32C(v) (v##U)
#define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF))
#define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0])

#define ROTATE(v,c) rotlFixed(v, c)
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))

#define QUARTERROUND(a,b,c,d) \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
#endif /* HAVE_CHACHA */


#if defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_ARMASM_NO_NEON)
/* implementation is located in wolfcrypt/src/port/arm/armv8-chacha.c */

#elif defined(WOLFSSL_RISCV_ASM)
/* implementation located in wolfcrypt/src/port/rsicv/riscv-64-chacha.c */

#else

/* BEGIN ChaCha C implementation */
#if defined(HAVE_CHACHA)

#include <wolfssl/wolfcrypt/chacha.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/cpuid.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif

#ifdef CHACHA_AEAD_TEST
#include <stdio.h>
Expand Down Expand Up @@ -88,31 +119,6 @@ Public domain.
static word32 cpuidFlags = 0;
#endif

#ifdef BIG_ENDIAN_ORDER
#define LITTLE32(x) ByteReverseWord32(x)
#else
#define LITTLE32(x) (x)
#endif

/* Number of rounds */
#define ROUNDS 20

#define U32C(v) (v##U)
#define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF))
#define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0])

#define ROTATE(v,c) rotlFixed(v, c)
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))

#define QUARTERROUND(a,b,c,d) \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);


/**
* Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version
* uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB.
Expand Down Expand Up @@ -238,86 +244,6 @@ static WC_INLINE void wc_Chacha_wordtobyte(word32 x[CHACHA_CHUNK_WORDS],
}
#endif /* !USE_INTEL_CHACHA_SPEEDUP */


#ifdef HAVE_XCHACHA

/*
* wc_HChacha_block - half a ChaCha block, for XChaCha
*
* see https://tools.ietf.org/html/draft-arciszewski-xchacha-03
*/
static WC_INLINE void wc_HChacha_block(ChaCha* ctx, word32 stream[CHACHA_CHUNK_WORDS/2], word32 nrounds)
{
word32 x[CHACHA_CHUNK_WORDS];
word32 i;

for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
x[i] = ctx->X[i];
}

for (i = nrounds; i > 0; i -= 2) {
QUARTERROUND(0, 4, 8, 12)
QUARTERROUND(1, 5, 9, 13)
QUARTERROUND(2, 6, 10, 14)
QUARTERROUND(3, 7, 11, 15)
QUARTERROUND(0, 5, 10, 15)
QUARTERROUND(1, 6, 11, 12)
QUARTERROUND(2, 7, 8, 13)
QUARTERROUND(3, 4, 9, 14)
}

for (i = 0; i < CHACHA_CHUNK_WORDS/4; ++i)
stream[i] = x[i];
for (i = CHACHA_CHUNK_WORDS/4; i < CHACHA_CHUNK_WORDS/2; ++i)
stream[i] = x[i + CHACHA_CHUNK_WORDS/2];
}

/* XChaCha -- https://tools.ietf.org/html/draft-arciszewski-xchacha-03 */
int wc_XChacha_SetKey(ChaCha *ctx,
const byte *key, word32 keySz,
const byte *nonce, word32 nonceSz,
word32 counter) {
word32 k[CHACHA_MAX_KEY_SZ];
byte iv[CHACHA_IV_BYTES];
int ret;

if (nonceSz != XCHACHA_NONCE_BYTES)
return BAD_FUNC_ARG;

if ((ret = wc_Chacha_SetKey(ctx, key, keySz)) < 0)
return ret;

/* form a first chacha IV from the first 16 bytes of the nonce.
* the first word is supplied in the "counter" arg, and
* the result is a full 128 bit nonceful IV for the one-time block
* crypto op that follows.
*/
if ((ret = wc_Chacha_SetIV(ctx, nonce + 4, U8TO32_LITTLE(nonce))) < 0)
return ret;

wc_HChacha_block(ctx, k, 20); /* 20 rounds, but keeping half the output. */

/* the HChacha output is used as a 256 bit key for the main cipher. */
XMEMCPY(&ctx->X[4], k, 8 * sizeof(word32));

/* use 8 bytes from the end of the 24 byte nonce, padded up to 12 bytes,
* to form the IV for the main cipher.
*/
XMEMSET(iv, 0, 4);
XMEMCPY(iv + 4, nonce + 16, 8);

if ((ret = wc_Chacha_SetIV(ctx, iv, counter)) < 0)
return ret;

ForceZero(k, sizeof k);
ForceZero(iv, sizeof iv);

return 0;
}

#endif /* HAVE_XCHACHA */


#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -441,14 +367,94 @@ int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input,
#endif
}

void wc_Chacha_purge_current_block(ChaCha* ctx) {
#endif /* HAVE_CHACHA */
#endif /* END ChaCha C implementation */

#if defined(HAVE_CHACHA) && defined(HAVE_XCHACHA)

void wc_Chacha_purge_current_block(ChaCha* ctx)
{
if (ctx->left > 0) {
byte scratch[CHACHA_CHUNK_BYTES];
XMEMSET(scratch, 0, sizeof(scratch));
(void)wc_Chacha_Process(ctx, scratch, scratch, CHACHA_CHUNK_BYTES - ctx->left);
}
}

#endif /* HAVE_CHACHA */
/*
* wc_HChacha_block - half a ChaCha block, for XChaCha
*
* see https://tools.ietf.org/html/draft-arciszewski-xchacha-03
*/
static WC_INLINE void wc_HChacha_block(ChaCha* ctx,
word32 stream[CHACHA_CHUNK_WORDS/2], word32 nrounds)
{
word32 x[CHACHA_CHUNK_WORDS];
word32 i;

for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
x[i] = ctx->X[i];
}

for (i = nrounds; i > 0; i -= 2) {
QUARTERROUND(0, 4, 8, 12)
QUARTERROUND(1, 5, 9, 13)
QUARTERROUND(2, 6, 10, 14)
QUARTERROUND(3, 7, 11, 15)
QUARTERROUND(0, 5, 10, 15)
QUARTERROUND(1, 6, 11, 12)
QUARTERROUND(2, 7, 8, 13)
QUARTERROUND(3, 4, 9, 14)
}

for (i = 0; i < CHACHA_CHUNK_WORDS/4; ++i)
stream[i] = x[i];
for (i = CHACHA_CHUNK_WORDS/4; i < CHACHA_CHUNK_WORDS/2; ++i)
stream[i] = x[i + CHACHA_CHUNK_WORDS/2];
}

/* XChaCha -- https://tools.ietf.org/html/draft-arciszewski-xchacha-03 */
int wc_XChacha_SetKey(ChaCha *ctx,
const byte *key, word32 keySz,
const byte *nonce, word32 nonceSz,
word32 counter)
{
int ret;
word32 k[CHACHA_MAX_KEY_SZ];
byte iv[CHACHA_IV_BYTES];

if (nonceSz != XCHACHA_NONCE_BYTES)
return BAD_FUNC_ARG;

if ((ret = wc_Chacha_SetKey(ctx, key, keySz)) < 0)
return ret;

/* form a first chacha IV from the first 16 bytes of the nonce.
* the first word is supplied in the "counter" arg, and
* the result is a full 128 bit nonceful IV for the one-time block
* crypto op that follows.
*/
if ((ret = wc_Chacha_SetIV(ctx, nonce + 4, U8TO32_LITTLE(nonce))) < 0)
return ret;

wc_HChacha_block(ctx, k, 20); /* 20 rounds, but keeping half the output. */

/* the HChacha output is used as a 256 bit key for the main cipher. */
XMEMCPY(&ctx->X[4], k, 8 * sizeof(word32));

/* use 8 bytes from the end of the 24 byte nonce, padded up to 12 bytes,
* to form the IV for the main cipher.
*/
XMEMSET(iv, 0, 4);
XMEMCPY(iv + 4, nonce + 16, 8);

if ((ret = wc_Chacha_SetIV(ctx, iv, counter)) < 0)
return ret;

ForceZero(k, sizeof k);
ForceZero(iv, sizeof iv);

return 0;
}

#endif /* WOLFSSL_ARMASM && !WOLFSSL_ARMASM_NO_NEON */
#endif /* HAVE_CHACHA && HAVE_XCHACHA */
2 changes: 1 addition & 1 deletion wolfcrypt/src/port/riscv/riscv-64-sha512.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,7 @@ int wc_Sha512Transform(wc_Sha512* sha512, const unsigned char* data)
ret = BAD_FUNC_ARG;
}
else {
ByteReverseWords(sha512->buffer, (word32*)data, WC_SHA512_BLOCK_SIZE);
ByteReverseWords((word32*)sha512->buffer, (word32*)data, WC_SHA512_BLOCK_SIZE);
Sha512Transform(sha512, (byte*)sha512->buffer, 1);
}

Expand Down
4 changes: 2 additions & 2 deletions wolfssl/wolfcrypt/chacha.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ WOLFSSL_API int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter);
WOLFSSL_API int wc_Chacha_Process(ChaCha* ctx, byte* cipher, const byte* plain,
word32 msglen);

WOLFSSL_LOCAL void wc_Chacha_purge_current_block(ChaCha* ctx);

WOLFSSL_API int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz);

#ifdef HAVE_XCHACHA
WOLFSSL_LOCAL void wc_Chacha_purge_current_block(ChaCha* ctx);

WOLFSSL_API int wc_XChacha_SetKey(ChaCha *ctx, const byte *key, word32 keySz,
const byte *nonce, word32 nonceSz,
word32 counter);
Expand Down
4 changes: 2 additions & 2 deletions wolfssl/wolfcrypt/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -3281,8 +3281,8 @@ extern void uITRON4_free(void *p) ;
#define WOLFSSL_NO_HASH_RAW
#endif

/* XChacha not implemented with ARM assembly ChaCha */
#if defined(WOLFSSL_ARMASM)
#if defined(HAVE_XCHACHA) && !defined(HAVE_CHACHA)
/* XChacha requires ChaCha */
#undef HAVE_XCHACHA
#endif

Expand Down

0 comments on commit ec6c705

Please sign in to comment.