Add CTS mode, krb5 integration test#3308
Conversation
Adds run_krb5_integration.sh, which builds MIT krb5 against AWS-LC's OpenSSL-compatible crypto backend (--with-crypto-impl=openssl), asserts linkage via check-linkage.sh, and runs krb5's crypto unit tests (src/lib/crypto/make check) which exercise hashes, HMAC, encryption types, PRF, and key derivation against AWS-LC. Pins to the latest krb5-*-final release tag resolved at runtime.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3308 +/- ##
==========================================
+ Coverage 78.16% 78.19% +0.03%
==========================================
Files 693 695 +2
Lines 123955 124083 +128
Branches 17213 17221 +8
==========================================
+ Hits 96887 97030 +143
+ Misses 26149 26131 -18
- Partials 919 922 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Adds a krb5 matrix entry alongside cyrus-sasl, modeled on the same shape (small ubuntu:22.04 / gcc-12 runner) so it gets picked up by the standard integration omnibus run.
When krb5 is configured with --with-crypto-impl=openssl, the lib/crypto/builtin/sha2/ subdir is still built unconditionally, even though sha256.c/sha512.c bodies compile to nothing under #ifdef K5_BUILTIN_SHA2. Their shared sha2.h, however, defines SHA256_CTX/SHA512_CTX typedefs unguarded. AWS-LC's <openssl/opensslv.h> transitively includes <openssl/base.h>, which defines its own SHA256_CTX/SHA512_CTX typedefs — colliding with sha2.h's. Stock OpenSSL's <openssl/opensslv.h> contains only version macros, so the conflict only surfaces against AWS-LC. Gate the typedef block in sha2.h on K5_BUILTIN_SHA2 to match the .c file bodies. No-op for the builtin build; resolves the build break against AWS-LC.
|
Blocked on #3309. Debugging the second build failure (job) revealed a real AWS-LC API gap, not a CI-hygiene issue. AWS-LC ships neither: Filed #3309 to add public CTS128 APIs + tests. Leaving this PR in draft — will rebase and retest once #3309 lands. |
Adds AES Ciphertext Stealing (CTS) mode in the CS1 / RFC 2040 convention
that OpenSSL's legacy |<openssl/modes.h>| API exposes: the last two
ciphertext blocks are unconditionally swapped, and an exact-block-multiple
input is treated as a 16-byte residue. Inputs of <= 16 bytes are
rejected with a return of zero (callers should use plain CBC for those).
Public surface lives at |<openssl/modes.h>|:
- |cbc128_f| typedef (matches |AES_cbc_encrypt|'s signature)
- |CRYPTO_cts128_encrypt|
- |CRYPTO_cts128_decrypt|
Internal block-oriented variants used by the implementation
(|CRYPTO_cts128_encrypt_block|, |CRYPTO_cts128_decrypt_block|) remain
internal-only.
Tests cover:
- All four AES-128 RFC 8009 Appendix A vectors and four AES-256
vectors, encrypt-then-decrypt round-trip, with the published "AES
Output" as the asserted ciphertext.
- Exhaustive random round-trip across input lengths 17..95 bytes for
AES-128, AES-192, and AES-256 (every residue and every length
boundary on either side of a block).
- Length contract: |len| <= 16 returns zero for both directions.
- At residue == 16, output equals raw CBC with the last two blocks
swapped (CS1 always-swap convention).
- IV is advanced to the (post-swap) penultimate ciphertext block
after encryption, matching OpenSSL's behavior so callers that
chain CTS calls (e.g. krb5) get correct IV continuity.
Resolves aws#3309. Unblocks the krb5 integration test in aws#3308.
Revert the BN_FLG_CONSTTIME compatibility shim — the macro was intentionally omitted to surface callers relying on it. Instead, patch krb5's SPAKE preauth plugin to remove the BN_set_flags call entirely, since AWS-LC's BN operations are unconditionally constant-time.
Address cppcoreguidelines-init-variables warnings for the |residue| variable in both CRYPTO_cts128_encrypt and CRYPTO_cts128_decrypt.
Add the canonical Kerberos AES-CTS test vectors from RFC 3962. These use AES-128 with the "chicken teriyaki" key at lengths 17, 31, 32, 47, 48, and 64 bytes — covering all boundary conditions including block-aligned inputs (where CS3 always-swap applies) and multi-block inputs with varying residue sizes.
Take the krb5 git ref to test as a positional argument instead of resolving the latest release at runtime. Pin the workflow to krb5-1.22.2-final for deterministic CI.
Three hygiene fixes from PR security review: 1. |OPENSSL_cleanse| the local |tmp[]| scratch in both |CRYPTO_cts128_encrypt| and |CRYPTO_cts128_decrypt| before return. In encrypt, |tmp[0..residue-1]| holds the trailing plaintext bytes; in decrypt, |tmp[0..15+residue-1]| holds the entire trailing 16+residue bytes of plaintext after the second |cbc| call. Cleansing matches AWS-LC's hygiene posture for plaintext-bearing scratch (cf. |gcm.c|). 2. Add |assert(key != NULL && ivec != NULL)| at function entry and |assert(in != NULL && out != NULL)| after the |len <= 16| early return, matching the |CRYPTO_cbc128_*| family this lives next to. 3. Add |assert(!buffers_alias(in, len, out, len))| to enforce the "may not alias" precondition documented in <openssl/modes.h>. Also adds |#include <openssl/mem.h>| for |OPENSSL_cleanse|.
Wrap all RAND_bytes calls in cts_test.cc in ASSERT_TRUE so a DRBG failure fails the test rather than silently proceeding with stale buffer contents.
The public <openssl/modes.h> and modes/internal.h both defined an identical cbc128_f typedef. Include the public header from the internal one and keep a single definition. The krb5 integration script copied check-linkage.sh into the scratch folder but never used the copy; the linkage assertion runs directly from AWS_LC_BUILD_FOLDER.
Addresses review feedback: AES_cbc_encrypt and the other cbc128_f implementations use unaligned loads (movups and equivalents) and impose no alignment requirement on their I/O buffers, so the alignas(16) on the stack scratch buffers had no effect worth keeping. The directive in cbc.c predates this file and was copied along without a concrete justification.
|
🔒 Security Review — View Report Please review before merging. |
The implementation unconditionally swaps the last two ciphertext blocks (even for block-aligned inputs), which is the defining characteristic of CBC-CS3 per NIST SP 800-38A Addendum. The old comments incorrectly labeled it CS1 and claimed CS3 was not provided. Update the header comment in cts.c and all CS1 references in the test file to correctly say CS3. No code changes.
samuel40791765
left a comment
There was a problem hiding this comment.
Should we look into upstreaming these patches? If so, it would probably be better to gate the ``BN_set_flags(w, BN_FLG_CONSTTIME);one behind theOPENSSL_IS_AWSLC` preprocessor macro.
Good idea. Upstream PR #1533. |
Adds a krb5 integration test for AWS-LC's CI, plus the public
<openssl/modes.h>API additions needed to make MIT krb5 build cleanly against AWS-LC.Integration test
tests/ci/integration/run_krb5_integration.shbuildskrb5-1.22.2-finalagainst AWS-LC and runs former's testskinitis linked against AWS-LC'slibcryptovia the existingcheck-linkage.shhelper (matching howcyrus-sasl,libgit2,tcpdump, etc. do their linkage checks).make checkundersrc/lib/crypto, which exercises hashes, HMAC, encryption types, PRF, and key derivation against AWS-LC. The full top-levelmake checkrequires Python and live KDCs and is out ofscope for this initial drop.
New CTS API
krb5's
lib/crypto/openssl/enc_provider/aes.ccallsCRYPTO_cts128_encrypt/CRYPTO_cts128_decrypt(and#include <openssl/modes.h>) on its OpenSSL <3.0 code path. AWS-LC didn't ship either:include/openssl/modes.hexportingcbc128_f,CRYPTO_cts128_encrypt, andCRYPTO_cts128_decrypt.crypto/fipsmodule/modes/cts.cimplementing CBC Ciphertext Stealing in the CS1 / RFC 2040 convention that OpenSSL's legacy API uses (last two ciphertext blocks unconditionally swapped;exact-block-multiple input treated as a 16-byte residue;
len <= 16returns zero — callers should use plain CBC for those). This is the convention RFC 3962 / RFC 8009 Kerberos enctypes operate under.bcm.clike the other modes (cbc.c,cfb.c, etc.).Tests for the new CTS API
crypto/fipsmodule/modes/cts_test.cccovers:5-byte after multi-block) are exercised.
covers every residue value and both sides of every block boundary.
ivecis advanced to the (post-swap) penultimate ciphertext block, matching OpenSSL behavior so consumers that chain CTS calls (e.g. krb5) get correct IV continuity.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.