Limit PEM data to 1 GiB. There should be no single PEM block of this size in existence. This limit however guards against possible integer overflows in other moduels. A PEM block larger than this will be skipped by libpki (which has no way to report errors to begin with), and return ERR_R_OVERFLOW from libcrypto. Update-Note: if you hit this, try reducing the size of your PEM blocks. Change-Id: I99962d363b54f40e963793f15f0dcda56a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/94967 Reviewed-by: Xiangfei Ding <xfding@google.com> Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> Commit-Queue: Rudolf Polzer <rpolzer@google.com>
diff --git a/crypto/pem/pem_lib.cc b/crypto/pem/pem_lib.cc index bbe9abd..3fb8515 100644 --- a/crypto/pem/pem_lib.cc +++ b/crypto/pem/pem_lib.cc
@@ -628,6 +628,14 @@ return false; } size_t new_len = out_len + i; + if (new_len > INT_MAX / 2) { + // Arbitrarily limit PEM data to INT_MAX / 2 bytes, which "ought to be + // enough for anyone". Hardens against possible integer overflows + // downstream. + OPENSSL_PUT_ERROR(PEM, ERR_R_OVERFLOW); + failed = true; + return false; + } if (!BUF_MEM_grow(out, new_len + 1)) { OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); failed = true;
diff --git a/include/openssl/pem.h b/include/openssl/pem.h index 5a4c2ab..0e49162 100644 --- a/include/openssl/pem.h +++ b/include/openssl/pem.h
@@ -38,6 +38,9 @@ // This library contains functions for reading and writing data encoded in PEM // format. This format originated in Privacy-Enhanced Mail (RFC 1421). // +// As an exception to RFC 1421, generally PEM data is limited to 1 GiB by this +// library. This limit should not affect anyone in practice. +// // TODO(crbug.com/42290574): Finish documenting this header.
diff --git a/pki/pem.cc b/pki/pem.cc index 54a7595..c5f84bc 100644 --- a/pki/pem.cc +++ b/pki/pem.cc
@@ -16,6 +16,7 @@ #include "string_util.h" #include <array> +#include <limits> #include <string_view> namespace { @@ -81,6 +82,14 @@ pos_ = footer_pos + it->footer.size(); block_type_ = it->type; + // Arbitrarily limit PEM data to INT_MAX / 2 bytes, which "ought to be + // enough for anyone". Hardens against possible integer overflows + // downstream. + if (footer_pos - data_begin > static_cast<std::string_view::size_type>( + std::numeric_limits<int>::max() / 2)) { + return false; + } + // Remove whitespace from the base64 data. std::string_view encoded = str_.substr(data_begin, footer_pos - data_begin);