Skip to content

Conversation

@ttungle96
Copy link

@ttungle96 ttungle96 commented Nov 8, 2025

Issues:

  1. Add EVP_AEAD API of XAES-256-GCM, which is extended AES-256-GCM with a derived key mode proposed by Filippo Valsorda in 2023, followed by a specification released in 2024.
  2. This implementation uses an optimized CMAC dedicated to the specific use case of XAES-256-GCM from XAES-256-GCM #2652.
  3. Support varying nonce sizes: 20 ≤ b ≤ 24 based on the extension: https://eprint.iacr.org/2025/758.pdf#page=24

Description of Changes

Implementation for API EVP_AEAD of XAES-256-GCM is appended to e_aes.c, and the tests are appended to aead_test.cc.

Testing

We use the test vectors provided here:
https://github.com/C2SP/C2SP/blob/main/XAES-256-GCM.md
https://github.com/C2SP/C2SP/blob/main/XAES-256-GCM/openssl/openssl.c
https://github.com/C2SP/C2SP/blob/main/XAES-256-GCM/go/XAES-256-GCM_test.go

./crypto_test --gtest_filter='All/PerAEADTest.*'
./crypto_test --gtest_filter='CipherTest.*'

Modifications compared with #2652

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.

@ttungle96 ttungle96 requested a review from a team as a code owner November 8, 2025 03:40
@codecov-commenter
Copy link

codecov-commenter commented Nov 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.31%. Comparing base (706e60b) to head (29ae452).

Additional details and impacted files
@@               Coverage Diff                @@
##           xaes-256-gcm    #2809      +/-   ##
================================================
+ Coverage         78.27%   78.31%   +0.03%     
================================================
  Files               683      683              
  Lines            117356   117484     +128     
  Branches          16482    16488       +6     
================================================
+ Hits              91865    92002     +137     
+ Misses            24609    24601       -8     
+ Partials            882      881       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

// ------------------------------------------------------------------------------
// ---------------- EVP_AEAD XAES-256-GCM Without Key Commitment ----------------
// ------------------------------------------------------------------------------
/* Since ctx->state capacity is 568 bytes, it does not have enough space
Copy link
Contributor

Choose a reason for hiding this comment

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

what's ctx->state?

Copy link
Author

Choose a reason for hiding this comment

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

As I write in design doc: "state is a void pointer in the EVP_AEAD_CTX object pointing to an opaque memory that can be used to store implementation-specific data".
See this:
https://github.com/ttungle96/aws-lc/blob/xaes-256-gcm/include/openssl/aead.h#L223
https://github.com/ttungle96/aws-lc/blob/xaes-256-gcm/include/openssl/aead.h#L213

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, but other people reading the code might not have access to your design doc :)

anyway, why don't you increase the size of ctx->state instead?

Copy link
Author

@ttungle96 ttungle96 Nov 12, 2025

Choose a reason for hiding this comment

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

Since I'm not sure whether it is allowed to do so. Increasing the size of ctx->state will simplify the code. Should I follow that direction?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so, @nebeid what do you think about this?

Copy link
Author

Choose a reason for hiding this comment

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

Thanks! I just increased the size of ctx->state and cleaned allocate/free memory code.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's better not to have a pointer, thanks, dkostic. On the other hand, do we need to have the gcm struct at all? What's different in using it compared to #2652 where it was created on the stack in the seal/open calls because nothing in it needs to be persisted between calls.
We're not considering yet reusing the gcm context, are you preparing for that usecase?

Copy link
Author

@ttungle96 ttungle96 Nov 13, 2025

Choose a reason for hiding this comment

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

I removed struct aead_aes_gcm_ctx gcm_ctx from AEAD_XAES_256_GCM_CTX.

AEAD_XAES_256_GCM_CTX *xaes_ctx = (AEAD_XAES_256_GCM_CTX*)&ctx->state;

// Allocate memory for xaes_ctx->gcm_ctx
xaes_ctx->gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx));
Copy link
Contributor

Choose a reason for hiding this comment

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

we should check that OPENSSL_malloc succeeded.

Copy link
Author

Choose a reason for hiding this comment

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

I'll add checking. The issue is it's hard to create a test case that could make it failed to increase test coverage.

Copy link
Contributor

Choose a reason for hiding this comment

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

that's ok, you can leave that particular code path untested.

@ttungle96 ttungle96 requested a review from dkostic November 12, 2025 21:09
dkostic
dkostic previously approved these changes Nov 12, 2025
AES_encrypt(M1, derived_key, &xaes_ctx->xaes_key);
AES_encrypt(M2, derived_key + AES_BLOCK_SIZE, &xaes_ctx->xaes_key);
AES_encrypt(M, derived_key, xaes_key);
M[1] ^= 0x03;
Copy link
Contributor

Choose a reason for hiding this comment

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

A comment would be good to clarify the outcome of this XOR

Copy link
Author

Choose a reason for hiding this comment

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

Thanks! I added a comment!

// ------------------------------------------------------------------------------
// ---------------- EVP_AEAD XAES-256-GCM Without Key Commitment ----------------
// ------------------------------------------------------------------------------
/* Since ctx->state capacity is 568 bytes, it does not have enough space
Copy link
Contributor

Choose a reason for hiding this comment

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

It's better not to have a pointer, thanks, dkostic. On the other hand, do we need to have the gcm struct at all? What's different in using it compared to #2652 where it was created on the stack in the seal/open calls because nothing in it needs to be persisted between calls.
We're not considering yet reusing the gcm context, are you preparing for that usecase?

tool/speed.cc Outdated
#if AWSLC_API_VERSION > 16
!SpeedKEM(selected) ||
#endif
#if AWSLC_API_VERSION > 31
Copy link
Contributor

Choose a reason for hiding this comment

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

The XAES APIs are introduced in

#define AWSLC_API_VERSION 35

so maybe we need to introduce a new #if AWSLC_API_VERSION > 34 for them.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you! I updated it.

// Test encryption and decryption with a plaintext
const uint8_t *plaintext = (const uint8_t *)"Hello, XAES-256-GCM!";
std::vector<uint8_t> ciphertext_and_tag;
DecodeHex(&ciphertext_and_tag, "01e5f78bc99de880bd2eeff2870d361f0eab5b2fc55268f34b14045878fe3668db980319");
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this being used in the test? I don't see it in the arguments.
Where are the results from? The EVP implementation?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah. They're redundant. Since for shorter nonce, we current only test to ensure encryption/decryption. I'll update. Thank you!

@ttungle96 ttungle96 requested a review from nebeid November 13, 2025 01:05
nebeid
nebeid previously approved these changes Nov 13, 2025
dkostic
dkostic previously approved these changes Nov 13, 2025
Copy link
Contributor

@sgmenda-aws sgmenda-aws left a comment

Choose a reason for hiding this comment

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

some non-blocking remarks

Comment on lines 1991 to 1995
// Reference for nonce size < 24 bytes:
// https://eprint.iacr.org/2025/758.pdf#page=24
/* When nonce size b < 24 bytes, it uses bytes [b-12:b]
* of input nonce as iv for the underlying AES encryption.
* nonce_len is b in the referece, where 20 <= b <= 24 */
Copy link
Contributor

Choose a reason for hiding this comment

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

this comment is repeated twice, here an in aead_xaes_256_gcm_open_gather. it would be clearer to make a helper function / macro that takes (nonce, nonce_len) and returns nonce + nonce_len - AES_GCM_NONCE_LENGTH and put the comment there.

Copy link
Author

@ttungle96 ttungle96 Nov 13, 2025

Choose a reason for hiding this comment

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

Good suggestion! I'll change.

Comment on lines 434 to 435
// EVP_aead_xaes_256_gcm is AES-256 in Galois Counter Mode with CMAC-based KDF
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_xaes_256_gcm(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not a TLS-specific AEAD, so disambiguate. Also link to spec.

Suggested change
// EVP_aead_xaes_256_gcm is AES-256 in Galois Counter Mode with CMAC-based KDF
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_xaes_256_gcm(void);
// Other AEAD algorithms.
// EVP_aead_xaes_256_gcm is AES-256 in Galois Counter Mode with CMAC-based KDF, as specified in https://c2sp.org/XAES-256-GCM
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_xaes_256_gcm(void);

Copy link
Author

@ttungle96 ttungle96 Nov 13, 2025

Choose a reason for hiding this comment

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

I'll move this next to EVP_aead_aes_256_gcm().

tool/speed.cc Outdated
#endif
#if AWSLC_API_VERSION > 31
!SpeedDigestSign(selected) ||
!SpeedDigestSign(selected) ||
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
!SpeedDigestSign(selected) ||
!SpeedDigestSign(selected) ||

@ttungle96 ttungle96 dismissed stale reviews from dkostic and nebeid via bba8f20 November 13, 2025 19:52
sgmenda-aws
sgmenda-aws previously approved these changes Nov 13, 2025
dkostic
dkostic previously approved these changes Nov 13, 2025
nebeid
nebeid previously approved these changes Nov 13, 2025
@ttungle96 ttungle96 dismissed stale reviews from nebeid, dkostic, and sgmenda-aws via 70cd651 November 13, 2025 22:57
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

dkostic
dkostic previously approved these changes Nov 13, 2025
@torben-hansen torben-hansen merged commit 92b4227 into aws:xaes-256-gcm Nov 14, 2025
370 of 388 checks passed
@ttungle96 ttungle96 deleted the xaes-256-gcm branch November 14, 2025 00:56
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.

7 participants