From 5ef01d14a92525e05a3c89099199b73094428b89 Mon Sep 17 00:00:00 2001 From: bol-van Date: Mon, 16 Feb 2026 12:46:22 +0300 Subject: [PATCH] nfqws: fixes backport from z2 --- nfq/crypto/aes-gcm.c | 2 ++ nfq/crypto/gcm.c | 27 ++++++++++++++++++--------- nfq/crypto/hkdf.c | 32 ++++++++++++-------------------- nfq/crypto/hmac.c | 35 ++++++++++++++--------------------- nfq/crypto/sha224-256.c | 12 ++++++------ nfq/nfqws.c | 1 + nfq/protocol.c | 20 +++++++++----------- 7 files changed, 62 insertions(+), 67 deletions(-) diff --git a/nfq/crypto/aes-gcm.c b/nfq/crypto/aes-gcm.c index 130cd609..7dffa42c 100644 --- a/nfq/crypto/aes-gcm.c +++ b/nfq/crypto/aes-gcm.c @@ -5,6 +5,8 @@ int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_ int ret = 0; gcm_context ctx; + gcm_initialize(); + if (!(ret = gcm_setkey(&ctx, key, (const uint)key_len))) { ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len); diff --git a/nfq/crypto/gcm.c b/nfq/crypto/gcm.c index 74842ce6..398b77c4 100644 --- a/nfq/crypto/gcm.c +++ b/nfq/crypto/gcm.c @@ -391,7 +391,9 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context uint64_t orig_add_len = ctx->add_len * 8; size_t i; - if (tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len); + if (tag_len>16) return -1; + + if (tag_len) memcpy(tag, ctx->base_ectr, tag_len); if (orig_len || orig_add_len) { memset(work_buf, 0x00, 16); @@ -443,10 +445,12 @@ int gcm_crypt_and_tag( prepare the gcm context with the keying material, we simply invoke each of the three GCM sub-functions in turn... */ - gcm_start(ctx, mode, iv, iv_len, add, add_len); - gcm_update(ctx, length, input, output); - gcm_finish(ctx, tag, tag_len); - return(0); + if (tag_len>16) return -1; + + int ret; + if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret; + if ((ret=gcm_update(ctx, length, input, output))) return ret; + return gcm_finish(ctx, tag, tag_len); } @@ -477,23 +481,28 @@ int gcm_auth_decrypt( uchar check_tag[16]; // the tag generated and returned by decryption int diff; // an ORed flag to detect authentication errors size_t i; // our local iterator + int ret; + + if (tag_len>16) return -1; + /* we use GCM_DECRYPT_AND_TAG (above) to perform our decryption (which is an identical XORing to reverse the previous one) and also to re-generate the matching authentication tag */ - gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len, - input, output, length, check_tag, tag_len); + if ((ret = gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len))) return ret; // now we verify the authentication tag in 'constant time' for (diff = 0, i = 0; i < tag_len; i++) diff |= tag[i] ^ check_tag[i]; - if (diff != 0) { // see whether any bits differed? + if (diff) + { + // see whether any bits differed? memset(output, 0, length); // if so... wipe the output data return(GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE } - return(0); + return 0; } /****************************************************************************** diff --git a/nfq/crypto/hkdf.c b/nfq/crypto/hkdf.c index 266cb37d..b62f6823 100644 --- a/nfq/crypto/hkdf.c +++ b/nfq/crypto/hkdf.c @@ -60,9 +60,9 @@ int hkdf(SHAversion whichSha, uint8_t okm[], size_t okm_len) { uint8_t prk[USHAMaxHashSize]; - return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) || - hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, - info_len, okm, okm_len); + int ret; + if ((ret=hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk))) return ret; + return hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, info_len, okm, okm_len); } /* @@ -103,9 +103,6 @@ int hkdfExtract(SHAversion whichSha, salt_len = USHAHashSize(whichSha); memset(nullSalt, '\0', salt_len); } - else if (salt_len < 0) { - return shaBadParam; - } return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk); } @@ -149,16 +146,13 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len, size_t hash_len, N; unsigned char T[USHAMaxHashSize]; size_t Tlen, where, i; + int ret; if (info == 0) { info = (const unsigned char *)""; info_len = 0; } - else if (info_len < 0) { - return shaBadParam; - } - if (okm_len <= 0) return shaBadParam; - if (!okm) return shaBadParam; + if (!okm || !okm_len) return shaBadParam; hash_len = USHAHashSize(whichSha); if (prk_len < hash_len) return shaBadParam; @@ -171,12 +165,11 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len, for (i = 1; i <= N; i++) { HMACContext context; unsigned char c = i; - int ret = hmacReset(&context, whichSha, prk, prk_len) || - hmacInput(&context, T, Tlen) || - hmacInput(&context, info, info_len) || - hmacInput(&context, &c, 1) || - hmacResult(&context, T); - if (ret != shaSuccess) return ret; + if ((ret=hmacReset(&context, whichSha, prk, prk_len))) return ret; + if ((ret=hmacInput(&context, T, Tlen))) return ret; + if ((ret=hmacInput(&context, info, info_len))) return ret; + if ((ret=hmacInput(&context, &c, 1))) return ret; + if ((ret=hmacResult(&context, T))) return ret; memcpy(okm + where, T, (i != N) ? hash_len : (okm_len - where)); where += hash_len; @@ -328,9 +321,8 @@ int hkdfResult(HKDFContext *context, if (!okm) return context->Corrupted = shaBadParam; if (!prk) prk = prkbuf; - ret = hmacResult(&context->hmacContext, prk) || - hkdfExpand(context->whichSha, prk, context->hashSize, info, - info_len, okm, okm_len); + if (!(ret = hmacResult(&context->hmacContext, prk))) + ret = hkdfExpand(context->whichSha, prk, context->hashSize, info, info_len, okm, okm_len); context->Computed = 1; return context->Corrupted = ret; } diff --git a/nfq/crypto/hmac.c b/nfq/crypto/hmac.c index 9e053255..6995da4d 100644 --- a/nfq/crypto/hmac.c +++ b/nfq/crypto/hmac.c @@ -49,9 +49,10 @@ int hmac(SHAversion whichSha, uint8_t digest[USHAMaxHashSize]) { HMACContext context; - return hmacReset(&context, whichSha, key, key_len) || - hmacInput(&context, message_array, length) || - hmacResult(&context, digest); + int ret; + if ((ret=hmacReset(&context, whichSha, key, key_len))) return ret; + if ((ret=hmacInput(&context, message_array, length))) return ret; + return hmacResult(&context, digest); } /* @@ -101,10 +102,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha, */ if (key_len > blocksize) { USHAContext tcontext; - int err = USHAReset(&tcontext, whichSha) || - USHAInput(&tcontext, key, key_len) || - USHAResult(&tcontext, tempkey); - if (err != shaSuccess) return err; + if ((ret=USHAReset(&tcontext, whichSha)) || (ret=USHAInput(&tcontext, key, key_len)) || (ret=USHAResult(&tcontext, tempkey))) + return ret; key = tempkey; key_len = hashsize; @@ -134,9 +133,9 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha, /* perform inner hash */ /* init context for 1st pass */ - ret = USHAReset(&context->shaContext, whichSha) || + if (!(ret = USHAReset(&context->shaContext, whichSha))) /* and start with inner pad */ - USHAInput(&context->shaContext, k_ipad, blocksize); + ret = USHAInput(&context->shaContext, k_ipad, blocksize); return context->Corrupted = ret; } @@ -197,8 +196,7 @@ int hmacFinalBits(HMACContext *context, if (context->Corrupted) return context->Corrupted; if (context->Computed) return context->Corrupted = shaStateError; /* then final bits of datagram */ - return context->Corrupted = - USHAFinalBits(&context->shaContext, bits, bit_count); + return context->Corrupted = USHAFinalBits(&context->shaContext, bits, bit_count); } /* @@ -229,21 +227,16 @@ int hmacResult(HMACContext *context, uint8_t *digest) /* finish up 1st pass */ /* (Use digest here as a temporary buffer.) */ - ret = - USHAResult(&context->shaContext, digest) || - + if (!(ret=USHAResult(&context->shaContext, digest)) && /* perform outer SHA */ /* init context for 2nd pass */ - USHAReset(&context->shaContext, context->whichSha) || - + !(ret=USHAReset(&context->shaContext, context->whichSha)) && /* start with outer pad */ - USHAInput(&context->shaContext, context->k_opad, - context->blockSize) || - + !(ret=USHAInput(&context->shaContext, context->k_opad, context->blockSize)) && /* then results of 1st hash */ - USHAInput(&context->shaContext, digest, context->hashSize) || + !(ret=USHAInput(&context->shaContext, digest, context->hashSize))) /* finish up 2nd pass */ - USHAResult(&context->shaContext, digest); + ret=USHAResult(&context->shaContext, digest); context->Computed = 1; return context->Corrupted = ret; diff --git a/nfq/crypto/sha224-256.c b/nfq/crypto/sha224-256.c index 2c9bc9c1..ec4954de 100644 --- a/nfq/crypto/sha224-256.c +++ b/nfq/crypto/sha224-256.c @@ -64,12 +64,12 @@ * Add "length" to the length. * Set Corrupted when overflow has occurred. */ -static uint32_t addTemp; -#define SHA224_256AddLength(context, length) \ - (addTemp = (context)->Length_Low, (context)->Corrupted = \ - (((context)->Length_Low += (length)) < addTemp) && \ - (++(context)->Length_High == 0) ? shaInputTooLong : \ - (context)->Corrupted ) +static int SHA224_256AddLength(SHA256Context *context, uint32_t length) +{ + uint32_t addTemp = context->Length_Low; + if (((context->Length_Low += length) < addTemp) && (++(context)->Length_High == 0)) context->Corrupted = shaInputTooLong; + return context->Corrupted; +} /* Local Function Prototypes */ static int SHA224_256Reset(SHA256Context *context, uint32_t *H0); diff --git a/nfq/nfqws.c b/nfq/nfqws.c index 8117be14..022a32f4 100644 --- a/nfq/nfqws.c +++ b/nfq/nfqws.c @@ -2304,6 +2304,7 @@ int main(int argc, char **argv) #endif srandom(time(NULL)); + aes_init_keygen_tables(); // required for aes PRINT_VER; diff --git a/nfq/protocol.c b/nfq/protocol.c index 77ab5857..3621779f 100644 --- a/nfq/protocol.c +++ b/nfq/protocol.c @@ -795,21 +795,19 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si return false; } - uint64_t payload_len,token_len; - size_t pn_offset; + uint64_t payload_len,token_len,pn_offset; pn_offset = 1 + 4 + 1 + data[5]; if (pn_offset >= data_len) return false; + // SCID length pn_offset += 1 + data[pn_offset]; - if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false; + if (pn_offset >= data_len || (pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false; + // token length pn_offset += tvb_get_varint(data + pn_offset, &token_len); pn_offset += token_len; - if (pn_offset >= data_len) return false; - if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false; + if (pn_offset >= data_len || (pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false; pn_offset += tvb_get_varint(data + pn_offset, &payload_len); if (payload_len<20 || (pn_offset + payload_len)>data_len) return false; - aes_init_keygen_tables(); - uint8_t sample_enc[16]; aes_context ctx; if (aes_setkey(&ctx, 1, aeshp, sizeof(aeshp)) || aes_cipher(&ctx, data + pn_offset + 4, sample_enc)) return false; @@ -827,13 +825,13 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si phton64(aesiv + sizeof(aesiv) - 8, pntoh64(aesiv + sizeof(aesiv) - 8) ^ pkn); - size_t cryptlen = payload_len - pkn_len - 16; + uint64_t cryptlen = payload_len - pkn_len - 16; if (cryptlen > *clean_len) return false; - *clean_len = cryptlen; + *clean_len = (size_t)cryptlen; const uint8_t *decrypt_begin = data + pn_offset + pkn_len; - uint8_t atag[16],header[256]; - size_t header_len = pn_offset + pkn_len; + uint8_t atag[16],header[2048]; + uint64_t header_len = pn_offset + pkn_len; if (header_len > sizeof(header)) return false; // not likely header will be so large memcpy(header, data, header_len); header[0] = packet0;