From 9695736c2bee6f3c131b074faccbdf1a4256f24b Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Wed, 26 Aug 2026 21:30:26 +0000 Subject: [PATCH 1/4] Patch edk2 for CVE-2026-75803, CVE-2026-63076, CVE-2026-63074, CVE-2026-63072, CVE-2026-54874 --- SPECS/edk2/CVE-2026-54874.patch | 299 ++++++++++++++++++++++++++++++++ SPECS/edk2/CVE-2026-63072.patch | 51 ++++++ SPECS/edk2/CVE-2026-63074.patch | 84 +++++++++ SPECS/edk2/CVE-2026-63076.patch | 42 +++++ SPECS/edk2/CVE-2026-75803.patch | 92 ++++++++++ SPECS/edk2/edk2.spec | 10 +- 6 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 SPECS/edk2/CVE-2026-54874.patch create mode 100644 SPECS/edk2/CVE-2026-63072.patch create mode 100644 SPECS/edk2/CVE-2026-63074.patch create mode 100644 SPECS/edk2/CVE-2026-63076.patch create mode 100644 SPECS/edk2/CVE-2026-75803.patch diff --git a/SPECS/edk2/CVE-2026-54874.patch b/SPECS/edk2/CVE-2026-54874.patch new file mode 100644 index 00000000000..19a5e923ba9 --- /dev/null +++ b/SPECS/edk2/CVE-2026-54874.patch @@ -0,0 +1,299 @@ +From 7a057b59814c1c6699dd2ee3e6b59abeb3b21f88 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Wed, 26 Aug 2026 21:22:16 +0000 +Subject: [PATCH] Backport DTLS buffered record memory and queue limit fixes + +Signed-off-by: rpm-build +Upstream-reference: AI Backport of https://github.com/openssl/openssl/commit/1ca5a124b48f1ffe6980ad33724b452fbd62da1e.patch https://github.com/openssl/openssl/commit/0321286f0cc7f2c5eef419cbf8b130a95af072e7.patch +--- + .../openssl/ssl/record/rec_layer_d1.c | 121 +++++++++++++----- + .../OpensslLib/openssl/ssl/record/record.h | 1 - + .../openssl/ssl/record/record_local.h | 11 +- + .../openssl/ssl/record/ssl3_record.c | 7 +- + 4 files changed, 104 insertions(+), 36 deletions(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c +index 7f3d1a7..fffb5ee 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c +@@ -70,7 +70,7 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) + + while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; +- OPENSSL_free(rdata->rbuf.buf); ++ OPENSSL_free(rdata->packet); + OPENSSL_free(item->data); + pitem_free(item); + } +@@ -78,8 +78,8 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) + while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT) +- OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len); +- OPENSSL_free(rdata->rbuf.buf); ++ OPENSSL_cleanse(rdata->packet, rdata->packet_length); ++ OPENSSL_free(rdata->packet); + OPENSSL_free(item->data); + pitem_free(item); + } +@@ -87,8 +87,8 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) + while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT) +- OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len); +- OPENSSL_free(rdata->rbuf.buf); ++ OPENSSL_cleanse(rdata->packet, rdata->packet_length); ++ OPENSSL_free(rdata->packet); + OPENSSL_free(item->data); + pitem_free(item); + } +@@ -130,26 +130,60 @@ static int dtls1_copy_record(SSL *s, pitem *item) + + rdata = (DTLS1_RECORD_DATA *)item->data; + +- SSL3_BUFFER_release(&s->rlayer.rbuf); ++ /* ++ * The record was read into a read buffer at least this size, so it must fit ++ * - see the length checks in ssl3_read_n(). Verify it rather than risk ++ * overrunning the buffer if that ever ceases to hold. ++ */ ++ if (!ossl_assert(rdata->packet_length <= s->rlayer.rbuf.len)) { ++ OPENSSL_free(rdata->packet); ++ return 0; ++ } + +- s->rlayer.packet = rdata->packet; ++ /* ++ * rdata->packet is a standalone copy of this record's on-wire bytes (see ++ * dtls1_buffer_record()). Copy it into the live read buffer so that ++ * s->rlayer.packet continues to point inside s->rlayer.rbuf.buf, as it ++ * does for every other record, then free our standalone copy. ++ */ ++ memcpy(s->rlayer.rbuf.buf, rdata->packet, rdata->packet_length); ++ s->rlayer.rbuf.offset = 0; ++ s->rlayer.rbuf.left = 0; ++ s->rlayer.packet = s->rlayer.rbuf.buf; + s->rlayer.packet_length = rdata->packet_length; +- memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER)); + memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD)); + ++ /* ++ * dtls1_buffer_record() rebased rrec.data/input onto rdata->packet if they ++ * pointed into this record's own bytes, so translate them again onto the ++ * record's new location in the read buffer. Anything still pointing ++ * outside rdata->packet is either a separate allocation (rr->comp) or a ++ * leftover from a previously processed record that will be overwritten ++ * before use, so leave it alone. ++ */ ++ if (rdata->rrec.data >= rdata->packet ++ && rdata->rrec.data < rdata->packet + rdata->packet_length) ++ s->rlayer.rrec[0].data = s->rlayer.packet + (rdata->rrec.data - rdata->packet); ++ if (rdata->rrec.input >= rdata->packet ++ && rdata->rrec.input < rdata->packet + rdata->packet_length) ++ s->rlayer.rrec[0].input = s->rlayer.packet + (rdata->rrec.input - rdata->packet); ++ ++ OPENSSL_free(rdata->packet); ++ + /* Set proper sequence number for mac calculation */ +- memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6); ++ memcpy(&(s->rlayer.read_sequence[2]), &(s->rlayer.packet[5]), 6); + + return 1; + } + +-int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) ++int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority, ++ size_t limit) + { + DTLS1_RECORD_DATA *rdata; + pitem *item; + + /* Limit the size of the queue to prevent DOS attacks */ +- if (pqueue_size(queue->q) >= 100) ++ if (pqueue_size(queue->q) >= limit) + return 0; + + rdata = OPENSSL_malloc(sizeof(*rdata)); +@@ -161,11 +195,37 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) + return -1; + } + +- rdata->packet = s->rlayer.packet; ++ /* ++ * Take a copy of just this record's own on-wire bytes - the header plus the ++ * record body, which for an already-processed record holds the plaintext ++ * decrypted in place - rather than the whole (much larger) read buffer. The ++ * live s->rlayer.rbuf is left untouched and continues to be used for ++ * subsequent reads. ++ */ + rdata->packet_length = s->rlayer.packet_length; +- memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER)); ++ rdata->packet = OPENSSL_memdup(s->rlayer.packet, s->rlayer.packet_length); ++ if (rdata->packet == NULL) { ++ OPENSSL_free(rdata); ++ pitem_free(item); ++ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); ++ return -1; ++ } + memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD)); + ++ /* ++ * The copied rrec.data/input still point into the live read buffer. Rebase ++ * any that point within this record's own bytes onto our standalone copy, ++ * so that dtls1_copy_record() can translate them again on retrieval. ++ * Pointers elsewhere (e.g. into rr->comp, or left over from a previously ++ * processed record) are not ours to move and are left alone. ++ */ ++ if (rdata->rrec.data >= s->rlayer.packet ++ && rdata->rrec.data < s->rlayer.packet + s->rlayer.packet_length) ++ rdata->rrec.data = rdata->packet + (rdata->rrec.data - s->rlayer.packet); ++ if (rdata->rrec.input >= s->rlayer.packet ++ && rdata->rrec.input < s->rlayer.packet + s->rlayer.packet_length) ++ rdata->rrec.input = rdata->packet + (rdata->rrec.input - s->rlayer.packet); ++ + item->data = rdata; + + #ifndef OPENSSL_NO_SCTP +@@ -178,22 +238,9 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) + } + #endif + +- s->rlayer.packet = NULL; +- s->rlayer.packet_length = 0; +- memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf)); +- memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec)); +- +- if (!ssl3_setup_buffers(s)) { +- /* SSLfatal() already called */ +- OPENSSL_free(rdata->rbuf.buf); +- OPENSSL_free(rdata); +- pitem_free(item); +- return -1; +- } +- + if (pqueue_insert(queue->q, item) == NULL) { + /* Must be a duplicate so ignore it */ +- OPENSSL_free(rdata->rbuf.buf); ++ OPENSSL_free(rdata->packet); + OPENSSL_free(rdata); + pitem_free(item); + } +@@ -204,15 +251,16 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) + int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) + { + pitem *item; ++ int ret; + + item = pqueue_pop(queue->q); + if (item) { +- dtls1_copy_record(s, item); ++ ret = dtls1_copy_record(s, item); + + OPENSSL_free(item->data); + pitem_free(item); + +- return 1; ++ return ret; + } + + return 0; +@@ -257,7 +305,13 @@ int dtls1_process_buffered_records(SSL *s) + + /* Process all the records. */ + while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) { +- dtls1_get_unprocessed_record(s); ++ if (!dtls1_get_unprocessed_record(s)) { ++ /* ++ * Should not happen. The record has been dropped, so move on ++ * to the next one. ++ */ ++ continue; ++ } + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* +@@ -294,7 +348,8 @@ int dtls1_process_buffered_records(SSL *s) + } + + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), +- SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) { ++ SSL3_RECORD_get_seq_num(s->rlayer.rrec), ++ DTLS1_MAX_BUFFERED_RECORDS) < 0) { + /* SSLfatal() already called */ + return 0; + } +@@ -401,6 +456,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, + } + #endif + ++ /* On failure the record is simply dropped */ + dtls1_copy_record(s, item); + + OPENSSL_free(item->data); +@@ -454,7 +510,8 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, + * data for later processing rather than dropping the connection. + */ + if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), +- SSL3_RECORD_get_seq_num(rr)) < 0) { ++ SSL3_RECORD_get_seq_num(rr), ++ DTLS1_MAX_BUFFERED_RECORDS) < 0) { + /* SSLfatal() already called */ + return -1; + } +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h +index b60f71c..22b683a 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h +@@ -85,7 +85,6 @@ typedef struct record_pqueue_st { + typedef struct dtls1_record_data_st { + unsigned char *packet; + size_t packet_length; +- SSL3_BUFFER rbuf; + SSL3_RECORD rrec; + #ifndef OPENSSL_NO_SCTP + struct bio_dgram_sctp_rcvinfo recordinfo; +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h +index 0a929c6..08b44aa 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h +@@ -41,9 +41,18 @@ __owur int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, + + DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, + unsigned int *is_next_epoch); ++/* ++ * Limits on the number of records dtls1_buffer_record() will hold, to prevent ++ * DOS attacks. Records arriving early for the next epoch get a tighter limit: ++ * a legitimate peer only ever has a small burst of those in flight. ++ */ ++#define DTLS1_MAX_UNPROCESSED_RECORDS 16 ++#define DTLS1_MAX_BUFFERED_RECORDS 100 ++ + int dtls1_process_buffered_records(SSL *s); + int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue); +-int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority); ++int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority, ++ size_t limit); + void ssl3_record_sequence_update(unsigned char *seq); + + /* Functions provided by the DTLS1_BITMAP component */ +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c +index dcaaeef..db5a8bf 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c +@@ -1664,8 +1664,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) + * after use :-). + */ + +- /* we have pulled in a full packet so zero things */ +- RECORD_LAYER_reset_packet_length(&s->rlayer); ++ /* ++ * Leave s->rlayer.packet_length alone: ssl3_read_n() starts each new record ++ * by resetting it, and it must still describe this record's on-wire bytes ++ * for dtls1_buffer_record() should this record end up being buffered. ++ */ + + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap); +-- +2.45.4 + diff --git a/SPECS/edk2/CVE-2026-63072.patch b/SPECS/edk2/CVE-2026-63072.patch new file mode 100644 index 00000000000..09de2aa4bbc --- /dev/null +++ b/SPECS/edk2/CVE-2026-63072.patch @@ -0,0 +1,51 @@ +From 2e2af3344548d38b48f88371270ef8d68ae87d5b Mon Sep 17 00:00:00 2001 +From: Daniel Kubec +Date: Sun, 2 Aug 2026 00:23:39 +0000 +Subject: [PATCH] Fix heap buffer overflow (8-byte OOB write) in AES-WRAP-PAD + unwrap + +On its integrity-failure paths that primitive writes and cleanses up to inlen +bytes of the output buffer. Size the buffer for that worst case so a failed +unwrap cannot write past the allocation. + +Fixes CVE-2026-63072 + +Reviewed-by: Milan Broz +Reviewed-by: Andrew Dinh +Merge-date: Mon Aug 24 14:44:55 2026 +Signed-off-by: rpm-build +Upstream-reference: https://github.com/openssl/openssl/commit/a0c8ec557d9cac078f032d76cdf684fe743eb382.patch +--- + .../Library/OpensslLib/openssl/crypto/cms/cms_kari.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/crypto/cms/cms_kari.c b/CryptoPkg/Library/OpensslLib/openssl/crypto/cms/cms_kari.c +index a2f422a..47e50d8 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/cms/cms_kari.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/cms/cms_kari.c +@@ -217,6 +217,7 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, + int rv = 0; + unsigned char *out = NULL; + int outlen; ++ size_t outsize; + + keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx); + if (keklen > EVP_MAX_KEY_LENGTH) +@@ -230,7 +231,13 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, + /* obtain output length of ciphered key */ + if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) + goto err; +- out = OPENSSL_malloc(outlen); ++ /* ++ * On its integrity-failure paths that primitive writes and cleanses up to ++ * inlen bytes of the output buffer. Size the buffer for that worst case so ++ * a failed unwrap cannot write past the allocation. ++ */ ++ outsize = (size_t)outlen < inlen ? inlen : (size_t)outlen; ++ out = OPENSSL_malloc(outsize); + if (out == NULL) + goto err; + if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) +-- +2.45.4 + diff --git a/SPECS/edk2/CVE-2026-63074.patch b/SPECS/edk2/CVE-2026-63074.patch new file mode 100644 index 00000000000..e9f480d5b51 --- /dev/null +++ b/SPECS/edk2/CVE-2026-63074.patch @@ -0,0 +1,84 @@ +From 10a51aea3c14ebb36267b5ad0b89b4cfc7c7e44a Mon Sep 17 00:00:00 2001 +From: Neil Horman +Date: Tue, 30 Jun 2026 15:09:01 -0400 +Subject: [PATCH] Fix unbounded cert cache growth in cmp + +If a remote user sends cmp messages to a server with a list of +extraCerts and the message is rejected, the extraCerts from the message +remain in the server contexts untrusted certificate stack. This exposes +servers with long lived ctx objects to denial of service attacks in +which an attacker sends messages intending to be rejected with a large +list of additional cerificated repeatedly, forcing the server to store +them indefinately. + +Fix it by rolling back the added extra certs if the message is rejected, +using the same method we do when the context is configured to not do +caching at all. + +Fixes openssl/srt#224 + +Fixes CVE-2026-63074 + +Reviewed-by: Milan Broz +Reviewed-by: Tomas Mraz +Reviewed-by: Igor Ustinov +Merge-date: Mon Aug 24 12:45:55 2026 +Signed-off-by: rpm-build +Upstream-reference: https://github.com/openssl/openssl/commit/21a5d9658b0c66daace60e10ea18ff32a448de9f.patch +--- + .../OpensslLib/openssl/crypto/cmp/cmp_vfy.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_vfy.c b/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_vfy.c +index b9d6fc2..6c246db 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_vfy.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_vfy.c +@@ -666,6 +666,7 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, + { + OSSL_CMP_PKIHEADER *hdr; + const X509_NAME *expected_sender; ++ int num_extra_before, num_extra_after, num_added; + + if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL)) + return 0; +@@ -700,17 +701,27 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, + * extraCerts because they do not belong to the protected msg part anyway. + * For efficiency, the extraCerts are prepended so they get used first. + */ ++ num_extra_before = sk_X509_num(ctx->untrusted); + if (!X509_add_certs(ctx->untrusted, msg->extraCerts, + /* this allows self-signed certs */ + X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP + | X509_ADD_FLAG_PREPEND)) + return 0; +- ++ num_extra_after = sk_X509_num(ctx->untrusted); ++ num_added = num_extra_after - num_extra_before; + /* validate message protection */ + if (hdr->protectionAlg != NULL) { + /* detect explicitly permitted exceptions for invalid protection */ + if (!OSSL_CMP_validate_msg(ctx, msg) + && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) { ++ /* ++ * remove extraCerts again if not caching ++ * or if we failed validation above, lest a remote user ++ * starts sending us lots of certificate in invalid messages ++ * leading to a DOS from unbounded certificate stack growth ++ */ ++ while (num_added-- > 0) ++ X509_free(sk_X509_shift(ctx->untrusted)); + #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION); + return 0; +@@ -719,6 +730,8 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, + } else { + /* detect explicitly permitted exceptions for missing protection */ + if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) { ++ while (num_added-- > 0) ++ X509_free(sk_X509_shift(ctx->untrusted)); + #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION); + return 0; +-- +2.45.4 + diff --git a/SPECS/edk2/CVE-2026-63076.patch b/SPECS/edk2/CVE-2026-63076.patch new file mode 100644 index 00000000000..0592120a760 --- /dev/null +++ b/SPECS/edk2/CVE-2026-63076.patch @@ -0,0 +1,42 @@ +From a03b98db440eb09cd61c29f1072ecf861ed9518d Mon Sep 17 00:00:00 2001 +From: Daniel Kubec +Date: Tue, 21 Jul 2026 11:19:29 +0200 +Subject: [PATCH] Fix Remote NULL deref in ossl_cmp_calc_protection() via + crafted protectionAlg + +ossl_cmp_calc_protection() only checked whether the protectionAlg parameter +(ppval) was NULL before treating it as a PBMParameter ASN1_STRING. + +X509_ALGOR_get0() does not validate the ASN.1 type of the parameter against what +the caller expects. For id-PasswordBasedMAC, a crafted message can encode the +parameter as a BOOLEAN instead of the expected PBMParameter SEQUENCE. Because +the ASN1_TYPE value union overlays the boolean int on the pointer field, ppval +comes back as a bogus non-NULL pointer (e.g. 0xff). + +Fixes CVE-2026-63076 + +Reviewed-by: Milan Broz +Reviewed-by: Norbert Pocs +Merge-date: Sat Aug 22 06:12:04 2026 +Signed-off-by: rpm-build +Upstream-reference: https://github.com/openssl/openssl/commit/37882aa2e0256e1072442a8f62f7db45b995c45b.patch +--- + CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_protect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_protect.c b/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_protect.c +index 0252619..bf24a8e 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_protect.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/cmp/cmp_protect.c +@@ -63,7 +63,7 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, + ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PBM_SECRET); + return NULL; + } +- if (ppval == NULL) { ++ if (pptype != V_ASN1_SEQUENCE || ppval == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CALCULATING_PROTECTION); + return NULL; + } +-- +2.45.4 + diff --git a/SPECS/edk2/CVE-2026-75803.patch b/SPECS/edk2/CVE-2026-75803.patch new file mode 100644 index 00000000000..d73bdd6b138 --- /dev/null +++ b/SPECS/edk2/CVE-2026-75803.patch @@ -0,0 +1,92 @@ +From e5a23c6fb3ec02e5358b724c8664362c8b3e60fd Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Wed, 26 Aug 2026 21:20:27 +0000 +Subject: [PATCH] Check the tag on EVP_Cipher() finalize: Poly1305 and OCB + AEADs + +Signed-off-by: rpm-build +Upstream-reference: AI Backport of https://github.com/openssl/openssl/commit/119ab9555dc62275bbd71f6f49529b1a44feba42.patch +--- + .../implementations/ciphers/cipher_aes_ocb.c | 4 +++ + .../ciphers/cipher_chacha20_poly1305.c | 27 ++++++++++++++----- + 2 files changed, 24 insertions(+), 7 deletions(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_aes_ocb.c b/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_aes_ocb.c +index 78ff071..040dcb2 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_aes_ocb.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_aes_ocb.c +@@ -502,6 +502,10 @@ static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl, + if (!ossl_prov_is_running()) + return 0; + ++ /* NULL input indicates Final, which must generate or check the tag. */ ++ if (in == NULL) ++ return aes_ocb_block_final(vctx, out, outl, outsize); ++ + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; +diff --git a/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_chacha20_poly1305.c b/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_chacha20_poly1305.c +index 0ba7483..bd7f66a 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_chacha20_poly1305.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/providers/implementations/ciphers/cipher_chacha20_poly1305.c +@@ -1,5 +1,5 @@ + /* +- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2019-2026 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -30,11 +30,11 @@ static OSSL_FUNC_cipher_get_params_fn chacha20_poly1305_get_params; + static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_poly1305_get_ctx_params; + static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_poly1305_set_ctx_params; + static OSSL_FUNC_cipher_cipher_fn chacha20_poly1305_cipher; ++static OSSL_FUNC_cipher_update_fn chacha20_poly1305_update; + static OSSL_FUNC_cipher_final_fn chacha20_poly1305_final; + static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_poly1305_gettable_ctx_params; + #define chacha20_poly1305_settable_ctx_params ossl_cipher_aead_settable_ctx_params + #define chacha20_poly1305_gettable_params ossl_cipher_generic_gettable_params +-#define chacha20_poly1305_update chacha20_poly1305_cipher + + static void *chacha20_poly1305_newctx(void *provctx) + { +@@ -276,11 +276,6 @@ static int chacha20_poly1305_cipher(void *vctx, unsigned char *out, + if (!ossl_prov_is_running()) + return 0; + +- if (inl == 0) { +- *outl = 0; +- return 1; +- } +- + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; +@@ -292,6 +287,24 @@ static int chacha20_poly1305_cipher(void *vctx, unsigned char *out, + return 1; + } + ++static int chacha20_poly1305_update(void *vctx, unsigned char *out, ++ size_t *outl, size_t outsize, ++ const unsigned char *in, size_t inl) ++{ ++ /* ++ * A zero-length update is a no-op. Only EVP_Cipher() and Final produce or ++ * check the authentication tag. ++ */ ++ if (inl == 0) { ++ if (!ossl_prov_is_running()) ++ return 0; ++ *outl = 0; ++ return 1; ++ } ++ ++ return chacha20_poly1305_cipher(vctx, out, outl, outsize, in, inl); ++} ++ + static int chacha20_poly1305_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) + { +-- +2.45.4 + diff --git a/SPECS/edk2/edk2.spec b/SPECS/edk2/edk2.spec index edf3b6443bb..5df236017e3 100644 --- a/SPECS/edk2/edk2.spec +++ b/SPECS/edk2/edk2.spec @@ -56,7 +56,7 @@ Distribution: Azure Linux Name: edk2 Version: %{GITDATE}git%{GITCOMMIT} -Release: 18%{?dist} +Release: 19%{?dist} Summary: UEFI firmware for 64-bit virtual machines License: Apache-2.0 AND (BSD-2-Clause OR GPL-2.0-or-later) AND BSD-2-Clause-Patent AND BSD-3-Clause AND BSD-4-Clause AND ISC AND MIT AND LicenseRef-Fedora-Public-Domain URL: https://www.tianocore.org @@ -160,6 +160,11 @@ Patch1022: CVE-2026-45445.patch Patch1023: CVE-2026-45447.patch Patch1024: CVE-2026-7383.patch Patch1025: CVE-2026-9076.patch +Patch1026: CVE-2026-54874.patch +Patch1027: CVE-2026-63072.patch +Patch1028: CVE-2026-63074.patch +Patch1029: CVE-2026-63076.patch +Patch1030: CVE-2026-75803.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -807,6 +812,9 @@ done %endif %changelog +* Wed Aug 26 2026 Azure Linux Security Servicing Account - 20240524git3e722403cd16-19 +- Patch for CVE-2026-75803, CVE-2026-63076, CVE-2026-63074, CVE-2026-63072, CVE-2026-54874 + * Tue Jun 16 2026 Azure Linux Security Servicing Account - 20240524git3e722403cd16-18 - Patch for CVE-2026-9076, CVE-2026-7383, CVE-2026-45447, CVE-2026-45445, CVE-2026-42767, CVE-2026-42766, CVE-2026-34182, CVE-2026-34180 From 225e70cde4e15ae49ebd445a09d31d5abec715c2 Mon Sep 17 00:00:00 2001 From: Aditya Singh Date: Thu, 27 Aug 2026 09:28:29 +0000 Subject: [PATCH 2/4] Removed patch for CVE-2026-54874 --- SPECS/edk2/CVE-2026-54874.patch | 48 ++++++++++++++++++++++++--------- SPECS/edk2/edk2.spec | 11 ++++---- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/SPECS/edk2/CVE-2026-54874.patch b/SPECS/edk2/CVE-2026-54874.patch index 19a5e923ba9..f4e9d19a9cd 100644 --- a/SPECS/edk2/CVE-2026-54874.patch +++ b/SPECS/edk2/CVE-2026-54874.patch @@ -4,16 +4,18 @@ Date: Wed, 26 Aug 2026 21:22:16 +0000 Subject: [PATCH] Backport DTLS buffered record memory and queue limit fixes Signed-off-by: rpm-build -Upstream-reference: AI Backport of https://github.com/openssl/openssl/commit/1ca5a124b48f1ffe6980ad33724b452fbd62da1e.patch https://github.com/openssl/openssl/commit/0321286f0cc7f2c5eef419cbf8b130a95af072e7.patch +Upstream-reference: +AI Backport of https://github.com/openssl/openssl/commit/1ca5a124b48f1ffe6980ad33724b452fbd62da1e.patch +AI Backport of https://github.com/openssl/openssl/commit/0321286f0cc7f2c5eef419cbf8b130a95af072e7.patch --- - .../openssl/ssl/record/rec_layer_d1.c | 121 +++++++++++++----- + .../openssl/ssl/record/rec_layer_d1.c | 122 +++++++++++++----- .../OpensslLib/openssl/ssl/record/record.h | 1 - .../openssl/ssl/record/record_local.h | 11 +- - .../openssl/ssl/record/ssl3_record.c | 7 +- - 4 files changed, 104 insertions(+), 36 deletions(-) + .../openssl/ssl/record/ssl3_record.c | 14 +- + 4 files changed, 110 insertions(+), 38 deletions(-) diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c -index 7f3d1a7..fffb5ee 100644 +index 7f3d1a7..6c6915e 100644 --- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c +++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c @@ -70,7 +70,7 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) @@ -212,17 +214,18 @@ index 7f3d1a7..fffb5ee 100644 bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); if (bitmap == NULL) { /* -@@ -294,7 +348,8 @@ int dtls1_process_buffered_records(SSL *s) +@@ -294,7 +348,9 @@ int dtls1_process_buffered_records(SSL *s) } if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), - SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) { + SSL3_RECORD_get_seq_num(s->rlayer.rrec), -+ DTLS1_MAX_BUFFERED_RECORDS) < 0) { ++ DTLS1_MAX_BUFFERED_RECORDS) ++ < 0) { /* SSLfatal() already called */ return 0; } -@@ -401,6 +456,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, +@@ -401,6 +457,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, } #endif @@ -230,13 +233,13 @@ index 7f3d1a7..fffb5ee 100644 dtls1_copy_record(s, item); OPENSSL_free(item->data); -@@ -454,7 +510,8 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, +@@ -454,7 +511,8 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, * data for later processing rather than dropping the connection. */ if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), - SSL3_RECORD_get_seq_num(rr)) < 0) { -+ SSL3_RECORD_get_seq_num(rr), -+ DTLS1_MAX_BUFFERED_RECORDS) < 0) { ++ SSL3_RECORD_get_seq_num(rr), DTLS1_MAX_BUFFERED_RECORDS) ++ < 0) { /* SSLfatal() already called */ return -1; } @@ -277,7 +280,7 @@ index 0a929c6..08b44aa 100644 /* Functions provided by the DTLS1_BITMAP component */ diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c -index dcaaeef..db5a8bf 100644 +index dcaaeef..75286e8 100644 --- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c +++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c @@ -1664,8 +1664,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) @@ -294,6 +297,27 @@ index dcaaeef..db5a8bf 100644 /* Mark receipt of record. */ dtls1_record_bitmap_update(s, bitmap); +@@ -1871,7 +1874,8 @@ int dtls1_get_record(SSL *s) + if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) { + if (dtls1_buffer_record (s, + &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)), +- rr->seq_num) < 0) { ++ rr->seq_num, DTLS1_MAX_UNPROCESSED_RECORDS) ++ < 0) { + /* SSLfatal() already called */ + return -1; + } +@@ -1914,7 +1918,9 @@ int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq, size_t off + rr->data = s->rlayer.packet + DTLS1_RT_HEADER_LENGTH; + + if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), +- SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) { ++ SSL3_RECORD_get_seq_num(s->rlayer.rrec), ++ DTLS1_MAX_BUFFERED_RECORDS) ++ <= 0) { + /* SSLfatal() already called */ + return 0; + } -- 2.45.4 diff --git a/SPECS/edk2/edk2.spec b/SPECS/edk2/edk2.spec index 5df236017e3..4374d399984 100644 --- a/SPECS/edk2/edk2.spec +++ b/SPECS/edk2/edk2.spec @@ -160,11 +160,10 @@ Patch1022: CVE-2026-45445.patch Patch1023: CVE-2026-45447.patch Patch1024: CVE-2026-7383.patch Patch1025: CVE-2026-9076.patch -Patch1026: CVE-2026-54874.patch -Patch1027: CVE-2026-63072.patch -Patch1028: CVE-2026-63074.patch -Patch1029: CVE-2026-63076.patch -Patch1030: CVE-2026-75803.patch +Patch1026: CVE-2026-63072.patch +Patch1027: CVE-2026-63074.patch +Patch1028: CVE-2026-63076.patch +Patch1029: CVE-2026-75803.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -813,7 +812,7 @@ done %changelog * Wed Aug 26 2026 Azure Linux Security Servicing Account - 20240524git3e722403cd16-19 -- Patch for CVE-2026-75803, CVE-2026-63076, CVE-2026-63074, CVE-2026-63072, CVE-2026-54874 +- Patch for CVE-2026-75803, CVE-2026-63076, CVE-2026-63074, CVE-2026-63072 * Tue Jun 16 2026 Azure Linux Security Servicing Account - 20240524git3e722403cd16-18 - Patch for CVE-2026-9076, CVE-2026-7383, CVE-2026-45447, CVE-2026-45445, CVE-2026-42767, CVE-2026-42766, CVE-2026-34182, CVE-2026-34180 From 707effa8e1f4cfab3cdf4dc312c7ff87de067c02 Mon Sep 17 00:00:00 2001 From: Aditya Singh Date: Thu, 27 Aug 2026 09:30:15 +0000 Subject: [PATCH 3/4] Bump up edk2-hvloader-signed release no. for consistency with edk2 spec --- SPECS-SIGNED/edk2-hvloader-signed/edk2-hvloader-signed.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SPECS-SIGNED/edk2-hvloader-signed/edk2-hvloader-signed.spec b/SPECS-SIGNED/edk2-hvloader-signed/edk2-hvloader-signed.spec index 05bdd913cee..26eccd6464a 100644 --- a/SPECS-SIGNED/edk2-hvloader-signed/edk2-hvloader-signed.spec +++ b/SPECS-SIGNED/edk2-hvloader-signed/edk2-hvloader-signed.spec @@ -11,7 +11,7 @@ Summary: Signed HvLoader.efi for %{buildarch} systems Name: edk2-hvloader-signed-%{buildarch} Version: %{GITDATE}git%{GITCOMMIT} -Release: 18%{?dist} +Release: 19%{?dist} License: MIT Vendor: Microsoft Corporation Distribution: Azure Linux @@ -74,6 +74,9 @@ popd /boot/efi/HvLoader.efi %changelog +* Thu Aug 27 2026 Azure Linux Security Servicing Account - 20240524git3e722403cd16-19 +- Bump release for consistency with edk2 spec. + * Tue Jun 16 2026 Azure Linux Security Servicing Account - 20240524git3e722403cd16-18 - Bump release for consistency with edk2 spec. From e78d6b7437a9bfde1ccce7fb4d87b8c67769431a Mon Sep 17 00:00:00 2001 From: Aditya Singh Date: Thu, 27 Aug 2026 09:40:12 +0000 Subject: [PATCH 4/4] Removed CVE-2026-54874 patch file --- SPECS/edk2/CVE-2026-54874.patch | 323 -------------------------------- 1 file changed, 323 deletions(-) delete mode 100644 SPECS/edk2/CVE-2026-54874.patch diff --git a/SPECS/edk2/CVE-2026-54874.patch b/SPECS/edk2/CVE-2026-54874.patch deleted file mode 100644 index f4e9d19a9cd..00000000000 --- a/SPECS/edk2/CVE-2026-54874.patch +++ /dev/null @@ -1,323 +0,0 @@ -From 7a057b59814c1c6699dd2ee3e6b59abeb3b21f88 Mon Sep 17 00:00:00 2001 -From: AllSpark -Date: Wed, 26 Aug 2026 21:22:16 +0000 -Subject: [PATCH] Backport DTLS buffered record memory and queue limit fixes - -Signed-off-by: rpm-build -Upstream-reference: -AI Backport of https://github.com/openssl/openssl/commit/1ca5a124b48f1ffe6980ad33724b452fbd62da1e.patch -AI Backport of https://github.com/openssl/openssl/commit/0321286f0cc7f2c5eef419cbf8b130a95af072e7.patch ---- - .../openssl/ssl/record/rec_layer_d1.c | 122 +++++++++++++----- - .../OpensslLib/openssl/ssl/record/record.h | 1 - - .../openssl/ssl/record/record_local.h | 11 +- - .../openssl/ssl/record/ssl3_record.c | 14 +- - 4 files changed, 110 insertions(+), 38 deletions(-) - -diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c -index 7f3d1a7..6c6915e 100644 ---- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c -+++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/rec_layer_d1.c -@@ -70,7 +70,7 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) - - while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) { - rdata = (DTLS1_RECORD_DATA *)item->data; -- OPENSSL_free(rdata->rbuf.buf); -+ OPENSSL_free(rdata->packet); - OPENSSL_free(item->data); - pitem_free(item); - } -@@ -78,8 +78,8 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) - while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) { - rdata = (DTLS1_RECORD_DATA *)item->data; - if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT) -- OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len); -- OPENSSL_free(rdata->rbuf.buf); -+ OPENSSL_cleanse(rdata->packet, rdata->packet_length); -+ OPENSSL_free(rdata->packet); - OPENSSL_free(item->data); - pitem_free(item); - } -@@ -87,8 +87,8 @@ void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl) - while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) { - rdata = (DTLS1_RECORD_DATA *)item->data; - if (rl->s->options & SSL_OP_CLEANSE_PLAINTEXT) -- OPENSSL_cleanse(rdata->rbuf.buf, rdata->rbuf.len); -- OPENSSL_free(rdata->rbuf.buf); -+ OPENSSL_cleanse(rdata->packet, rdata->packet_length); -+ OPENSSL_free(rdata->packet); - OPENSSL_free(item->data); - pitem_free(item); - } -@@ -130,26 +130,60 @@ static int dtls1_copy_record(SSL *s, pitem *item) - - rdata = (DTLS1_RECORD_DATA *)item->data; - -- SSL3_BUFFER_release(&s->rlayer.rbuf); -+ /* -+ * The record was read into a read buffer at least this size, so it must fit -+ * - see the length checks in ssl3_read_n(). Verify it rather than risk -+ * overrunning the buffer if that ever ceases to hold. -+ */ -+ if (!ossl_assert(rdata->packet_length <= s->rlayer.rbuf.len)) { -+ OPENSSL_free(rdata->packet); -+ return 0; -+ } - -- s->rlayer.packet = rdata->packet; -+ /* -+ * rdata->packet is a standalone copy of this record's on-wire bytes (see -+ * dtls1_buffer_record()). Copy it into the live read buffer so that -+ * s->rlayer.packet continues to point inside s->rlayer.rbuf.buf, as it -+ * does for every other record, then free our standalone copy. -+ */ -+ memcpy(s->rlayer.rbuf.buf, rdata->packet, rdata->packet_length); -+ s->rlayer.rbuf.offset = 0; -+ s->rlayer.rbuf.left = 0; -+ s->rlayer.packet = s->rlayer.rbuf.buf; - s->rlayer.packet_length = rdata->packet_length; -- memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER)); - memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD)); - -+ /* -+ * dtls1_buffer_record() rebased rrec.data/input onto rdata->packet if they -+ * pointed into this record's own bytes, so translate them again onto the -+ * record's new location in the read buffer. Anything still pointing -+ * outside rdata->packet is either a separate allocation (rr->comp) or a -+ * leftover from a previously processed record that will be overwritten -+ * before use, so leave it alone. -+ */ -+ if (rdata->rrec.data >= rdata->packet -+ && rdata->rrec.data < rdata->packet + rdata->packet_length) -+ s->rlayer.rrec[0].data = s->rlayer.packet + (rdata->rrec.data - rdata->packet); -+ if (rdata->rrec.input >= rdata->packet -+ && rdata->rrec.input < rdata->packet + rdata->packet_length) -+ s->rlayer.rrec[0].input = s->rlayer.packet + (rdata->rrec.input - rdata->packet); -+ -+ OPENSSL_free(rdata->packet); -+ - /* Set proper sequence number for mac calculation */ -- memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6); -+ memcpy(&(s->rlayer.read_sequence[2]), &(s->rlayer.packet[5]), 6); - - return 1; - } - --int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) -+int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority, -+ size_t limit) - { - DTLS1_RECORD_DATA *rdata; - pitem *item; - - /* Limit the size of the queue to prevent DOS attacks */ -- if (pqueue_size(queue->q) >= 100) -+ if (pqueue_size(queue->q) >= limit) - return 0; - - rdata = OPENSSL_malloc(sizeof(*rdata)); -@@ -161,11 +195,37 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) - return -1; - } - -- rdata->packet = s->rlayer.packet; -+ /* -+ * Take a copy of just this record's own on-wire bytes - the header plus the -+ * record body, which for an already-processed record holds the plaintext -+ * decrypted in place - rather than the whole (much larger) read buffer. The -+ * live s->rlayer.rbuf is left untouched and continues to be used for -+ * subsequent reads. -+ */ - rdata->packet_length = s->rlayer.packet_length; -- memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER)); -+ rdata->packet = OPENSSL_memdup(s->rlayer.packet, s->rlayer.packet_length); -+ if (rdata->packet == NULL) { -+ OPENSSL_free(rdata); -+ pitem_free(item); -+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); -+ return -1; -+ } - memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD)); - -+ /* -+ * The copied rrec.data/input still point into the live read buffer. Rebase -+ * any that point within this record's own bytes onto our standalone copy, -+ * so that dtls1_copy_record() can translate them again on retrieval. -+ * Pointers elsewhere (e.g. into rr->comp, or left over from a previously -+ * processed record) are not ours to move and are left alone. -+ */ -+ if (rdata->rrec.data >= s->rlayer.packet -+ && rdata->rrec.data < s->rlayer.packet + s->rlayer.packet_length) -+ rdata->rrec.data = rdata->packet + (rdata->rrec.data - s->rlayer.packet); -+ if (rdata->rrec.input >= s->rlayer.packet -+ && rdata->rrec.input < s->rlayer.packet + s->rlayer.packet_length) -+ rdata->rrec.input = rdata->packet + (rdata->rrec.input - s->rlayer.packet); -+ - item->data = rdata; - - #ifndef OPENSSL_NO_SCTP -@@ -178,22 +238,9 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) - } - #endif - -- s->rlayer.packet = NULL; -- s->rlayer.packet_length = 0; -- memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf)); -- memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec)); -- -- if (!ssl3_setup_buffers(s)) { -- /* SSLfatal() already called */ -- OPENSSL_free(rdata->rbuf.buf); -- OPENSSL_free(rdata); -- pitem_free(item); -- return -1; -- } -- - if (pqueue_insert(queue->q, item) == NULL) { - /* Must be a duplicate so ignore it */ -- OPENSSL_free(rdata->rbuf.buf); -+ OPENSSL_free(rdata->packet); - OPENSSL_free(rdata); - pitem_free(item); - } -@@ -204,15 +251,16 @@ int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) - int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) - { - pitem *item; -+ int ret; - - item = pqueue_pop(queue->q); - if (item) { -- dtls1_copy_record(s, item); -+ ret = dtls1_copy_record(s, item); - - OPENSSL_free(item->data); - pitem_free(item); - -- return 1; -+ return ret; - } - - return 0; -@@ -257,7 +305,13 @@ int dtls1_process_buffered_records(SSL *s) - - /* Process all the records. */ - while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) { -- dtls1_get_unprocessed_record(s); -+ if (!dtls1_get_unprocessed_record(s)) { -+ /* -+ * Should not happen. The record has been dropped, so move on -+ * to the next one. -+ */ -+ continue; -+ } - bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); - if (bitmap == NULL) { - /* -@@ -294,7 +348,9 @@ int dtls1_process_buffered_records(SSL *s) - } - - if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), -- SSL3_RECORD_get_seq_num(s->rlayer.rrec)) < 0) { -+ SSL3_RECORD_get_seq_num(s->rlayer.rrec), -+ DTLS1_MAX_BUFFERED_RECORDS) -+ < 0) { - /* SSLfatal() already called */ - return 0; - } -@@ -401,6 +457,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, - } - #endif - -+ /* On failure the record is simply dropped */ - dtls1_copy_record(s, item); - - OPENSSL_free(item->data); -@@ -454,7 +511,8 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, - * data for later processing rather than dropping the connection. - */ - if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data), -- SSL3_RECORD_get_seq_num(rr)) < 0) { -+ SSL3_RECORD_get_seq_num(rr), DTLS1_MAX_BUFFERED_RECORDS) -+ < 0) { - /* SSLfatal() already called */ - return -1; - } -diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h -index b60f71c..22b683a 100644 ---- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h -+++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record.h -@@ -85,7 +85,6 @@ typedef struct record_pqueue_st { - typedef struct dtls1_record_data_st { - unsigned char *packet; - size_t packet_length; -- SSL3_BUFFER rbuf; - SSL3_RECORD rrec; - #ifndef OPENSSL_NO_SCTP - struct bio_dgram_sctp_rcvinfo recordinfo; -diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h -index 0a929c6..08b44aa 100644 ---- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h -+++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/record_local.h -@@ -41,9 +41,18 @@ __owur int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, - - DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, - unsigned int *is_next_epoch); -+/* -+ * Limits on the number of records dtls1_buffer_record() will hold, to prevent -+ * DOS attacks. Records arriving early for the next epoch get a tighter limit: -+ * a legitimate peer only ever has a small burst of those in flight. -+ */ -+#define DTLS1_MAX_UNPROCESSED_RECORDS 16 -+#define DTLS1_MAX_BUFFERED_RECORDS 100 -+ - int dtls1_process_buffered_records(SSL *s); - int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue); --int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority); -+int dtls1_buffer_record(SSL *s, record_pqueue *q, unsigned char *priority, -+ size_t limit); - void ssl3_record_sequence_update(unsigned char *seq); - - /* Functions provided by the DTLS1_BITMAP component */ -diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c -index dcaaeef..75286e8 100644 ---- a/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c -+++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/record/ssl3_record.c -@@ -1664,8 +1664,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) - * after use :-). - */ - -- /* we have pulled in a full packet so zero things */ -- RECORD_LAYER_reset_packet_length(&s->rlayer); -+ /* -+ * Leave s->rlayer.packet_length alone: ssl3_read_n() starts each new record -+ * by resetting it, and it must still describe this record's on-wire bytes -+ * for dtls1_buffer_record() should this record end up being buffered. -+ */ - - /* Mark receipt of record. */ - dtls1_record_bitmap_update(s, bitmap); -@@ -1871,7 +1874,8 @@ int dtls1_get_record(SSL *s) - if ((SSL_in_init(s) || ossl_statem_get_in_handshake(s))) { - if (dtls1_buffer_record (s, - &(DTLS_RECORD_LAYER_get_unprocessed_rcds(&s->rlayer)), -- rr->seq_num) < 0) { -+ rr->seq_num, DTLS1_MAX_UNPROCESSED_RECORDS) -+ < 0) { - /* SSLfatal() already called */ - return -1; - } -@@ -1914,7 +1918,9 @@ int dtls_buffer_listen_record(SSL *s, size_t len, unsigned char *seq, size_t off - rr->data = s->rlayer.packet + DTLS1_RT_HEADER_LENGTH; - - if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds), -- SSL3_RECORD_get_seq_num(s->rlayer.rrec)) <= 0) { -+ SSL3_RECORD_get_seq_num(s->rlayer.rrec), -+ DTLS1_MAX_BUFFERED_RECORDS) -+ <= 0) { - /* SSLfatal() already called */ - return 0; - } --- -2.45.4 -