Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/api_ref/pkcs12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ PKCS12
is malformed, or ``Invalid_Authentication_Tag`` if MAC verification
fails.

Every private key found in the file is verified for internal
consistency with ``Private_Key::check_key`` (non-strong variant) and
the file is rejected with ``Decoding_Error`` if a key fails. The MAC is
optional in PKCS#12 and the key encryption is not authenticated, so
without this check a modification of a MAC-less file could yield a key
whose private scalar no longer matches its public point.

Accessors
^^^^^^^^^

Expand Down
60 changes: 32 additions & 28 deletions news.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Release Notes
========================================
=============

Version 3.14.0, Not Yet Released
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* Add new type ``PK_Signature_Options`` which allows precisely controlling how
signatures are created and verified. (GH #5849)
Expand All @@ -11,6 +11,10 @@ Version 3.14.0, Not Yet Released
``RandomNumberGenerator::randomize_with_ts_input`` passed only the low 32 bits
of the timestamp, and never the process id, as additional input. (GH #5924)

* The PKCS#12 parser now verifies each private key with ``check_key`` and
rejects keys whose private and public components are inconsistent, as can
result from tampering with a PKCS#12 file that has no MAC.

* Password hash tuning (``PasswordHashFamily::tune_params``) now measures the
CPU time of the calling thread where available (falling back to a monotonic
clock), and uses the fastest of several samples rather than the mean. This
Expand Down Expand Up @@ -61,7 +65,7 @@ Version 3.14.0, Not Yet Released
(GH #5541)

Version 3.13.0, 2026-08-13
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^

* Fix a blind SSRF during OCSP request processing. A malicious OCSP responder or
network attacker could cause the application to perform a blind GET to an
Expand Down Expand Up @@ -231,7 +235,7 @@ Version 3.13.0, 2026-08-13
* Upgrade to TLS-Anvil 1.5 (GH #5630)

Version 3.12.0, 2026-05-06
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^

* CVE-2026-44378: Resolve a CPU based denial of service when decoding
BER encoded data.
Expand Down Expand Up @@ -307,7 +311,7 @@ Version 3.12.0, 2026-05-06
headers without the ``botan-3/`` subdirectory (GH #5528)

Version 3.11.1, 2026-03-31
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^

* CVE-2026-34580: Resolve certificate verification bypass bug introduced in 3.11.0 (GH #5500)

Expand Down Expand Up @@ -353,7 +357,7 @@ Version 3.11.1, 2026-03-31
* Enable explicit_bzero, getentropy, getrandom on Hurd (GH #5488)

Version 3.11.0, 2026-03-15
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^

* CVE-2026-32877: Fix a heap over-read during SM2 decryption (GH #5450)

Expand Down Expand Up @@ -462,7 +466,7 @@ Version 3.11.0, 2026-03-15
* Fix various clang-tidy and cppcheck warnings (GH #5172 #5207 #5204 #5205)

Version 3.10.0, 2025-11-06
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^

* Add support for Ascon AEAD, hash and XOF from NIST SP 800-232 (GH #5061 #5076 #5097)

Expand Down Expand Up @@ -517,7 +521,7 @@ Version 3.10.0, 2025-11-06
* Add a ``.devcontainer`` setup (GH #5094)

Version 3.9.0, 2025-08-05
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Add SHA-1 implementation using AVX2/BMI2 (GH #4852)

Expand Down Expand Up @@ -578,7 +582,7 @@ Version 3.9.0, 2025-08-05
* CI improvements (GH #4920 #4294 #4926 #4929)

Version 3.8.1, 2025-05-07
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Fix a bug that prevented building using the ``fips140`` or ``modern`` module
policies. (GH #4854 #4856)
Expand All @@ -587,7 +591,7 @@ Version 3.8.1, 2025-05-07
(GH #4855 #4857)

Version 3.8.0, 2025-05-06
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Discussion has started regarding plans for Botan4, current ETA 2027. Check the
tracking ticket in https://github.com/randombit/botan/issues/4666 for the
Expand Down Expand Up @@ -710,13 +714,13 @@ Version 3.8.0, 2025-05-06
* Update GHA CodeQL actions (GH #4644)

Version 3.7.1, 2025-02-05
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Revert a change that prevented ``build.h`` from being usable from
C applications. (GH #4636 #4637)

Version 3.7.0, 2025-02-04
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Add post-quantum scheme Classic McEliece (GH #3883 #4448 #4458 #4508 #4605)

Expand Down Expand Up @@ -823,7 +827,7 @@ Version 3.7.0, 2025-02-04
* Address some new warnings from Clang 19 (GH #4544 #4545 #4548)

Version 3.6.1, 2024-10-26
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Notice: Botan 3.7.0 will remove support for the currently supported
experimental Kyber r3 TLS ciphersuites, leaving only the standardized
Expand All @@ -842,7 +846,7 @@ Version 3.6.1, 2024-10-26
(GH #4381)

Version 3.6.0, 2024-10-21
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Fully integrate and further optimize the new ECC library first introduced in
3.5.0. For common curves, operations are 2 to 3 times faster. This also
Expand Down Expand Up @@ -925,7 +929,7 @@ Version 3.6.0, 2024-10-21
* Add compile time option to disable all use of inline assembly (GH #4273 #4265)

Version 3.5.0, 2024-07-08
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* CVE-2024-34702: Fix a DoS caused by excessive name constraints. (GH #4186)

Expand Down Expand Up @@ -1049,7 +1053,7 @@ Version 3.5.0, 2024-07-08
* Fix Roughtime to not reference a deprecated Cloudflare server. (GH #4002 #3937)

Version 3.4.0, 2024-04-08
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Add Ed448 signatures and X448 key exchange (GH #3933)

Expand Down Expand Up @@ -1096,7 +1100,7 @@ Version 3.4.0, 2024-04-08
(GH #3935 #3910)

Version 3.3.0, 2024-02-20
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* CVE-2024-34703 Fix a potential denial of service caused by accepting
arbitrary length primes as potential elliptic curve parameters in
Expand Down Expand Up @@ -1228,7 +1232,7 @@ Version 3.3.0, 2024-02-20
(GH #3783 #3833 #3888)

Version 3.2.0, 2023-10-09
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Add support for (experimental!) post-quantum secure key exchange
in TLS 1.3 (GH #3609 #3732 #3733 #3739)
Expand Down Expand Up @@ -1324,14 +1328,14 @@ Version 3.2.0, 2023-10-09
due to spurious warnings in that version. (GH #3711 #3709)

Version 3.1.1, 2023-07-13
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Fix two tests which were insufficiently serialized. This would
cause sporadic test failures, particularly on machines with
many cores. (GH #3625 #3623)

Version 3.1.0, 2023-07-11
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Add SPHINCS+ post quantum hash based signature scheme (GH #3564 #3549)

Expand Down Expand Up @@ -1404,13 +1408,13 @@ Version 3.1.0, 2023-07-11
* Remove the (undocumented, unsupported) support for CMake (GH #3501)

Version 3.0.0, 2023-04-11
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^

* Botan is now a C++20 codebase; compiler requirements have been
increased to GCC 11, Clang 14, or MSVC 2022. (GH #2455 #3086)

Breaking Changes
----------------------------------------
----------------

* Remove many deprecated headers. In particular all algorithm specific
headers (such as ``aes.h``) are no longer available; instead objects
Expand Down Expand Up @@ -1452,7 +1456,7 @@ Breaking Changes
(GH #3186)

TLS Changes
----------------------------------------
-----------

* Added support for TLS v1.3

Expand All @@ -1465,7 +1469,7 @@ TLS Changes
DHE_PSK suites (GH #2512), CECPQ1 ciphersuites (GH #3094)

New Cryptographic Algorithms
----------------------------------------
----------------------------

* Add support for Kyber post-quantum KEM (GH #2872 #2500)

Expand All @@ -1477,7 +1481,7 @@ New Cryptographic Algorithms
* Add support for keyed BLAKE2b (GH #2524)

New APIs
----------------------------------------
--------

* Add new interface ``T::new_object`` which supplants ``T::clone``. The
difference is that ``new_object`` returns a ``unique_ptr<T>`` instead of a raw
Expand All @@ -1504,7 +1508,7 @@ New APIs
* Many new functions in the C89 interface; see the API reference for more details.

Implementation Improvements
----------------------------------------
---------------------------

* Add AVX2 implementation of Argon2 (GH #3205)

Expand All @@ -1527,7 +1531,7 @@ Implementation Improvements
are always chosen to be 8-bit aligned. (GH #2545)

Other Improvements
----------------------------------------
------------------

* Changes to ``TLS::Stream`` to make it compatible with generic completion tokens.
(GH #2667 #2648)
Expand All @@ -1539,7 +1543,7 @@ Other Improvements
provided for each message. (GH #2908)

Older Versions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^

* The release notes for versions 2.0.0 through 2.19.5 can be found in
``doc/news_2x.rst``
Expand Down
39 changes: 37 additions & 2 deletions src/lib/pkcs12/pkcs12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,41 @@ void parse_bag_attributes(BER_Decoder& decoder, std::string& friendly_name, std:
attrs.end_cons();
}

/*
* Load a PKCS#8 private key from a KeyBag or a decrypted PKCS8ShroudedKeyBag
* and verify that it is internally consistent.
*
* The PKCS#12 MAC is optional, and the PBE schemes provide no authentication
* of their own. In a file without a MAC (or with a MAC computed under a
* password known to the attacker) the CBC encrypted key is malleable: a
* modification that lands inside the private scalar of an EC key produces a
* key that still decodes, still carries the original public point, and still
* matches the end-entity certificate, but signs with a different scalar.
* Private_Key::check_key (non-strong) detects this class of corruption for
* all key types that can verify the private/public relation; for EC keys it
* costs one fixed-base multiplication.
*
* No RNG is available in this context. The non-strong checks of the common
* key types do not require randomness (primality tests fall back to fixed
* bases when the RNG is unseeded). A key type whose check demands randomness
* reports PRNG_Unseeded and is accepted without the check.
*/
std::shared_ptr<Private_Key> load_checked_private_key(DataSource& src) {
std::shared_ptr<Private_Key> key(PKCS8::load_key(src));

Null_RNG null_rng;
try {
if(!key->check_key(null_rng, false)) {
throw Decoding_Error("PKCS#12: private key failed consistency check");
}
} catch(const PRNG_Unseeded&) {
// check_key for this algorithm requires randomness which we cannot
// supply here; the key is accepted as decoded.
}

return key;
}

// Helper bag carrying a parsed private key with its attributes.
struct ParsedKey {
std::shared_ptr<Private_Key> key;
Expand Down Expand Up @@ -249,14 +284,14 @@ void parse_safe_contents(BER_Decoder& decoder,

auto decrypted = pkcs12_pbe_decrypt(encrypted_key, password, pbe_algo, openssl_empty_pwd_compat);
DataSource_Memory src(decrypted);
key_entries.push_back({std::shared_ptr<Private_Key>(PKCS8::load_key(src)), {}, {}});
key_entries.push_back({load_checked_private_key(src), {}, {}});
pushed_key = true;
} else if(bag_type == key_bag_oid) {
secure_vector<uint8_t> key_data;
bag_value.raw_bytes(key_data);
bag_value.verify_end();
DataSource_Memory src(key_data);
key_entries.push_back({std::shared_ptr<Private_Key>(PKCS8::load_key(src)), {}, {}});
key_entries.push_back({load_checked_private_key(src), {}, {}});
pushed_key = true;
} else if(bag_type == safe_contents_bag_oid) {
BER_Decoder nested_sc = bag_value.start_sequence();
Expand Down
5 changes: 4 additions & 1 deletion src/lib/pkcs12/pkcs12.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ class BOTAN_PUBLIC_API(3, 13) PKCS12 final {
*
* @param data the PFX file contents
* @param password the password to decrypt the file
* @throws Decoding_Error if parsing fails
* @throws Decoding_Error if parsing fails, or if a private key in the
* file fails its consistency check (Private_Key::check_key);
* such keys can result from tampering with a file that carries
* no MAC, since the key encryption itself is unauthenticated.
* @throws Invalid_Authentication_Tag if MAC verification fails
*/
PKCS12(std::span<const uint8_t> data, std::string_view password);
Expand Down
Binary file added src/tests/data/pkcs12/key_ec_3des_nomac.pfx
Binary file not shown.
Binary file added src/tests/data/pkcs12/key_inconsistent_ec.der
Binary file not shown.
Binary file added src/tests/data/pkcs12/key_inconsistent_ec_3des.pfx
Binary file not shown.
Binary file added src/tests/data/pkcs12/key_inconsistent_ec_keybag.pfx
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions src/tests/data/pkcs12/key_inconsistent_ec_pubkey.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKOQxpLN6o+t1OTyPTcLLTHTNP0Oy
WzDHtqiXupH4JPNxI7yKcqPkxknLqbOBR9C2Ryfh4q08gobaGIWvjqQa0w==
-----END PUBLIC KEY-----
Binary file added src/tests/data/pkcs12/key_inconsistent_rsa.der
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added src/tests/data/pkcs12/key_mlkem512_3des.pfx
Binary file not shown.
Binary file added src/tests/data/pkcs12/key_mlkem512_pbes2.pfx
Binary file not shown.
Loading
Loading