SipHash: add separate setter for the hash size
This was originally part of SipHash_Init. However, there are cases where there isn't any key material to initialize from when setting the hash size, and we do allow doing so with a EVP_PKEY control. The solution is to provide a separate hash_size setter and to use it in the corresponding EVP_PKEY_METHOD. Fixes #7143 Reviewed-by: Tim Hudson <tjh@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7145)
This commit is contained in:
parent
2725232132
commit
d74f23d2db
4 changed files with 42 additions and 29 deletions
|
@ -18,7 +18,8 @@ typedef struct siphash_st SIPHASH;
|
|||
|
||||
size_t SipHash_ctx_size(void);
|
||||
size_t SipHash_hash_size(SIPHASH *ctx);
|
||||
int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int hash_size,
|
||||
int SipHash_set_hash_size(SIPHASH *ctx, size_t hash_size);
|
||||
int SipHash_Init(SIPHASH *ctx, const unsigned char *k,
|
||||
int crounds, int drounds);
|
||||
void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen);
|
||||
int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen);
|
||||
|
|
|
@ -80,17 +80,32 @@ size_t SipHash_hash_size(SIPHASH *ctx)
|
|||
return ctx->hash_size;
|
||||
}
|
||||
|
||||
static size_t siphash_adjust_hash_size(size_t hash_size)
|
||||
{
|
||||
if (hash_size == 0)
|
||||
hash_size = SIPHASH_MAX_DIGEST_SIZE;
|
||||
return hash_size;
|
||||
}
|
||||
|
||||
int SipHash_set_hash_size(SIPHASH *ctx, size_t hash_size)
|
||||
{
|
||||
hash_size = siphash_adjust_hash_size(hash_size);
|
||||
if (hash_size != SIPHASH_MIN_DIGEST_SIZE
|
||||
&& hash_size != SIPHASH_MAX_DIGEST_SIZE)
|
||||
return 0;
|
||||
|
||||
ctx->hash_size = hash_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* hash_size = crounds = drounds = 0 means SipHash24 with 16-byte output */
|
||||
int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int hash_size, int crounds, int drounds)
|
||||
int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int crounds, int drounds)
|
||||
{
|
||||
uint64_t k0 = U8TO64_LE(k);
|
||||
uint64_t k1 = U8TO64_LE(k + 8);
|
||||
|
||||
if (hash_size == 0)
|
||||
hash_size = SIPHASH_MAX_DIGEST_SIZE;
|
||||
else if (hash_size != SIPHASH_MIN_DIGEST_SIZE &&
|
||||
hash_size != SIPHASH_MAX_DIGEST_SIZE)
|
||||
return 0;
|
||||
/* If the hash size wasn't set, i.e. is zero */
|
||||
ctx->hash_size = siphash_adjust_hash_size(ctx->hash_size);
|
||||
|
||||
if (drounds == 0)
|
||||
drounds = SIPHASH_D_ROUNDS;
|
||||
|
@ -99,7 +114,6 @@ int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int hash_size, int cround
|
|||
|
||||
ctx->crounds = crounds;
|
||||
ctx->drounds = drounds;
|
||||
ctx->hash_size = hash_size;
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->total_inlen = 0;
|
||||
|
|
|
@ -95,16 +95,13 @@ static int siphash_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
|||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
const unsigned char* key;
|
||||
size_t len;
|
||||
int hash_size;
|
||||
|
||||
key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
|
||||
if (key == NULL || len != SIPHASH_KEY_SIZE)
|
||||
return 0;
|
||||
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
|
||||
EVP_MD_CTX_set_update_fn(mctx, int_update);
|
||||
/* use default rounds (2,4) */
|
||||
hash_size = SipHash_hash_size(&pctx->ctx);
|
||||
return SipHash_Init(&pctx->ctx, key, hash_size, 0, 0);
|
||||
return SipHash_Init(&pctx->ctx, key, 0, 0);
|
||||
}
|
||||
static int siphash_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
EVP_MD_CTX *mctx)
|
||||
|
@ -122,7 +119,6 @@ static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
|||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
const unsigned char *key;
|
||||
size_t len;
|
||||
int hash_size;
|
||||
|
||||
switch (type) {
|
||||
|
||||
|
@ -131,12 +127,7 @@ static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
|||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
|
||||
if (p1 != SIPHASH_MIN_DIGEST_SIZE &&
|
||||
p1 != SIPHASH_MAX_DIGEST_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
/* use default rounds (2,4) */
|
||||
return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp), p1, 0, 0);
|
||||
return SipHash_set_hash_size(&pctx->ctx, p1);
|
||||
|
||||
case EVP_PKEY_CTRL_SET_MAC_KEY:
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
|
@ -152,8 +143,8 @@ static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
|||
!ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
|
||||
return 0;
|
||||
/* use default rounds (2,4) */
|
||||
hash_size = SipHash_hash_size(&pctx->ctx);
|
||||
return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp), hash_size, 0, 0);
|
||||
return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp),
|
||||
0, 0);
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
|
|
@ -196,7 +196,8 @@ static int test_siphash(int idx)
|
|||
for (i = 0; i < inlen; i++)
|
||||
in[i] = (unsigned char)i;
|
||||
|
||||
if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
|
||||
if (!TEST_true(SipHash_set_hash_size(&siphash, expectedlen))
|
||||
|| !TEST_true(SipHash_Init(&siphash, key, 0, 0)))
|
||||
return 0;
|
||||
SipHash_Update(&siphash, in, inlen);
|
||||
if (!TEST_true(SipHash_Final(&siphash, out, expectedlen))
|
||||
|
@ -204,7 +205,8 @@ static int test_siphash(int idx)
|
|||
return 0;
|
||||
|
||||
if (inlen > 16) {
|
||||
if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
|
||||
if (!TEST_true(SipHash_set_hash_size(&siphash, expectedlen))
|
||||
|| !TEST_true(SipHash_Init(&siphash, key, 0, 0)))
|
||||
return 0;
|
||||
SipHash_Update(&siphash, in, 1);
|
||||
SipHash_Update(&siphash, in+1, inlen-1);
|
||||
|
@ -220,7 +222,8 @@ static int test_siphash(int idx)
|
|||
if (inlen > 32) {
|
||||
size_t half = inlen / 2;
|
||||
|
||||
if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
|
||||
if (!TEST_true(SipHash_set_hash_size(&siphash, expectedlen))
|
||||
|| !TEST_true(SipHash_Init(&siphash, key, 0, 0)))
|
||||
return 0;
|
||||
SipHash_Update(&siphash, in, half);
|
||||
SipHash_Update(&siphash, in+half, inlen-half);
|
||||
|
@ -233,7 +236,8 @@ static int test_siphash(int idx)
|
|||
}
|
||||
|
||||
for (half = 16; half < inlen; half += 16) {
|
||||
if (!TEST_true(SipHash_Init(&siphash, key, expectedlen, 0, 0)))
|
||||
if (!TEST_true(SipHash_set_hash_size(&siphash, expectedlen))
|
||||
|| !TEST_true(SipHash_Init(&siphash, key, 0, 0)))
|
||||
return 0;
|
||||
SipHash_Update(&siphash, in, half);
|
||||
SipHash_Update(&siphash, in+half, inlen-half);
|
||||
|
@ -258,19 +262,22 @@ static int test_siphash_basic(void)
|
|||
unsigned char output[SIPHASH_MAX_DIGEST_SIZE];
|
||||
|
||||
/* Use invalid hash size */
|
||||
return TEST_int_eq(SipHash_Init(&siphash, key, 4, 0, 0), 0)
|
||||
return TEST_int_eq(SipHash_set_hash_size(&siphash, 4), 0)
|
||||
/* Use hash size = 8 */
|
||||
&& TEST_true(SipHash_Init(&siphash, key, 8, 0, 0))
|
||||
&& TEST_true(SipHash_set_hash_size(&siphash, 8))
|
||||
&& TEST_true(SipHash_Init(&siphash, key, 0, 0))
|
||||
&& TEST_true(SipHash_Final(&siphash, output, 8))
|
||||
&& TEST_int_eq(SipHash_Final(&siphash, output, 16), 0)
|
||||
|
||||
/* Use hash size = 16 */
|
||||
&& TEST_true(SipHash_Init(&siphash, key, 16, 0, 0))
|
||||
&& TEST_true(SipHash_set_hash_size(&siphash, 16))
|
||||
&& TEST_true(SipHash_Init(&siphash, key, 0, 0))
|
||||
&& TEST_int_eq(SipHash_Final(&siphash, output, 8), 0)
|
||||
&& TEST_true(SipHash_Final(&siphash, output, 16))
|
||||
|
||||
/* Use hash size = 0 (default = 16) */
|
||||
&& TEST_true(SipHash_Init(&siphash, key, 0, 0, 0))
|
||||
&& TEST_true(SipHash_set_hash_size(&siphash, 0))
|
||||
&& TEST_true(SipHash_Init(&siphash, key, 0, 0))
|
||||
&& TEST_int_eq(SipHash_Final(&siphash, output, 8), 0)
|
||||
&& TEST_true(SipHash_Final(&siphash, output, 16));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue