Skip to content

[FIPS 5 Backport] CLI and Symbol Versioning backport - #3647

Merged
justsmth merged 57 commits into
aws:fips-2026-06-26-snapshotfrom
justsmth:fips-2026-cli-symver-backport
Nov 5, 2026
Merged

justsmth merged 57 commits into
aws:fips-2026-06-26-snapshotfrom
justsmth:fips-2026-cli-symver-backport

Conversation

@justsmth

@justsmth justsmth commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Description of changes:

Backports merged mainline OpenSSL CLI, symbol-versioning, and crypto-policy support to fips-2026-06-26-snapshot, the FIPS 5 snapshot based on v5.1.0. This is the FIPS 5 counterpart of #3615 and #3618, including self-service symbol registration and the latest EOF, Windows build, and integration-CI fixes listed below.

The branch contains 54 cherry-picks with upstream commit references: 46 carry unchanged upstream edits, and eight document their FIPS-branch adaptations. Three additional branch-specific commits establish the AWS_LC_FIPS5_<major>.<minor> namespace, align the documentation, and add the FIPS silent-drop check. Nothing in the FIPS module itself changes; the only edit under crypto/fipsmodule/ is the test-only rand_isolated_test.cc warning fix from #3648, which is not part of bcm.o.

PR Change Deviation
#3331 Fix libgit2/xtrabackup/grpc tests; add OSSL3 peer cert APIs
#3096 Symbol versioning Keeps ABI_VERSION 0. Registers FIPS_module_name (from #3474)
#3338 Symbol versioning follow-ups
#3343 Pin libssh2 integration
#3341 SSL_OP_IGNORE_UNEXPECTED_EOF over sockets
#3373 Flaky s_client cipher tests
#3386 Document building against AWS-LC
#3347 Harden CLI input validation
#3423 Self-service symbol registration Drops the brainpool entries (#3286 is not on this branch)
#3407 Network s_client tests to integration
#3426 Decouple symbol versioning from dist-pkg
#3370 OpenSSL-compat .pc files with the shim
#3446 BN_FLG_CONSTTIME as zero Drops the krb5 patch removal; the #3308 pick below simply never adds that patch
#3469 req -extensions / -reqexts
#3481 OpenSSL long names for ML-DSA OIDs
#3492 bssl client -tls1_2/-tls1_3
#3501 ERR_num_errors/ERR_pop_to_count
#3529 Error-queue suppression scope
#3502 Crypto-policies reader Leaves cpu_getauxval_linux.h (in bcm.o) untouched and defines AT_SECURE in crypto_policy.cc
#3527 Export the reader; CI job
#3536 CLI exit codes
#3503 Seed ciphers and version bounds
#3548 verify/x509 compatibility
#3532 pkcs12 import
#3499 Quote shell args in tool tests
#3551 SIGPIPE race in linkage checks
#3560 Reject malformed end-of-contents
#3563 rehash -compat
#3543 Harden code paths Drops the e_aesccm.c guard (in bcm.o)
#3568 ca fails on unwritable cert
#3504 Seed groups and sigalgs No SSL_CTX_set1_group_ids (#3346) here, so the deduped list is installed into supported_group_list directly. ML-DSA sigalg merge unchanged
#3575 pkcs12 -export, req -batch
#3592 CSR proof-of-possession on x509 -req
#3605 RSA enc/dec and more ciphers
#3484 OpenSSL 3.x unexpected-EOF behavior and retry guard; CLI/shim adaptations
#3645 Fix Windows -Wunused-but-set-global build failure
#3430 Use preinstalled Rust in pyOpenSSL integration
#3431 Pin librelp and wrap SSL_get_shutdown in its integration test
#3507 Fix tpm2-tss integration build without SM4
#3648 Fix Windows -Wunused-but-set-global in rand_isolated_test.cc Test-only file under crypto/fipsmodule/; bcm.o unchanged
#3666 Cipher name as command (openssl aes-256-cbc)
#3680 PKCS12 password prompt test isolation on OpenBSD
#3664 rand subcommand
#3665 Password-based key derivation in enc
#3636 x509 -serial/-addtrust/-trustout
#3634 CA signing, revocation, and CRLs in ca
#3635 ocsp command
#3687 Self-contained s_client TLS 1.1 integration tests
#3690 Fix wrapper escape in rand
#3703 dgst -r coreutils output flag
#3308 CTS mode (<openssl/modes.h>, CRYPTO_cts128_*) and krb5 integration test Leaves crypto/fipsmodule/modes/internal.h untouched (its hunk only re-homed the cbc128_f typedef and removed a dead declaration; no TU includes both headers). Registers the two symbols under AWS_LC_FIPS5_1.0. Omits the BN_FLG_CONSTTIME krb5 patch that #3446 removed on main. Integration script symlinks libcrypto.so* rather than hardcoding .so.1 (this branch is ABI_VERSION 0)
#3349 Built-in Camellia in the krb5 patch; CTS doc label Drops its bn.h comment hunk, superseded by #3446
#3405 Register the thread-exit TLS callback on MinGW/clang64
#3669 Run the msys2 mingw64 - MSYS Makefiles job in the MSYS2 shell

Call-outs:

  • Add CTS mode, krb5 integration test #3308 is the one backport that adds public API: a new installed header include/openssl/modes.h and two new exported functions, CRYPTO_cts128_encrypt and CRYPTO_cts128_decrypt, registered under AWS_LC_FIPS5_1.0. MIT krb5's OpenSSL backend requires them, and they were two of the symbols the release ABI check reports as missing relative to mainline. The implementation lives outside the module in crypto/cipher_extra/cts.c and is driven by a caller-supplied cbc128_f, so it is not a module service.
  • The complete Report unexpected EOF as SSL_ERROR_SSL for OpenSSL 3.x parity #3484 backport changes non-ignored unexpected transport EOF from SSL_ERROR_SYSCALL to SSL_ERROR_SSL with SSL_R_UNEXPECTED_EOF_WHILE_READING, matching main. It also fixes retryable reads being treated as EOF; the shared CLI transport enables SSL_OP_IGNORE_UNEXPECTED_EOF as upstream does.
  • ABI_VERSION remains 0 (libcrypto-awslc.so.0), SOFTWARE_NAME remains awslc, and symbol nodes use AWS_LC_FIPS5_1.0, distinct from versioned mainline's AWS_LC_* nodes. A product rename at release would also require updating distribution-package documentation and test globs.
  • ci: use preinstalled Rust in pyopenssl integration #3430 relies on Rust/Cargo in the shared CI images; their presence was confirmed in the existing pyOpenSSL job log. Independently rebuilt branch images must also supply Rust (main's image setup is ci: install Rust in the Linux docker images #3393).

Testing:

Latest validation covers #3405 and #3669, which fix the windows-alt failures that surfaced once #3645/#3648 let the msys2 jobs compile: ThreadTest.ThreadLocal on clang64 (LLD 22 no longer emits the TLS directory, so the thread-exit callback never ran) and the mingw64 - MSYS Makefiles ABI-detection failure. Both picks are patch-identical to main.

  • Windows Server 2022, msys2 clang64 (Clang/LLD 22.1.8) Release, static non-FIPS with Go/Perl disabled: reproduced the ThreadTest.ThreadLocal failure at 5b192eb85, then at the new head confirmed llvm-readobj --coff-tls-directory shows a TLS directory with AddressOfCallBacks, ThreadTest.* 6/6 pass, and the full crypto_test passes (2,700 passed, 1 skipped).
  • fix(ci): running ci in dedicated msys shell #3669 is workflow-only; the msys2 job section of windows-alt.yml now matches main. CI on this push is the verification.

Latest validation covers the #3308/#3349 picks:

  • Ubuntu 24.04 ARM64 Release with FIPS=1, shared libraries, symbol versioning, and crypto policies: clean build; bcm.o is byte-identical (SHA-256 match) to a same-path build of the previous head 8c966f08e; all 6 CTS128Test cases and the full crypto_test (3,761 passed, 2 skipped) pass; nm --with-symbol-versions shows both CRYPTO_cts128_* exported as @@AWS_LC_FIPS5_1.0, and AWS_LC_FIPS5_1.0 remains the only version node.
  • util/update_symbol_version.sh --current reports no unregistered symbols and leaves the tree unchanged, so the manual registry entries match what the tooling produces.
  • Ran tests/ci/integration/run_krb5_integration.sh krb5-1.22.2-final end to end in an ubuntu:22.04 container on ARM64 (gcc 11): both krb5 patches apply, krb5 configures and builds against the installed AWS-LC, check-linkage.sh confirms kinit links our libcrypto.so.0, and make check under src/lib/crypto passes, including the aes-test CTS vectors and the built-in Camellia test. Exit status 0.
  • cts.c, cts_test.cc, modes.h, and the krb5 patches are byte-identical to main; the script differs from main only by the libcrypto.so* symlink loop and the absent record_repo_commit call (that helper is not on this branch).

Validation of the eleven CLI/CI cherry-picks (#3648 through #3703), all of which applied without conflicts and are patch-identical to their mainline commits:

  • Ubuntu 24.04 ARM64 Release with FIPS=1, shared libraries, symbol versioning, and crypto policies: clean build; tool_openssl_test 846 passed / 0 failed / 4 pre-existing skips (CLI comparisons used OpenSSL 3.0.13), rand_isolated_test passed, and all 5 SClientIntegrationTest cases passed, including the Tls1_1 cases that failed in the previous ocsp-external CI run and that [ci] fix: Make s_client TLS 1.1 integration tests self-contained #3687 fixes.
  • Windows Server 2022 msys2 clang64 (Clang 22) Release, static non-FIPS with Go/Perl disabled: rand_isolated_test, openssl, tool_openssl_test, and integration_test build cleanly, confirming Fix -Wunused-but-set-global in rand_isolated_test.cc #3648 resolves the previous -Werror,-Wunused-but-set-global failure; rand_isolated_test and the 218 tests in the new/changed CLI suites (RandTest, CipherAliasTest, DgstTest, EncTest, OcspTest, CATest, X509Test, PKCS12Test) passed against the msys2 OpenSSL.
  • git diff against the base still touches nothing in bcm.o; the only crypto/ library change in the new picks is the static b64_ctrl flush fix from tool-openssl: add openssl rand subcommand #3664, so no exported-symbol registry updates are needed.

Previous validation (through #3507):

  • Ubuntu 24.04 ARM64 Release with FIPS=1, shared libraries, distribution packaging/OpenSSL shim, symbol versioning, and crypto policies: 3,755 crypto, 2,669 SSL, 744 CLI, and 7 bssl tests passed; all 69 selected SSL shutdown runner cases passed. CLI comparisons used OpenSSL 3.0.13. Unavailable system-policy cases and other configuration-dependent cases skipped.
  • Windows Server 2022 clang64 Release, static non-FIPS with Go/Perl disabled: build succeeded using pregenerated sources; 27 targeted UBE/EOF/shutdown tests passed.
  • Regenerated SSL error metadata and generated-src/err_data.c with the repository generators; independently verified the error table matches generator output. The committed tree is identical to the tested tree.
  • Original PR base and updated bcm.o are byte-identical in same-path Linux ARM64 builds. No new exported symbols require registry updates.
  • Modified integration scripts pass bash -n; external integration suites were not rerun end to end. Whitespace checking reports only inherited whitespace inside the unchanged upstream librelp patch.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

WillChilds-Klein and others added 30 commits October 9, 2026 18:01
(cherry picked from commit db0dc86)

[fips-2026-06-26-snapshot backport] Kept ABI_VERSION at 0; mainline bumps it to
1, which would change this branch's SONAME from libcrypto-awslc.so.0. Registered
FIPS_module_name, which this branch exports (from aws#3474) but mainline's registry
at this commit predates.
### Issues:
Addresses `V2066643219`

### Description of changes:
Follow-up to aws#3294, which gated `SSL_OP_IGNORE_UNEXPECTED_EOF` on
[`BIO_eof(ssl->rbio.get())`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/ssl/ssl_buffer.cc#L585-L591).

[`BIO_eof()`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L443)
calls [`BIO_ctrl(bio, BIO_CTRL_EOF,
…)`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L390),
and socket BIOs (`BIO_s_socket`, used by
[`SSL_set_fd`](https://github.com/python/cpython/blob/main/Modules/_ssl.c#L985)
in CPython) don't implement it, and
[`sock_ctrl`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/socket.c#L106)
falls through to `default: ret = 0`, so the guard was always false and
the condition was never met.

The testing didn't catch this because it used
[`BIO_pair`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/pair.c#L381),
which does implement `BIO_CTRL_EOF` and returns 1 at EOF so the guard
passed in the test. Will need to be backported to the FIPS 3.0 and 4.0
branches.

### Testing:
Added a test that reads through a dummy BIO that emulates a socket, as
it returns 0 on read, and checks the client and server both get
`SSL_ERROR_ZERO_RETURN` on an unexpected EOF. Confirmed the test fails
with the old guard and passes with the fix.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 4cec1f7)
### Issues:
Resolves P469904855

### Description of changes:
Fixes input validation gaps and tightens file permissions in the CLI
tool:
- Always fail on DNS resolution errors in s_client regardless of quiet
mode
- Reject unrecognized -v2 cipher names in pkcs8 -topk8 instead of
falling through
- Set restrictive permissions (0600) when writing private key files

### Testing:
Tests added for each change.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 216d28b)
…elf-service (aws#3423)

### Context/Motivation

The five `EC_group_brainpoolP*r1()` functions added in aws#3286 were never
registered.
* New `OPENSSL_EXPORT` symbols that are not added to the symbol registry
are compiled into shared libraries but hidden by the version script,
preventing applications from linking against them.

### Description of changes:

This PR registers the Brainpool EC group APIs in `AWS_LC_1.0` and makes
the registration path when updating the current node explicit with
`./util/update_symbol_version.sh --current`.

The symbol-versioning tool now distinguishes adding API to the current
open node from opening a new node, rejects accidental reuse of an
existing version node, and uses a deterministic byte-order sort.
Documentation and CI failure messages now explain the impact of
unregistered symbols and how to remediate them.

### Call-outs:

Opening a new symbol-version node is now documented and treated as a
release-level decision. Most API additions should use `--current`;
providing a version creates a new node and closes the current one by
convention.

### Testing:

- `git diff --check`
- Full build and CI tests not run locally.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit c528a49)

[fips-2026-06-26-snapshot backport] Did not register the EC_group_brainpoolP*r1
functions: brainpool support (aws#3286) is not on this branch. The rest of the
commit, which makes symbol registration self-service, applies unchanged.
### Description of changes:
Five of the eight `SClientTest` cases connect to `amazon.com:443`, so
they fail whenever egress is unavailable or rate limited. This moves
them into a new `tool-openssl/s_client_integration_test.cc`, built into
the existing `integration_test` executable alongside the OCSP responder
tests, and renames them to `SClientIntegrationTest` to match
`OCSPIntegrationTest`.

`integration_test` is deliberately absent from `util/all_tests.json`, so
the default test run (`go run util/all_tests.go`, `ninja run_tests`)
never invokes it. Environments without outbound access, such as internal
sandbox builds, get a hermetic default suite without having to opt out
of anything.

### Call-outs:
* The moved cases no longer run in the default suite. That is the goal,
but the trade-off is that nothing exercises `s_client` against a live
host unless `integration_test` is run explicitly.
* `UnresolvableHost` stays in `tool_openssl_test` even though it passes
`-connect`. It only needs DNS resolution to fail, not egress, so it is
hermetic. I extended its comment to say so, since otherwise it reads
like it was missed during the move.
* `ssl/CMakeLists.txt` gains a few extra sources (`s_client.cc`,
`ordered_args.cc`, `tool/args.cc`, `tool/client.cc`, `tool/file.cc`)
purely as the link closure for `SClientTool`. No new library
dependencies.

### Testing:
Existing tests, relocated rather than rewritten. `tool_openssl_test` and
`integration_test` both pass locally (macOS/arm64): the 3 remaining
`SClientTest` cases and all 5 moved `SClientIntegrationTest` cases. Test
count balances -- 8 before, 3 + 5 after. Also ran `ssl_test` to confirm
the `ssl/CMakeLists.txt` change did not disturb anything else.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 85a931c)
### Description of changes:
Symbol versioning was previously enabled only through `ENABLE_DIST_PKG`,
which also relocates headers and renames binaries. This change adds an
independent `ENABLE_SYMBOL_VERSIONING` setting that defaults to
`ENABLE_DIST_PKG`, preserving existing behavior while allowing consumers
to adopt versioned ELF symbols without the other distribution packaging
changes. Explicit requests are rejected for unsupported static, Apple,
and Windows builds, while inherited settings remain disabled without
breaking existing static distribution package configurations.

This also adds `SYMBOL_VERSION_NAMESPACE` for private distributions that
need version nodes other than `AWS_LC_*`. Custom version scripts are
generated in the build tree without modifying the checked-in `.map`
files, and the standalone version script generator supports the same
namespace override.

Documentation is updated to describe the independent configuration,
platform restrictions, and ABI implications of custom namespaces.

### Call-outs:
- `ENABLE_SYMBOL_VERSIONING` intentionally does not use CMake's
`option()` because doing so would cache its initial default and prevent
an unset value from continuing to track `ENABLE_DIST_PKG` across
reconfiguration.
- A custom `SYMBOL_VERSION_NAMESPACE` changes the ABI contract and is
only appropriate for privately distributed libraries. It is rejected
when symbol versioning is disabled.
- Namespace rewriting exists in both CMake and the Go generator so
builds can continue using checked-in version scripts with
`DISABLE_GO=ON`. The tests verify that both implementations produce
identical output.

### Testing:
- Added Go unit coverage for valid and invalid namespaces, single-node
and multi-node rewrites, namespace collisions, inheritance preservation,
and end-to-end version script generation.
- Extended `run_symbol_version_test.sh` to verify that symbol versioning
can be enabled without distribution packaging, does not enable header or
binary cohabitation, writes namespaced scripts only into the build tree,
rejects namespaces when versioning is disabled, and keeps the CMake and
Go rewrite implementations equivalent.
- Existing integration coverage continues to verify version definitions,
versioned exports, linking, and detection of unversioned or silently
dropped symbols.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit af86c72)
…3370)

### Context and motivation

The OpenSSL shim installs compatible headers and library symlinks, but
its pkg-config interface is incomplete. It provides only `openssl.pc`,
so consumers that require `libcrypto` or `libssl` by package name cannot
resolve the shim. Its metadata can also expose suffixed library names
that CMake's `FindOpenSSL` treats as unresolvable extra dependencies.

### Description of changes

Install `openssl.pc`, `libcrypto.pc`, and `libssl.pc` for the shim, with
metadata describing the unsuffixed OpenSSL interface: the plain
`include` directory, unsuffixed package dependencies, and
`-lcrypto`/`-lssl`. These names resolve through the shim symlinks, while
the native AWS-LC pkg-config modules remain suffixed for cohabitation.

When `BUILD_LIBSSL=OFF`, omit the native and compatibility `libssl.pc`
files, the `libssl` shim symlink, and `libssl` package dependencies.
Update `INCORPORATING.md` to document both pkg-config interfaces.

### Testing

Extended the installation tests across shared, static, shim-disabled,
and `BUILD_LIBSSL=OFF` configurations. They validate the installed
modules and exact pkg-config metadata, compile and run consumers through
the shim, cover a `Requires.private: libcrypto` dependency, exercise
CMake's standard `find_package(OpenSSL)`, and confirm that the native
suffixed interface is unchanged.

### Review considerations

This does not change the public C API or ABI. The compatibility modules
emit unsuffixed linker names, but those names resolve to libraries
retaining their suffixed SONAMEs, so runtime cohabitation with a system
OpenSSL is preserved.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 8049abf)
(cherry picked from commit 8670e12)

[fips-2026-06-26-snapshot backport] Dropped the krb5 integration patch removal;
this branch does not carry the krb5 integration test. The bn.h comment replaces
this branch's variant of the old text, so it now matches mainline.
…aws#3469)

### Context and motivation

`openssl req -extensions` was incorrectly applied to CSRs, which could
make CSR generation fail when the selected certificate extension section
required issuer context, such as `authorityKeyIdentifier`.

### Description of changes

Route `-extensions` to certificates generated with `-x509` and add
`-reqexts` for selecting CSR extensions. The options independently
override `x509_extensions` and `req_extensions`, matching OpenSSL 1.1.1
and 3.0 behavior.

### Testing

Added unit and OpenSSL comparison tests covering command-line overrides,
config fallbacks, invalid sections, issuer-dependent extensions, and the
end-to-end CSR signing flow.

### Review considerations

OpenSSL 3.2 and later alias `-reqexts` and `-extensions`; this change
intentionally follows the separate option semantics from OpenSSL 1.1.1
and 3.0.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit fac7cb9)
### Context and motivation

AWS-LC registers the three ML-DSA OIDs with both short and long name set
to the compact "MLDSA44"/"MLDSA65"/"MLDSA87" spelling. OpenSSL 3.5
registers the same OIDs with the long name
"ML-DSA-44"/"ML-DSA-65"/"ML-DSA-87". Anything that looks up ML-DSA by
name, or reads the name back off a parsed key or certificate, doesn't
interoperate between the two libraries. RubyGems, for example,
identifies ML-DSA keys by the OpenSSL 3.5 long name and fails to
recognize a valid ML-DSA key produced or parsed by AWS-LC.

### Description of changes

Set the long name of the three ML-DSA OIDs to the OpenSSL 3.5 spelling
("ML-DSA-xx") while keeping the short name as "MLDSAxx".
`OBJ_ln2nid`/`OBJ_txt2nid` now resolve the OpenSSL name and `OBJ_nid2ln`
returns it; `OBJ_sn2nid`/`OBJ_txt2nid` still resolve the existing short
name, so no current caller breaks. New `LN_MLDSAxx` macros are added to
`nid.h`.

A couple of things worth knowing:

- `!Cname` in `objects.txt` pins the generated C identifier. Without it,
`objects.go` derives the macro name from the long name and would have
produced `NID_ML_DSA_44` with a freshly allocated NID. With it,
`NID_MLDSAxx`, `OBJ_MLDSAxx`, and `obj_mac.num` are all unchanged.
- `OBJ_obj2txt` prefers the long name, so `i2a_ASN1_OBJECT` and
everything built on it (`X509_print`, `X509_signature_print`, etc.) will
now print `ML-DSA-44` instead of `MLDSA44` for ML-DSA keys and signature
algorithms. This is the intended outcome (matches `openssl x509 -text`
on 3.5), but it is a visible string change for anyone parsing that
output.

This only touches the object-name database. It does not add ML-DSA key
generation by algorithm name; AWS-LC still selects the parameter set by
NID through `EVP_PKEY_CTX`.

### Testing

Added `ObjTest.MLDSANames`, which for each parameter set checks
`OBJ_nid2sn`/`OBJ_nid2ln`, that both spellings resolve through
`OBJ_ln2nid`/`OBJ_sn2nid`/`OBJ_txt2nid`, and that `OBJ_obj2txt` returns
the long name (the path `X509_print` uses). `obj_dat.h` and `nid.h` were
regenerated with `go run objects.go`; re-running the generator on the
branch produces no diff.

### Review considerations

Public API: adds `LN_MLDSA44`/`LN_MLDSA65`/`LN_MLDSA87`. No existing
symbols or NID values change. ML-KEM has the same naming asymmetry with
OpenSSL 3.5 (`MLKEM768` vs `ML-KEM-768`) and is intentionally left for a
follow-up.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 254c4cf)
Stack, split out of aws#3442, to merge bottom-up:

1. **aws#3501 -- error-queue primitives (this PR)**
2. aws#3502 -- policy file reader
3. aws#3503 -- cipher lists and version bounds
4. aws#3504 -- groups and signature algorithms
5. aws#3505 -- post-quantum defaults

## Description

- Adds `ERR_num_errors` and `ERR_pop_to_count`, so code that calls into
libcrypto on a caller's behalf can drop the errors it raised and leave
the queue it was handed untouched.
- The existing mark APIs cannot do this. `ERR_set_mark` needs an entry
to mark, so it is a no-op on an empty queue, and popping to a mark
consumes one the caller had already set.
- `ERR_clear_error` and `ERR_restore_state` rebuild the queue, which
dangles the data pointer the caller got from its last
`ERR_get_error_line_data`.
- A count is a position rather than a mark, so it nests inside a
caller's mark without disturbing it.

## Testing / verification

- New error-queue tests cover popping back to a recorded count, a count
taken from an empty queue, and a count at or above the queue's length.
- One case fills the ring past its capacity to confirm a stale count
leaves the caller's errors alone.
- One case wraps a nested call in the caller's own mark and an error
carrying a data string, then checks the mark still pops and the string
is intact.
- One case pins that a mark does not survive
`ERR_save_state`/`ERR_restore_state`, since a snapshot can be restored
many times and would re-arm a mark nobody set.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 973b592)
Stack, split out of aws#3442, to merge bottom-up (aws#3501, the error-queue
primitives, has landed):

1. **aws#3502 -- policy file reader (this PR)**
2. aws#3527 -- shared-build symbol export and CI
3. aws#3503 -- cipher lists and version bounds
4. aws#3504 -- groups and signature algorithms
5. aws#3505 -- post-quantum defaults

- Adds an off-by-default build flag, `-DENABLE_CRYPTO_POLICIES`, and a
reader for the OpenSSL back-end file that Amazon Linux 2023 and Fedora
render from the operator's chosen system policy.
- `AWSLC_CRYPTO_POLICY_FILE` relocates that file at build time and is
declared in the CMake cache, so `cmake -L` and cmake-gui list it for a
packager who is not reading the CMakeLists.
- Parses the directives AWS-LC could act on into a fixed-size config
struct. Nothing consumes the result yet.
- Comments, section headers, and unknown keys are ignored, so the reader
tolerates the rest of what the framework writes today and whatever it
adds later. A value too long to represent is ignored the same way, even
where an earlier line set the same key.
- The reader succeeds only if it read the whole file, so half a policy
cannot pass for a shorter one.
- The policy path is fixed at build time and overridable at runtime,
which is how the tests here and in the rest of the stack drive it. The
override is dropped in a secure execution, where the environment sits on
the far side of a privilege boundary from the root-owned default path.

- Parse tests cover a full stock policy, quoting, surrounding
whitespace, a repeated key, and a final line with no trailing newline.
- An overlong value or line is dropped whole rather than truncated, and
drops the value an earlier line gave the same key, so a policy larger
than the reader's buffers cannot quietly become a different policy.
- A missing file, a read error, and null arguments all fail rather than
yielding a half-filled config. The read-error case opens a directory,
which fails on the first read rather than on the open.
- The runtime path override is exercised directly, since every later
test in the stack rests on it.
- Checked the override drop against a real binary: honored as an
ordinary process, ignored once that binary carries file capabilities,
which leave the real and effective ids equal.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 6d8a1d6)

[fips-2026-06-26-snapshot backport] Dropped the change to
crypto/fipsmodule/cpucap/cpu_getauxval_linux.h so bcm.o is unchanged. This
branch's copy of that header already has the same <sys/auxv.h> detection and
/proc/self/auxv fallback; it only lacks the AT_SECURE define, which
ssl/crypto_policy.cc now supplies locally. Did not take the BUILD_AWSLC_PROVIDER
options that sit next to the new cache entries in CMakeLists.txt; the provider
is not on this branch.
Stack, split out of aws#3442, to merge bottom-up (aws#3501, the error-queue
primitives, has landed):

1. aws#3502 -- policy file reader
2. **aws#3527 -- shared-build symbol export and CI (this PR)**
3. aws#3503 -- cipher lists and version bounds
4. aws#3504 -- groups and signature algorithms
5. aws#3505 -- post-quantum defaults

## Description

- Exports the two policy-reader internals the tests call and registers
them in the libssl symbol registry. A shared build needs both: hidden
visibility keeps them out of the library, and the version script an
`ENABLE_DIST_PKG` build applies keeps them out again.
- Runs the symbol extractor once more with the crypto-policies build
flag defined, so declarations sitting behind that guard reach the
registry at all.
- Adds the Amazon Linux 2023 CI job for the feature: the suite with the
flag on in stock CMake and in the shared, symbol-versioned
`ENABLE_DIST_PKG` build a distribution packages, a run against the
policy file the system renders, and a build with libssl off.
- The job's seeding-specific parts, the neutralizing path override and
the require-system flag, are inert until aws#3503 adds seeding and the test
hook that reads them.
- The build flag stays off by default, so no shipped configuration
changes.

## Testing / verification

- Ran both build configurations the job runs and the policy tests in
each. Only the distribution one fails to link without this change, which
is why a stock build alone let the gap through.
- Reverting only the generated version script brings the undefined
references back, so the registry entries earn their place alongside the
export attribute.
- Regenerating the version script from the registry is byte-identical,
the invariant the symbol-check job's `mapcheck` mode enforces.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 828175d)
### Context and motivation

Tool entry points in `tool-openssl/` return a `bool` that `main()`
collapses to exit status 0 or 1. OpenSSL's CLI uses other exit codes in
a few places that scripts rely on -- notably `verify` (exit 2 on
verification failure) and `x509 -checkend` (exit 1 when the certificate
is about to expire). Our tool always exited 0 for `-checkend` and 1 for
every `verify` failure, so scripts using it as a drop-in replacement got
the wrong answer.

### Description of changes

`tool_func_t` now returns `int`: the process exit status directly.
`kToolExitSuccess` / `kToolExitFailure` (0/1) are defined in
`internal.h`, and `main()` returns whatever the tool returns (still
dumping the error queue on any nonzero status). All tools except two
just map their existing `bool` result to 0/1, so their exit codes are
unchanged.

The two with real behavior changes, now matching OpenSSL 1.1.1 and 3.x:

- `verify` exits 2 when any input certificate fails to load or verify,
and 1 for option/setup errors (bad option, unreadable `-CAfile` or
`-untrusted`). As part of this, the `-untrusted` bundle is loaded once
up front instead of once per input certificate; `X509_STORE_CTX_init`
only borrows the stack, so sharing it is fine. This also fixes the
`-untrusted` fopen error message, which printed the cert path instead of
the chain path.
- `x509 -checkend` exits 1 when the certificate will expire within the
window and 0 otherwise. As before (and like OpenSSL), `-checkend` writes
only its verdict and suppresses the certificate output.

### Testing

Existing tests are updated to assert on the exact exit code rather than
`true`/`false`. New unit tests cover each `verify` exit path
(verification failure, one failing input among several, unparseable
input, missing `-CAfile`, missing `-untrusted`, unknown option) and both
`-checkend` outcomes including the `-out` contents. New comparison tests
(`VerifyComparisonTest.ExitCodes`,
`X509ComparisonTest.CheckendExitCode`) run the built binary against the
reference `openssl` from `OPENSSL_TOOL_PATH` and assert the exit codes
match; these pass locally against OpenSSL 1.1.1, 3.0, and 3.6.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 5c7719d)
…ws#3503)

Stack, split out of aws#3442, to merge bottom-up. Below this PR, aws#3501 and
aws#3529 (error-queue primitives and the suppression scope), aws#3502 (policy
file reader), and aws#3527 (shared-build symbol export and CI) have landed.

1. **aws#3503 -- cipher lists and version bounds (this PR)**
2. aws#3504 -- groups and signature algorithms
3. aws#3505 -- post-quantum defaults

## Description

- `SSL_CTX_new` now applies the policy's cipher lists and protocol
bounds when built with the flag, taking the TLS or DTLS directives
according to the context's method.
- Seeding is best-effort and cannot report failure, so it runs inside
`bssl::ScopedErrorSuppression`, which rejects the errors it raises at
the source and is false when the queue cannot be protected, where
seeding is skipped. Trimming afterwards is not enough for a caller whose
queue is already full: there each error seeding raises evicts one of
theirs, and no later trim brings an evicted entry back.
- A cipher rule the setters refuse leaves the built-in list, which
neither setter gives on its own: they install an empty list before
reporting that a rule matched nothing, and allocate again to merge the
TLS 1.2 and 1.3 lists. Both lists are built aside and moved in only once
every step has succeeded.
- A protocol floor the policy names and AWS-LC cannot resolve rises to
the ceiling. Dropping it would leave the built-in floor of TLS 1.0,
below every floor `crypto-policies` renders, so a context would offer
the versions the policy exists to forbid. A floor naming a protocol
older than any AWS-LC implements keeps the built-in one, which is
already stricter, and a ceiling AWS-LC cannot resolve stays unapplied.
- The bounds are resolved as a pair before either is applied, since the
setters check each against the method's whole range and never against
each other, and both are put back if either is refused.
- The `@SECLEVEL=N` prefix of `CipherString` is parsed and dropped,
since AWS-LC has no security levels; the key-size and hash constraints a
level implies are therefore not enforced.
- A policy read whole is cached per process, keyed on the resolved path,
matching how OpenSSL reads `openssl.cnf`: a policy change takes effect
only in processes started afterward, while a changed override path still
misses.
- A read that fails is not cached, since no errno tells a transient
error from a file that is simply absent. Caching the negative let one
bad read decide the policy for every context the process went on to
create; the price is a failing `open()` per `SSL_CTX_new` on a host with
no policy.

## Testing / verification

- The crypto-policies job from aws#3527 covers this code: the whole suite
in debug and release with seeding compiled in but pointed at a path that
does not exist, so the thousands of existing tests still see AWS-LC's
built-in defaults.
- That job's system run drops the override and reads the file
`crypto-policies` itself renders, comparing the automatically seeded
context against one seeded by hand from the same path; the
require-system flag this PR teaches the tests to honor turns an absent
file into a failure rather than a skip.
- The fixture policy is the Amazon Linux 2023 DEFAULT file copied byte
for byte, so it carries the spellings, modifiers, and unimplemented
algorithm names the code has to cope with.
- A `CipherString` the policy applies is checked to leave the TLS 1.3
suites in place, and a `Ciphersuites` value the TLS 1.2 ciphers, which
is the merge seeding now performs itself.
- The caller's error queue is checked five ways: its entries, a mark it
had set, the data pointer from its last `ERR_get_error_line_data`, a
queue filled to capacity, and one with a single slot free.
- The unresolvable floor is exercised for TLS and for DTLS, against a
policy ceiling, against none, against a ceiling below the newest version
the method offers, and with a value too long to store; each case fails
when the raise is neutered.
- Unsatisfiable cipher rules, inverted bounds, a one-sided bound below
an existing floor, a floor naming an older protocol, an unresolvable
ceiling, and a version-locked method are each checked to leave the
context as it was.
- A path that fails and then becomes readable is checked to seed the
second context, which a cached failure prevents.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 7ee4bcd)
### Context and motivation

Scripts commonly extract certs and keys with `openssl pkcs12 -in
bundle.p12 ...`. Our CLI had no `pkcs12` subcommand, so this adds an
import-only one aimed at the usual non-interactive invocations.

### Description of changes

Supports `-in`, `-out`, `-nokeys`, `-nocerts`, `-nodes`, `-noout`,
`-passin`, `-password`, `-passout`, `-legacy`, and `-help`. Built on
`PKCS12_get_key_and_certs`, so the MAC is verified before `-out` is
opened. That is stricter than OpenSSL 1.1.x, which truncates `-out`
before parsing; a successful run still opens/truncates `-out` even when
`-noout` or `-nocerts -nokeys` writes nothing.

Output order (certs, then key), `-password` overriding `-passin`
regardless of order, empty-password handling, and the `Mac verify error`
message match OpenSSL 1.1.x. If a key is to be written, `-nodes`
(unencrypted PKCS#8) or `-passout` (PKCS#8 encrypted with AES-256-CBC)
is required; there is no interactive prompt. `-nodes` overrides
`-passout`.

`-legacy` is accepted as a no-op so OpenSSL 3 scripts keep working. This
library already decrypts the RC2/3DES bags that flag loads the legacy
provider for.

Not implemented: `-export`, `-info`, `-clcerts`/`-cacerts`, `-twopass`,
`-nomacver`, `-chain`, `-descert`, interactive prompts, and the `Bag
Attributes` comment lines. Those unsupported options fail rather than
being ignored.

### Testing

38 unit tests plus two comparison tests that export a bundle with the
reference OpenSSL and check that both tools produce the same
certificates and PEM block sequence. Comparison tests run in CI against
OpenSSL 1.1.1 and 3.0.

The unit-test builder uses `PKCS12_create` defaults, so cert bags are
RC2-40 and the key bag is 3DES. Tests do not construct RC4 or OpenSSL 3
PBES2/AES-encrypted bundles (the latter is covered only when the
comparison job uses a 3.x `openssl pkcs12 -export`), and they do not
exercise BER indefinite-length inputs (the library handles those).

### Review considerations

CLI-only, no public API or FIPS changes. The AWS-LC parser is stricter
than OpenSSL in ways that surface here: bundles without a MAC (`-export
-nomac`) are rejected rather than imported with a warning, and bundles
with more than one private key are rejected. Like the other subcommands,
the CLI `ReadAll` helper caps input at 1 MiB.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 2b530cf)
### Context and motivation
With pipefail enabled, `ldd | grep -q` can fail even when the expected
library is found: grep exits early, and a subsequent write from ldd
triggers SIGPIPE. The install test misinterprets this failure as static
linkage.

### Description of changes
Capture ldd output before searching it, use literal path matching, and
print the output on failure. Require ldd to succeed so loader errors
containing the expected library path cannot produce false positives.

### Testing
Reproduced the SIGPIPE race on Linux. Ad hoc macOS/Linux tests verified
the fix and covered successful linkage, missing libraries, nonzero
exits, literal paths, and SONAMEs. A real Linux corrupted-library test
confirmed that loader failures are rejected. Shell syntax and whitespace
checks passed. The full install CI job was not run.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit d821e4c)
### Context and motivation
`ASN1_parse` (the `ASN.1` dumper used by `asn1parse` and diagnostic
output) treated any `[UNIVERSAL 0]` element as an end-of-contents marker
without checking its length. A malformed `[UNIVERSAL 0]` with content
inside an indefinite-length parent elements would truncate that element
and mis-render later elements at the wrong depth. The output is wrong
but the parser stays in-bounds. This is a display/rendering issue in the
dumper, not a memory-safety or broad parsing-rejection change.

### Description of changes
Stops treating malformed tag-zero elements as terminators in the `ASN.1`
dumper. Signal `EOC` only when the element matches the two-byte form:
`tag V_ASN1_EOC`, `class 0`, `content length 0`, `header length 2`.
Anything else falls through as an ordinary unknown primitive and the
loop keeps iterating. Well-formed `EOC` is unaffected.

### Testing
- New test feeds dummy data to `ASN1_parse` followed by a real `INTEGER`
sibling and checks the `INTEGER` prints at the right depth.
- Full `ASN1Test` and `asn1parse` suites still pass.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 4a1316d)
…ws#3543)

Harden various code-paths

(cherry picked from commit 6b4fded)

[fips-2026-06-26-snapshot backport] Dropped the INT_MAX length guard in
crypto/fipsmodule/cipher/e_aesccm.c, which is inside bcm.o. None of the tests
this commit adds exercise it. Everything else applies unchanged.
prasden and others added 2 commits October 12, 2026 13:30
…tion test (aws#3431)

Fixes failing CI job `integration-omnibus / librelp-x86_64`

### Description of changes:

The librelp integration was previously running on the latest tip of main
("master" branch on librelp), causing integration failures with AWS-LC
when a new incompatible test was added upstream. We now add a required
release tag to track in our integration tests, and a non-required job to
continue tracking integration against the latest tip of main, similiar
to aws#3343

librelp also added a [new
test](rsyslog/librelp@cfd92093), in their new
release, `tls-ossl retry-state`, that wraps
`SSL_write`/`SSL_read`/`SSL_get_error` with `ld --wrap`.

But
[`relpTcpSend_ossl`](https://github.com/rsyslog/librelp/blob/v1.13/src/tcp.c#L3420)
also calls `SSL_get_shutdown`, which isn't wrapped. That unwrapped call
dereferences `ssl->s3` on the fake `SSL` token and segfaults, failing
the `librelp-x86_64` job. This PR extends `aws-lc-librelp.patch` to also
`--wrap=SSL_get_shutdown`.

### Callouts:
The test uses a fake SSL object to simulate `WANT_READ` and
`WANT_WRITE`, which mean the TLS operation should be retried because the
connection is still open. `SSL_get_shutdown` returns 0 because no
shutdown flags should be set as returning `SSL_RECEIVED_SHUTDOWN` would
make librelp treat the connection as closed and abort instead of testing
the retry path.

### Testing:
- `patch -p1 --dry-run -d "$LIBRELP_SRC" <
"$SRC_ROOT/tests/ci/integration/librelp_patch/aws-lc-librelp.patch`
- `git diff --check`
- Ran ` ./tests/ci/integration/run_librelp_integration.sh` on a
throwaway instance to verify
-
https://github.com/aws/aws-lc/actions/runs/32400252222/job/96526464696?pr=3431

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit e597639)
### Context and motivation

An [upstream tpm2-tss
change](tpm2-software/tpm2-tss@d32903d)
added an unguarded `EVP_sm4_cfb128()` call, breaking our integration job
because AWS-LC does not support SM4.

### Description of changes

Update the integration patch to guard the new SM4 case using the same
capability checks already used elsewhere in tpm2-tss. This preserves AES
support and keeps testing upstream HEAD without relaxing compiler
warnings.

### Testing

Reproduced the original failure, then successfully ran the full TPM2
integration runner on Ubuntu 24.04 x86-64 with GCC 13.3. All 57 tpm2-tss
and 26 tpm2-abrmd tests passed, tpm2-tools built successfully, and
AWS-LC linkage checks passed.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 25dd8bd)
@justsmth
justsmth force-pushed the fips-2026-cli-symver-backport branch from b03d0fa to ee43ea4 Compare October 12, 2026 17:41
@justsmth
justsmth marked this pull request as ready for review October 12, 2026 19:11
@justsmth
justsmth requested a review from a team as a code owner October 12, 2026 19:11

@WillChilds-Klein WillChilds-Klein left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we also backport this PR? it "touches" the FIPS module to remove a function declaration from an internal header -- no changes to the fipsmodule itself

#3308

justsmth and others added 13 commits November 2, 2026 11:15
### Context and motivation

msys2 clang64 moved to LLVM 23.1.3, whose new `-Wunused-but-set-global`
fails the three msys2 clang64 jobs in `windows-alt.yml` under `-Werror`,
on `main` since aws#3645. That PR fixed the same warning in
`fork_ube_detect.c`; `rand_isolated_test.cc` increments four
entropy-method call counters it never reads.

### Description of changes

Drops the dead counters (`initialize_count`, `zeroize_thread_count`,
`free_thread_count`, `get_prediction_resistance_count`) and makes those
overrides plain no-ops. They still exist so every method in
`entropy_methods` is non-null; only the seed and extra-entropy counts
were ever asserted on, and those are unchanged.

### Testing

A full `ninja -k 0` build with Homebrew clang 23.1.3 confirms this was
the only remaining offender in the tree. With the fix, the build is
clean and `rand_isolated_test` passes on macOS (clang 23) and in a Linux
`FIPS=1` shared build.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 80ea500)
…c) (aws#3666)

## Summary
- Add cipher-name-as-command aliasing to `main()` in `tool.cc`
- When `FindTool` returns nullptr, check if the command name is a valid
cipher via `EVP_get_cipherbyname` and redirect to `encTool` with the
cipher flag prepended
- e.g. `openssl aes-256-cbc -d -in file` becomes equivalent to `openssl
enc -aes-256-cbc -d -in file`

## Motivation
OpenSSL allows invoking a cipher directly as a command name. Deployment
scripts use this form — for example, `openssl aes-256-cbc -md sha256 -d
-in file.enc -kfile key`. Without this aliasing, the command fails with
"unknown command" during the Openssl-default migration.

## Test plan
- [ ] `openssl aes-256-cbc -K <hex> -iv <hex> -in plain -out cipher`
encrypts
- [ ] `openssl aes-256-cbc -d -K <hex> -iv <hex> -in cipher` decrypts
correctly
- [ ] `openssl des-ede3-cbc -K <hex> -iv <hex> -in plain -out cipher`
works
- [ ] Invalid cipher names still show the usage menu
- [ ] Existing tool dispatch (e.g. `openssl enc`, `openssl rand`) is
unaffected

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 2bb507a)
### Context and motivation

OpenBSD static FIPS jobs fail PKCS12 password-prompt tests because
replacing fd 0 underneath `stdin` leaves platform-specific buffered
stream state behind.

### Description of changes

Run each POSIX invocation in an isolated child with fresh `stdin` and
`stderr` streams. The Windows path is unchanged.

### Testing

[OpenBSD 7.5 and 7.6 static FIPS
validation](https://github.com/justsmth/aws-lc/actions/runs/39672801547)
passed the PKCS12 suite and affected full shards. Static FIPS tests also
passed on Ubuntu 24.04, and non-FIPS tests passed on macOS.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit ebc3a40)
## Summary
- Add the `rand` subcommand to the OpenSSL-compatible CLI with
`-base64`, `-hex`, and `-out` options
- Uses `RAND_bytes` for cryptographically secure random byte generation
and `BIO_f_base64` for base64 encoding
- Registers the command in `kTools`, `internal.h`, and `CMakeLists.txt`

## Motivation
Scripts that call `openssl rand` during the Openssl-default migration
from OpenSSL to AWS-LC fail because the subcommand doesn't exist. Build
scripts commonly use patterns like `until openssl rand -base64 -out
"$KEYFILE" 32`, which loop forever because the missing subcommand
returns non-zero.

## Test plan
- [ ] Existing `tool_openssl_test` suite passes (766 tests, 0 failures)
- [ ] `openssl rand 32` produces 32 raw bytes
- [ ] `openssl rand -base64 32` produces valid base64
- [ ] `openssl rand -hex 16` produces 32 hex characters
- [ ] `openssl rand -out /tmp/test 32` writes to file

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 73daefe)
)

## Summary
- Add `-kfile`, `-k`, `-pass`, `-md`, `-nosalt`, and `-S` options to the
`enc` subcommand
- Implement password-based key derivation via `EVP_BytesToKey` with
proper `Salted__` header handling
- Support passphrase sources: direct (`-k`), file (`-kfile`), and
`pass:`/`file:`/`env:`/`stdin` via `-pass`
- Default digest is `sha256`, matching OpenSSL 3.x behavior

## Motivation
The `enc` subcommand previously only accepted raw hex keys (`-K`/`-iv`)
and explicitly rejected password-based key derivation. Scripts that use
`openssl enc -kfile <file>` or `openssl enc -k <pass>` — a common
pattern in build and deployment tooling — failed with "Error: A raw key
is required" during the Openssl-default migration.

The existing raw key path (`-K`/`-iv`) is preserved unchanged.

## Test plan
- [ ] Existing `tool_openssl_test` enc tests pass (11 tests, 0 failures)
- [ ] `openssl enc -aes-256-cbc -k "password" -in plain -out cipher`
encrypts
- [ ] `openssl enc -aes-256-cbc -d -k "password" -in cipher` decrypts
and matches
- [ ] `-kfile` reads passphrase from first line of file
- [ ] `-pass file:path`, `-pass env:VAR`, `-pass pass:literal` all work
- [ ] `-md sha256` (default) and `-md sha1` produce correct key
derivation
- [ ] `-nosalt` omits salt header, `-S <hex>` uses explicit salt
- [ ] Encrypted output interoperates with OpenSSL's `enc -d`

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit a9c92fe)
### Context and motivation

`tool-openssl`'s `x509` command was missing several common options
(`-serial`, `-addtrust`, `-trustout`) and truncated its input when `-in`
and `-out` named the same file, which broke in-place edits that callers
of the `openssl x509` CLI rely on. The goal is to add those options and
make in-place rewrites safe.

### Description of changes

Adds `-serial` (print the serial number), `-addtrust` (add a trusted
use, which implies `-trustout` as in OpenSSL), and `-trustout` (emit a
`TRUSTED CERTIFICATE` PEM; ignored for `-outform DER`, which writes a
plain cert to match OpenSSL); both apply to the plain-cert and `-req`
paths. Also reads the entire input before opening the output, and opens
the output only after all parsing, signing, and trust validation succeed
— buffering print output and validating `-checkend` up front — so a
failed in-place `-in`/`-out` rewrite no longer truncates its own input.
Reads back its own output: PEM via `PEM_read_bio_X509_AUX`, DER via
`d2i_X509_AUX` with a `d2i_X509` fallback for trailing bytes.

### Testing

Covered by `X509Test` unit tests (54 total) plus `X509ComparisonTest`
parity cases against the system `openssl` (`Serial`, `Trustout`,
`AddTrustTrustout`), including new cases for the `-req` trust path, DER
`-trustout` plain-cert output, DER-with-aux input, read-back of trusted
output, and a failed in-place rewrite preserving its input. All pass
under the repo's `-Werror` build.

### Review considerations

CLI-tool behavior only — no public library API/ABI or FIPS boundary
impact. The in-place change affects all `x509` input handling (now
buffered through memory), so it is worth focused review.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit dbf3bd9)
…ws#3634)

### Context and motivation

`tool-openssl`'s `ca` command could only self-sign. It could not act as
a CA signing CSRs with a separate key and certificate, revoke issued
certificates, or generate CRLs — so callers that invoke the `openssl ca`
CLI expecting OpenSSL-compatible behavior could not complete a basic
issue/revoke/CRL workflow. The goal is to close that gap for common CA
operations.

### Description of changes

Adds CA signing with a distinct key/cert (`-keyfile`/`-cert`/`-subj`),
dropping the self-sign-only restriction and validating that the key
matches the cert. The CA cert loader accepts plain and trusted (`X509
AUX`) PEM, and a missing `certindex.attr` sidecar is tolerated, matching
OpenSSL.

Adds `-revoke`, `-gencrl`, and `-crldays`:

- `-revoke` matches on serial **and** subject name (as OpenSSL's
`do_revoke`), so a colliding serial on a different cert is rejected.
- `-gencrl` emits a v2 CRL when an entry carries an extension (e.g. a
reason code), per RFC 5280.
- `-crldays` is a strict non-negative integer, required for `-gencrl`
(else config `default_crl_days`).
- `-in`, `-revoke`, and `-gencrl` are mutually exclusive.

Modeled on OpenSSL's `apps/ca.c`; a focused subset, not full parity.

### Testing

`CATest` unit tests: separate-key signing and `-subj`; revocation; CRL
generation; and two data-driven tests for valid/malformed reason-code
fields.

### Review considerations

CLI-tool behavior only — no public library API/ABI or FIPS boundary
impact. The command intentionally implements a subset of OpenSSL's `ca`;
some helper logic is adapted from OpenSSL's `apps/ca.c`.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 1276963)
### Context and motivation

`tool-openssl` had no `ocsp` command, so callers that invoke the
`openssl ocsp` CLI — for example to produce signed OCSP responses in a
test or PKI setup — had no equivalent. The goal is to provide the
minimal client and responder operations needed for that offline,
file-based workflow.

### Description of changes

Adds an `ocsp` command with two file-based modes: a client mode that
writes a DER-encoded OCSP request for a cert/issuer (`-reqout`), and a
responder mode that reads a request, determines each certificate's
status from a CA index database, and writes a signed DER response
(`-reqin`/`-respout` with `-index`/`-CA`/`-rsigner`/`-rkey`/`-ndays`).
Logic is modeled on OpenSSL's `apps/ocsp.c`. This is intentionally a
minimal subset — no HTTP responder (`-port`), nonce/response
verification, request signing, or response printing. One behavioral
note: a revoked entry reports the reason stored in its index field,
defaulting to `unspecified` only when none is present, because AWS-LC's
`OCSP_basic_add1_status` requires a concrete reason code.

### Testing
Covered by `OcspTest` unit tests (16): request construction,
good/revoked/unknown/expired status resolution, revocation reason
round-trip, and a request→response round trip, plus rejection of
corrupt, empty, and invalid inputs. All pass under the repo's `-Werror`
build.

### Review considerations

New CLI command — no existing library API/ABI or FIPS boundary impact.
Scope is a deliberate minimal subset of OpenSSL's `ocsp`; an HTTP
responder and response verification are possible follow-ups. Some
CA-index helpers are duplicated from `ca.cc` and could be factored into
a shared helper later.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit e05ca51)
…#3687)

### Context and motivation

The `ocsp-external` CI job is failing because `amazon.com:443` no longer
negotiates TLS 1.1 and now replies with a protocol_version alert, so the
two `SClientIntegrationTest` cases that force `-tls1_1` against it can
no longer complete a handshake. TLS 1.0/1.1 are being disabled
industry-wide, so no public Amazon endpoint will accept TLS 1.1 going
forward.

### Description of changes

The `Tls1_1` and `CipherAndTls1_1` tests now run against an in-process
loopback server pinned to TLS 1.1, instead of a remote host. This keeps
coverage of the tool's `-tls1_1` path without depending on an external
server's willingness to speak a deprecated protocol. The remaining
`amazon.com` cases are unchanged. `Listener::GetLocalPort()` is added so
the test can bind an ephemeral port and discover it.

### Testing

The full `SClientIntegrationTest` suite passes (5/5), including the two
reworked TLS 1.1 tests, which now negotiate a real TLS 1.1 handshake
over loopback and would fail if the `-tls1_1` path stopped negotiating
TLS 1.1.

### Review considerations

The two reworked tests are now hermetic (no network egress), unlike the
rest of the `integration_test` binary; I can gate them differently if
you'd prefer they stay grouped as network-dependent. No public API
change -- `Listener` is internal tooling. aws-lc rejects OpenSSL's
`@SECLEVEL=` cipher-string token, so the loopback server uses a plain
explicit cipher list.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 7274a24)
## Summary
- Transfers `FILE*` ownership from `ScopedFILE` to BIO via `BIO_CLOSE`
in the base64 output path of `tool-openssl/rand.cc`
- Only releases when `out_scoped` owns a file (not stdout) and
`BIO_new_fp` succeeds — no leak on failure
- Nulls `out_file` after `BIO_free_all` to prevent use-after-close in
the final `fflush`
- Resolves Coverity defect PREVIEWCID718359 (WRAPPER_ESCAPE, High
severity)

## Context
Coverity flagged that the raw `FILE*` extracted via `out_scoped.get()`
escapes into a `BIO` created with `BIO_NOCLOSE`. While the current code
is safe (both live in the same function scope), the ownership model is
fragile — a future refactoring that narrows `out_scoped`'s scope would
cause silent data loss via writes to a closed file descriptor.

This is a code-fragility fix, not a runtime-bug fix. The original code
works correctly today because `out_scoped` and the BIO share the same
function scope. The change makes ownership explicit so the code remains
correct even if the scope structure is later refactored.

## Test plan
This fix addresses code fragility (Coverity static analysis), not a
runtime defect. No new tests are added because:
- The base64 output path is already covered by
`RandTempFileTest.Base64Output`, `LargeBase64Output`,
`WriteFailureBase64`, `BrokenPipeBase64`, and
`UnbufferedBrokenPipeBase64`
- The ownership transfer doesn't change observable behavior — it only
makes the code safe against future refactoring

Regression verification:
- [ ] Existing `RandTempFileTest.Base64Output` passes (base64 to file,
exercises `BIO_CLOSE` path)
- [ ] Existing `BrokenPipeBase64` passes (base64 to stdout, exercises
`BIO_NOCLOSE` path)
- [ ] CI ASAN build passes (would catch double-close if ownership
handoff is wrong)
- [ ] Coverity rescan no longer flags WRAPPER_ESCAPE on this path

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 10811a9)
### Context and motivation

OpenSSL's `dgst` accepts `-r` to print digests in coreutils format
(`<hash> *<file>`), the form behind the common `openssl dgst -r | awk
'{print $1}'`
idiom. AWS-LC's `dgst` rejects `-r` with `Unknown flag: -r`, so scripts
relying on
that idiom break when moving from OpenSSL to AWS-LC. This change makes
`dgst`
accept `-r` and produce output matching OpenSSL.

### Description of changes

Adds `-r` to the `dgst` tool as an output-format option. When set,
output is
`<hex> *<file>` for file input and `<hex> *stdin` for stdin, matching
OpenSSL
byte-for-byte (separator and `stdin` label included). The flag is
additive and
gated: the default, `-binary`, `-sign`, and `-verify` paths are
unchanged, so
existing callers see no difference, and `-r` has no effect alongside
binary
output (consistent with OpenSSL).

### Testing

Added to `tool_openssl_test`:
- `DgstComparisonTest.Reverse` — asserts AWS-LC's `-r` output is
byte-identical
  to the reference OpenSSL for both file and stdin input.
- `DgstTest.ReverseOutput` / `DgstTest.ReverseOutputCustomDigest` — pin
the exact
`<hash> *<file>` bytes for SHA-256 and SHA-1 with no reference binary,
so a
regression in the format, separator, `stdin` label, or hash ordering
fails
  immediately.

Builds and passes under the repo's `-Werror`.

### Review considerations

CLI-only, additive flag; no public API/ABI change and no FIPS boundary
impact.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

---------

Co-authored-by: Spencer Walgren <swalgren@amazon.com>
(cherry picked from commit dc2ba66)
(cherry picked from commit 7f94b8f)

[fips-2026-06-26-snapshot backport] Dropped the change to
crypto/fipsmodule/modes/internal.h so bcm.o is unchanged. That hunk only
re-homed the cbc128_f typedef into the new public <openssl/modes.h> and removed
a dead CRYPTO_cts128_encrypt_block declaration; nothing includes both headers
in one translation unit, so the typedef can stay duplicated. Registered the new
symbols under this branch's AWS_LC_FIPS5_1.0 node. Did not add
0003-Remove-BN_FLG_CONSTTIME-from-SPAKE-plugin.patch, which main removed in
aws#3446 (already on this branch). The integration script symlinks every
libcrypto.so* from the install instead of hardcoding libcrypto.so.1, because
this branch keeps ABI_VERSION 0.
…ws#3349)

(cherry picked from commit b06d89b)

[fips-2026-06-26-snapshot backport] Dropped the include/openssl/bn.h comment
rewording; aws#3446, already on this branch, rewrote that comment when it defined
BN_FLG_CONSTTIME as zero, so bn.h already matches main.
justsmth and others added 2 commits November 3, 2026 09:03
### Description of changes:

The MSYS2 clang64 CI jobs began failing `ThreadTest.ThreadLocal` after
updating to LLVM 22 because the linked test executable no longer
contained the Thread Local Storage (TLS) directory needed to register
thread-exit callbacks. The existing callback registration relies on
MSVC-specific section and linker pragmas that are not reliable when
Clang targets MinGW.

This change preserves the existing MSVC path and adds a MinGW-compatible
path that places the callback in `.CRT$XLC` using GCC-style attributes.
It also retains a reference to the MinGW CRT's `_tls_used` symbol so the
linker emits the Thread Local Storage directory required for the Windows
loader to invoke the callback.

### Call-outs:

The explicit `_tls_used` reference is necessary because LLVM 22's LLD no
longer pulls in the MinGW TLS support object by default.

### Testing:

- Reproduced the `ThreadTest.ThreadLocal` failure on `main` using
Windows Server 2022 with MSYS2 clang64 and Clang/LLD 22.1.8.
- Verified that `ThreadTest.ThreadLocal` passes with this change.
- Verified that the full `crypto_test` suite passes (2715 tests).

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 8cca33b)
### Context and motivation

The Windows Alternative Compilers workflow is red: the `msys2 mingw64 -
MSYS Makefiles` cell fails CMake's compiler setup, which then builds the
wrong (32-bit) assembly and fails to link. The cause is environmental,
not our code — the mingw64 toolchain picks up a foreign subsystem's
runtime DLLs and crashes its assembler. It also fails on `main`. This
change gets the workflow green again.

### Description of changes

Run that job's configure and build in the MSYS2 shell (`msys2 {0}`) so
the toolchain resolves its own matching runtime DLLs, and install the
msys `make` the MSYS Makefiles generator needs. Workflow-only; scoped to
the `msys2` job.

### Testing

CI configuration only — no source or test changes. The workflow is the
verification: the failing cell now configures and builds, and the other
cells stay green.

### Review considerations

CI-only; no public API, ABI, or FIPS impact. Works around environmental
DLL-resolution drift on the Windows runners (MSYS2 defaults to UCRT64
and deprecated MINGW64). aws-lc already builds and passes under `ucrt64`
in the same matrix, so dropping or migrating the deprecated `mingw64`
cell is a possible follow-up.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 33e73b3)
@justsmth justsmth changed the title [FIPS 5 Backport] CLI and Semantic Versioning backport [FIPS 5 Backport] CLI and Symbol Versioning backport Nov 5, 2026
@justsmth
justsmth merged commit 180049e into aws:fips-2026-06-26-snapshot Nov 5, 2026
488 of 510 checks passed
@justsmth
justsmth deleted the fips-2026-cli-symver-backport branch November 5, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.