Merge pull request #10803 from Frauschi/fenrir

Fenrir fixes
This commit is contained in:
Daniel Pouzzner
2026-07-03 01:11:03 -05:00
committed by GitHub
15 changed files with 331 additions and 37 deletions
+10
View File
@@ -631,6 +631,16 @@ static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data,
if (len <= 0)
return 0; /* Nothing to write */
/* Reject sizes that would overflow the buffer growth calculation, which
* rounds the requested size up to the next multiple of 4/3 via
* (size + 3) / 3 * 4. The extra rounding slack means the safe ceiling is
* one below (INT_MAX / 4) * 3. Without this an oversized length grows a
* short buffer and copies past the source. */
if (len > ((INT_MAX / 4) * 3) - 1 - bio->wrSz) {
WOLFSSL_MSG("write length too large");
return WOLFSSL_BIO_ERROR;
}
if (wolfSSL_BUF_MEM_grow_ex(bio->mem_buf, ((size_t)bio->wrSz) +
((size_t)len), 0) == 0) {
WOLFSSL_MSG("Error growing memory area");
+49 -28
View File
@@ -2222,6 +2222,7 @@ WOLFSSL_ASN1_OBJECT *wolfSSL_d2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a,
WOLFSSL_ASN1_OBJECT* ret = NULL;
int len = 0;
word32 idx = 0;
word32 maxIdx;
WOLFSSL_ENTER("wolfSSL_d2i_ASN1_OBJECT");
@@ -2231,7 +2232,17 @@ WOLFSSL_ASN1_OBJECT *wolfSSL_d2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a,
return NULL;
}
if (GetASNHeader(*der, ASN_OBJECT_ID, &idx, &len, (word32)length) < 0) {
/* An ASN.1 OBJECT is an OID, whose DER encoding cannot exceed the OID
* ceiling: a tag byte, a single short-form length byte (content is at
* most MAX_OID_SZ, which is below the long-form threshold) and the OID
* content. Cap the parse window so an oversized length argument cannot
* drive the header decode to read past the end of the actual buffer. */
maxIdx = (word32)length;
if (maxIdx > (word32)(MAX_OID_SZ + 2)) {
maxIdx = (word32)(MAX_OID_SZ + 2);
}
if (GetASNHeader(*der, ASN_OBJECT_ID, &idx, &len, maxIdx) < 0) {
WOLFSSL_MSG("error getting tag");
return NULL;
}
@@ -3163,42 +3174,52 @@ int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int sz)
* when sz == INT_MAX. By this point sz >= 0 (negative sz is
* handled above as OpenSSL -1/strlen compat). */
size_t allocSz = (size_t)sz + 1;
char* oldData = asn1->data;
int oldDynamic = asn1->isDynamic;
char* dst;
/* Dispose of any existing dynamic data. */
if (asn1->isDynamic) {
XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
asn1->data = NULL;
}
/* Check string will fit - including NUL. */
/* Select the destination buffer WITHOUT disposing of the existing
* data yet. Deferring the free keeps the copy below safe even when
* the source aliases the object's own buffer (data == asn1->data),
* avoiding a use-after-free or clear-before-copy without needing an
* ephemeral allocation. */
if (allocSz > CTC_NAME_SIZE) {
/* Allocate new buffer. */
asn1->data = (char*)XMALLOC(allocSz, NULL,
DYNAMIC_TYPE_OPENSSL);
if (asn1->data == NULL) {
dst = (char*)XMALLOC(allocSz, NULL, DYNAMIC_TYPE_OPENSSL);
if (dst == NULL) {
ret = 0;
}
else {
/* Ensure buffer will be freed. */
asn1->isDynamic = 1;
}
}
else {
/* Clear out fixed array and use it for data. */
XMEMSET(asn1->strData, 0, CTC_NAME_SIZE);
asn1->data = asn1->strData;
asn1->isDynamic = 0;
/* Use the fixed array for data. */
dst = asn1->strData;
}
}
if (ret == 1) {
/* Check if there is a string to copy. */
if (data != NULL) {
/* Copy string and append NUL. */
XMEMCPY(asn1->data, data, (size_t)sz);
asn1->data[sz] = '\0';
if (ret == 1) {
/* Copy string and append NUL. XMEMMOVE handles the case where
* data aliases the fixed array (source and destination overlap). */
if (data != NULL) {
XMEMMOVE(dst, data, (size_t)sz);
}
dst[sz] = '\0';
/* Clear any remainder of the fixed array (matches prior behavior
* of zeroing the whole array). Done after the copy so it never
* disturbs an aliased source. */
if (dst == asn1->strData) {
XMEMSET(dst + sz + 1, 0, CTC_NAME_SIZE - (size_t)sz - 1);
}
/* Dispose of any old dynamic buffer now the copy is complete. */
if (oldDynamic && (oldData != dst)) {
XFREE(oldData, NULL, DYNAMIC_TYPE_OPENSSL);
}
/* Commit the new buffer and its properties. */
asn1->data = dst;
asn1->isDynamic = (allocSz > CTC_NAME_SIZE) ? 1 : 0;
asn1->length = sz;
}
/* Set size of string. */
asn1->length = sz;
}
return ret;
+19 -1
View File
@@ -13590,6 +13590,16 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
case key_update:
/* Valid on both sides. */
#ifdef WOLFSSL_QUIC
/* RFC 9001 Section 6: QUIC performs key updates at the QUIC
* packet-protection layer, so a TLS KeyUpdate message must be
* rejected as a fatal unexpected_message connection error. */
if (WOLFSSL_IS_QUIC(ssl)) {
WOLFSSL_MSG("KeyUpdate received over QUIC");
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
return SANITY_MSG_E;
}
#endif
/* Check state.
* Client and server must have received finished message from other
* side.
@@ -14976,6 +14986,13 @@ int Tls13UpdateKeys(WOLFSSL* ssl)
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
return BAD_FUNC_ARG;
#ifdef WOLFSSL_QUIC
/* RFC 9001 Section 6: a QUIC connection must not send a TLS KeyUpdate;
* key updates are handled at the QUIC packet-protection layer. */
if (WOLFSSL_IS_QUIC(ssl))
return BAD_FUNC_ARG;
#endif
#ifdef WOLFSSL_DTLS13
/* we are already waiting for the ack of a sent key update message. We can't
send another one before receiving its ack. Either wolfSSL_update_keys()
@@ -14995,7 +15012,8 @@ int Tls13UpdateKeys(WOLFSSL* ssl)
* calling wolfSSL_write() will have the message sent when ready.
*
* ssl The SSL/TLS object.
* returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
* returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or running over
* QUIC (RFC 9001 handles key updates at the QUIC packet-protection layer),
* WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write,
* WOLFSSL_SUCCESS on success and otherwise failure.
*/