Skip to content

Add ASCON-AEAD128 cipher implementation per NIST SP 800-232 - #29934

Closed
evil-cry wants to merge 2 commits into
openssl:masterfrom
evil-cry:feature/ascon128
Closed

evil-cry wants to merge 2 commits into
openssl:masterfrom
evil-cry:feature/ascon128

Conversation

@evil-cry

@evil-cry evil-cry commented Feb 3, 2026

Copy link
Copy Markdown

Add Ascon-AEAD128 cipher provider implementation

This PR adds a complete OpenSSL provider implementation for ASCON-AEAD128. The implementation supports both streaming and one-shot encryption/decryption operations with AAD.

  • documentation is added or updated
  • tests are added or updated

Fixes: #28271

Co-authored-by: Billy Brumley [email protected]

@evil-cry

evil-cry commented Feb 3, 2026

Copy link
Copy Markdown
Author

See #29115 for provenance

@paulidale paulidale added branch: master Applies to master branch approval: review pending This pull request needs review by a committer triaged: feature The issue/pr requests/adds a feature tests: present The PR has suitable tests present labels Feb 3, 2026
@bbbrumley

Copy link
Copy Markdown
Contributor

We could really use eyes on the provider bits, or generally any OpenSSL "glue"

@levitte

levitte commented Feb 5, 2026

Copy link
Copy Markdown
Member

This needs a rebase to a fresher master. My offer to help still stands.
Among others, a rebase should resolve the current conflict with master, and enable running the workflows.

@levitte

levitte commented Feb 5, 2026

Copy link
Copy Markdown
Member

Regarding the provider bits, I could see nothing wrong.

A cursory look at the build shows that the algorithm is discoverable and what the params for it are:

$ util/wrap.pl apps/openssl list -cipher-algorithms -verbose
...
  ASCON-AEAD128 @ default
    description: undefined
    retrievable algorithm parameters:
      blocksize: unsigned integer (max 8 bytes large)
      keylen: unsigned integer (max 8 bytes large)
      ivlen: unsigned integer (max 8 bytes large)
      aead: unsigned integer (max 8 bytes large)
    retrievable operation parameters:
      keylen: unsigned integer (max 8 bytes large)
      ivlen: unsigned integer (max 8 bytes large)
      taglen: unsigned integer (max 8 bytes large)
      tag: octet string (arbitrary size)
      updated-iv: octet string (arbitrary size)
    settable operation parameters:
      tag: octet string (arbitrary size)
      taglen: unsigned integer (max 8 bytes large)
...

Running the EVP tests also shows that the provider does its work (this is essentially what make test TESTS=test_evp, but limited to just the ASCON tests):

$ util/wrap.pl test/evp_test test/recipes/30-test_evp_data/evpciph_ascon_aead128.txt
1..1
    # Subtest: run_file_tests
    1..1
    # INFO:  @ ../test/testutil/stanza.c:21
    # Reading test/recipes/30-test_evp_data/evpciph_ascon_aead128.txt
    # INFO:  @ ../test/testutil/stanza.c:123
    # Starting "Ascon AEAD 128 Test Vectors" tests at line 14
    # INFO:  @ ../test/evp_test.c:1028
    # ascon-aead128 is fetched
    # INFO:  @ ../test/evp_test.c:1594
    # RUNNING TEST FOR CIPHER ASCON-AEAD128
    # 
    # INFO:  @ ../test/evp_test.c:1028
    # ascon-aead128 is fetched
    # INFO:  @ ../test/evp_test.c:1594
    # RUNNING TEST FOR CIPHER ASCON-AEAD128
    # 
...
    # INFO:  @ ../test/evp_test.c:1028
    # ascon-aead128 is fetched
    # INFO:  @ ../test/evp_test.c:1594
    # RUNNING TEST FOR CIPHER ASCON-AEAD128
    # 
    # INFO:  @ ../test/testutil/stanza.c:32
    # Completed 1089 tests with 0 errors and 0 skipped
    ok 1 - iteration 1
ok 1 - run_file_tests

Not sure what more to say at this level.

@bbbrumley

bbbrumley commented Feb 5, 2026

Copy link
Copy Markdown
Contributor

Regarding the provider bits, I could see nothing wrong

Running the EVP tests also shows that the provider does its work

Thank you. I'm still hoping OP pushes some additional commits to add more (text-based) EVP tests, including negative tests. And perhaps at the same time, rebases off fresh master (thank you for your offer on the other thread, but let's see if OP sorts it first.)

@t8m t8m left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I do not see any major issue but there are a few nits that need to be fixed before this can be merged.

There could be an option to take over the PR by the team to finalize it if the contributor prefers that.

Comment thread build.info Outdated
Comment thread providers/implementations/ciphers/cipher_ascon_aead128.inc Outdated
Comment thread crypto/ascon/ascon_aead128.c Outdated
@t8m

t8m commented Feb 6, 2026

Copy link
Copy Markdown
Member

@aisle-analyzer

@aisle-research-bot

aisle-research-bot Bot commented Feb 6, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

We found 6 potential security issue(s) in this PR:

# Severity Title
1 🟡 Medium Out-of-bounds write in ASCON-AEAD128 provider update due to missing outsize validation
2 🟡 Medium ASCON-AEAD128 provider init can silently reuse stale key when key and IV are set in multiple steps
3 🔵 Low Ascon-AEAD128 manpage omits critical nonce-uniqueness and tag-verification guidance
4 🔵 Low ASCON-AEAD128 decryption releases plaintext before tag verification (unauthenticated plaintext on tag failure)
5 🔵 Low ASCON-AEAD128 registered in default provider without OPENSSL_NO_ASCON128 guard
6 🔵 Low Inconsistent disable token for ASCON-AEAD128 breaks configuration-based disabling

Each finding is detailed in a separate comment below.


Analyzed PR: #29934 at commit 1a33d27

Comment thread providers/implementations/ciphers/cipher_ascon_aead128.c Outdated
Comment on lines +151 to +208
/* Handle reinitialization with NULL key but new IV */
if (key == NULL && iv != NULL && ctx->key_set) {
/* Preserve tag for decryption - it may have been set before reinitialization */
uint8_t saved_tag[FIXED_TAG_LENGTH];
int tag_was_set = ctx->is_tag_set;

if (tag_was_set && direction == DECRYPTION)
memcpy(saved_tag, ctx->tag, FIXED_TAG_LENGTH);

ascon_aead128_cleanctx(ctx);
ctx->direction = direction;
/* Use stored key for reinitialization */
ossl_ascon_aead128_init(ctx->internal_ctx, ctx->key, iv);
/* Store the IV for get_updated_iv */
memcpy(ctx->iv, iv, ASCON_AEAD_NONCE_LEN);
ctx->iv_set = true;
ctx->is_ongoing = true;

/* Restore tag for decryption if it was set before reinitialization */
if (tag_was_set && direction == DECRYPTION) {
memcpy(ctx->tag, saved_tag, FIXED_TAG_LENGTH);
ctx->is_tag_set = true;
}

return OSSL_RV_SUCCESS;
}

/* Only clean and initialize if both key and IV are provided */
if (key != NULL && iv != NULL) {
/* Preserve tag for decryption - it may have been set before reinitialization */
uint8_t saved_tag[FIXED_TAG_LENGTH];
int tag_was_set = ctx->is_tag_set;

if (tag_was_set && direction == DECRYPTION)
memcpy(saved_tag, ctx->tag, FIXED_TAG_LENGTH);

ascon_aead128_cleanctx(ctx);
ctx->direction = direction;
ossl_ascon_aead128_init(ctx->internal_ctx, key, iv);
/* Store the key and IV for reinitialization */
memcpy(ctx->key, key, ASCON_AEAD128_KEY_LEN);
ctx->key_set = true;
memcpy(ctx->iv, iv, ASCON_AEAD_NONCE_LEN);
ctx->iv_set = true;
ctx->is_ongoing = true;

/* Restore tag for decryption if it was set before reinitialization */
if (tag_was_set && direction == DECRYPTION) {
memcpy(ctx->tag, saved_tag, FIXED_TAG_LENGTH);
ctx->is_tag_set = true;
}

return OSSL_RV_SUCCESS;
}

/* If only direction is being set (key/IV not provided yet), just set direction */
ctx->direction = direction;
return OSSL_RV_SUCCESS;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2. 🟡 ASCON-AEAD128 provider init can silently reuse stale key when key and IV are set in multiple steps

Property Value
Severity Medium
CWE CWE-320

Description

The ASCON-AEAD128 provider implementation mishandles multi-step initialisation sequences that are valid/expected in OpenSSL EVP (e.g. setting a new key first, then setting the IV later).

In ascon_aead128_internal_init():

  • A call that supplies a new key with iv == NULL only validates the key length and then does not store the new key, does not clear/refresh internal state, and does not update ctx->key_set.
  • A subsequent call that supplies a new IV with key == NULL will take the special reinitialisation path when ctx->key_set is already true and will initialise the cipher using the previously stored key (ctx->key).
  • Because ascon_aead128_cleanctx() intentionally does not clear ctx->key/ctx->key_set, the stale key persists across operations.

This can lead to encryption proceeding under an unintended old key silently, which can cause cross-session/key confusion and unintended disclosure if an attacker-controlled key remains active in a reused EVP_CIPHER_CTX.

Vulnerable code (key reuse on IV-only init + ignoring key-only init):

if (key == NULL && iv != NULL && ctx->key_set) {
    ascon_aead128_cleanctx(ctx);
    ossl_ascon_aead128_init(ctx->internal_ctx, ctx->key, iv);
    ...
    return OSSL_RV_SUCCESS;
}

/* Only clean and initialize if both key and IV are provided */
if (key != NULL && iv != NULL) {
    ...
    memcpy(ctx->key, key, ASCON_AEAD128_KEY_LEN);
    ctx->key_set = true;
    ...
    return OSSL_RV_SUCCESS;
}

/* Otherwise, key-only init is effectively ignored */
ctx->direction = direction;
return OSSL_RV_SUCCESS;

Recommendation

Handle EVP-valid partial init sequences safely by tracking key/IV independently and only starting the operation when both are available.

Suggested approach:

  • If key != NULL, always copy it into ctx->key and set ctx->key_set = true (even when iv == NULL).
  • If iv != NULL, always copy it into ctx->iv and set ctx->iv_set = true.
  • When either key or IV is updated, reset per-message state (ascon_aead128_cleanctx()), but preserve the stored key/IV buffers as needed.
  • Only call ossl_ascon_aead128_init() and set ctx->is_ongoing = true when both ctx->key_set && ctx->iv_set.
  • If an IV-only init occurs when !ctx->key_set, either store the IV and wait for the key, or return an explicit error; do not silently succeed without becoming usable.

Example sketch:

if (key != NULL) {
    if (keylen != ASCON_AEAD128_KEY_LEN) return 0;
    memcpy(ctx->key, key, ASCON_AEAD128_KEY_LEN);
    ctx->key_set = true;
}
if (iv != NULL) {
    if (ivlen != ASCON_AEAD_NONCE_LEN) return 0;
    memcpy(ctx->iv, iv, ASCON_AEAD_NONCE_LEN);
    ctx->iv_set = true;
}

ascon_aead128_cleanctx(ctx); /* reset per-message state */
ctx->direction = direction;

if (ctx->key_set && ctx->iv_set) {
    ossl_ascon_aead128_init(ctx->internal_ctx, ctx->key, ctx->iv);
    ctx->is_ongoing = true;
}

This prevents stale-key reuse and ensures EVP_EncryptInit_ex() multi-step sequences behave consistently with other provider AEAD ciphers (e.g., GCM).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a valid suggestion. Another option would be to return a failure if key is set but iv is NULL, but other algorithms handle this case gracefully. I.e. they allow setting a key first and an iv later.

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.

other algorithms handle this case gracefully

@t8m Would it make sense to have a unit test for all AEAD schemes for this? At first glance, this doesn't seem ASCON-specific.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

other algorithms handle this case gracefully

@t8m Would it make sense to have a unit test for all AEAD schemes for this? At first glance, this doesn't seem ASCON-specific.

Sure. We should unify this behavior across all the ciphers. Not sure why AEAD should be specific.

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.

I wrote a test for this bug and a couple of different multi-step initialization orders, and the test successfully found the bug. I ran it against this fork/branch. Here is the PR for the tests: https://github.com/openssl/openssl/pull/30141

        # ERROR: (memory) 'ct_reinit == ct_onestep' failed @ test/evp_extra_test.c:5743                                                                                                                              
        # --- ct_reinit                                                                                                                                                                                              
        # +++ ct_onestep                                                                                                                                                                                             
        # 0000:-981aaa8bd1190a7e 9a3302378166bc71 b17457158a4fd9de 32518f84b6cdb5                                                                                                                                    
        # 0000:+9212cc88f2472d1d b73d27b799d601b9 80bf4ffb3f645834 82cc23104015f1                                                                                                                                    
        #       ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^                                                                                                                                    
        #                                                                                                                                                                                                            
        # INFO:  @ test/evp_extra_test.c:5757                                                                                                                                                                        
        # evp_stale_key_integrity_test 76, CT_MISMATCH_SINGLE_vs_KEYIV: ASCON-AEAD128                                                                                                                                
#         # OPENSSL_TEST_RAND_SEED=1772048948

Additionally, the decrypt test had a similar issue but instead of mismatching the key is not set correctly:

       # ERROR: (bool) 'EVP_DecryptUpdate(ctx_dec, rt, &rt_len, ct, ct_len) == true' failed @ test/evp_extra_test.c:5957
        # false
        # INFO:  @ test/evp_extra_test.c:5978
        # evp_decrypt_roundtrip_multistep 76, DEC_UPDATE: ASCON-AEAD128
        # C0F7CA86747F0000:error:1C800072:Provider routines:ascon_aead128_update:no key set:providers/implementations/ciphers/cipher_ascon_aead128.c:236:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed! Albeit I did not have time today to test against @Jlg1061 changes.

Comment thread doc/man7/EVP_CIPHER-ASCON-AEAD128.pod
Comment thread crypto/ascon/ascon_aead128.c
@aisle-research-bot

Copy link
Copy Markdown

5. 🔵 ASCON-AEAD128 registered in default provider without OPENSSL_NO_ASCON128 guard

Property Value
Severity Low
CWE CWE-16
Location providers/defltprov.c:198-207

Description

The default provider registers the new ASCON cipher unconditionally:

  • providers/implementations/include/prov/implementations.h only declares ossl_ascon_aead128_functions[] when OPENSSL_NO_ASCON128 is not defined.
  • However, providers/defltprov.c registers ossl_ascon_aead128_functions with no corresponding #ifndef OPENSSL_NO_ASCON128 guard.
  • If a downstream build defines OPENSSL_NO_ASCON128 (e.g., to enforce a policy / compliance profile) or if a future no-ascon128 Configure option is added, this becomes a build-time failure (undeclared identifier / missing symbol) and prevents reliably disabling the algorithm.

Vulnerable code:

ALG(PROV_NAMES_ASCON_AEAD128, ossl_ascon_aead128_functions),

Recommendation

Guard the registration the same way the dispatch table is guarded, using the same macro name everywhere.

Example:

#ifndef OPENSSL_NO_ASCON128
    ALG(PROV_NAMES_ASCON_AEAD128, ossl_ascon_aead128_functions),
#endif

Also ensure the build system and tests use the same disable token/macro (see next report) so no-ascon128 (or equivalent) consistently removes the cipher from the build and provider algorithm list.

Comment thread providers/implementations/ciphers/build.info Outdated

@levitte levitte left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I found a curiosity...

Comment thread include/crypto/ascon.h
@evil-cry

Copy link
Copy Markdown
Author

I will be working on these requested changes throughout the week and merging into one commit so we don't have a bunch of commit churn again. Thanks all, sorry for the delay on my part.

Jlg1061 added a commit to Jlg1061/openssl that referenced this pull request Mar 2, 2026
discover all provided ciphers with non-zero IV length and verify
correct multi-step initialization semantics.

The EVP API permits key and IV to be supplied in separate
`EVP_CipherInit_ex()` calls (e.g. key-only followed by IV-only).
A recent bug (PR openssl#29934, ASCON-AEAD128) demonstrated that a
provider may silently ignore a key-only init, resulting in reuse
of a previously loaded key during a subsequent IV-only init.

To prevent similar regressions, this change introduces three
generic tests that automatically cover all IV-taking ciphers:

Verifies that:
- `init(key) → init(iv)`
- `init(iv) → init(key)`

produce identical ciphertext (and authentication tag for AEAD
ciphers) compared to single-call `init(key, iv)`.

Primes a context with `key1/iv1`, then re-initializes via
`init(key2) → init(iv2)` and verifies the output matches a fresh
`encrypt(key2, iv2)` operation, ensuring that no previously stored
key is reused.

Encrypts using single-call initialization and then decrypts using
multi-step initialization, verifying plaintext recovery. For AEAD
ciphers, this also exercises tag verification through the
multi-step path.

Ciphers are discovered using `EVP_CIPHER_do_all_provided()`,
requiring no maintenance when new IV-taking ciphers are added.
SIV mode is skipped due to its synthetic IV semantics. CCM mode
handling includes required length declarations.

This provides broad regression coverage for the provider
implementations that support multi-step EVP initialization.

@bbbrumley
CLA: [https://docuseal.com/e/4ToT8de57L7nHb](url)
<!--
Thank you for your pull request. Please review these requirements:

Contributors guide: https://github.com/openssl/openssl/blob/master/CONTRIBUTING.md

Other than that, provide a description above this comment if there isn't one already

If this fixes a GitHub issue, make sure to have a line saying 'Fixes #XXXX' (without quotes) in the commit message.
-->

<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
- [x] documentation is added or updated
- [x] tests are added or updated
@openssl-machine

Copy link
Copy Markdown
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago

@evil-cry

Copy link
Copy Markdown
Author

Resolved all addressable comments here

@evil-cry
evil-cry requested review from levitte and t8m March 22, 2026 23:12
@bbbrumley

Copy link
Copy Markdown
Contributor

Resolved all addressable comments here

@evil-cry thanks for the new commits!

  • This PR still needs a rebase off of fresh master.
  • I sent some unit test details via email -- please take a look.

@bbbrumley
bbbrumley force-pushed the feature/ascon128 branch 2 times, most recently from 39699a0 to fcb74ab Compare March 30, 2026 16:10
@bbbrumley

Copy link
Copy Markdown
Contributor

rebased on master and conflict resolved -- reviews can continue IMO

@bbbrumley

Copy link
Copy Markdown
Contributor

Unrelated PR but in the #27015 discussion I realized I wasn't rigging in negative tests in the optimal way.

Tweaked in dd5a0ea

@bbbrumley

bbbrumley commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

OK so follow-up to my own test tweak ☝️

I'm writing another generic AEAD interface test, on a dev branch now but will file the PR tomorrow, I get

#         # Subtest: test_evp_aead_bad_decrypt_reason
        # test_evp_aead_bad_decrypt_reason 3, DEC_BADTAG_WRONG_REASON: ARIA-192-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 9, DEC_BADTAG_WRONG_REASON: ARIA-192-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 12, DEC_BADTAG_WRONG_REASON: ARIA-256-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 20, DEC_BADTAG_WRONG_REASON: AES-128-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 24, DEC_BADTAG_WRONG_REASON: ARIA-256-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 26, DEC_BADTAG_WRONG_REASON: AES-256-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 29, DEC_BADTAG_WRONG_REASON: AES-128-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 30, DEC_BADTAG_WRONG_REASON: AES-256-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 35, DEC_BADTAG_WRONG_REASON: ARIA-128-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 36, DEC_BADTAG_WRONG_REASON: AES-192-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 40, DEC_BADTAG_WRONG_REASON: ARIA-128-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 41, DEC_BADTAG_WRONG_REASON: AES-192-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 71, DEC_BADTAG_WRONG_REASON: AES-256-OCB (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 72, DEC_BADTAG_WRONG_REASON: AES-192-OCB (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 73, DEC_BADTAG_WRONG_REASON: AES-128-OCB (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 74, DEC_BADTAG_WRONG_REASON: AES-128-GCM-SIV (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 75, DEC_BADTAG_WRONG_REASON: AES-192-GCM-SIV (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 76, DEC_BADTAG_WRONG_REASON: AES-256-GCM-SIV (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 108, DEC_BADTAG_WRONG_REASON: SM4-GCM (expected reason 100, got 0)
        # test_evp_aead_bad_decrypt_reason 109, DEC_BADTAG_WRONG_REASON: SM4-CCM (expected reason 100, got 102)
        # test_evp_aead_bad_decrypt_reason 112, DEC_BADTAG_WRONG_REASON: ChaCha20-Poly1305 (expected reason 100, got 0)
#     not ok 65 - test_evp_aead_bad_decrypt_reason

so

  1. CCM fails with reason PROV_R_CIPHER_OPERATION_FAILED (102)
  2. Everything else "silently" fails (0) (so still returns a failure code, but doesn't put a reason on the stack)
  3. ASCON here fails with reason PROV_R_BAD_DECRYPT (100)

What do we prefer? (so I can adjust this PR, and also file a generic AEAD regression test in another PR)

@mbroz
mbroz self-requested a review August 1, 2026 16:24
@github-actions github-actions Bot added the severity: ABI change This pull request contains ABI changes label Aug 1, 2026
rickyringler pushed a commit to rickyringler/openssl that referenced this pull request Aug 21, 2026
discover all provided ciphers with non-zero IV length and verify
correct multi-step initialization semantics.

The EVP API permits key and IV to be supplied in separate
`EVP_CipherInit_ex()` calls (e.g. key-only followed by IV-only).
A recent bug (PR openssl#29934, ASCON-AEAD128) demonstrated that a
provider may silently ignore a key-only init, resulting in reuse
of a previously loaded key during a subsequent IV-only init.

To prevent similar regressions, this change introduces three
generic tests that automatically cover all IV-taking ciphers:

Verifies that:
- `init(key) → init(iv)`
- `init(iv) → init(key)`

produce identical ciphertext (and authentication tag for AEAD
ciphers) compared to single-call `init(key, iv)`.

Primes a context with `key1/iv1`, then re-initializes via
`init(key2) → init(iv2)` and verifies the output matches a fresh
`encrypt(key2, iv2)` operation, ensuring that no previously stored
key is reused.

Encrypts using single-call initialization and then decrypts using
multi-step initialization, verifying plaintext recovery. For AEAD
ciphers, this also exercises tag verification through the
multi-step path.

Ciphers are discovered using `EVP_CIPHER_do_all_provided()`,
requiring no maintenance when new IV-taking ciphers are added.
SIV mode is skipped due to its synthetic IV semantics. CCM mode
handling includes required length declarations.

This provides broad regression coverage for the provider
implementations that support multi-step EVP initialization.

Reviewed-by: Dmitry Belyavskiy <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
MergeDate: Thu Apr 16 07:08:17 2026
(Merged from openssl#30141)
@bbbrumley

Copy link
Copy Markdown
Contributor

file a generic AEAD regression test in another PR

done in #32587

rebased

I think we're almost there. I've got one more related PR open to sort.

@github-actions github-actions Bot removed the severity: ABI change This pull request contains ABI changes label Sep 10, 2026
nhorman
nhorman previously approved these changes Sep 10, 2026

@nhorman nhorman 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.

Just the one nit regarding the extra ASCONF_INLINE macro, but don't change it unless you're going to make other updates

Comment thread crypto/ascon/ascon_aead128.c Outdated
#include <openssl/crypto.h>

/* semi-portable inline declaration */
#define ASCON_INLINE ossl_inline

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.

not at all critical, but I'm not sure we need the additional indirection here, you can just use ossl_inline directly.

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.

not sure we need the additional indirection here

oof thought I stripped out all of those already, solely an upstream thing

fixed in fb8eff0

thanks

@bbbrumley

Copy link
Copy Markdown
Contributor

here is the planned CHANGES.md entry, dropping that commit for now (tired of solving conflicts)

* Added the ASCON-AEAD128 cipher as specified in NIST SP 800-232. ASCON-AEAD128
  provides authenticated encryption with associated data (AEAD) using 128-bit
  keys, nonces, and tags. The cipher is available through the EVP interface and
  the default provider. This implementation only supports byte-aligned inputs
  and full-length tags.

  *Dominic Cunningham, Billy Bob Brumley*

evil-cry and others added 2 commits September 11, 2026 04:05
Integrate ASCON-AEAD128 authenticated encryption cipher into OpenSSL's
default provider and libcrypto. ASCON-AEAD128 is specified in NIST
SP 800-232 and provides authenticated encryption with associated data
(AEAD) using a 128-bit key and 128-bit nonce.

Implementation details:
- Add cleanroom crypto/ascon implementation
- Add provider cipher implementation following OpenSSL stream cipher
  patterns with generated parameter dispatch tables
- Support standard AEAD operations including AAD handling, tag
  generation/verification, and context reinitialization

Fixes: openssl#28271

Co-authored-by: Billy Brumley <[email protected]>
@openssl-ci-bot openssl-ci-bot Bot added approval: done This pull request has the required number of approvals approval: ready to merge The 24 hour grace period has passed, ready to merge and removed approval: review pending This pull request needs review by a committer approval: done This pull request has the required number of approvals labels Sep 15, 2026
@openssl-ci-bot

Copy link
Copy Markdown

This pull request is ready to merge

openssl-machine pushed a commit that referenced this pull request Sep 16, 2026
Integrate ASCON-AEAD128 authenticated encryption cipher into OpenSSL's
default provider and libcrypto. ASCON-AEAD128 is specified in NIST
SP 800-232 and provides authenticated encryption with associated data
(AEAD) using a 128-bit key and 128-bit nonce.

Implementation details:
- Add cleanroom crypto/ascon implementation
- Add provider cipher implementation following OpenSSL stream cipher
  patterns with generated parameter dispatch tables
- Support standard AEAD operations including AAD handling, tag
  generation/verification, and context reinitialization

Fixes: #28271

Co-authored-by: Billy Brumley <[email protected]>
Reviewed-by: Neil Horman <[email protected]>
Reviewed-by: Andrew Dinh <[email protected]>
Merge-date: Wed Sep 16 14:25:19 2026
Merged-from: #29934
openssl-machine pushed a commit that referenced this pull request Sep 16, 2026
…and negative

check the following for test provenance

https: //gitlab.com/platsec/sp800232-rit
Reviewed-by: Neil Horman <[email protected]>
Reviewed-by: Andrew Dinh <[email protected]>
Merge-date: Wed Sep 16 14:25:19 2026
Merged-from: #29934
@jogme

jogme commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Merged to master. Thank you!

@bbbrumley please open a PR for the changes.md.

@jogme jogme closed this Sep 16, 2026
@beldmit

beldmit commented Sep 16, 2026

Copy link
Copy Markdown
Member

Wow finally! Great!

@dominic-dirac

Copy link
Copy Markdown

Wooo! @bbbrumley Thank you for helping get this across the finish line on my behalf. A massive thank you to the entire cohort of reviewers and maintainers as well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: ready to merge The 24 hour grace period has passed, ready to merge branch: master Applies to master branch cla: 1.0 no AI CLAv1.0 applies to one of the commits. Check whether it wasn't created with AI assistance. severity: fips change The pull request changes FIPS provider sources tests: present The PR has suitable tests present triaged: feature The issue/pr requests/adds a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lightweight crypto [SP 800-232]