Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion docs/draft/async-crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ is:
| Sha256Request / Sha512Request | resumeState + control fields
| resumeState.hiLen (4 bytes) |
| resumeState.loLen (4 bytes) |
| resumeState.hash (32 or 64 bytes) | intermediate digest
| resumeState.hash (32 or 64 bytes) | intermediate digest (see below)
| [resumeState.hashType (4 bytes)] | SHA-512 family only
| isLastBlock (4 bytes) |
| inSz (4 bytes) |
Expand Down Expand Up @@ -346,6 +346,22 @@ reaches the server:
The hash state (`resumeState`) always travels **inline**, not via DMA, for
cross-architecture concerns (endian translation, etc.)

### Endianness of `resumeState.hash`

`resumeState.hash` is not an opaque byte array. wolfCrypt keeps the SHA-2
chaining variables in `wc_Sha256.digest` / `wc_Sha512.digest` as **host-order**
`word32` / `word64`, and the client copies them to the wire verbatim, so the
field carries eight chaining words in the *client's* byte order. The server
byte-swaps each word when the client's `magic` reports the opposite endianness,
exactly as it does for the SHA-3 Keccak state (`whMessageCrypto_Sha3State`).

The response field is context-dependent: on a non-final update it carries the
same host-order chaining words, but on `isLastBlock` it carries the finalized
digest, which wolfCrypt has already emitted in canonical big-endian byte order
and which must not be swapped. The response translation helpers therefore take
the chaining word size (4, 8, or 0 for a finalized digest) from the caller —
see `wh_MessageCrypto_TranslateSha2Response_ex()`.

DMA async functions require the client to stash the translated DMA address
across the Request/Response boundary for POST cleanup. This context is stored
in `whClientContext.dma.asyncCtx.sha`:
Expand Down
102 changes: 75 additions & 27 deletions src/wh_message_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,43 @@ int wh_MessageCrypto_TranslateEd25519VerifyResponse(
return 0;
}

/* Number of chaining words in a SHA-2 intermediate state, for every variant */
#define WH_MESSAGE_CRYPTO_SHA2_STATE_WORDS 8

/* Swap the host-order chaining words of a serialized SHA-2 state, as the SHA3
* Keccak state does. wordSize is 4 (SHA224/256) or 8 (SHA384/512); any other
* value, including 0 for a finalized digest, copies the array verbatim. */
static void _TranslateSha2State(uint16_t magic, uint8_t* dest,
const uint8_t* src, uint32_t hashSz,
uint32_t wordSize)
{
uint32_t i;
uint32_t stateSz = WH_MESSAGE_CRYPTO_SHA2_STATE_WORDS * wordSize;
uint32_t w32;
uint64_t w64;

if (dest != src) {
memcpy(dest, src, hashSz);
}
if (stateSz > hashSz) {
return;
}
if (wordSize == sizeof(uint32_t)) {
for (i = 0; i < stateSz; i += wordSize) {
memcpy(&w32, dest + i, sizeof(w32));
w32 = wh_Translate32(magic, w32);
memcpy(dest + i, &w32, sizeof(w32));
}
}
else if (wordSize == sizeof(uint64_t)) {
for (i = 0; i < stateSz; i += wordSize) {
memcpy(&w64, dest + i, sizeof(w64));
w64 = wh_Translate64(magic, w64);
memcpy(dest + i, &w64, sizeof(w64));
}
}
}

/* SHA256 Request translation. Only the fixed-size header is translated; any
* trailing variable-length input bytes (uint8_t in[inSz]) are raw bytes that
* do not need endian translation. */
Expand All @@ -651,11 +688,10 @@ int wh_MessageCrypto_TranslateSha256Request(
}
WH_T32(magic, dest, src, resumeState.hiLen);
WH_T32(magic, dest, src, resumeState.loLen);
/* Hash value is just a byte array, no translation needed */
if (src != dest) {
memcpy(dest->resumeState.hash, src->resumeState.hash,
sizeof(src->resumeState.hash));
}
/* A request always carries intermediate state, even on the last block */
_TranslateSha2State(magic, dest->resumeState.hash, src->resumeState.hash,
(uint32_t)sizeof(src->resumeState.hash),
(uint32_t)sizeof(uint32_t));
WH_T32(magic, dest, src, isLastBlock);
WH_T32(magic, dest, src, inSz);
return 0;
Expand All @@ -675,32 +711,38 @@ int wh_MessageCrypto_TranslateSha512Request(
WH_T32(magic, dest, src, resumeState.hiLen);
WH_T32(magic, dest, src, resumeState.loLen);
WH_T32(magic, dest, src, resumeState.hashType);
/* Hash value is just a byte array, no translation needed */
if (src != dest) {
memcpy(dest->resumeState.hash, src->resumeState.hash,
sizeof(src->resumeState.hash));
}
/* A request always carries intermediate state, even on the last block */
_TranslateSha2State(magic, dest->resumeState.hash, src->resumeState.hash,
(uint32_t)sizeof(src->resumeState.hash),
(uint32_t)sizeof(uint64_t));
WH_T32(magic, dest, src, isLastBlock);
WH_T32(magic, dest, src, inSz);
return 0;
}
#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */

/* SHA2 Response translation */
/* SHA2 Response translation, treating hash as a finalized digest */
int wh_MessageCrypto_TranslateSha2Response(
uint16_t magic, const whMessageCrypto_Sha2Response* src,
whMessageCrypto_Sha2Response* dest)
{
return wh_MessageCrypto_TranslateSha2Response_ex(magic, src, dest, 0);
}

/* SHA2 Response translation. stateWordSize is the chaining word size when hash
* carries intermediate state, or 0 when it carries a finalized digest. */
int wh_MessageCrypto_TranslateSha2Response_ex(
uint16_t magic, const whMessageCrypto_Sha2Response* src,
whMessageCrypto_Sha2Response* dest, uint32_t stateWordSize)
{
if ((src == NULL) || (dest == NULL)) {
return WH_ERROR_BADARGS;
}
WH_T32(magic, dest, src, hiLen);
WH_T32(magic, dest, src, loLen);
WH_T32(magic, dest, src, hashType);
/* Hash value is just a byte array, no translation needed */
if (src != dest) {
memcpy(dest->hash, src->hash, sizeof(src->hash));
}
_TranslateSha2State(magic, dest->hash, src->hash,
(uint32_t)sizeof(src->hash), stateWordSize);
return 0;
}

Expand Down Expand Up @@ -1024,10 +1066,9 @@ int wh_MessageCrypto_TranslateSha256DmaRequest(

WH_T32(magic, dest, src, resumeState.hiLen);
WH_T32(magic, dest, src, resumeState.loLen);
if (src != dest) {
memcpy(dest->resumeState.hash, src->resumeState.hash,
sizeof(src->resumeState.hash));
}
_TranslateSha2State(magic, dest->resumeState.hash, src->resumeState.hash,
(uint32_t)sizeof(src->resumeState.hash),
(uint32_t)sizeof(uint32_t));

ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input);
if (ret != 0) {
Expand All @@ -1053,10 +1094,9 @@ int wh_MessageCrypto_TranslateSha512DmaRequest(

WH_T32(magic, dest, src, resumeState.hiLen);
WH_T32(magic, dest, src, resumeState.loLen);
if (src != dest) {
memcpy(dest->resumeState.hash, src->resumeState.hash,
sizeof(src->resumeState.hash));
}
_TranslateSha2State(magic, dest->resumeState.hash, src->resumeState.hash,
(uint32_t)sizeof(src->resumeState.hash),
(uint32_t)sizeof(uint64_t));
WH_T32(magic, dest, src, resumeState.hashType);

ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input);
Expand All @@ -1070,20 +1110,28 @@ int wh_MessageCrypto_TranslateSha512DmaRequest(
return 0;
}

/* SHA2 DMA Response translation */
/* SHA2 DMA Response translation, treating hash as a finalized digest */
int wh_MessageCrypto_TranslateSha2DmaResponse(
uint16_t magic, const whMessageCrypto_Sha2DmaResponse* src,
whMessageCrypto_Sha2DmaResponse* dest)
{
return wh_MessageCrypto_TranslateSha2DmaResponse_ex(magic, src, dest, 0);
}

/* SHA2 DMA Response translation. stateWordSize is the chaining word size when
* hash carries intermediate state, or 0 when it carries a finalized digest. */
int wh_MessageCrypto_TranslateSha2DmaResponse_ex(
uint16_t magic, const whMessageCrypto_Sha2DmaResponse* src,
whMessageCrypto_Sha2DmaResponse* dest, uint32_t stateWordSize)
{
if ((src == NULL) || (dest == NULL)) {
return WH_ERROR_BADARGS;
}

WH_T32(magic, dest, src, hiLen);
WH_T32(magic, dest, src, loLen);
if (src != dest) {
memcpy(dest->hash, src->hash, sizeof(src->hash));
}
_TranslateSha2State(magic, dest->hash, src->hash,
(uint32_t)sizeof(src->hash), stateWordSize);
WH_T32(magic, dest, src, hashType);

return wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus,
Expand Down
40 changes: 24 additions & 16 deletions src/wh_server_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -4234,8 +4234,9 @@ static int _HandleSha256(whServerContext* ctx, uint16_t magic, int devId,

/* Translate the response */
if (ret == 0) {
ret =
wh_MessageCrypto_TranslateSha2Response(magic, &res, cryptoDataOut);
ret = wh_MessageCrypto_TranslateSha2Response_ex(
magic, &res, cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint32_t));
if (ret == 0) {
*outSize = sizeof(res);
}
Expand Down Expand Up @@ -4325,8 +4326,9 @@ static int _HandleSha224(whServerContext* ctx, uint16_t magic, int devId,

/* Translate the response */
if (ret == 0) {
ret =
wh_MessageCrypto_TranslateSha2Response(magic, &res, cryptoDataOut);
ret = wh_MessageCrypto_TranslateSha2Response_ex(
magic, &res, cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint32_t));
if (ret == 0) {
*outSize = sizeof(res);
}
Expand Down Expand Up @@ -4421,8 +4423,9 @@ static int _HandleSha384(whServerContext* ctx, uint16_t magic, int devId,

/* Translate the response */
if (ret == 0) {
ret =
wh_MessageCrypto_TranslateSha2Response(magic, &res, cryptoDataOut);
ret = wh_MessageCrypto_TranslateSha2Response_ex(
magic, &res, cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint64_t));
if (ret == 0) {
*outSize = sizeof(res);
}
Expand Down Expand Up @@ -4545,8 +4548,9 @@ static int _HandleSha512(whServerContext* ctx, uint16_t magic, int devId,

/* Translate the response */
if (ret == 0) {
ret =
wh_MessageCrypto_TranslateSha2Response(magic, &res, cryptoDataOut);
ret = wh_MessageCrypto_TranslateSha2Response_ex(
magic, &res, cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint64_t));
if (ret == 0) {
*outSize = sizeof(res);
}
Expand Down Expand Up @@ -5920,8 +5924,9 @@ static int _HandleSha256Dma(whServerContext* ctx, uint16_t magic, int devId,
}
}

(void)wh_MessageCrypto_TranslateSha2DmaResponse(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut);
(void)wh_MessageCrypto_TranslateSha2DmaResponse_ex(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint32_t));
*outSize = sizeof(res);

return ret;
Expand Down Expand Up @@ -6024,8 +6029,9 @@ static int _HandleSha224Dma(whServerContext* ctx, uint16_t magic, int devId,
}
}

(void)wh_MessageCrypto_TranslateSha2DmaResponse(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut);
(void)wh_MessageCrypto_TranslateSha2DmaResponse_ex(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint32_t));
*outSize = sizeof(res);

return ret;
Expand Down Expand Up @@ -6128,8 +6134,9 @@ static int _HandleSha384Dma(whServerContext* ctx, uint16_t magic, int devId,
}
}

(void)wh_MessageCrypto_TranslateSha2DmaResponse(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut);
(void)wh_MessageCrypto_TranslateSha2DmaResponse_ex(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint64_t));
*outSize = sizeof(res);

return ret;
Expand Down Expand Up @@ -6266,8 +6273,9 @@ static int _HandleSha512Dma(whServerContext* ctx, uint16_t magic, int devId,
}
}

(void)wh_MessageCrypto_TranslateSha2DmaResponse(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut);
(void)wh_MessageCrypto_TranslateSha2DmaResponse_ex(
magic, &res, (whMessageCrypto_Sha2DmaResponse*)cryptoDataOut,
req.isLastBlock ? 0 : (uint32_t)sizeof(uint64_t));
*outSize = sizeof(res);

return ret;
Expand Down
Loading
Loading