Skip to content

[DO NOT MERGE] PQC TESTING BRANCH - #274

Draft
Doug Flick (Flickdm) wants to merge 42 commits into
mainfrom
feat/v2-onecrypto
Draft

[DO NOT MERGE] PQC TESTING BRANCH#274
Doug Flick (Flickdm) wants to merge 42 commits into
mainfrom
feat/v2-onecrypto

Conversation

@Flickdm

Copy link
Copy Markdown
Member

Description

<Include a description of the change and why this change was made.>

For details on how to complete these options and their meaning refer to CONTRIBUTING.md.

  • Impacts functionality?
  • Impacts security?
  • Breaking change?
  • Includes tests?
  • Includes documentation?

How This Was Tested

<Describe the test(s) that were run to verify the changes.>

Integration Instructions

<Describe how these changes should be integrated. Use N/A if nothing is required.>

@Flickdm Doug Flick (Flickdm) changed the title [DO NO MERGE] PQC TESTING BRANCH [DO NOT MERGE] PQC TESTING BRANCH Aug 7, 2026
@mu-automation mu-automation Bot added language:python Pull requests that update Python code impact:non-functional Does not have a functional impact labels Aug 7, 2026
Update the openssl submodule pointer to the openssl-4.0.0 tag.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Fix X64-MSFT assembly filename conversion to handle both .S and
.s extensions.

Disable SM3 assembly sources in the asm filter to work around
build issues with OpenSSL 4.0.0. SM3 support will need
to be re-evaluated in a future update.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Regenerate all intermediate files in OpensslGen including headers,
architecture-specific assembly files, DER encoding sources, and
the new .inc files generated from .inc.in templates introduced
in OpenSSL 4.0.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Update the autogenerated source file lists in all OpensslLib INF
files to reflect the new and changed source files in OpenSSL
4.0.0.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add Library/OpensslLib/OpensslGen as a package include path in
OpensslPkg.dec. OpenSSL 4.0 introduces .inc files generated from
.inc.in templates that are included by provider source files
using paths relative to the build root. The OpensslGen directory
must be in the include search path to resolve these references.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add va_copy, vsnprintf, INT64_C, UINT64_C, INT32_C, and UINT32_C
macros to CrtLibSupport.h. These are required by OpenSSL 4.0
source files that were not needed in previous versions.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Replace the vsnprintf and sprintf macros in CrtLibSupport.h with
proper function implementations that translate standard C format
specifiers to EDK2 BasePrintLib equivalents. OpenSSL 4.0 error
reporting calls BIO_vsnprintf with C %s (ASCII string), but EDK2
BasePrintLib treats %s as Unicode, causing a segfault in the
host unit tests. The new TranslateFormatSpecifiers helper converts
C %s to EDK2 %a before calling AsciiVSPrint.

(OpenSSL PR #28305) removed its self-contained BIO_snprintf formatter
(_dopr) and now routes BIO_(v)snprintf through the platform vsnprintf.
That old formatter substituted "<NULL>" for a NULL %s argument; OpenSSL
error paths still pass NULL to %s (openssl issues #30402, #31581), which
is undefined behaviour in standard C.  EDK2 AsciiVSPrint guards NULL
string arguments (prints "<null string>"), so the wrapper avoids the
Solaris-class NULL-%s crash.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Replace direct struct member access with OpenSSL accessor
functions for ASN1_STRING, ASN1_TYPE, and ASN1_OBJECT types.
OpenSSL 4.0 makes these struct fields opaque, requiring use of
ASN1_STRING_get0_data(), ASN1_STRING_length(),
ASN1_STRING_type(), OBJ_get0_data(), and OBJ_length().

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add null stubs for tls_parse_ctos_ech() and
tls_construct_stoc_ech() in SslExtServNull.c for the new
Encrypted Client Hello (ECH) extension in OpenSSL 4.0.

Update tls_construct_cert_status_body() signature in
SslStatServNull.c to include the new OCSP_RESPONSE parameter.

Update OSSL_STORE_SEARCH_by_name() in ossl_store.c to use
const X509_NAME parameter matching the OpenSSL 4.0 API.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Replace OpenSSL's enc_b64_avx2.c with a UEFI stub that avoids
immintrin.h/CRT macro conflicts under the UEFI OpenSSL build flags.
Update OpenSSL INF source lists to use the stubbed implementation and
suppress MSVC warning C4005 for OSSL_SSIZE_MAX in BaseCryptLib.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Remove no-ml-dsa, no-ml-kem, and no-tls1_3 from configure.py
to enable Post-Quantum Cryptography support in OpenSSL 4.0.0.

Regenerated configuration headers and INF files with:
- ML-KEM (FIPS 203) key encapsulation sources
- ML-DSA (FIPS 204) digital signature sources
- MLX hybrid key exchange sources
- TLS 1.3 protocol support (required for PQC key exchange)

OpenSSL 4.0.0 has native PQC support - no external provider
(oqsprovider) needed.

Note: Build is blocked by pre-existing missing decoders.inc
in uefiprov.c (not related to this change).

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Extend the UEFI built-in OpenSSL provider (uefiprov.c) so that libssl
can discover the algorithms required for the post-quantum TLS 1.3 key
exchange groups defined by IANA codepoints 0x11EB (SecP256r1MLKEM768),
0x11EC (X25519MLKEM768), and 0x11ED (SecP384r1MLKEM1024), as well as
the classical X25519 / X448 groups.

The UEFI provider previously omitted ECX (X25519, X448), ML-KEM, and
the ML-KEM hybrid algorithms. Without keymgmt and KEM dispatch entries,
SSL_set1_groups_list() would reject those names and TlsSetEcCurve()
would return EFI_UNSUPPORTED for both classical and PQC groups.

Add the following entries (gated to match per-variant source coverage
in the OpensslLib*.inf files):

  * deflt_keyexch[]: X25519, X448 (gated by OPENSSL_NO_EC / OPENSSL_NO_ECX)
  * deflt_keymgmt[]: X25519, X448, ML-KEM-768/1024, X25519MLKEM768,
    SecP256r1MLKEM768, SecP384r1MLKEM1024
  * deflt_asym_kem[] (new table): RSA, EC, X25519, X448, ML-KEM-768/1024,
    and the three TLS hybrid KEMs
  * deflt_query(): dispatch OSSL_OP_KEM to the new deflt_asym_kem table

Verified against the TlsLib host unit tests: X25519 / X448 report
SUPPORTED, and all three PQC hybrid groups report SUPPORTED (3 / 3).
All 119 host unit tests continue to pass.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Rewrite TlsSetEcCurve to use SSL_set1_groups_list with string
group names, replacing the deprecated EC_KEY_new_by_curve_name
and SSL_set_tmp_ecdh APIs. This enables P-256 (previously
rejected), X25519, X448, and PQC hybrid key exchange groups
(X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024).

Add TLS 1.3 cipher suite support to TlsSetCipherList by
detecting IANA IDs in the 0x1300 range and routing them
through SSL_set_ciphersuites instead of SSL_set_cipher_list.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Enable OpenSSL CMS module by removing OPENSSL_NO_CMS from
configuration-ec.h and configuration-noec.h, and adding 19
CMS source files to OpensslLibFull.inf and OpensslLibAccel.inf.

Register ML-DSA-44/65/87 signature and keymgmt providers, plus
SHAKE-128/256 and ML-DSA-MU digest providers in the UEFI
OpenSSL provider (uefiprov.c). Without these registrations,
the EVP provider framework cannot locate the ML-DSA algorithms.

Add CMS verification fallback to Pkcs7Verify. OpenSSL's
PKCS7_verify does not support ML-DSA (returns 'provider
signature not supported'). When PKCS7 verification fails,
the function now attempts CMS_verify which has explicit
ML-DSA support through the cms_sd.c key2data table.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Replace the PKCS7-first + CMS-fallback approach with a single
CMS_verify call. CMS (RFC 5652) is the successor to PKCS#7 and
is backward-compatible at the ASN.1 level. CMS_verify supports
RSA, ECDSA, Ed25519, ML-DSA, and future algorithms through the
OpenSSL EVP provider framework.

PKCS7_verify cannot verify ML-DSA signatures (returns 'provider
signature not supported'). Using CMS exclusively simplifies the
code and provides crypto-agile verification for both classical
and post-quantum algorithms.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add 19 CMS source files to OpensslLibFullAccel.inf to resolve
linker errors when building OneCryptoPkg. The CMS module is
required for ML-DSA signature verification through Pkcs7Verify.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Switch AuthenticodeVerify() from the legacy PKCS7_verify path (via
Pkcs7Verify) to CMS_verify so the function can dispatch through the
OpenSSL EVP provider framework. This enables verification of
post-quantum signature algorithms (ML-DSA-44/65/87) in addition to
the traditional RSA and ECDSA paths.

CMS (RFC 5652) requires eContent to be an OCTET STRING, while
Authenticode (PKCS#7 v1.5) encodes SpcIndirectDataContent as a raw
SEQUENCE. To bridge this format mismatch without losing CMS-based
verification, temporarily remove eContent from the parsed PKCS#7 to
produce a detached signature, re-encode that detached form to DER,
parse it as CMS ContentInfo, and supply the original
SpcIndirectDataContent separately via a BIO to CMS_verify.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
X509ConstructCertificateStackV initialized Status to FALSE and only
set it to TRUE after successfully constructing a certificate. When
the caller supplied only the NULL terminator (an empty list), the
loop exited with Status still FALSE and the function returned an
error instead of the documented success path "A NULL terminates the
list".

Set Status to TRUE when the loop reaches the NULL terminator so an
empty list yields an empty stack and TRUE, matching the function
documentation and the new TestX509ConstructCertificateStackEmptyList
host unit test. Also set Status to FALSE explicitly when CertSize
is zero so the failure indication is independent of whether a
previous iteration succeeded.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
The EVP_add_digest_alias() registration mapping sha1WithRSAEncryption
to sha1WithRSA was needed for legacy OpenSSL OID handling.  OpenSSL
4.0 with the EVP provider framework resolves this alias internally;
the explicit registration is no longer required and SHA-1 with RSA is
deprecated for new signatures.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add Scripts/sync_readme_versions.py to derive the OpenSSL and Mbed TLS
badge versions in README.md from the submodule sources of truth
(OpenSSL VERSION.dat and Mbed TLS build_info.h) instead of hand-editing
them. The OpenSSL badge is corrected from 3.5.5 to 4.0.0 to match the
pinned submodule.

Wire a --check invocation into the continuous-integration workflow so a
stale badge fails CI. Each package job verifies only the badge whose
submodule it materializes: OpensslPkg checks OpenSSL, MbedTlsPkg checks
Mbed TLS.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Implement AllocateCopyPool in MemoryAllocationLibOnOneCrypto using
the supported OneCryptoAllocatePool and CopyMem primitives. The
function was previously stubbed to ASSERT and return NULL, which
broke GetTrustAnchorX509FromAuthData in the trust-anchor path when
running in the OneCrypto environment.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add the OneCrypto v1.1 GetAuthenticodeHash() implementation in the
OpensslPkg BaseCryptLib instance. The function computes a PE/COFF
Authenticode-style image hash: it parses and validates the PE/COFF
headers, hashes the image header up to and excluding the CheckSum
and Cert Directory entry, hashes the sections in PointerToRawData
order, and hashes any trailing bytes between the end of the last
section and the start of the certificate table.

The hashing primitives are the BaseCryptLib Sha1 / Sha256 / Sha384 /
Sha512 routines, so this source is independent of the underlying
provider library. The digest algorithm is selected by GUID
(gEfiCertSha1Guid, gEfiCertSha256Guid, gEfiCertSha384Guid,
gEfiCertSha512Guid). A separate CryptAuthenticodeHashNull.c stub is
added for the PEI / Runtime / SEC / SMM phase library instances that
do not provide the implementation.

Caution: The PE/COFF image is treated as untrusted input. All header
fields are bounds-checked against FileSize before use to avoid
out-of-bounds reads.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add the OneCrypto v1.1 GetAuthenticodeHash() implementation in the
MbedTlsPkg BaseCryptLib instance. The function computes a PE/COFF
Authenticode-style image hash: it parses and validates the PE/COFF
headers, hashes the image header up to and excluding the CheckSum
and Cert Directory entry, hashes the sections in PointerToRawData
order, and hashes any trailing bytes between the end of the last
section and the start of the certificate table.

The hashing primitives are the BaseCryptLib Sha1 / Sha256 / Sha384 /
Sha512 routines, so this source is independent of the underlying
provider library. The digest algorithm is selected by GUID
(gEfiCertSha1Guid, gEfiCertSha256Guid, gEfiCertSha384Guid,
gEfiCertSha512Guid). A separate CryptAuthenticodeHashNull.c stub is
added for the PEI / Runtime / SEC / SMM phase library instances that
do not provide the implementation.

Caution: The PE/COFF image is treated as untrusted input. All header
fields are bounds-checked against FileSize before use to avoid
out-of-bounds reads.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Wire the GetAuthenticodeHash function pointer into the OneCryptoBin
ONE_CRYPTO_PROTOCOL

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add the OneCrypto v1.1 GetTrustAnchorX509FromAuthData() and
FreeTrustAnchorX509Cache() implementation in the OpensslPkg
BaseCryptLib instance. The function walks a PKCS#7 SignedData blob,
hashes each embedded X.509 certificate's TBSCertificate, and returns
the certificate whose digest matches the caller-supplied hash.

The PKCS#7 ASN.1 DER is parsed in-place with bounds-checked length
decoding; both the bare SignedData and the ContentInfo wrapper forms
are accepted. The certificates [0] IMPLICIT field is enumerated and
each Certificate SEQUENCE is matched on its TBSCertificate digest.
The hash algorithm is selected by the caller-supplied hash size
(20=SHA-1, 32=SHA-256, 48=SHA-384, 64=SHA-512). The hashing
primitives are taken from BaseCryptLib so the source is independent
of the underlying provider library.

The optional caller-managed cache stores up to 64 entries; each entry
holds a copy of the certificate DER bytes and lazily-computed TBS
digests under each algorithm. A separate CryptTrustAnchorNull.c stub
is added for the PEI / Runtime / SEC / SMM phase library instances
that do not provide the implementation.

Caution: AuthData is treated as untrusted input. All ASN.1 length
fields are bounds-checked against the remaining input before the
parser advances.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add the OneCrypto v1.1 GetTrustAnchorX509FromAuthData() and
FreeTrustAnchorX509Cache() implementation in the MbedTlsPkg
BaseCryptLib instance. The implementation walks a PKCS#7 SignedData
blob, hashes each embedded X.509 certificate's TBSCertificate, and
returns the certificate whose digest matches the caller-supplied
hash.

The source is shared with OpensslPkg: the parser uses only ASN.1 DER
primitives and the BaseCryptLib hash API, so it does not depend on
the underlying provider library. This is required because the
MbedTlsPkg PKCS#7 helper Pkcs7GetCertificatesList() is currently
ASSERT(FALSE)-stubbed and cannot be used for certificate
enumeration.

A CryptTrustAnchorNull.c stub is added for the PEI / Runtime / SEC /
SMM phase library instances.

Caution: AuthData is treated as untrusted input. All ASN.1 length
fields are bounds-checked against the remaining input before the
parser advances.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Wire GetTrustAnchorX509FromAuthData and FreeTrustAnchorX509Cache in
OneCryptoBin protocol

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add the GetAuthenticodeHashAlgorithm implementation and its Null
variant to the OpensslPkg BaseCryptLib instance. The provider copy
parses the Authenticode SpcIndirectDataContent with bounds-checked
ASN.1 decoding to recover the digest-algorithm GUID from untrusted
signature data, mapping the digestAlgorithm OID to the matching
signature-type GUID.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add the GetAuthenticodeHashAlgorithm implementation and its Null
variant to the MbedTlsPkg BaseCryptLib instance. The provider copy is
byte-identical to the OpensslPkg copy and parses the Authenticode
SpcIndirectDataContent with bounds-checked ASN.1 decoding to recover
the digest-algorithm GUID from untrusted signature data, mapping the
digestAlgorithm OID to the matching signature-type GUID.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Wire GetAuthenticodeHashAlgorithm into the OneCryptoBin protocol
dispatch table

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Implement X509GetTbsCertHash() for the OpenSSL BaseCryptLib instance.
The implementation reuses the existing X509GetTBSCert() to extract the
TBSCertificate byte range and the provider-independent hash dispatch
table to digest it under the caller-selected algorithm. Add the
matching BaseCryptLib null stub.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Implement X509GetTbsCertHash() for the Mbed TLS BaseCryptLib instance.
The implementation reuses the existing X509GetTBSCert() to extract the
TBSCertificate byte range and the provider-independent hash dispatch
table to digest it under the caller-selected algorithm. Add the
matching BaseCryptLib null stub. The OpenSSL and Mbed TLS sources
remain byte-identical.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Wire the new X509GetTbsCertHash service into the OneCrypto protocol
binary

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Implement AuthenticodeVerifyEx() for the MbedTls BaseCryptLib. MbedTls
cannot expose the verifier-built certificate chain, so a chain request
returns EFI_UNSUPPORTED; when no chain is requested it behaves like
AuthenticodeVerify(). Add the CryptAuthenticodeNull stub.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Implement AuthenticodeVerifyEx() for the OpenSSL BaseCryptLib. On
success it returns the signer's cryptographically-verified certificate
chain in EFI_CERT_STACK form, captured from OpenSSL's own X509_STORE
verification via an observe-only verify callback
(X509_STORE_CTX_get1_chain). The returned chain is the one that was
verified, so a caller can run per-certificate revocation (dbx) checks
without a second, independent chain-building pass.

Verification is factored into a shared internal CmsVerify() built on
CMS_verify, which optionally captures and serializes the signer chain.
Pkcs7Verify() becomes a thin wrapper over CmsVerify(), and
AuthenticodeVerify()/AuthenticodeVerifyEx() route through it, so both
classical (RSA, ECDSA, Ed25519) and post-quantum (ML-DSA) signatures
dispatch through the OpenSSL EVP provider framework.

Add the CryptAuthenticodeNull stub for AuthenticodeVerifyEx().

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Wire the AuthenticodeVerifyEx service into the OneCrypto protocol.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Prototyping-only pin: track the microsoft/mu_basecore
dev/202511/post-quantum-staging branch, which carries the new
BaseCryptLib/OneCrypto APIs this branch consumes (GetAuthenticodeHash,
GetTrustAnchorX509FromAuthData, FreeTrustAnchorX509Cache,
GetAuthenticodeHashAlgorithm, X509GetTbsCertHash, AuthenticodeVerifyEx).
These live on a non-default branch, so the dependency tracks the branch
instead of pinning a commit. Update both the CI (.pytool/CISettings.py)
and OneCrypto driver build (OneCryptoPkg/DriverBuild.py) manifests.

Drop this commit once the APIs land on a released mu_basecore commit.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add HashAllByGuid(), a generic one-shot digest helper that selects the
algorithm from a hash-algorithm GUID (Protocol/Hash.h) and hashes a raw
buffer with the matching BaseCryptLib primitive. Cover SHA-1/256/384/512
and MD5, compiling the deprecated MD5 and SHA-1 entries only when their
BaseCryptLib interfaces are enabled. Add a Null instance for the
reduced-profile library instances.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Add HashAllByGuid(), a generic one-shot digest helper that selects the
algorithm from a hash-algorithm GUID (Protocol/Hash.h) and hashes a raw
buffer with the matching BaseCryptLib primitive. Cover SHA-1/256/384/512
and MD5, compiling the deprecated MD5 and SHA-1 entries only when their
BaseCryptLib interfaces are enabled. Add a Null instance for the
reduced-profile library instances.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Wire the HashAllByGuid BaseCryptLib service into the published
ONE_CRYPTO_PROTOCOL so consumers can compute a buffer digest by
hash-algorithm GUID through the OneCrypto binary.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Temporarily repoint the MU_BASECORE build dependency (CI and OneCrypto
driver build) at flickdm/mu_basecore dev/onecrypto-hashallbyguid, which
adds the HashAllByGuid crypto service consumed by OneCryptoBin. Drop once
HashAllByGuid lands on the upstream staging branch.

Signed-off-by: Doug Flick <dougflick@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

impact:non-functional Does not have a functional impact language:python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant