Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only SHA3/SHAKE Init Updates via FIPS202 API layer #2101

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 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
8 changes: 4 additions & 4 deletions crypto/fipsmodule/digest/digests.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) {


static void sha3_224_init(EVP_MD_CTX *ctx) {
CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_224_DIGEST_BITLENGTH));
CHECK(SHA3_Init(ctx->md_data, SHA3_224_DIGEST_BITLENGTH));
}

static void sha3_224_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
Expand All @@ -351,7 +351,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha3_224) {


static void sha3_256_init(EVP_MD_CTX *ctx) {
CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_256_DIGEST_BITLENGTH));
CHECK(SHA3_Init(ctx->md_data, SHA3_256_DIGEST_BITLENGTH));
}

static void sha3_256_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
Expand All @@ -376,7 +376,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha3_256) {


static void sha3_384_init(EVP_MD_CTX *ctx) {
CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_384_DIGEST_BITLENGTH));
CHECK(SHA3_Init(ctx->md_data, SHA3_384_DIGEST_BITLENGTH));
}

static void sha3_384_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
Expand All @@ -401,7 +401,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha3_384) {


static void sha3_512_init(EVP_MD_CTX *ctx) {
CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_512_DIGEST_BITLENGTH));
CHECK(SHA3_Init(ctx->md_data, SHA3_512_DIGEST_BITLENGTH));
}

static void sha3_512_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
Expand Down
2 changes: 1 addition & 1 deletion crypto/fipsmodule/sha/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len);
void SHA3_Reset(KECCAK1600_CTX *ctx);

// SHA3_Init initialises |ctx| fields and returns 1 on success and 0 on failure.
OPENSSL_EXPORT int SHA3_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t bitlen);
OPENSSL_EXPORT int SHA3_Init(KECCAK1600_CTX *ctx, size_t bitlen);

// SHA3_Update processes all data blocks that don't need pad through
// |Keccak1600_Absorb| and returns 1 and 0 on failure.
Expand Down
84 changes: 47 additions & 37 deletions crypto/fipsmodule/sha/sha3.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ uint8_t *SHA3_224(const uint8_t *data, size_t len,
uint8_t out[SHA3_224_DIGEST_LENGTH]) {
FIPS_service_indicator_lock_state();
KECCAK1600_CTX ctx;
int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_224_DIGEST_BITLENGTH) &&
int ok = (SHA3_Init(&ctx, SHA3_224_DIGEST_BITLENGTH) &&
SHA3_Update(&ctx, data, len) &&
SHA3_Final(out, &ctx));

Expand All @@ -31,7 +31,7 @@ uint8_t *SHA3_256(const uint8_t *data, size_t len,
uint8_t out[SHA3_256_DIGEST_LENGTH]) {
FIPS_service_indicator_lock_state();
KECCAK1600_CTX ctx;
int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_256_DIGEST_BITLENGTH) &&
int ok = (SHA3_Init(&ctx, SHA3_256_DIGEST_BITLENGTH) &&
SHA3_Update(&ctx, data, len) &&
SHA3_Final(out, &ctx));

Expand All @@ -48,7 +48,7 @@ uint8_t *SHA3_384(const uint8_t *data, size_t len,
uint8_t out[SHA3_384_DIGEST_LENGTH]) {
FIPS_service_indicator_lock_state();
KECCAK1600_CTX ctx;
int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_384_DIGEST_BITLENGTH) &&
int ok = (SHA3_Init(&ctx, SHA3_384_DIGEST_BITLENGTH) &&
SHA3_Update(&ctx, data, len) &&
SHA3_Final(out, &ctx));

Expand All @@ -65,7 +65,7 @@ uint8_t *SHA3_512(const uint8_t *data, size_t len,
uint8_t out[SHA3_512_DIGEST_LENGTH]) {
FIPS_service_indicator_lock_state();
KECCAK1600_CTX ctx;
int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_512_DIGEST_BITLENGTH) &&
int ok = (SHA3_Init(&ctx, SHA3_512_DIGEST_BITLENGTH) &&
SHA3_Update(&ctx, data, len) &&
SHA3_Final(out, &ctx));

Expand Down Expand Up @@ -109,49 +109,43 @@ uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t
return out;
}

int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size) {
// The SHAKE block size depends on the security level of the algorithm only
// It is independent of the output size
ctx->block_size = block_size;
return SHA3_Init(ctx, SHAKE_PAD_CHAR, 0);
// FIPS202 APIs manage internal input/output buffer on top of Keccak1600 API layer
static void FIPS202_Reset(KECCAK1600_CTX *ctx) {
memset(ctx->A, 0, sizeof(ctx->A));
andrewhop marked this conversation as resolved.
Show resolved Hide resolved
ctx->buf_load = 0;
ctx->padded=0;
}


int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) {
ctx->md_size = len;
return SHA3_Final(md, ctx);
static int FIPS202_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t block_size, size_t bit_len) {
if (pad != SHA3_PAD_CHAR &&
pad != SHAKE_PAD_CHAR) {
return 0;
Comment on lines +120 to +122
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading FIPS 202 section B.2 where it defines the sha and shake pad values, why are we using the q = 2 values? Should that be configurable in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values for the padding are the same, however, they are 'interleaved' by 0's in case the message is shorter than the block. E.g. the pad for sha3 is 0x06 (added after the last byte of the input); the rest of the block size is set to zero, where the last byte of the block is set to 0x80. When the last byte (+1 byte) of the message (message of length block size - 1 bytes) and the last byte of the block coincide, the last byte becomes 0x06 ^ 0x80, which will be 0x86. When messages are shorter, more zero's are added in the middle of these values. However, the implementation covers all the cases using only the 0x06 and 0x1f pad, where all the rest is 0's and last block byte is 0x80.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the message length is -1 modulo the block size, i.e. one byte is left, and is filled with 0x86, how is it differentiated from a similar message that's one byte longer and has this value, 0x86, as the last byte? should another full block be added for padding?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in this case another full block is absorbed; consisting of padding 0x06 ... 0x00 ... 0x80 with block_size-2 bytes of 0x00's.

}

if (block_size <= sizeof(ctx->buf)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: my preference is to check for the erroneous condition and return 0 within the if statement, then continue with the regular processing afterwards as in (most of, if not all) the rest of the code base.
Update: I see that similar processing below is following the same pattern, so you can ignore this comment.

FIPS202_Reset(ctx);
ctx->block_size = block_size;
ctx->md_size = bit_len / 8;
ctx->pad = pad;
return 1;
}
return 0;
}

// SHA3 APIs implement SHA3 functionalities on top of FIPS202 API layer
void SHA3_Reset(KECCAK1600_CTX *ctx) {
memset(ctx->A, 0, sizeof(ctx->A));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call FIPS202_Reset()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I change it in the next PR:

static void FIPS202_Reset(KECCAK1600_CTX *ctx) {

ctx->buf_load = 0;
ctx->padded = 0;
}

int SHA3_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t bit_len) {
size_t block_size;

// The block size is computed differently depending on which algorithm
// is calling |SHA3_Init|:
// - for SHA3 we compute it by calling SHA3_BLOCKSIZE(bit_len)
// because the block size depends on the digest bit-length,
// - for SHAKE we take the block size from the context.
// We use the given padding character to differentiate between SHA3 and SHAKE.
if (pad == SHA3_PAD_CHAR) {
block_size = SHA3_BLOCKSIZE(bit_len);
} else if (pad == SHAKE_PAD_CHAR) {
block_size = ctx->block_size;
} else {
return 0;
}
ctx->padded = 0;

if (block_size <= sizeof(ctx->buf)) {
SHA3_Reset(ctx);
ctx->block_size = block_size;
ctx->md_size = bit_len / 8;
ctx->pad = pad;
return 1;
int SHA3_Init(KECCAK1600_CTX *ctx, size_t bit_len) {
if (bit_len == SHA3_224_DIGEST_BITLENGTH ||
bit_len == SHA3_256_DIGEST_BITLENGTH ||
bit_len == SHA3_384_DIGEST_BITLENGTH ||
bit_len == SHA3_512_DIGEST_BITLENGTH) {
// |block_size| depends on the SHA3 |bit_len| output (digest) length
return FIPS202_Init(ctx, SHA3_PAD_CHAR, SHA3_BLOCKSIZE(bit_len), bit_len);
}
return 0;
}
Expand Down Expand Up @@ -230,3 +224,19 @@ int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx) {

return 1;
}

// SHAKE APIs implement SHAKE functionalities on top of FIPS202 API layer
int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size) {
if (block_size == SHAKE128_BLOCKSIZE ||
block_size == SHAKE256_BLOCKSIZE) {
// |block_size| depends on the SHAKE security level
// The output length |bit_len| is initialized to 0
return FIPS202_Init(ctx, SHAKE_PAD_CHAR, block_size, 0);
}
return 0;
}

int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) {
ctx->md_size = len;
return SHA3_Final(md, ctx);
}
2 changes: 1 addition & 1 deletion crypto/fipsmodule/sha/sha3_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ TEST(KeccakInternalTest, SqueezeOutputBufferOverflow) {
const size_t out_lens[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, (1 << 5), (1 << 16) + 1};
for (auto out_len : out_lens) {
EXPECT_TRUE(SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_384_DIGEST_BITLENGTH));
EXPECT_TRUE(SHA3_Init(&ctx, SHA3_384_DIGEST_BITLENGTH));
out.resize(out_len + canary.size());
std::copy(canary.begin(), canary.end(), out.end() - canary.size());
Keccak1600_Squeeze(ctx.A, out.data(), out_len, ctx.block_size, 1);
Expand Down
Loading