mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-08 21:50:48 +02:00
Merge pull request #10442 from JeremiahM37/zd21783
Fix SAKKE OOB write and correctness gap in sakke_hash_to_range
This commit is contained in:
+38
-16
@@ -6169,20 +6169,28 @@ static int sakke_calc_h_v(SakkeKey* key, enum wc_HashType hashType,
|
||||
static void sakke_xor_in_v(const byte* v, word32 hashSz, byte* out, word32 idx,
|
||||
word32 n)
|
||||
{
|
||||
int o;
|
||||
word32 i;
|
||||
word32 skip;
|
||||
word32 off;
|
||||
word32 len;
|
||||
|
||||
/* RFC 6508, Section 5.1: output is the low n octets of
|
||||
* v_1||v_2||...||v_l (the concatenation of l hash outputs taken
|
||||
* modulo 2^(n*8)). When n is not a multiple of hashSz, drop the
|
||||
* leading 'skip' high bytes of the first hash output. */
|
||||
skip = n % hashSz;
|
||||
skip = (skip == 0) ? 0 : (hashSz - skip);
|
||||
|
||||
if (idx == 0) {
|
||||
i = hashSz - (n % hashSz);
|
||||
if (i == hashSz) {
|
||||
i = 0;
|
||||
}
|
||||
xorbuf(out, v + skip, hashSz - skip);
|
||||
}
|
||||
else {
|
||||
i = 0;
|
||||
off = idx - skip;
|
||||
len = n - off;
|
||||
if (len > hashSz) {
|
||||
len = hashSz;
|
||||
}
|
||||
xorbuf(out + off, v, len);
|
||||
}
|
||||
o = (int)i;
|
||||
xorbuf(out + idx + i - o, v + i, hashSz - i);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6689,8 +6697,9 @@ static int sakke_compute_point_r(SakkeKey* key, const byte* id, word16 idSz,
|
||||
* @param [out] auth Authentication data.
|
||||
* @param [out] authSz Size of authentication data in bytes.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, ssv or encSz is NULL, ssvSz is to big or
|
||||
* encSz is too small.
|
||||
* @return BAD_FUNC_ARG when key, ssv or authSz is NULL, ssvSz is 0 or
|
||||
* larger than the curve modulus byte length, or *authSz is too
|
||||
* small when encapsulating.
|
||||
* @return BAD_STATE_E when identity not set.
|
||||
* @return LENGTH_ONLY_E when auth is NULL. authSz contains required size of
|
||||
* auth in bytes.
|
||||
@@ -6706,7 +6715,7 @@ int wc_MakeSakkeEncapsulatedSSV(SakkeKey* key, enum wc_HashType hashType,
|
||||
word16 outSz = 0;
|
||||
byte a[WC_MAX_DIGEST_SIZE];
|
||||
|
||||
if ((key == NULL) || (ssv == NULL) || (authSz == NULL)) {
|
||||
if ((key == NULL) || (ssv == NULL) || (authSz == NULL) || (ssvSz == 0)) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
if ((err == 0) && (key->idSz == 0)) {
|
||||
@@ -6725,7 +6734,14 @@ int wc_MakeSakkeEncapsulatedSSV(SakkeKey* key, enum wc_HashType hashType,
|
||||
/* Uncompressed point */
|
||||
outSz = (word16)(1 + 2 * n);
|
||||
|
||||
if ((auth != NULL) && (*authSz < outSz)) {
|
||||
/* RFC 6508, Section 6.2.1, Step 1 places SSV in 0..2^n-1, so
|
||||
* ssvSz must be <= n. Enforced on both the encapsulation and
|
||||
* size-query paths so callers cannot probe authSz with an
|
||||
* invalid ssvSz. */
|
||||
if (ssvSz > n) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
else if ((auth != NULL) && (*authSz < outSz)) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
@@ -6820,7 +6836,7 @@ int wc_GenerateSakkeSSV(SakkeKey* key, WC_RNG* rng, byte* ssv, word16* ssvSz)
|
||||
if (err == 0) {
|
||||
n = (word16)WC_BITS_TO_BYTES(mp_count_bits(&key->params.prime));
|
||||
|
||||
if ((ssv != NULL) && (*ssvSz > n)) {
|
||||
if ((ssv != NULL) && ((*ssvSz == 0) || (*ssvSz > n))) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
@@ -6864,7 +6880,8 @@ int wc_GenerateSakkeSSV(SakkeKey* key, WC_RNG* rng, byte* ssv, word16* ssvSz)
|
||||
* @param [in] auth Authentication data.
|
||||
* @param [in] authSz Size of authentication data in bytes.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, ssv or auth is NULL.
|
||||
* @return BAD_FUNC_ARG when key, ssv or auth is NULL, ssvSz is 0 or
|
||||
* larger than the curve modulus byte length.
|
||||
* @return BAD_STATE_E when RSK or identity not set.
|
||||
* @return SAKKE_VERIFY_FAIL_E when calculated R doesn't match the encapsulated
|
||||
* data's R.
|
||||
@@ -6883,7 +6900,7 @@ int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, byte* ssv,
|
||||
byte* test = NULL;
|
||||
byte a[WC_MAX_DIGEST_SIZE] = {0};
|
||||
|
||||
if ((key == NULL) || (ssv == NULL) || (auth == NULL)) {
|
||||
if ((key == NULL) || (ssv == NULL) || (auth == NULL) || (ssvSz == 0)) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
if ((err == 0) && (!key->rsk.set || (key->idSz == 0))) {
|
||||
@@ -6902,6 +6919,11 @@ int wc_DeriveSakkeSSV(SakkeKey* key, enum wc_HashType hashType, byte* ssv,
|
||||
if (authSz != 2 * n + 1) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
/* RFC 6508, Section 6.2.1: SSV is in 0..2^n-1, so ssvSz must
|
||||
* be <= n. */
|
||||
else if (ssvSz > n) {
|
||||
err = BAD_FUNC_ARG;
|
||||
}
|
||||
}
|
||||
if (err == 0) {
|
||||
err = sakke_load_base_point(key);
|
||||
|
||||
@@ -61310,6 +61310,73 @@ static wc_test_ret_t sakke_op_test(SakkeKey* priv, SakkeKey* pub, WC_RNG* rng,
|
||||
authSz);
|
||||
if (ret != 0)
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
|
||||
{
|
||||
/* All three SSV entry points reject ssvSz=0 and ssvSz>n. */
|
||||
word16 zeroSz = 0;
|
||||
word16 hugeSz = 0xFFFF;
|
||||
|
||||
ret = wc_GenerateSakkeSSV(pub, rng, ssv, &zeroSz);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
zeroSz = 0;
|
||||
ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssv, zeroSz,
|
||||
auth, &authSz);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssv, zeroSz, auth,
|
||||
authSz);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
ret = wc_GenerateSakkeSSV(pub, rng, ssv, &hugeSz);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
hugeSz = 0xFFFF;
|
||||
ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssv, hugeSz,
|
||||
auth, &authSz);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssv, hugeSz, auth,
|
||||
authSz);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
{
|
||||
/* Round-trip encap/derive across ssvSz shapes that exercise the
|
||||
* multi-iteration paths in sakke_xor_in_v. SHA-256 hashSz=32:
|
||||
* 48: 2 iterations, partial first block.
|
||||
* 72: 3 iterations, exercises the len-clamp on the middle iter.
|
||||
* 64: 2 iterations, exact-multiple (skip==0). */
|
||||
static const word16 extSzs[3] = { 48, 72, 64 };
|
||||
byte ssvExt[72];
|
||||
byte ssvRef[72];
|
||||
word16 extAuthSz;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
word16 extSz = extSzs[i];
|
||||
|
||||
ret = wc_RNG_GenerateBlock(rng, ssvRef, extSz);
|
||||
if (ret != 0)
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
XMEMCPY(ssvExt, ssvRef, extSz);
|
||||
|
||||
extAuthSz = 257;
|
||||
ret = wc_MakeSakkeEncapsulatedSSV(pub, WC_HASH_TYPE_SHA256, ssvExt,
|
||||
extSz, auth, &extAuthSz);
|
||||
if (ret != 0)
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
|
||||
ret = wc_DeriveSakkeSSV(priv, WC_HASH_TYPE_SHA256, ssvExt, extSz,
|
||||
auth, extAuthSz);
|
||||
if (ret != 0)
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
if (XMEMCMP(ssvExt, ssvRef, extSz) != 0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user