-
Notifications
You must be signed in to change notification settings - Fork 122
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
SHA3 and SHAKE - New API Design #2098
Changes from 74 commits
c6ed451
a05d255
50cf7fa
4b0b92e
eb992ea
d40fbec
adb910d
02b8085
e61be0d
3008821
2a1622f
c5d0afd
b6a5590
7ccaeba
7edb6c7
7386c1b
e424771
6597af1
7766425
ff3cbd8
680dd43
872d368
5780ee5
3f43dde
07bac7c
2973e4a
86fa4b0
36ab448
b2228b6
14da500
97b02c6
95c7e26
077ef78
b4ce7b2
5b18483
d3bba6b
f48fb78
6ce3a3b
72373f3
820394a
26544da
0239af3
2ddcd83
94bc599
6933d45
9462df8
9d433cb
705f36c
a03e160
507ff49
863387d
5a4dc9c
ebfb590
b80f99e
3001ac9
8d6b7f5
64f25eb
80260d9
2d90347
55742fa
c91bd6a
a66a1a5
7fb93e8
95a9e8a
0b9ef21
df51857
9d3b72b
3b18668
3cdcaa3
cb6f877
96f8169
7848023
1fdb30e
9c559df
0973fc2
2616442
85a0d6f
873f017
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -71,6 +71,14 @@ extern "C" { | |||||||
// SHAKE128 has the maximum block size among the SHA3/SHAKE algorithms. | ||||||||
#define SHA3_MAX_BLOCKSIZE SHAKE128_BLOCKSIZE | ||||||||
|
||||||||
// Define state flag values for Keccak-based functions | ||||||||
#define KECCAK1600_STATE_ABSORB 0 | ||||||||
#define KECCAK1600_STATE_SQUEEZE 1 | ||||||||
// KECCAK1600_STATE_FINAL restricts the incremental calls to SHAKE_Final . | ||||||||
// KECCAK1600_STATE_FINAL can be called once. SHAKE_Squeeze cannot be called after SHAKE_Final. | ||||||||
// SHAKE_Squeeze should be called for streaming XOF output. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understood correctly,
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||||||||
#define KECCAK1600_STATE_FINAL 2 | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to represent a failure state if one of the operations were to fail (or only partially succeed). Is it possible to get a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this should be covered by the returns of the functions. I don't think an additional value for |state| is needed since the purpose is to restrict the number/sequence of: absorb (only before padding is performed), squeeze (incremental squeezes are performed with no limitation), final (one call to final is allowed) function. Once a squeeze is called, no further absorb should be allowed, once final is called, no further absorb, squeeze, or final is allowed. |
||||||||
|
||||||||
typedef struct keccak_st KECCAK1600_CTX; | ||||||||
|
||||||||
// The data buffer should have at least the maximum number of | ||||||||
|
@@ -82,7 +90,7 @@ struct keccak_st { | |||||||
size_t buf_load; // used bytes in below buffer | ||||||||
uint8_t buf[SHA3_MAX_BLOCKSIZE]; // should have at least the max data block size bytes | ||||||||
uint8_t pad; // padding character | ||||||||
uint8_t padded; // denotes if padding has been performed | ||||||||
uint8_t state; // denotes the keccak phase (absorb, squeeze, final) | ||||||||
}; | ||||||||
|
||||||||
// Define SHA{n}[_{variant}]_ASM if sha{n}_block_data_order[_{variant}] is | ||||||||
|
@@ -396,32 +404,43 @@ OPENSSL_EXPORT uint8_t *SHAKE128(const uint8_t *data, const size_t in_len, | |||||||
OPENSSL_EXPORT uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, | ||||||||
uint8_t *out, size_t out_len); | ||||||||
|
||||||||
// SHAKE_Init initializes |ctx| with specified |block_size|, returns 1 on | ||||||||
// success and 0 on failure. Calls SHA3_Init under the hood. | ||||||||
int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size); | ||||||||
|
||||||||
// SHAKE_Final writes |len| bytes of finalized digest to |md|, returns 1 on | ||||||||
// success and 0 on failure. Calls SHA3_Final under the hood. | ||||||||
int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); | ||||||||
|
||||||||
// SHA3_Reset zeros the bitstate and the amount of processed input. | ||||||||
void SHA3_Reset(KECCAK1600_CTX *ctx); | ||||||||
|
||||||||
// SHA3_Init initialises |ctx| fields and returns 1 on success and 0 on failure. | ||||||||
// SHA3_Init initialises |ctx| fields through |FIPS202_Init| and | ||||||||
// returns 1 on success and 0 on failure. | ||||||||
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. | ||||||||
// SHA3_Update check |ctx| pointer and |len| value, calls |FIPS202_Update| | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it not do what it used to do: "processes all full blocks of the input data" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SHA3_Update technically does the same: "processes all data blocks that don't need pad through". However, now it is performed via call to FIPS202_Update, which internally "processes all data blocks that don't need pad through". |
||||||||
// and returns 1 on success and 0 on failure. | ||||||||
int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len); | ||||||||
|
||||||||
// SHA3_Final pads the last data block and processes it through |Keccak1600_Absorb|. | ||||||||
// It processes the data through |Keccak1600_Squeeze| and returns 1 and 0 on failure. | ||||||||
// SHA3_Final pads the last data block and absorbs it through |FIPS202_Finalize|. | ||||||||
// It processes the data through |Keccak1600_Squeeze| and returns 1 on success | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
// and 0 on failure. | ||||||||
int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx); | ||||||||
|
||||||||
// Keccak1600_Absorb processes the largest multiple of |r| out of |len| bytes and | ||||||||
// returns the remaining number of bytes. | ||||||||
// SHAKE_Init initialises |ctx| fields through |FIPS202_Init| and | ||||||||
// returns 1 on success and 0 on failure. | ||||||||
int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a historical reason why we chose to input bitlength to SHA3_Init and block_size to SHAKE_Init? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good observation! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine to leave the bitlength in SHA3_Init because there isn't an equivalent function for SHA2 that we need to align with (e.g. using byte length). If we used bitlength with SHAKE_Init, it would identify 128 or 256. It's minor anyway and if it makes more sense to you this way, that's good. |
||||||||
|
||||||||
// SHAKE_Absorb checks |ctx| pointer and |len| values. It updates and absorbs | ||||||||
// input blocks via |FIPS202_Update|. | ||||||||
int SHAKE_Absorb(KECCAK1600_CTX *ctx, const void *data, | ||||||||
size_t len); | ||||||||
|
||||||||
// SHAKE_Squeeze pads the last data block and absorbs it through | ||||||||
// |FIPS202_Finalize| on first call. It writes |len| bytes of incremental | ||||||||
// XOF output to |md| and returns 1 on success and 0 on failure. It can be | ||||||||
// called multiple times. | ||||||||
int SHAKE_Squeeze(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); | ||||||||
|
||||||||
// SHAKE_Final writes |len| bytes of finalized extendible output to |md|, returns 1 on | ||||||||
// success and 0 on failure. It should be called once to finalize absorb and | ||||||||
// squeeze phases. Incremental XOF output should be generated via |SHAKE_Squeeze|. | ||||||||
int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); | ||||||||
|
||||||||
// Keccak1600_Absorb processes the largest multiple of |r| (block size) out of | ||||||||
// |len| bytes and returns the remaining number of bytes. | ||||||||
size_t Keccak1600_Absorb(uint64_t A[KECCAK1600_ROWS][KECCAK1600_ROWS], | ||||||||
const uint8_t *data, size_t len, size_t r); | ||||||||
const uint8_t *data, size_t len, size_t r); | ||||||||
|
||||||||
// Keccak1600_Squeeze generates |out| value of |len| bytes (per call). It can be called | ||||||||
// multiple times when used as eXtendable Output Function. |padded| indicates | ||||||||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -82,7 +82,7 @@ uint8_t *SHAKE128(const uint8_t *data, const size_t in_len, uint8_t *out, size_t | |||||||
FIPS_service_indicator_lock_state(); | ||||||||
KECCAK1600_CTX ctx; | ||||||||
int ok = (SHAKE_Init(&ctx, SHAKE128_BLOCKSIZE) && | ||||||||
SHA3_Update(&ctx, data, in_len) && | ||||||||
SHAKE_Absorb(&ctx, data, in_len) && | ||||||||
SHAKE_Final(out, &ctx, out_len)); | ||||||||
|
||||||||
OPENSSL_cleanse(&ctx, sizeof(ctx)); | ||||||||
|
@@ -98,7 +98,7 @@ uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t | |||||||
FIPS_service_indicator_lock_state(); | ||||||||
KECCAK1600_CTX ctx; | ||||||||
int ok = (SHAKE_Init(&ctx, SHAKE256_BLOCKSIZE) && | ||||||||
SHA3_Update(&ctx, data, in_len) && | ||||||||
SHAKE_Absorb(&ctx, data, in_len) && | ||||||||
SHAKE_Final(out, &ctx, out_len)); | ||||||||
OPENSSL_cleanse(&ctx, sizeof(ctx)); | ||||||||
FIPS_service_indicator_unlock_state(); | ||||||||
|
@@ -113,7 +113,7 @@ uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t | |||||||
static void FIPS202_Reset(KECCAK1600_CTX *ctx) { | ||||||||
memset(ctx->A, 0, sizeof(ctx->A)); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this instead use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, Justin. Updated it. |
||||||||
ctx->buf_load = 0; | ||||||||
ctx->padded=0; | ||||||||
ctx->state = KECCAK1600_STATE_ABSORB; | ||||||||
} | ||||||||
|
||||||||
static int FIPS202_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t block_size, size_t bit_len) { | ||||||||
|
@@ -132,33 +132,17 @@ static int FIPS202_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t block_size, siz | |||||||
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)); | ||||||||
ctx->buf_load = 0; | ||||||||
ctx->padded = 0; | ||||||||
} | ||||||||
|
||||||||
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; | ||||||||
} | ||||||||
|
||||||||
int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { | ||||||||
static int FIPS202_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { | ||||||||
uint8_t *data_ptr_copy = (uint8_t *) data; | ||||||||
size_t block_size = ctx->block_size; | ||||||||
size_t num, rem; | ||||||||
|
||||||||
if (len == 0) { | ||||||||
return 1; | ||||||||
if (ctx->state == KECCAK1600_STATE_SQUEEZE || | ||||||||
ctx->state == KECCAK1600_STATE_FINAL ) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
// Case |len| equals 0 is checked in SHA3/SHAKE higher level APIs | ||||||||
// Process intermediate buffer. | ||||||||
num = ctx->buf_load; | ||||||||
if (num != 0) { | ||||||||
|
@@ -169,9 +153,9 @@ int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { | |||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
// There is enough data to fill or overflow the intermediate | ||||||||
// buffer. So we append |rem| bytes and process the block, | ||||||||
// leaving the rest for later processing. | ||||||||
// There is enough data to fill or overflow the intermediate | ||||||||
// buffer. So we append |rem| bytes and process the block, | ||||||||
// leaving the rest for later processing. | ||||||||
memcpy(ctx->buf + num, data_ptr_copy, rem); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this instead use |
||||||||
data_ptr_copy += rem, len -= rem; | ||||||||
if (Keccak1600_Absorb(ctx->A, ctx->buf, block_size, block_size) != 0 ) { | ||||||||
|
@@ -196,36 +180,73 @@ int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { | |||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx) { | ||||||||
// FIPS202_Finalize processes padding and absorb of last input block | ||||||||
// This function should be called once to finalize absorb and initiate squeeze phase | ||||||||
static int FIPS202_Finalize(uint8_t *md, KECCAK1600_CTX *ctx) { | ||||||||
size_t block_size = ctx->block_size; | ||||||||
size_t num = ctx->buf_load; | ||||||||
|
||||||||
if (ctx->md_size == 0) { | ||||||||
if (ctx->state == KECCAK1600_STATE_SQUEEZE || | ||||||||
ctx->state == KECCAK1600_STATE_FINAL ) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
// Pad the data with 10*1. Note that |num| can be |block_size - 1| | ||||||||
// in which case both byte operations below are performed on | ||||||||
// the same byte. | ||||||||
memset(ctx->buf + num, 0, block_size - num); | ||||||||
ctx->buf[num] = ctx->pad; | ||||||||
ctx->buf[block_size - 1] |= 0x80; | ||||||||
|
||||||||
if (Keccak1600_Absorb(ctx->A, ctx->buf, block_size, block_size) != 0) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
// SHA3 APIs implement SHA3 functionalities on top of FIPS202 API layer | ||||||||
int SHA3_Init(KECCAK1600_CTX *ctx, size_t bit_len) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the logic in SHA3_Init and SHAKE_Init be reversed in terms of returning 0 inside the if statement? I believe they're the only ones in this file that return 0 at the end. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had it reversed at the beginning... then I decided to switch since it looked a little bit cleaner to me. I updated it. Let me know what do you think :) |
||||||||
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; | ||||||||
} | ||||||||
|
||||||||
int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { | ||||||||
if (ctx == NULL) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
if (len == 0) { | ||||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
if (ctx->padded == 0) { | ||||||||
// Pad the data with 10*1. Note that |num| can be |block_size - 1| | ||||||||
// in which case both byte operations below are performed on | ||||||||
// the same byte. | ||||||||
memset(ctx->buf + num, 0, block_size - num); | ||||||||
ctx->buf[num] = ctx->pad; | ||||||||
ctx->buf[block_size - 1] |= 0x80; | ||||||||
return FIPS202_Update(ctx, data, len); | ||||||||
} | ||||||||
|
||||||||
if (Keccak1600_Absorb(ctx->A, ctx->buf, block_size, block_size) != 0) { | ||||||||
return 0; | ||||||||
} | ||||||||
// SHA3_Final should be called once to process final digest value | ||||||||
// |ctx->state| flag does not need to be updated | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The state is updated within the function, though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, my confusion here! |
||||||||
int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||
if (ctx->md_size == 0) { | ||||||||
return 1; | ||||||||
} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verify that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added these check in all functions! Thank you! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that the checks here should not be needed in this "layer" if we're confident the parameters are checked on all logic paths going into these functions. What I noticed was that there was some inconsistency between the functions, where some were checking certain parameters and others were not, and it wasn't clear to me why they weren't all performing the same checks. |
||||||||
|
||||||||
Keccak1600_Squeeze(ctx->A, md, ctx->md_size, block_size, ctx->padded); | ||||||||
ctx->padded = 1; | ||||||||
if (FIPS202_Finalize(md, ctx) == 0) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
Keccak1600_Squeeze(ctx->A, md, ctx->md_size, ctx->block_size, ctx->state); | ||||||||
ctx->state = KECCAK1600_STATE_FINAL; | ||||||||
|
||||||||
FIPS_service_indicator_update_state(); | ||||||||
|
||||||||
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) { | ||||||||
|
@@ -236,7 +257,62 @@ int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size) { | |||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
int SHAKE_Absorb(KECCAK1600_CTX *ctx, const void *data, size_t len) { | ||||||||
if (ctx == NULL) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
if (len == 0) { | ||||||||
return 1; | ||||||||
} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verify that |
||||||||
|
||||||||
return FIPS202_Update(ctx, data, len); | ||||||||
} | ||||||||
|
||||||||
// SHAKE_Final is a single-shot API and can be called once to finalize absorb and squeeze phases | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think "single-shot" here is not the right term because it's used with non-streaming APIs such as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. Thank you! |
||||||||
// |ctx->state| restricts consecutive calls to FIPS202_Finalize | ||||||||
// Function SHAKE_Squeeze should be used for incremental XOF output | ||||||||
int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) { | ||||||||
ctx->md_size = len; | ||||||||
return SHA3_Final(md, ctx); | ||||||||
if (ctx->md_size == 0) { | ||||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
if (FIPS202_Finalize(md, ctx) == 0) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
Keccak1600_Squeeze(ctx->A, md, ctx->md_size, ctx->block_size, ctx->state); | ||||||||
ctx->state = KECCAK1600_STATE_FINAL; | ||||||||
|
||||||||
FIPS_service_indicator_update_state(); | ||||||||
|
||||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
// SHAKE_Squeeze can be called multiple times | ||||||||
// SHAKE_Squeeze should be called for incremental XOF output | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
int SHAKE_Squeeze(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have unit tests for SHAKE_Squeeze or we're relying on ml_dsa and ml_kem? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am adding multiple tests for SHAKE_Squeeze in #2155. Currently, the SHAKE_Squeeze is not exposed through the EVP functions, therefore, I only tested it through ML-KEM. |
||||||||
ctx->md_size = len; | ||||||||
|
||||||||
if (ctx->md_size == 0) { | ||||||||
return 1; | ||||||||
} | ||||||||
|
||||||||
if (ctx->state == KECCAK1600_STATE_FINAL) { | ||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
if (ctx->state == KECCAK1600_STATE_ABSORB) { | ||||||||
// Skip FIPS202_Finalize if the input has been padded and the last block has been processed | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe move this comment one line up because it's talking about skipping this if statement (if I understood correctly). |
||||||||
if (FIPS202_Finalize(md, ctx) == 0) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment feels like it's in the wrong place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! Fixed it. |
||||||||
return 0; | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
Keccak1600_Squeeze(ctx->A, md, len, ctx->block_size, ctx->state); | ||||||||
ctx->state = KECCAK1600_STATE_SQUEEZE; | ||||||||
|
||||||||
//FIPS_service_indicator_update_state(); | ||||||||
return 1; | ||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like to put a comment here like
'''
// KECCAK1600_STATE_SQUEEZE is set when |SHAKE_Squeeze| is called.
// It remains set while |SHAKE_Squeeze| is called repeatedly to output chunks of the XOF output.
'''
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, Nevine. Added!