Skip to content

Commit

Permalink
SHA2 Increment with arbitrary length (non-block sizes) (#1614)
Browse files Browse the repository at this point in the history
* Enhanced with new SHA2 API that allows arbitary length updates

* Fix style

* Fix format

* Document struct members

* Fix comparison sign

* Use OQS SHA2 API

* Add nl at end

* Use OQS_MEM_secure_free instead of free

* Updated per review... mem check after malloc, use memcpy

* Fix style
  • Loading branch information
ashman-p authored and SWilson4 committed May 14, 2024
1 parent 47740ad commit a7b2987
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 263 deletions.
4 changes: 4 additions & 0 deletions src/common/sha2/sha2.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, s
callbacks->SHA2_sha256_inc_blocks(state, in, inblocks);
}

void OQS_SHA2_sha256_inc(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len) {
callbacks->SHA2_sha256_inc(state, in, len);
}

void OQS_SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen) {
callbacks->SHA2_sha256_inc_finalize(out, state, in, inlen);
}
Expand Down
38 changes: 38 additions & 0 deletions src/common/sha2/sha2.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@
extern "C" {
#endif

/** Data structure for the state of the SHA-224 incremental hashing API. */
typedef struct {
/** Internal state */
void *ctx;
/** current number of bytes in data */
size_t data_len;
/** unprocessed data buffer */
uint8_t data[128];
} OQS_SHA2_sha224_ctx;

/**
* \brief Process a message with SHA-256 and return the hash code in the output byte array.
*
Expand All @@ -39,6 +49,10 @@ void OQS_SHA2_sha256(uint8_t *output, const uint8_t *input, size_t inplen);
typedef struct {
/** Internal state */
void *ctx;
/** current number of bytes in data */
size_t data_len;
/** unprocessed data buffer */
uint8_t data[128];
} OQS_SHA2_sha256_ctx;

/**
Expand Down Expand Up @@ -74,6 +88,17 @@ void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha
*/
void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks);

/**
* \brief Process message bytes with SHA-256 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha256_inc_init or OQS_SHA2_sha256_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param len The number of bytes of message to process
*/
void OQS_SHA2_sha256_inc(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len);

/**
* \brief Process more message bytes with SHA-256 and return the hash code in the output byte array.
*
Expand Down Expand Up @@ -113,6 +138,10 @@ void OQS_SHA2_sha384(uint8_t *output, const uint8_t *input, size_t inplen);
typedef struct {
/** Internal state. */
void *ctx;
/** current number of bytes in data */
size_t data_len;
/** unprocessed data buffer */
uint8_t data[128];
} OQS_SHA2_sha384_ctx;

/**
Expand Down Expand Up @@ -187,6 +216,10 @@ void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen);
typedef struct {
/** Internal state. */
void *ctx;
/** current number of bytes in data */
size_t data_len;
/** unprocessed data buffer */
uint8_t data[128];
} OQS_SHA2_sha512_ctx;

/**
Expand Down Expand Up @@ -264,6 +297,11 @@ struct OQS_SHA2_callbacks {
*/
void (*SHA2_sha256_inc_ctx_clone)(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src);

/**
* Implementation of function OQS_SHA2_sha256_inc.
*/
void (*SHA2_sha256_inc)(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t len);

/**
* Implementation of function OQS_SHA2_sha256_inc_blocks.
*/
Expand Down
99 changes: 86 additions & 13 deletions src/common/sha2/sha2_armv8.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <oqs/oqs.h>

#include "sha2_local.h"

#include <string.h>
#include <stdint.h>
// ARM includes
#ifndef WIN32
Expand Down Expand Up @@ -169,23 +169,43 @@ static size_t crypto_hashblocks_sha256_armv8(uint8_t *statebytes,
return length;

}

void oqs_sha2_sha256_inc_finalize_armv8(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen) {
uint8_t padded[128];
uint64_t bytes = load_bigendian_64(state->ctx + 32) + inlen;

crypto_hashblocks_sha256_armv8(state->ctx, in, inlen);
in += inlen;
inlen &= 63;
in -= inlen;
size_t new_inlen = state->data_len + inlen;
size_t tmp_len = new_inlen;
const uint8_t *new_in;
uint8_t *tmp_in = NULL;

if (new_inlen == inlen) {
new_in = in;
} else { //Combine incremental data with final input
tmp_in = malloc(tmp_len);
if (tmp_in == NULL) {
exit(111);
}

memcpy(tmp_in, state->data, state->data_len);
memcpy(tmp_in + state->data_len, in, inlen);
new_in = tmp_in;
}

uint64_t bytes = load_bigendian_64(state->ctx + 32) + new_inlen;

crypto_hashblocks_sha256_armv8(state->ctx, new_in, new_inlen);
new_in += new_inlen;
new_inlen &= 63;
new_in -= new_inlen;


for (size_t i = 0; i < inlen; ++i) {
padded[i] = in[i];
for (size_t i = 0; i < new_inlen; ++i) {
padded[i] = new_in[i];
}
padded[inlen] = 0x80;
padded[new_inlen] = 0x80;

if (inlen < 56) {
for (size_t i = inlen + 1; i < 56; ++i) {
if (new_inlen < 56) {
for (size_t i = new_inlen + 1; i < 56; ++i) {
padded[i] = 0;
}
padded[56] = (uint8_t) (bytes >> 53);
Expand All @@ -198,7 +218,7 @@ void oqs_sha2_sha256_inc_finalize_armv8(uint8_t *out, sha256ctx *state, const ui
padded[63] = (uint8_t) (bytes << 3);
crypto_hashblocks_sha256_armv8(state->ctx, padded, 64);
} else {
for (size_t i = inlen + 1; i < 120; ++i) {
for (size_t i = new_inlen + 1; i < 120; ++i) {
padded[i] = 0;
}
padded[120] = (uint8_t) (bytes >> 53);
Expand All @@ -216,6 +236,7 @@ void oqs_sha2_sha256_inc_finalize_armv8(uint8_t *out, sha256ctx *state, const ui
out[i] = state->ctx[i];
}
oqs_sha2_sha256_inc_ctx_release_c(state);
OQS_MEM_secure_free(tmp_in, tmp_len);
}

void oqs_sha2_sha224_inc_finalize_armv8(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen) {
Expand All @@ -229,11 +250,63 @@ void oqs_sha2_sha224_inc_finalize_armv8(uint8_t *out, sha224ctx *state, const ui

void oqs_sha2_sha256_inc_blocks_armv8(sha256ctx *state, const uint8_t *in, size_t inblocks) {
uint64_t bytes = load_bigendian_64(state->ctx + 32);
const uint8_t *new_in;
size_t buf_len = 64 * inblocks;
uint8_t *tmp_in = NULL;

/* Process any existing incremental data first */
if (state->data_len) {
tmp_in = malloc(buf_len);
if (tmp_in == NULL) {
exit(111);
}

memcpy(tmp_in, state->data, state->data_len);
memcpy(tmp_in + state->data_len, in, buf_len - state->data_len);

/* store the reminder input as incremental data */
memcpy(state->data, in + (buf_len - state->data_len), state->data_len);
new_in = tmp_in;
} else {
new_in = in;
}

crypto_hashblocks_sha256_armv8(state->ctx, in, 64 * inblocks);
crypto_hashblocks_sha256_armv8(state->ctx, new_in, 64 * inblocks);
bytes += 64 * inblocks;

store_bigendian_64(state->ctx + 32, bytes);
OQS_MEM_secure_free(tmp_in, buf_len);
}

void oqs_sha2_sha256_inc_armv8(sha256ctx *state, const uint8_t *in, size_t len) {
uint64_t bytes = 0;
while (len) {
size_t incr = 64 - state->data_len;
if (incr > len) {
incr = len;
}

for (size_t i = 0; i < incr; ++i, state->data_len++) {
state->data[state->data_len] = in[i];
}

if (state->data_len < 64) {
break;
}

/*
* Process a complete block now
*/
bytes = load_bigendian_64(state->ctx + 32) + 64;
crypto_hashblocks_sha256_armv8(state->ctx, state->data, 64);
store_bigendian_64(state->ctx + 32, bytes);

/*
* update the remaining input
*/
len -= incr;
state->data_len = 0;
}
}

void oqs_sha2_sha224_inc_blocks_armv8(sha224ctx *state, const uint8_t *in, size_t inblocks) {
Expand Down
Loading

0 comments on commit a7b2987

Please sign in to comment.